diff --git a/llvm/include/llvm/MC/MCWinCOFFStreamer.h b/llvm/include/llvm/MC/MCWinCOFFStreamer.h --- a/llvm/include/llvm/MC/MCWinCOFFStreamer.h +++ b/llvm/include/llvm/MC/MCWinCOFFStreamer.h @@ -58,6 +58,7 @@ unsigned ByteAlignment) override; void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; + void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; void emitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment, SMLoc Loc = SMLoc()) override; void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, diff --git a/llvm/lib/MC/MCParser/COFFMasmParser.cpp b/llvm/lib/MC/MCParser/COFFMasmParser.cpp --- a/llvm/lib/MC/MCParser/COFFMasmParser.cpp +++ b/llvm/lib/MC/MCParser/COFFMasmParser.cpp @@ -53,6 +53,8 @@ bool ParseDirectiveSegmentEnd(StringRef, SMLoc); bool ParseDirectiveIncludelib(StringRef, SMLoc); + bool ParseDirectiveAlias(StringRef, SMLoc); + bool ParseSEHDirectiveAllocStack(StringRef, SMLoc); bool ParseSEHDirectiveEndProlog(StringRef, SMLoc); @@ -124,7 +126,7 @@ // purge // Miscellaneous directives - // alias + addDirectiveHandler<&COFFMasmParser::ParseDirectiveAlias>("alias"); // assume // .fpo addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>( @@ -384,6 +386,26 @@ return false; } +bool COFFMasmParser::ParseDirectiveAlias(StringRef Directive, SMLoc Loc) { + std::string AliasName, ActualName; + if (getTok().isNot(AsmToken::Less) || + getParser().parseAngleBracketString(AliasName)) + return Error(getTok().getLoc(), "expected "); + if (getParser().parseToken(AsmToken::Equal)) + return addErrorSuffix(" in " + Directive + " directive"); + if (getTok().isNot(AsmToken::Less) || + getParser().parseAngleBracketString(ActualName)) + return Error(getTok().getLoc(), "expected "); + + MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); + MCSymbol *Actual = getContext().getOrCreateSymbol(ActualName); + + Alias->setVariableValue(MCSymbolRefExpr::create(Actual, getContext())); + getStreamer().emitWeakReference(Alias, Actual); + + return false; +} + bool COFFMasmParser::ParseSEHDirectiveAllocStack(StringRef Directive, SMLoc Loc) { int64_t Size; diff --git a/llvm/lib/MC/MCWinCOFFStreamer.cpp b/llvm/lib/MC/MCWinCOFFStreamer.cpp --- a/llvm/lib/MC/MCWinCOFFStreamer.cpp +++ b/llvm/lib/MC/MCWinCOFFStreamer.cpp @@ -308,6 +308,18 @@ PopSection(); } +void MCWinCOFFStreamer::emitWeakReference(MCSymbol *AliasS, + const MCSymbol *Symbol) { + auto *Alias = cast(AliasS); + Alias->setIsWeakExternal(); + + BeginCOFFSymbolDef(AliasS); + EmitCOFFSymbolStorageClass( + COFF::SymbolStorageClass::IMAGE_SYM_CLASS_WEAK_EXTERNAL); + EmitCOFFSymbolType(COFF::SymbolBaseType::IMAGE_SYM_TYPE_NULL); + EndCOFFSymbolDef(); +} + void MCWinCOFFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment, SMLoc Loc) { diff --git a/llvm/test/tools/llvm-ml/alias.test b/llvm/test/tools/llvm-ml/alias.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ml/alias.test @@ -0,0 +1,44 @@ +; RUN: llvm-ml -filetype=obj %s | llvm-objdump --syms - | FileCheck %s + +.code + +t1 PROC + ret +t1 ENDP +; CHECK: [[T1_ADDRESS:0x[0-9a-fA-F]+]] t1 + +t2 PROC + ret +t2 ENDP +; CHECK: [[T2_ADDRESS:0x[0-9a-fA-F]+]] t2 + +alias = +; CHECK: (scl 69){{.*}}t3 +; CHECK-NEXT: AUX indx [[T3_DEFAULT_INDEX:[0-9]+]] srch 3 +; CHECK: {{^\[}} [[T3_DEFAULT_INDEX]]{{\]}} +; CHECK-SAME: [[T1_ADDRESS]] + +alias = +; CHECK: (scl 69){{.*}}t4 +; CHECK-NEXT: AUX indx [[T4_DEFAULT_INDEX:[0-9]+]] srch 3 +; CHECK: {{^\[}} [[T4_DEFAULT_INDEX]]{{\]}} +; CHECK-SAME: [[T2_ADDRESS]] + +alias = +; CHECK: (scl 69){{.*}}t5 +; CHECK-NEXT: AUX indx [[T5_REFERENCE_INDEX:[0-9]+]] srch 3 +; CHECK: {{^\[}}[[T5_REFERENCE_INDEX]]{{\]}} +; CHECK-SAME: foo{{$}} + +alias = +; CHECK: (scl 69){{.*}}t6 +; CHECK-NEXT: AUX indx [[T6_DEFAULT_INDEX:[0-9]+]] srch 3 +; CHECK: {{^\[}}[[T6_DEFAULT_INDEX]]{{\]}} +; CHECK-SAME: [[BAR_ADDRESS:0x[0-9a-fA-F]+]] .weak +; CHECK: [[BAR_ADDRESS]] bar + +bar PROC + ret +bar ENDP + +END diff --git a/llvm/test/tools/llvm-ml/alias_errors.test b/llvm/test/tools/llvm-ml/alias_errors.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ml/alias_errors.test @@ -0,0 +1,36 @@ +; RUN: not llvm-ml -filetype=asm %s 2>&1 | FileCheck %s + +.code + +foo PROC + ret +foo ENDP + +bar PROC + ret +bar ENDP + +t1: +alias foo = bar +alias foo = +alias = bar + +; CHECK: error: expected +; CHECK: error: expected +; CHECK: error: expected + +t2: +alias +alias , + +; CHECK: error: unexpected token in alias directive +; CHECK: error: unexpected token in alias directive + +t3: +alias +alias + +END \ No newline at end of file