[llvm] 4cbb912 - [ms] [llvm-ml] Add support for numeric built-in symbols

Eric Astor via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 21 08:43:20 PDT 2021


Author: Eric Astor
Date: 2021-07-21T11:43:07-04:00
New Revision: 4cbb912d7576312babfe4a95c17155687e474a4b

URL: https://github.com/llvm/llvm-project/commit/4cbb912d7576312babfe4a95c17155687e474a4b
DIFF: https://github.com/llvm/llvm-project/commit/4cbb912d7576312babfe4a95c17155687e474a4b.diff

LOG: [ms] [llvm-ml] Add support for numeric built-in symbols

Support @Version and @Line as built-in symbols. For now, resolves @Version to 1427 (the same as for the VS 2019 release of ML.EXE).

Reviewed By: thakis

Differential Revision: https://reviews.llvm.org/D104964

Added: 
    llvm/test/tools/llvm-ml/builtin_symbols.asm

Modified: 
    llvm/lib/MC/MCParser/MasmParser.cpp
    llvm/test/tools/llvm-ml/variable_redef_errors.asm

Removed: 
    


################################################################################
diff  --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
index a5a48d4b1e9d8..beb8c3af34f9b 100644
--- a/llvm/lib/MC/MCParser/MasmParser.cpp
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -389,7 +389,6 @@ class MasmParser : public MCAsmParser {
     StringRef Name;
     RedefinableKind Redefinable = REDEFINABLE;
     bool IsText = false;
-    int64_t NumericValue = 0;
     std::string TextValue;
   };
   StringMap<Variable> Variables;
@@ -796,6 +795,34 @@ class MasmParser : public MCAsmParser {
   /// def_range types parsed by this class.
   StringMap<CVDefRangeType> CVDefRangeTypeMap;
 
+  // Generic (target and platform independent) directive parsing.
+  enum BuiltinSymbol {
+    BI_NO_SYMBOL, // Placeholder
+    BI_DATE,
+    BI_TIME,
+    BI_VERSION,
+    BI_FILECUR,
+    BI_FILENAME,
+    BI_LINE,
+    BI_CURSEG,
+    BI_CPU,
+    BI_INTERFACE,
+    BI_CODE,
+    BI_DATA,
+    BI_FARDATA,
+    BI_WORDSIZE,
+    BI_CODESIZE,
+    BI_DATASIZE,
+    BI_MODEL,
+    BI_STACK,
+  };
+
+  /// Maps builtin name --> BuiltinSymbol enum, for builtins handled by this
+  /// class.
+  StringMap<BuiltinSymbol> BuiltinSymbolMap;
+
+  const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
+
   // ".ascii", ".asciz", ".string"
   bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
 
@@ -1019,6 +1046,7 @@ class MasmParser : public MCAsmParser {
 
   void initializeDirectiveKindMap();
   void initializeCVDefRangeTypeMap();
+  void initializeBuiltinSymbolMap();
 };
 
 } // end anonymous namespace
@@ -1057,6 +1085,7 @@ MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
   initializeDirectiveKindMap();
   PlatformParser->Initialize(*this);
   initializeCVDefRangeTypeMap();
+  initializeBuiltinSymbolMap();
 
   NumOfMacroInstantiations = 0;
 }
@@ -1610,6 +1639,19 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
 
     MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
     if (!Sym) {
+      // If this is a built-in numeric value, treat it as a constant.
+      auto BuiltinIt = BuiltinSymbolMap.find(SymbolName.lower());
+      const BuiltinSymbol Symbol = (BuiltinIt == BuiltinSymbolMap.end())
+                                       ? BI_NO_SYMBOL
+                                       : BuiltinIt->getValue();
+      if (Symbol != BI_NO_SYMBOL) {
+        const MCExpr *Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
+        if (Value) {
+          Res = Value;
+          return false;
+        }
+      }
+
       // Variables use case-insensitive symbol names; if this is a variable, we
       // find the symbol using its canonical name.
       auto VarIt = Variables.find(SymbolName.lower());
@@ -1621,14 +1663,14 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
     // If this is an absolute variable reference, substitute it now to preserve
     // semantics in the face of reassignment.
     if (Sym->isVariable()) {
-      auto V = Sym->getVariableValue(/*SetUsed*/ false);
+      auto V = Sym->getVariableValue(/*SetUsed=*/false);
       bool DoInline = isa<MCConstantExpr>(V) && !Variant;
       if (auto TV = dyn_cast<MCTargetExpr>(V))
         DoInline = TV->inlineAssignedExpr();
       if (DoInline) {
         if (Variant)
           return Error(EndLoc, "unexpected modifier on variable reference");
-        Res = Sym->getVariableValue(/*SetUsed*/ false);
+        Res = Sym->getVariableValue(/*SetUsed=*/false);
         return false;
       }
     }
@@ -3377,6 +3419,10 @@ bool MasmParser::parseIdentifier(StringRef &Res,
 ///    | name "textequ" text-list (redefinability unspecified)
 bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
                                       DirectiveKind DirKind, SMLoc NameLoc) {
+  auto BuiltinIt = BuiltinSymbolMap.find(Name.lower());
+  if (BuiltinIt != BuiltinSymbolMap.end())
+    return Error(NameLoc, "cannot redefine a built-in symbol");
+
   Variable &Var = Variables[Name.lower()];
   if (Var.Name.empty()) {
     Var.Name = Name;
@@ -3429,12 +3475,18 @@ bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
   SMLoc EndLoc;
   if (parseExpression(Expr, EndLoc))
     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+  StringRef ExprAsString = StringRef(
+      StartLoc.getPointer(), EndLoc.getPointer() - StartLoc.getPointer());
 
   int64_t Value;
   if (!Expr->evaluateAsAbsolute(Value, getStreamer().getAssemblerPtr())) {
+    if (DirKind == DK_ASSIGN)
+      return Error(
+          StartLoc,
+          "expected absolute expression; not all symbols have known values",
+          {StartLoc, EndLoc});
+
     // Not an absolute expression; define as a text replacement.
-    StringRef ExprAsString = StringRef(
-        StartLoc.getPointer(), EndLoc.getPointer() - StartLoc.getPointer());
     if (!Var.IsText || Var.TextValue != ExprAsString) {
       switch (Var.Redefinable) {
       case Variable::NOT_REDEFINABLE:
@@ -3449,29 +3501,40 @@ bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
         break;
       }
     }
+
     Var.IsText = true;
     Var.TextValue = ExprAsString.str();
-  } else {
-    if (Var.IsText || Var.NumericValue != Value) {
-      switch (Var.Redefinable) {
-      case Variable::NOT_REDEFINABLE:
-        return Error(getTok().getLoc(), "invalid variable redefinition");
-      case Variable::WARN_ON_REDEFINITION:
-        if (Warning(NameLoc, "redefining '" + Name +
-                                 "', already defined on the command line")) {
-          return true;
-        }
-        break;
-      default:
-        break;
+    Var.Redefinable = Variable::REDEFINABLE;
+
+    return false;
+  }
+
+  MCSymbol *Sym = getContext().getOrCreateSymbol(Var.Name);
+
+  const MCConstantExpr *PrevValue =
+      Sym->isVariable() ? dyn_cast_or_null<MCConstantExpr>(
+                              Sym->getVariableValue(/*SetUsed=*/false))
+                        : nullptr;
+  if (Var.IsText || !PrevValue || PrevValue->getValue() != Value) {
+    switch (Var.Redefinable) {
+    case Variable::NOT_REDEFINABLE:
+      return Error(getTok().getLoc(), "invalid variable redefinition");
+    case Variable::WARN_ON_REDEFINITION:
+      if (Warning(NameLoc, "redefining '" + Name +
+                               "', already defined on the command line")) {
+        return true;
       }
+      break;
+    default:
+      break;
     }
-    Var.NumericValue = Value;
   }
+
+  Var.IsText = false;
+  Var.TextValue.clear();
   Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
                                            : Variable::NOT_REDEFINABLE;
 
-  MCSymbol *Sym = getContext().getOrCreateSymbol(Var.Name);
   Sym->setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
   Sym->setVariableValue(Expr);
   Sym->setExternal(false);
@@ -6181,7 +6244,9 @@ bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
           parseToken(AsmToken::EndOfStatement, "unexpected token in 'ifdef'"))
         return true;
 
-      if (Variables.find(Name.lower()) != Variables.end()) {
+      if (BuiltinSymbolMap.find(Name.lower()) != BuiltinSymbolMap.end()) {
+        is_defined = true;
+      } else if (Variables.find(Name.lower()) != Variables.end()) {
         is_defined = true;
       } else {
         MCSymbol *Sym = getContext().lookupSymbol(Name.lower());
@@ -6303,7 +6368,9 @@ bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
                      "unexpected token in 'elseifdef'"))
         return true;
 
-      if (Variables.find(Name.lower()) != Variables.end()) {
+      if (BuiltinSymbolMap.find(Name.lower()) != BuiltinSymbolMap.end()) {
+        is_defined = true;
+      } else if (Variables.find(Name.lower()) != Variables.end()) {
         is_defined = true;
       } else {
         MCSymbol *Sym = getContext().lookupSymbol(Name);
@@ -6473,7 +6540,9 @@ bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
     if (check(parseIdentifier(Name), "expected identifier after '.errdef'"))
       return true;
 
-    if (Variables.find(Name.lower()) != Variables.end()) {
+    if (BuiltinSymbolMap.find(Name.lower()) != BuiltinSymbolMap.end()) {
+      IsDefined = true;
+    } else if (Variables.find(Name.lower()) != Variables.end()) {
       IsDefined = true;
     } else {
       MCSymbol *Sym = getContext().lookupSymbol(Name);
@@ -7520,6 +7589,58 @@ bool MasmParser::parseMSInlineAsm(
   return false;
 }
 
+void MasmParser::initializeBuiltinSymbolMap() {
+  // Numeric built-ins (supported in all versions)
+  BuiltinSymbolMap["@version"] = BI_VERSION;
+  BuiltinSymbolMap["@line"] = BI_LINE;
+
+  // Text built-ins (supported in all versions)
+  // BuiltinSymbolMap["@date"] = BI_DATE;
+  // BuiltinSymbolMap["@time"] = BI_TIME;
+  // BuiltinSymbolMap["@filecur"] = BI_FILECUR;
+  // BuiltinSymbolMap["@filename"] = BI_FILENAME;
+  // BuiltinSymbolMap["@curseg"] = BI_CURSEG;
+
+  // Some built-ins exist only for MASM32 (32-bit x86)
+  if (getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
+      Triple::x86) {
+    // Numeric built-ins
+    // BuiltinSymbolMap["@cpu"] = BI_CPU;
+    // BuiltinSymbolMap["@interface"] = BI_INTERFACE;
+    // BuiltinSymbolMap["@wordsize"] = BI_WORDSIZE;
+    // BuiltinSymbolMap["@codesize"] = BI_CODESIZE;
+    // BuiltinSymbolMap["@datasize"] = BI_DATASIZE;
+    // BuiltinSymbolMap["@model"] = BI_MODEL;
+
+    // Text built-ins
+    // BuiltinSymbolMap["@code"] = BI_CODE;
+    // BuiltinSymbolMap["@data"] = BI_DATA;
+    // BuiltinSymbolMap["@fardata?"] = BI_FARDATA;
+    // BuiltinSymbolMap["@stack"] = BI_STACK;
+  }
+}
+
+const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
+                                               SMLoc StartLoc) {
+  switch (Symbol) {
+  default:
+    return nullptr;
+  case BI_VERSION:
+    // Match a recent version of ML.EXE.
+    return MCConstantExpr::create(1427, getContext());
+  case BI_LINE: {
+    int64_t Line;
+    if (ActiveMacros.empty())
+      Line = SrcMgr.FindLineNumber(StartLoc, CurBuffer);
+    else
+      Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
+                                   ActiveMacros.front()->ExitBuffer);
+    return MCConstantExpr::create(Line, getContext());
+  }
+  }
+  llvm_unreachable("unhandled built-in symbol");
+}
+
 /// Create an MCAsmParser instance.
 MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C,
                                       MCStreamer &Out, const MCAsmInfo &MAI,

diff  --git a/llvm/test/tools/llvm-ml/builtin_symbols.asm b/llvm/test/tools/llvm-ml/builtin_symbols.asm
new file mode 100644
index 0000000000000..844f9f260cb63
--- /dev/null
+++ b/llvm/test/tools/llvm-ml/builtin_symbols.asm
@@ -0,0 +1,35 @@
+; RUN: llvm-ml -filetype=s %s /Fo /dev/null 2>&1 | FileCheck %s
+
+version_val TEXTEQU %@Version
+
+ECHO t1:
+%ECHO @Version = version_val
+; CHECK-LABEL: t1:
+; CHECK-NEXT: 1427
+
+ECHO
+
+ECHO t2:
+if @Version gt 510
+ECHO @Version gt 510
+endif
+; CHECK-LABEL: t2:
+; CHECK-NEXT: @Version gt 510
+
+ECHO
+
+ECHO t3:
+if @Version le 510
+ECHO le 510
+endif
+; CHECK-LABEL: t3:
+; CHECK-NOT: @Version le 510
+
+ECHO
+
+line_val TEXTEQU %@Line
+
+ECHO t4:
+%ECHO @Line = line_val
+; CHECK-LABEL: t4:
+; CHECK-NEXT: @Line = [[# @LINE - 5]]

diff  --git a/llvm/test/tools/llvm-ml/variable_redef_errors.asm b/llvm/test/tools/llvm-ml/variable_redef_errors.asm
index c5a0844500ef4..faee829ee0fe7 100644
--- a/llvm/test/tools/llvm-ml/variable_redef_errors.asm
+++ b/llvm/test/tools/llvm-ml/variable_redef_errors.asm
@@ -7,6 +7,12 @@ equated_number equ 3
 ; CHECK: :[[# @LINE + 1]]:21: error: invalid variable redefinition
 equated_number equ 4
 
+; CHECK: :[[# @LINE + 1]]:1: error: cannot redefine a built-in symbol
+ at Line equ 5
+
+; CHECK: :[[# @LINE + 1]]:1: error: cannot redefine a built-in symbol
+ at Version equ 6
+
 .code
 
 end


        


More information about the llvm-commits mailing list