Skip to content

Commit da368f2

Browse files
committed
[MCParser] .altmacro: Support argument expansion not preceded by \
In the .altmacro mode, an argument can be expanded even if not preceded by \. This behavior is not enabled for Darwin, which uses $ (`isIdentifierChar('$')` is true) for macro expansion. This is f8b1ca4 with a fix.
1 parent ec50f58 commit da368f2

File tree

2 files changed

+60
-36
lines changed

2 files changed

+60
-36
lines changed

llvm/lib/MC/MCParser/AsmParser.cpp

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2504,7 +2504,34 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,
25042504
ArrayRef<MCAsmMacroArgument> A,
25052505
bool EnableAtPseudoVariable) {
25062506
unsigned NParameters = Parameters.size();
2507-
bool HasVararg = NParameters ? Parameters.back().Vararg : false;
2507+
auto expandArg = [&](unsigned Index) {
2508+
bool HasVararg = NParameters ? Parameters.back().Vararg : false;
2509+
bool VarargParameter = HasVararg && Index == (NParameters - 1);
2510+
for (const AsmToken &Token : A[Index])
2511+
// For altmacro mode, you can write '%expr'.
2512+
// The prefix '%' evaluates the expression 'expr'
2513+
// and uses the result as a string (e.g. replace %(1+2) with the
2514+
// string "3").
2515+
// Here, we identify the integer token which is the result of the
2516+
// absolute expression evaluation and replace it with its string
2517+
// representation.
2518+
if (AltMacroMode && Token.getString().front() == '%' &&
2519+
Token.is(AsmToken::Integer))
2520+
// Emit an integer value to the buffer.
2521+
OS << Token.getIntVal();
2522+
// Only Token that was validated as a string and begins with '<'
2523+
// is considered altMacroString!!!
2524+
else if (AltMacroMode && Token.getString().front() == '<' &&
2525+
Token.is(AsmToken::String)) {
2526+
OS << angleBracketString(Token.getStringContents());
2527+
}
2528+
// We expect no quotes around the string's contents when
2529+
// parsing for varargs.
2530+
else if (Token.isNot(AsmToken::String) || VarargParameter)
2531+
OS << Token.getString();
2532+
else
2533+
OS << Token.getStringContents();
2534+
};
25082535

25092536
// A macro without parameters is handled differently on Darwin:
25102537
// gas accepts no arguments and does no substitutions
@@ -2538,39 +2565,15 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,
25382565
for (; Index < NParameters; ++Index)
25392566
if (Parameters[Index].Name == Argument)
25402567
break;
2541-
if (Index == NParameters) {
2568+
if (Index == NParameters)
25422569
OS << '\\' << Argument;
2543-
} else {
2544-
bool VarargParameter = HasVararg && Index == (NParameters - 1);
2545-
for (const AsmToken &Token : A[Index]) {
2546-
// For altmacro mode, you can write '%expr'.
2547-
// The prefix '%' evaluates the expression 'expr'
2548-
// and uses the result as a string (e.g. replace %(1+2) with the
2549-
// string "3").
2550-
// Here, we identify the integer token which is the result of the
2551-
// absolute expression evaluation and replace it with its string
2552-
// representation.
2553-
if (AltMacroMode && Token.getString().front() == '%' &&
2554-
Token.is(AsmToken::Integer))
2555-
// Emit an integer value to the buffer.
2556-
OS << Token.getIntVal();
2557-
// Only Token that was validated as a string and begins with '<'
2558-
// is considered altMacroString!!!
2559-
else if (AltMacroMode && Token.getString().front() == '<' &&
2560-
Token.is(AsmToken::String)) {
2561-
OS << angleBracketString(Token.getStringContents());
2562-
}
2563-
// We expect no quotes around the string's contents when
2564-
// parsing for varargs.
2565-
else if (Token.isNot(AsmToken::String) || VarargParameter)
2566-
OS << Token.getString();
2567-
else
2568-
OS << Token.getStringContents();
2569-
}
2570-
}
2570+
else
2571+
expandArg(Index);
25712572
continue;
25722573
}
25732574

2575+
// In Darwin mode, $ is used for macro expansion, not considered an
2576+
// identifier char.
25742577
if (Body[I] == '$' && I + 1 != End && IsDarwin && !NParameters) {
25752578
// This macro has no parameters, look for $0, $1, etc.
25762579
switch (Body[I + 1]) {
@@ -2599,8 +2602,28 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,
25992602
}
26002603
}
26012604

2602-
OS << Body[I];
2603-
++I;
2605+
if (!isIdentifierChar(Body[I]) || IsDarwin) {
2606+
OS << Body[I++];
2607+
continue;
2608+
}
2609+
2610+
const size_t Start = I;
2611+
while (++I && isIdentifierChar(Body[I])) {
2612+
}
2613+
StringRef Token(Body.data() + Start, I - Start);
2614+
if (AltMacroMode) {
2615+
unsigned Index = 0;
2616+
for (; Index != NParameters; ++Index)
2617+
if (Parameters[Index].Name == Token)
2618+
break;
2619+
if (Index != NParameters) {
2620+
expandArg(Index);
2621+
if (I != End && Body[I] == '&')
2622+
++I;
2623+
continue;
2624+
}
2625+
}
2626+
OS << Token;
26042627
}
26052628

26062629
++Macro.Count;

llvm/test/MC/AsmParser/altmacro-arg.s

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1+
## Arguments can be expanded even if they are not preceded by \
12
# RUN: rm -rf %t && split-file %s %t && cd %t
23
# RUN: llvm-mc -triple=x86_64 a.s | FileCheck %s
34
# RUN: llvm-mc -triple=x86_64 b.s | FileCheck %s --check-prefix=CHECK1
45

56
#--- a.s
67
.altmacro
78
# CHECK: ja .Ltmp0
8-
# CHECK-NEXT: xorq %rax, %rax
9+
# CHECK-NEXT: xorq %rbx, %rbx
910
# CHECK: .data
1011
# CHECK-NEXT: .ascii "b cc rbx"
11-
# CHECK-NEXT: .ascii "ara rax rax raxx"
12+
# CHECK-NEXT: .ascii "bcc ccx rbx raxx"
1213
.macro gen a, ra, rax
1314
ja 1f
1415
xorq %rax, %rax
@@ -21,8 +22,8 @@ gen b, cc, rbx
2122

2223
#--- b.s
2324
.altmacro
24-
# CHECK1: 1 1 ._a&a
25-
# CHECK1-NEXT: 1 2 ._a&a $b&b
25+
# CHECK1: 1 1 1a
26+
# CHECK1-NEXT: 1 2 1a 2b
2627
# CHECK1-NEXT: \$b \$b
2728
.irp ._a,1
2829
.print "\._a \._a& ._a&a"

0 commit comments

Comments
 (0)