summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorToma Tabacu <toma.tabacu@imgtec.com>2015-04-27 10:50:29 +0000
committerToma Tabacu <toma.tabacu@imgtec.com>2015-04-27 10:50:29 +0000
commit217116e684550545f88e45a0c7411153dcccf1ee (patch)
tree32937d7b8dc6e21fce4772a2013c155415c487a8 /llvm
parent6325cd2fcdd72678e6b856d55e9fadcb9fa61feb (diff)
downloadbcm5719-llvm-217116e684550545f88e45a0c7411153dcccf1ee.tar.gz
bcm5719-llvm-217116e684550545f88e45a0c7411153dcccf1ee.zip
[MC] [IAS] Add support for the \@ .macro pseudo-variable.
Summary: When used, it is substituted with the number of .macro instantiations we've done up to that point in time. So if this is the 1st time we've instantiated a .macro (any .macro, regardless of name), \@ will instantiate to 0, if it's the 2nd .macro instantiation, it will instantiate to 1 etc. It can only be used inside a .macro definition, an .irp definition or an .irpc definition (those last 2 uses are undocumented). Reviewers: echristo, rafael Reviewed By: rafael Subscribers: dsanders, llvm-commits Differential Revision: http://reviews.llvm.org/D9197 llvm-svn: 235862
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp82
-rw-r--r--llvm/test/MC/AsmParser/at-pseudo-variable-bad.s23
-rw-r--r--llvm/test/MC/AsmParser/at-pseudo-variable.s64
3 files changed, 140 insertions, 29 deletions
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 12b9cf561a8..fe8b8844366 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -147,6 +147,9 @@ private:
/// Boolean tracking whether macro substitution is enabled.
unsigned MacrosEnabledFlag : 1;
+ /// \brief Keeps track of how many .macro's have been instantiated.
+ unsigned NumOfMacroInstantiations;
+
/// Flag tracking whether any errors have been encountered.
unsigned HadError : 1;
@@ -251,7 +254,7 @@ private:
ArrayRef<MCAsmMacroParameter> Parameters);
bool expandMacro(raw_svector_ostream &OS, StringRef Body,
ArrayRef<MCAsmMacroParameter> Parameters,
- ArrayRef<MCAsmMacroArgument> A,
+ ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
const SMLoc &L);
/// \brief Are macros enabled in the parser?
@@ -519,6 +522,8 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
PlatformParser->Initialize(*this);
initializeDirectiveKindMap();
+
+ NumOfMacroInstantiations = 0;
}
AsmParser::~AsmParser() {
@@ -1764,7 +1769,8 @@ static bool isIdentifierChar(char c) {
bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
ArrayRef<MCAsmMacroParameter> Parameters,
- ArrayRef<MCAsmMacroArgument> A, const SMLoc &L) {
+ ArrayRef<MCAsmMacroArgument> A,
+ bool EnableAtPseudoVariable, const SMLoc &L) {
unsigned NParameters = Parameters.size();
bool HasVararg = NParameters ? Parameters.back().Vararg : false;
if ((!IsDarwin || NParameters != 0) && NParameters != A.size())
@@ -1830,36 +1836,47 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
Pos += 2;
} else {
unsigned I = Pos + 1;
- while (isIdentifierChar(Body[I]) && I + 1 != End)
+
+ // Check for the \@ pseudo-variable.
+ if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End)
++I;
+ else
+ while (isIdentifierChar(Body[I]) && I + 1 != End)
+ ++I;
const char *Begin = Body.data() + Pos + 1;
StringRef Argument(Begin, I - (Pos + 1));
unsigned Index = 0;
- for (; Index < NParameters; ++Index)
- if (Parameters[Index].Name == Argument)
- break;
- if (Index == NParameters) {
- if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
- Pos += 3;
- else {
- OS << '\\' << Argument;
- Pos = I;
- }
+ if (Argument == "@") {
+ OS << NumOfMacroInstantiations;
+ Pos += 2;
} else {
- bool VarargParameter = HasVararg && Index == (NParameters - 1);
- for (MCAsmMacroArgument::const_iterator it = A[Index].begin(),
- ie = A[Index].end();
- it != ie; ++it)
- // We expect no quotes around the string's contents when
- // parsing for varargs.
- if (it->getKind() != AsmToken::String || VarargParameter)
- OS << it->getString();
- else
- OS << it->getStringContents();
-
- Pos += 1 + Argument.size();
+ for (; Index < NParameters; ++Index)
+ if (Parameters[Index].Name == Argument)
+ break;
+
+ if (Index == NParameters) {
+ if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
+ Pos += 3;
+ else {
+ OS << '\\' << Argument;
+ Pos = I;
+ }
+ } else {
+ bool VarargParameter = HasVararg && Index == (NParameters - 1);
+ for (MCAsmMacroArgument::const_iterator it = A[Index].begin(),
+ ie = A[Index].end();
+ it != ie; ++it)
+ // We expect no quotes around the string's contents when
+ // parsing for varargs.
+ if (it->getKind() != AsmToken::String || VarargParameter)
+ OS << it->getString();
+ else
+ OS << it->getStringContents();
+
+ Pos += 1 + Argument.size();
+ }
}
}
// Update the scan point.
@@ -2117,7 +2134,7 @@ bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
StringRef Body = M->Body;
raw_svector_ostream OS(Buf);
- if (expandMacro(OS, Body, M->Parameters, A, getTok().getLoc()))
+ if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc()))
return true;
// We include the .endmacro in the buffer as our cue to exit the macro
@@ -2133,6 +2150,8 @@ bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size());
ActiveMacros.push_back(MI);
+ ++NumOfMacroInstantiations;
+
// Jump to the macro instantiation and prime the lexer.
CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
@@ -4378,7 +4397,8 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
SmallString<256> Buf;
raw_svector_ostream OS(Buf);
while (Count--) {
- if (expandMacro(OS, M->Body, None, None, getTok().getLoc()))
+ // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
+ if (expandMacro(OS, M->Body, None, None, false, getTok().getLoc()))
return true;
}
instantiateMacroLikeBody(M, DirectiveLoc, OS);
@@ -4417,7 +4437,9 @@ bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
raw_svector_ostream OS(Buf);
for (MCAsmMacroArguments::iterator i = A.begin(), e = A.end(); i != e; ++i) {
- if (expandMacro(OS, M->Body, Parameter, *i, getTok().getLoc()))
+ // Note that the AtPseudoVariable is enabled for instantiations of .irp.
+ // This is undocumented, but GAS seems to support it.
+ if (expandMacro(OS, M->Body, Parameter, *i, true, getTok().getLoc()))
return true;
}
@@ -4464,7 +4486,9 @@ bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
MCAsmMacroArgument Arg;
Arg.push_back(AsmToken(AsmToken::Identifier, Values.slice(I, I + 1)));
- if (expandMacro(OS, M->Body, Parameter, Arg, getTok().getLoc()))
+ // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
+ // This is undocumented, but GAS seems to support it.
+ if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
return true;
}
diff --git a/llvm/test/MC/AsmParser/at-pseudo-variable-bad.s b/llvm/test/MC/AsmParser/at-pseudo-variable-bad.s
new file mode 100644
index 00000000000..885f18b2d4f
--- /dev/null
+++ b/llvm/test/MC/AsmParser/at-pseudo-variable-bad.s
@@ -0,0 +1,23 @@
+# RUN: not llvm-mc -triple i386-unknown-unknown < %s 2>&1 | FileCheck %s
+
+add $1\@, %eax
+# CHECK: :[[@LINE-1]]:8: error: unexpected token in argument list
+
+.macro A @
+ mov %eax, %eax
+.endm
+# CHECK: :[[@LINE-3]]:11: error: expected identifier in '.macro' directive
+
+.rept 2
+ addi $8, $8, \@
+.endr
+# CHECK: error: unknown token in expression
+# CHECK: :[[@LINE-4]]:1: note: while in macro instantiation
+# CHECK-NEXT: .rept 2
+
+.rep 3
+ addi $9, $9, \@
+.endr
+# CHECK: error: unknown token in expression
+# CHECK: :[[@LINE-4]]:1: note: while in macro instantiation
+# CHECK-NEXT: .rep 3
diff --git a/llvm/test/MC/AsmParser/at-pseudo-variable.s b/llvm/test/MC/AsmParser/at-pseudo-variable.s
new file mode 100644
index 00000000000..b0966e13717
--- /dev/null
+++ b/llvm/test/MC/AsmParser/at-pseudo-variable.s
@@ -0,0 +1,64 @@
+# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s
+
+.macro A
+ add $1\@, %eax
+.endm
+
+.macro B
+ sub $1\@, %eax
+.endm
+
+ A
+# CHECK: addl $10, %eax
+ A
+# CHECK: addl $11, %eax
+ B
+# CHECK: subl $12, %eax
+ B
+# CHECK: subl $13, %eax
+
+# The following uses of \@ are undocumented, but valid:
+.irpc foo,234
+ add $\foo\@, %eax
+.endr
+# CHECK: addl $24, %eax
+# CHECK: addl $34, %eax
+# CHECK: addl $44, %eax
+
+.irp reg,%eax,%ebx
+ sub $2\@, \reg
+.endr
+# CHECK: subl $24, %eax
+# CHECK: subl $24, %ebx
+
+# Test that .irp(c) and .rep(t) do not increase \@.
+# Only the use of A should increase \@, so we can test that it increases by 1
+# each time.
+
+.irpc foo,123
+ sub $\foo, %eax
+.endr
+
+ A
+# CHECK: addl $14, %eax
+
+.irp reg,%eax,%ebx
+ sub $4, \reg
+.endr
+
+ A
+# CHECK: addl $15, %eax
+
+.rept 2
+ sub $5, %eax
+.endr
+
+ A
+# CHECK: addl $16, %eax
+
+.rep 3
+ sub $6, %eax
+.endr
+
+ A
+# CHECK: addl $17, %eax
OpenPOWER on IntegriCloud