mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
[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 llvm-svn: 301797
This commit is contained in:
parent
01c4c20127
commit
db35bad707
@ -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
|
||||
|
@ -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(ParseStatementInfo &Info,
|
||||
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_ostream &OS, StringRef Body,
|
||||
} 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(const MCAsmMacro *M,
|
||||
|
||||
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::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
|
||||
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::initializeDirectiveKindMap() {
|
||||
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;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MCAsmLexer::MCAsmLexer() {
|
||||
MCAsmLexer::MCAsmLexer() : AltMacroMode(false) {
|
||||
CurTok.emplace_back(AsmToken::Space, StringRef());
|
||||
}
|
||||
|
||||
|
65
test/MC/AsmParser/altmacro_expression.s
Normal file
65
test/MC/AsmParser/altmacro_expression.s
Normal file
@ -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
|
34
test/MC/AsmParser/negativ_altmacro_expression.s
Normal file
34
test/MC/AsmParser/negativ_altmacro_expression.s
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user