[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