[llvm] 82c5e30 - [llvm-ml] Implement support for MASM's extern directive
Eric Astor via llvm-commits
llvm-commits at lists.llvm.org
Tue May 10 11:36:34 PDT 2022
Author: Alan Zhao
Date: 2022-05-10T14:36:06-04:00
New Revision: 82c5e302f9e63a3491b5e40aa33771f355791598
URL: https://github.com/llvm/llvm-project/commit/82c5e302f9e63a3491b5e40aa33771f355791598
DIFF: https://github.com/llvm/llvm-project/commit/82c5e302f9e63a3491b5e40aa33771f355791598.diff
LOG: [llvm-ml] Implement support for MASM's extern directive
The EXTERN keyword defines external symbols in MASM.
Credit goes to epastor@ for implementing most of the logic; I (ayzhao@)
added some bugfixes and tests.
[0]: https://docs.microsoft.com/en-us/cpp/assembler/masm/extern-masm?view=msvc-170
Reviewed By: epastor
Submitted By: epastor
Differential Revision: https://reviews.llvm.org/D125273
Added:
llvm/test/tools/llvm-ml/extern.asm
llvm/test/tools/llvm-ml/extern_errors.asm
Modified:
llvm/lib/MC/MCParser/MasmParser.cpp
llvm/test/tools/llvm-ml/indirect_branch.asm
Removed:
################################################################################
diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
index be478e2fac5d..da84a91eddd9 100644
--- a/llvm/lib/MC/MCParser/MasmParser.cpp
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -976,6 +976,8 @@ class MasmParser : public MCAsmParser {
bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
bool parseDirectiveNestedEnds();
+ bool parseDirectiveExtern();
+
/// Parse a directive like ".globl" which accepts a single symbol (which
/// should be a label or an external).
bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
@@ -2405,8 +2407,7 @@ bool MasmParser::parseStatement(ParseStatementInfo &Info,
case DK_ORG:
return parseDirectiveOrg();
case DK_EXTERN:
- eatToEndOfStatement(); // .extern is the default, ignore it.
- return false;
+ return parseDirectiveExtern();
case DK_PUBLIC:
return parseDirectiveSymbolAttribute(MCSA_Global);
case DK_COMM:
@@ -6019,6 +6020,37 @@ bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
return false;
}
+bool MasmParser::parseDirectiveExtern() {
+ // .extern is the default - but we still need to take any provided type info.
+ auto parseOp = [&]() -> bool {
+ StringRef Name;
+ SMLoc NameLoc = getTok().getLoc();
+ if (parseIdentifier(Name))
+ return Error(NameLoc, "expected name");
+ if (parseToken(AsmToken::Colon))
+ return true;
+
+ StringRef TypeName;
+ SMLoc TypeLoc = getTok().getLoc();
+ if (parseIdentifier(TypeName))
+ return Error(TypeLoc, "expected type");
+ AsmTypeInfo Type;
+ if (lookUpType(TypeName, Type))
+ return Error(TypeLoc, "unrecognized type");
+ KnownType[Name.lower()] = Type;
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ Sym->setExternal(true);
+ getStreamer().emitSymbolAttribute(Sym, MCSA_Extern);
+
+ return false;
+ };
+
+ if (parseMany(parseOp))
+ return addErrorSuffix(" in directive 'extern'");
+ return false;
+}
+
/// parseDirectiveSymbolAttribute
/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
diff --git a/llvm/test/tools/llvm-ml/extern.asm b/llvm/test/tools/llvm-ml/extern.asm
new file mode 100644
index 000000000000..87cfba48e948
--- /dev/null
+++ b/llvm/test/tools/llvm-ml/extern.asm
@@ -0,0 +1,17 @@
+; RUN: llvm-ml -m32 -filetype=s %s /Fo - | FileCheck %s --check-prefixes=CHECK,CHECK-32
+; RUN: llvm-ml -m64 -filetype=s %s /Fo - | FileCheck %s --check-prefixes=CHECK,CHECK-64
+
+extern foo : dword, bar : word
+; CHECK: .extern foo
+; CHECK: .extern bar
+
+.code
+mov ebx, foo
+; CHECK-32: mov ebx, dword ptr [foo]
+; CHECK-64: mov ebx, dword ptr [rip + foo]
+
+mov bx, bar
+; CHECK-32: mov bx, word ptr [bar]
+; CHECK-64: mov bx, word ptr [rip + bar]
+
+END
diff --git a/llvm/test/tools/llvm-ml/extern_errors.asm b/llvm/test/tools/llvm-ml/extern_errors.asm
new file mode 100644
index 000000000000..72ce8d8c4367
--- /dev/null
+++ b/llvm/test/tools/llvm-ml/extern_errors.asm
@@ -0,0 +1,22 @@
+; RUN: not llvm-ml -filetype=s %s /Fo /dev/null 2>&1 | FileCheck %s --implicit-check-not=error:
+
+; CHECK: :[[# @LINE + 1]]:8: error: expected name in directive 'extern'
+extern 123
+
+; CHECK: :[[# @LINE + 1]]:14: error: expected type in directive 'extern'
+extern foo0 :
+
+; CHECK: :[[# @LINE + 1]]:15: error: unrecognized type in directive 'extern'
+extern bar0 : typedoesnotexist
+
+extern foo1 : dword, bar1 : word
+
+.code
+
+; CHECK: :[[# @LINE + 1]]:1: error: invalid operand for instruction
+mov bx, foo1
+
+; CHECK: :[[# @LINE + 1]]:1: error: invalid operand for instruction
+mov bl, bar1
+
+END
diff --git a/llvm/test/tools/llvm-ml/indirect_branch.asm b/llvm/test/tools/llvm-ml/indirect_branch.asm
index c4b28ba0fad9..391153b73e99 100644
--- a/llvm/test/tools/llvm-ml/indirect_branch.asm
+++ b/llvm/test/tools/llvm-ml/indirect_branch.asm
@@ -1,6 +1,13 @@
; RUN: llvm-ml -m64 -filetype=s %s /Fo - | FileCheck %s --check-prefixes=CHECK-64,CHECK
; RUN: llvm-ml -m32 -filetype=s %s /Fo - | FileCheck %s --check-prefixes=CHECK-32,CHECK
+ifdef rax
+ extern fn_ref_extern : qword
+else
+ extern fn_ref_extern : dword
+endif
+extern fn_ref_extern_word : word
+
.data
ifdef rax
@@ -186,3 +193,58 @@ t16:
je [t16];
; CHECK-LABEL: t16:
; CHECK: je t16
+
+t17:
+call fn_ref_extern
+jmp fn_ref_extern
+; CHECK-LABEL: t17:
+; CHECK-64: call qword ptr [rip + fn_ref_extern]
+; CHECK-64: jmp qword ptr [rip + fn_ref_extern]
+; CHECK-32: call dword ptr [fn_ref_extern]
+; CHECK-32: jmp dword ptr [fn_ref_extern]
+
+t18:
+call [fn_ref_extern]
+jmp [fn_ref_extern]
+; CHECK-LABEL: t18:
+; CHECK-64: call qword ptr [rip + fn_ref_extern]
+; CHECK-64: jmp qword ptr [rip + fn_ref_extern]
+; CHECK-32: call dword ptr [fn_ref_extern]
+; CHECK-32: jmp dword ptr [fn_ref_extern]
+
+ifdef rax
+ t19:
+ call qword ptr [fn_ref_extern]
+ jmp qword ptr [fn_ref_extern]
+ ; CHECK-64-LABEL: t19:
+ ; CHECK-64: call qword ptr [rip + fn_ref_extern]
+ ; CHECK-64: jmp qword ptr [rip + fn_ref_extern]
+else
+ t19:
+ call dword ptr [fn_ref_extern]
+ jmp dword ptr [fn_ref_extern]
+ ; CHECK-32-LABEL: t19:
+ ; CHECK-32: call dword ptr [fn_ref_extern]
+ ; CHECK-32: jmp dword ptr [fn_ref_extern]
+
+ t20:
+ call fn_ref_extern_word
+ jmp fn_ref_extern_word
+ ; CHECK-32-LABEL: t20:
+ ; CHECK-32: call word ptr [fn_ref_extern_word]
+ ; CHECK-32-NEXT: jmp word ptr [fn_ref_extern_word]
+
+ t21:
+ call [fn_ref_extern_word]
+ jmp [fn_ref_extern_word]
+ ; CHECK-32-LABEL: t21:
+ ; CHECK-32: call word ptr [fn_ref_extern_word]
+ ; CHECK-32-NEXT: jmp word ptr [fn_ref_extern_word]
+
+ t22:
+ call word ptr [fn_ref_extern_word]
+ jmp word ptr [fn_ref_extern_word]
+ ; CHECK-32-LABEL: t22:
+ ; CHECK-32: call word ptr [fn_ref_extern_word]
+ ; CHECK-32-NEXT: jmp word ptr [fn_ref_extern_word]
+endif
More information about the llvm-commits
mailing list