diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/llvm/include/llvm/MC/MCParser/MCAsmParser.h --- a/llvm/include/llvm/MC/MCParser/MCAsmParser.h +++ b/llvm/include/llvm/MC/MCParser/MCAsmParser.h @@ -184,6 +184,8 @@ virtual bool isParsingMasm() const { return false; } + virtual bool defineMacro(StringRef Name, StringRef Value) { return true; } + virtual bool lookUpField(StringRef Name, AsmFieldInfo &Info) const { return true; } diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -501,6 +501,8 @@ bool isParsingMasm() const override { return true; } + bool defineMacro(StringRef Name, StringRef Value) override; + bool lookUpField(StringRef Name, AsmFieldInfo &Info) const override; bool lookUpField(StringRef Base, StringRef Member, AsmFieldInfo &Info) const override; @@ -6905,6 +6907,19 @@ llvm_unreachable("Unstable rewrite sort."); } +bool MasmParser::defineMacro(StringRef Name, StringRef Value) { + Variable &Var = Variables[Name.lower()]; + if (Var.Name.empty()) { + Var.Name = Name; + } else if (!Var.Redefinable) { + return TokError("invalid variable redefinition"); + } + Var.Redefinable = true; + Var.IsText = true; + Var.TextValue = Value.str(); + return false; +} + bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info) const { const std::pair BaseMember = Name.split('.'); const StringRef Base = BaseMember.first, Member = BaseMember.second; diff --git a/llvm/test/tools/llvm-ml/command_line_defines.asm b/llvm/test/tools/llvm-ml/command_line_defines.asm new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ml/command_line_defines.asm @@ -0,0 +1,38 @@ +; RUN: llvm-ml -filetype=s %s /Fo - /DT1=test1 /D T2=test2 | FileCheck %s + +.code + +t1: + ret +; CHECK-NOT: t1: +; CHECK-LABEL: test1: +; CHECK-NOT: t1: + +t2: + ret +; CHECK-NOT: t2: +; CHECK-LABEL: test2: +; CHECK-NOT: t2: + +t3: +ifdef t1 + xor eax, eax +endif + ret +; CHECK-LABEL: t3: +; CHECK: xor eax, eax +; CHECK: ret + +t4: +ifdef undefined + xor eax, eax +elseifdef t2 + xor ebx, ebx +endif + ret +; CHECK-LABEL: t4: +; CHECK-NOT: xor eax, eax +; CHECK: xor ebx, ebx +; CHECK: ret + +end diff --git a/llvm/tools/llvm-ml/Opts.td b/llvm/tools/llvm-ml/Opts.td --- a/llvm/tools/llvm-ml/Opts.td +++ b/llvm/tools/llvm-ml/Opts.td @@ -31,6 +31,9 @@ HelpText<"Display available options">; def help_long : MLFlag<"help">, Alias; def assemble_only : MLFlag<"c">, HelpText<"Assemble only; do not link">; +def define : MLJoinedOrSeparate<"D">, MetaVarName<"=">, + HelpText<"Define to (or blank if " + "omitted)">; def output_file : MLJoinedOrSeparate<"Fo">, HelpText<"Names the output file">; def include_path : MLJoinedOrSeparate<"I">, HelpText<"Sets path for include files">; @@ -72,7 +75,6 @@ def preserve_identifier_case : UnsupportedFlag<"Cp">, HelpText<"">; def uppercase_identifiers : UnsupportedFlag<"Cu">, HelpText<"">; def preserve_extern_case : UnsupportedFlag<"Cx">, HelpText<"">; -def define : UnsupportedJoinedOrSeparate<"D">, HelpText<"">; def output_preprocessed : UnsupportedFlag<"EP">, HelpText<"">; def errorreport : UnsupportedJoined<"ERRORREPORT">, HelpText<"">; def stacksize : UnsupportedSeparate<"F">, HelpText<"">; diff --git a/llvm/tools/llvm-ml/llvm-ml.cpp b/llvm/tools/llvm-ml/llvm-ml.cpp --- a/llvm/tools/llvm-ml/llvm-ml.cpp +++ b/llvm/tools/llvm-ml/llvm-ml.cpp @@ -147,6 +147,17 @@ Parser->getLexer().setLexMasmHexFloats(true); Parser->getLexer().setLexMasmStrings(true); + auto Defines = InputArgs.getAllArgValues(OPT_define); + for (StringRef Define : Defines) { + const auto NameValue = Define.split('='); + StringRef Name = NameValue.first, Value = NameValue.second; + if (Parser->defineMacro(Name, Value)) { + WithColor::error(errs(), ProgName) + << "can't define macro '" << Name << "' = '" << Value << "'\n"; + return 1; + } + } + int Res = Parser->Run(/*NoInitialTextSection=*/true); return Res;