[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