[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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235862 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Toma Tabacu
2015-04-27 10:50:29 +00:00
parent 59764b94a7
commit 0b5a15b779
3 changed files with 139 additions and 28 deletions

View File

@@ -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();
for (; Index < NParameters; ++Index)
if (Parameters[Index].Name == Argument)
break;
Pos += 1 + Argument.size();
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;
}