mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
Represent .rept as an anonymous macro. This removes the need for the ActiveRept
vector. No functionality change. Extracted from a patch by the PaX Team. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157909 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
28c1f666bf
commit
761cb06756
@ -113,9 +113,6 @@ private:
|
||||
/// ActiveMacros - Stack of active macro instantiations.
|
||||
std::vector<MacroInstantiation*> ActiveMacros;
|
||||
|
||||
/// ActiveRept - Stack of active .rept directives.
|
||||
std::vector<SMLoc> ActiveRept;
|
||||
|
||||
/// Boolean tracking whether macro substitution is enabled.
|
||||
unsigned MacrosEnabled : 1;
|
||||
|
||||
@ -183,7 +180,7 @@ private:
|
||||
bool ParseCppHashLineFilenameComment(const SMLoc &L);
|
||||
|
||||
bool HandleMacroEntry(StringRef Name, SMLoc NameLoc, const Macro *M);
|
||||
bool expandMacro(SmallString<256> &Buf, StringRef Body,
|
||||
bool expandMacro(raw_svector_ostream &OS, StringRef Body,
|
||||
const std::vector<StringRef> &Parameters,
|
||||
const std::vector<MacroArgument> &A,
|
||||
const SMLoc &L);
|
||||
@ -271,8 +268,12 @@ private:
|
||||
const MCExpr *ApplyModifierToExpr(const MCExpr *E,
|
||||
MCSymbolRefExpr::VariantKind Variant);
|
||||
|
||||
bool ParseDirectiveRept(SMLoc DirectiveLoc);
|
||||
bool ParseDirectiveEndRept(SMLoc DirectiveLoc);
|
||||
// Macro-like directives
|
||||
Macro *ParseMacroLikeBody(SMLoc DirectiveLoc);
|
||||
void InstantiateMacroLikeBody(Macro *M, SMLoc DirectiveLoc,
|
||||
raw_svector_ostream &OS);
|
||||
bool ParseDirectiveRept(SMLoc DirectiveLoc); // ".rept"
|
||||
bool ParseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
|
||||
};
|
||||
|
||||
/// \brief Generic implementations of directive handling, etc. which is shared
|
||||
@ -1270,10 +1271,11 @@ bool AsmParser::ParseStatement() {
|
||||
if (IDVal == ".code16" || IDVal == ".code16gcc")
|
||||
return TokError(Twine(IDVal) + " not supported yet");
|
||||
|
||||
// Macro-like directives
|
||||
if (IDVal == ".rept")
|
||||
return ParseDirectiveRept(IDLoc);
|
||||
if (IDVal == ".endr")
|
||||
return ParseDirectiveEndRept(IDLoc);
|
||||
return ParseDirectiveEndr(IDLoc);
|
||||
|
||||
// Look up the handler in the handler table.
|
||||
std::pair<MCAsmParserExtension*, DirectiveHandler> Handler =
|
||||
@ -1438,11 +1440,10 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
|
||||
NewDiag.print(0, OS);
|
||||
}
|
||||
|
||||
bool AsmParser::expandMacro(SmallString<256> &Buf, StringRef Body,
|
||||
bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
|
||||
const std::vector<StringRef> &Parameters,
|
||||
const std::vector<MacroArgument> &A,
|
||||
const SMLoc &L) {
|
||||
raw_svector_ostream OS(Buf);
|
||||
unsigned NParameters = Parameters.size();
|
||||
if (NParameters != 0 && NParameters != A.size())
|
||||
return Error(L, "Wrong number of arguments");
|
||||
@ -1527,9 +1528,6 @@ bool AsmParser::expandMacro(SmallString<256> &Buf, StringRef Body,
|
||||
Body = Body.substr(Pos);
|
||||
}
|
||||
|
||||
// We include the .endmacro in the buffer as our queue to exit the macro
|
||||
// instantiation.
|
||||
OS << ".endmacro\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1582,12 +1580,17 @@ bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc,
|
||||
// to hold the macro body with substitutions.
|
||||
SmallString<256> Buf;
|
||||
StringRef Body = M->Body;
|
||||
raw_svector_ostream OS(Buf);
|
||||
|
||||
if (expandMacro(Buf, Body, M->Parameters, MacroArguments, getTok().getLoc()))
|
||||
if (expandMacro(OS, Body, M->Parameters, MacroArguments, getTok().getLoc()))
|
||||
return true;
|
||||
|
||||
// We include the .endmacro in the buffer as our queue to exit the macro
|
||||
// instantiation.
|
||||
OS << ".endmacro\n";
|
||||
|
||||
MemoryBuffer *Instantiation =
|
||||
MemoryBuffer::getMemBufferCopy(Buf.str(), "<instantiation>");
|
||||
MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
|
||||
|
||||
// Create the macro instantiation object and add to the current macro
|
||||
// instantiation stack.
|
||||
@ -3137,50 +3140,38 @@ bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) {
|
||||
const MCExpr *Value;
|
||||
|
||||
if (ParseExpression(Value))
|
||||
return true;
|
||||
|
||||
int64_t Count;
|
||||
if (!Value->EvaluateAsAbsolute(Count))
|
||||
return TokError("Cannot evaluate value");
|
||||
|
||||
if (Count < 0)
|
||||
return TokError("Count is negative");
|
||||
|
||||
Macro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) {
|
||||
AsmToken EndToken, StartToken = getTok();
|
||||
unsigned Nest = 1;
|
||||
|
||||
// Lex the macro definition.
|
||||
unsigned NestLevel = 0;
|
||||
for (;;) {
|
||||
// Check whether we have reached the end of the file.
|
||||
if (getLexer().is(AsmToken::Eof))
|
||||
return Error(DirectiveLoc, "no matching '.endr' in definition");
|
||||
|
||||
// Chcek if we have a nested .rept.
|
||||
if (getLexer().is(AsmToken::Identifier) &&
|
||||
(getTok().getIdentifier() == ".rept")) {
|
||||
Nest++;
|
||||
EatToEndOfStatement();
|
||||
continue;
|
||||
if (getLexer().is(AsmToken::Eof)) {
|
||||
Error(DirectiveLoc, "no matching '.endr' in definition");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Otherwise, check whether we have reach the .endr.
|
||||
if (getLexer().is(AsmToken::Identifier) &&
|
||||
(getTok().getIdentifier() == ".endr")) {
|
||||
Nest--;
|
||||
if (Nest == 0) {
|
||||
if (Lexer.is(AsmToken::Identifier) &&
|
||||
(getTok().getIdentifier() == ".rept")) {
|
||||
++NestLevel;
|
||||
}
|
||||
|
||||
// Otherwise, check whether we have reached the .endr.
|
||||
if (Lexer.is(AsmToken::Identifier) &&
|
||||
getTok().getIdentifier() == ".endr") {
|
||||
if (NestLevel == 0) {
|
||||
EndToken = getTok();
|
||||
Lex();
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement))
|
||||
return TokError("unexpected token in '.endr' directive");
|
||||
if (Lexer.isNot(AsmToken::EndOfStatement)) {
|
||||
TokError("unexpected token in '.endr' directive");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
--NestLevel;
|
||||
}
|
||||
|
||||
// Otherwise, scan til the end of the statement.
|
||||
// Otherwise, scan till the end of the statement.
|
||||
EatToEndOfStatement();
|
||||
}
|
||||
|
||||
@ -3188,33 +3179,75 @@ bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) {
|
||||
const char *BodyEnd = EndToken.getLoc().getPointer();
|
||||
StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
|
||||
|
||||
SmallString<256> Buf;
|
||||
raw_svector_ostream OS(Buf);
|
||||
for (int i = 0; i < Count; i++)
|
||||
OS << Body;
|
||||
// We Are Anonymous.
|
||||
StringRef Name;
|
||||
std::vector<StringRef> Parameters;
|
||||
return new Macro(Name, Body, Parameters);
|
||||
}
|
||||
|
||||
void AsmParser::InstantiateMacroLikeBody(Macro *M, SMLoc DirectiveLoc,
|
||||
raw_svector_ostream &OS) {
|
||||
OS << ".endr\n";
|
||||
|
||||
MemoryBuffer *Instantiation =
|
||||
MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
|
||||
|
||||
CurBuffer = SrcMgr.AddNewSourceBuffer(Instantiation, SMLoc());
|
||||
Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
|
||||
// Create the macro instantiation object and add to the current macro
|
||||
// instantiation stack.
|
||||
MacroInstantiation *MI = new MacroInstantiation(M, DirectiveLoc,
|
||||
getTok().getLoc(),
|
||||
Instantiation);
|
||||
ActiveMacros.push_back(MI);
|
||||
|
||||
ActiveRept.push_back(getTok().getLoc());
|
||||
// Jump to the macro instantiation and prime the lexer.
|
||||
CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc());
|
||||
Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
|
||||
Lex();
|
||||
}
|
||||
|
||||
bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) {
|
||||
int64_t Count;
|
||||
if (ParseAbsoluteExpression(Count))
|
||||
return TokError("unexpected token in '.rept' directive");
|
||||
|
||||
if (Count < 0)
|
||||
return TokError("Count is negative");
|
||||
|
||||
if (Lexer.isNot(AsmToken::EndOfStatement))
|
||||
return TokError("unexpected token in '.rept' directive");
|
||||
|
||||
// Eat the end of statement.
|
||||
Lex();
|
||||
|
||||
// Lex the rept definition.
|
||||
Macro *M = ParseMacroLikeBody(DirectiveLoc);
|
||||
if (!M)
|
||||
return true;
|
||||
|
||||
// Macro instantiation is lexical, unfortunately. We construct a new buffer
|
||||
// to hold the macro body with substitutions.
|
||||
SmallString<256> Buf;
|
||||
std::vector<StringRef> Parameters;
|
||||
const std::vector<MacroArgument> A;
|
||||
raw_svector_ostream OS(Buf);
|
||||
while (Count--) {
|
||||
if (expandMacro(OS, M->Body, Parameters, A, getTok().getLoc()))
|
||||
return true;
|
||||
}
|
||||
InstantiateMacroLikeBody(M, DirectiveLoc, OS);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AsmParser::ParseDirectiveEndRept(SMLoc DirectiveLoc) {
|
||||
if (ActiveRept.empty())
|
||||
bool AsmParser::ParseDirectiveEndr(SMLoc DirectiveLoc) {
|
||||
if (ActiveMacros.empty())
|
||||
return TokError("unexpected '.endr' directive, no current .rept");
|
||||
|
||||
// The only .repl that should get here are the ones created by
|
||||
// ParseDirectiveRept.
|
||||
// InstantiateMacroLikeBody.
|
||||
assert(getLexer().is(AsmToken::EndOfStatement));
|
||||
|
||||
JumpToLoc(ActiveRept.back());
|
||||
ActiveRept.pop_back();
|
||||
HandleMacroExit();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user