[llvm] r301797 - [LLVM][inline-asm] Altmacro absolute expression '%' feature

Michael Zuckerman via llvm-commits llvm-commits at lists.llvm.org
Mon May 1 06:20:13 PDT 2017


Author: mzuckerm
Date: Mon May  1 08:20:12 2017
New Revision: 301797

URL: http://llvm.org/viewvc/llvm-project?rev=301797&view=rev
Log:
[LLVM][inline-asm] Altmacro absolute expression '%' feature

In this patch, I introduce a new alt macro feature.
This feature adds meaning for the % when using it as a prefix to the calling macro arguments.

In the altmacro mode, the percent sign '%' before an absolute expression convert the expression first to a string. 
As described in the https://sourceware.org/binutils/docs-2.27/as/Altmacro.html
"Expression results as strings
You can write `%expr' to evaluate the expression expr and use the result as a string."

expression assumptions:

1. '%' can only evaluate an absolute expression.
2. Altmacro '%' must be the first character of the evaluated expression.
3. If no '%' is located before the expression, a regular module operation is expected.
4. The result of Absolute Expressions can be only integer.

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

Added:
    llvm/trunk/test/MC/AsmParser/altmacro_expression.s
    llvm/trunk/test/MC/AsmParser/negativ_altmacro_expression.s
Modified:
    llvm/trunk/include/llvm/MC/MCParser/MCAsmLexer.h
    llvm/trunk/lib/MC/MCParser/AsmParser.cpp
    llvm/trunk/lib/MC/MCParser/MCAsmLexer.cpp

Modified: llvm/trunk/include/llvm/MC/MCParser/MCAsmLexer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCParser/MCAsmLexer.h?rev=301797&r1=301796&r2=301797&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCParser/MCAsmLexer.h (original)
+++ llvm/trunk/include/llvm/MC/MCParser/MCAsmLexer.h Mon May  1 08:20:12 2017
@@ -161,6 +161,7 @@ protected: // Can only create subclasses
   bool IsAtStartOfStatement = true;
   AsmCommentConsumer *CommentConsumer = nullptr;
 
+  bool AltMacroMode;
   MCAsmLexer();
 
   virtual AsmToken LexToken() = 0;
@@ -175,6 +176,14 @@ public:
   MCAsmLexer &operator=(const MCAsmLexer &) = delete;
   virtual ~MCAsmLexer();
 
+  bool IsaAltMacroMode() {
+    return AltMacroMode;
+  }
+
+  void SetAltMacroMode(bool AltMacroSet) {
+    AltMacroMode = AltMacroSet;
+  }
+
   /// Consume the next token from the input stream and return it.
   ///
   /// The lexer will continuosly return the end-of-file token once the end of

Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=301797&r1=301796&r2=301797&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Mon May  1 08:20:12 2017
@@ -412,7 +412,7 @@ private:
     DK_CFI_REMEMBER_STATE, DK_CFI_RESTORE_STATE, DK_CFI_SAME_VALUE,
     DK_CFI_RESTORE, DK_CFI_ESCAPE, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED,
     DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE,
-    DK_MACROS_ON, DK_MACROS_OFF,
+    DK_MACROS_ON, DK_MACROS_OFF, DK_ALTMACRO, DK_NOALTMACRO,
     DK_MACRO, DK_EXITM, DK_ENDM, DK_ENDMACRO, DK_PURGEM,
     DK_SLEB128, DK_ULEB128,
     DK_ERR, DK_ERROR, DK_WARNING,
@@ -484,7 +484,8 @@ private:
   bool parseDirectiveEndMacro(StringRef Directive);
   bool parseDirectiveMacro(SMLoc DirectiveLoc);
   bool parseDirectiveMacrosOnOff(StringRef Directive);
-
+  // alternate macro mode directives
+  bool parseDirectiveAltmacro(StringRef Directive);
   // ".bundle_align_mode"
   bool parseDirectiveBundleAlignMode();
   // ".bundle_lock"
@@ -1922,6 +1923,9 @@ bool AsmParser::parseStatement(ParseStat
       return parseDirectiveMacrosOnOff(IDVal);
     case DK_MACRO:
       return parseDirectiveMacro(IDLoc);
+    case DK_ALTMACRO:
+    case DK_NOALTMACRO:
+      return parseDirectiveAltmacro(IDVal);
     case DK_EXITM:
       return parseDirectiveExitMacro(IDVal);
     case DK_ENDM:
@@ -2270,9 +2274,18 @@ bool AsmParser::expandMacro(raw_svector_
         } else {
           bool VarargParameter = HasVararg && Index == (NParameters - 1);
           for (const AsmToken &Token : A[Index])
+            // For altmacro mode, you can write '%expr'.
+            // The prefix '%' evaluates the expression 'expr'
+            // and uses the result as a string (e.g. replace %(1+2) with the string "3").
+            // Here, we identify the integer token which is the result of the
+            // absolute expression evaluation and replace it with its string representation.
+            if ((Lexer.IsaAltMacroMode()) &&
+                 (*(Token.getString().begin()) == '%') && Token.is(AsmToken::Integer))
+              // Emit an integer value to the buffer.
+              OS << Token.getIntVal();
             // We expect no quotes around the string's contents when
             // parsing for varargs.
-            if (Token.getKind() != AsmToken::String || VarargParameter)
+            else if (Token.isNot(AsmToken::String) || VarargParameter)
               OS << Token.getString();
             else
               OS << Token.getStringContents();
@@ -2443,13 +2456,29 @@ bool AsmParser::parseMacroArguments(cons
 
       NamedParametersFound = true;
     }
+    bool Vararg = HasVararg && Parameter == (NParameters - 1);
 
     if (NamedParametersFound && FA.Name.empty())
       return Error(IDLoc, "cannot mix positional and keyword arguments");
 
-    bool Vararg = HasVararg && Parameter == (NParameters - 1);
-    if (parseMacroArgument(FA.Value, Vararg))
-      return true;
+    if (Lexer.IsaAltMacroMode() && Lexer.is(AsmToken::Percent)) {
+        SMLoc StrLoc = Lexer.getLoc();
+        SMLoc EndLoc;
+        const MCExpr *AbsoluteExp;
+        int64_t Value;
+        /// Eat '%'
+        Lex();
+        if (parseExpression(AbsoluteExp, EndLoc))
+          return false;
+        if (!AbsoluteExp->evaluateAsAbsolute(Value))
+          return Error(StrLoc, "expected absolute expression");
+        const char *StrChar = StrLoc.getPointer();
+        const char *EndChar = EndLoc.getPointer();
+        AsmToken newToken(AsmToken::Integer, StringRef(StrChar , EndChar - StrChar), Value);
+        FA.Value.push_back(newToken);
+    }
+    else if(parseMacroArgument(FA.Value, Vararg))
+        return true;
 
     unsigned PI = Parameter;
     if (!FA.Name.empty()) {
@@ -3841,6 +3870,19 @@ bool AsmParser::parseDirectiveCFIUndefin
   return false;
 }
 
+/// parseDirectiveAltmacro
+/// ::= .altmacro
+/// ::= .noaltmacro
+bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
+  if (getLexer().isNot(AsmToken::EndOfStatement))
+    return TokError("unexpected token in '" + Directive + "' directive");
+  if (Directive == ".altmacro")
+    getLexer().SetAltMacroMode(true);
+  else
+    getLexer().SetAltMacroMode(false);
+  return false;
+}
+
 /// parseDirectiveMacrosOnOff
 /// ::= .macros_on
 /// ::= .macros_off
@@ -4938,6 +4980,8 @@ void AsmParser::initializeDirectiveKindM
   DirectiveKindMap[".err"] = DK_ERR;
   DirectiveKindMap[".error"] = DK_ERROR;
   DirectiveKindMap[".warning"] = DK_WARNING;
+  DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
+  DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
   DirectiveKindMap[".reloc"] = DK_RELOC;
   DirectiveKindMap[".dc"] = DK_DC;
   DirectiveKindMap[".dc.a"] = DK_DC_A;

Modified: llvm/trunk/lib/MC/MCParser/MCAsmLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/MCAsmLexer.cpp?rev=301797&r1=301796&r2=301797&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/MCAsmLexer.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/MCAsmLexer.cpp Mon May  1 08:20:12 2017
@@ -13,7 +13,7 @@
 
 using namespace llvm;
 
-MCAsmLexer::MCAsmLexer() {
+MCAsmLexer::MCAsmLexer() : AltMacroMode(false) {
   CurTok.emplace_back(AsmToken::Space, StringRef());
 }
 

Added: llvm/trunk/test/MC/AsmParser/altmacro_expression.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/altmacro_expression.s?rev=301797&view=auto
==============================================================================
--- llvm/trunk/test/MC/AsmParser/altmacro_expression.s (added)
+++ llvm/trunk/test/MC/AsmParser/altmacro_expression.s Mon May  1 08:20:12 2017
@@ -0,0 +1,65 @@
+# RUN: llvm-mc  %s| FileCheck %s
+
+# Checking that the '%' was evaluated as a string first
+# In a fail scenario: The asmprint will print: addl $%(1+4), %eax
+
+# CHECK:  addl $5, %eax
+.altmacro
+.macro percent_expr arg
+    addl $\arg, %eax
+.endm
+
+percent_expr %(1+4)
+
+
+# Checking that the second '%' acts as modulo operator
+# The altmacro percent '%' must be located before the first argument
+# If a percent is located in the middle of the estimated argument without any
+# '%' in the beginning , error will be generated.
+# The second percent '%' after the first altmacro percent '%' is a regular operator.
+
+# CHECK:  addl $1, %eax
+.macro inner_percent arg
+    addl $\arg, %eax
+.endm
+
+inner_percent %(1%4)
+
+
+# Checking for nested macro
+# The first argument use is for the calling function and the second use is for the evaluation.
+
+# CHECK:  addl    $1, %eax
+.macro macro_call_0 number
+    addl $\number, %eax
+.endm
+
+.macro macro_call_1 number
+    macro_call_\number %(\number + 1)
+.endm
+
+macro_call_1 %(1-1)
+
+
+# Checking the ability to pass a number of arguments.
+# The arguments can be separated by ',' or not.
+
+# CHECK: label013:
+# CHECK:  addl $0, %eax
+# CHECK:  addl $1, %eax
+# CHECK:  addl $3, %eax
+
+# CHECK: label014:
+# CHECK:  addl $0, %eax
+# CHECK:  addl $1, %eax
+# CHECK:  addl $4, %eax
+
+.macro multi_args_macro arg1 arg2 arg3
+    label\arg1\arg2\arg3:
+	addl $\arg1, %eax
+	addl $\arg2, %eax
+	addl $\arg3, %eax
+.endm
+
+multi_args_macro %(1+4-5) 1 %2+1
+multi_args_macro %(1+4-5),1,%4%10

Added: llvm/trunk/test/MC/AsmParser/negativ_altmacro_expression.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/negativ_altmacro_expression.s?rev=301797&view=auto
==============================================================================
--- llvm/trunk/test/MC/AsmParser/negativ_altmacro_expression.s (added)
+++ llvm/trunk/test/MC/AsmParser/negativ_altmacro_expression.s Mon May  1 08:20:12 2017
@@ -0,0 +1,34 @@
+# RUN: not llvm-mc  %s 2>&1 | FileCheck %s
+
+# This test is a negative test for the altmacro expression.
+# In this test we check the '.noaltmacro' directive.
+# We expect that '.altmacro' and '.noaltmacro' will act as a switch on/off directives to the alternate macro mode.
+# .noaltmacro returns the format into a regular macro handling.
+# The defult mode is ".noaltmacro" as first test checks.
+
+# CHECK:  error: unknown token in expression
+# CHECK-NEXT: addl $%(1%4), %eax
+.macro inner_percent arg
+    addl $\arg, %eax
+.endm
+
+inner_percent %(1%4)
+
+.altmacro
+.noaltmacro
+
+# CHECK: multi_args_macro %(1+4-5) 1 %2+1
+# CHECK: error: unknown token in expression
+# CHECK-NEXT: addl $%(1+4-5), %eax
+
+
+# CHECK: multi_args_macro %(1+4-5),1,%4%10
+# CHECK: error: unknown token in expression
+# CHECK-NEXT: addl $%(1+4-5), %eax
+.macro multi_args_macro arg1 arg2 arg3
+  label\arg1\arg2\arg3:
+  addl $\arg1, %eax
+.endm
+
+multi_args_macro %(1+4-5) 1 %2+1
+multi_args_macro %(1+4-5),1,%4%10




More information about the llvm-commits mailing list