mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-27 13:30:05 +00:00
Add support for the .rept directive. Patch by Vladmir Sorokin. I added support
for nesting. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156714 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6a80f9da8c
commit
2ec304c0bf
@ -111,6 +111,9 @@ 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;
|
||||
|
||||
@ -265,6 +268,9 @@ private:
|
||||
|
||||
const MCExpr *ApplyModifierToExpr(const MCExpr *E,
|
||||
MCSymbolRefExpr::VariantKind Variant);
|
||||
|
||||
bool ParseDirectiveRept(SMLoc DirectiveLoc);
|
||||
bool ParseDirectiveEndRept(SMLoc DirectiveLoc);
|
||||
};
|
||||
|
||||
/// \brief Generic implementations of directive handling, etc. which is shared
|
||||
@ -1262,6 +1268,11 @@ bool AsmParser::ParseStatement() {
|
||||
if (IDVal == ".code16" || IDVal == ".code16gcc")
|
||||
return TokError(Twine(IDVal) + " not supported yet");
|
||||
|
||||
if (IDVal == ".rept")
|
||||
return ParseDirectiveRept(IDLoc);
|
||||
if (IDVal == ".endr")
|
||||
return ParseDirectiveEndRept(IDLoc);
|
||||
|
||||
// Look up the handler in the handler table.
|
||||
std::pair<MCAsmParserExtension*, DirectiveHandler> Handler =
|
||||
DirectiveMap.lookup(IDVal);
|
||||
@ -3125,6 +3136,86 @@ 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");
|
||||
|
||||
AsmToken EndToken, StartToken = getTok();
|
||||
unsigned Nest = 1;
|
||||
|
||||
// Lex the macro definition.
|
||||
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;
|
||||
}
|
||||
|
||||
// Otherwise, check whether we have reach the .endr.
|
||||
if (getLexer().is(AsmToken::Identifier) &&
|
||||
(getTok().getIdentifier() == ".endr")) {
|
||||
Nest--;
|
||||
if (Nest == 0) {
|
||||
EndToken = getTok();
|
||||
Lex();
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement))
|
||||
return TokError("unexpected token in '.endr' directive");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, scan til the end of the statement.
|
||||
EatToEndOfStatement();
|
||||
}
|
||||
|
||||
const char *BodyStart = StartToken.getLoc().getPointer();
|
||||
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;
|
||||
OS << ".endr\n";
|
||||
|
||||
MemoryBuffer *Instantiation =
|
||||
MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
|
||||
|
||||
CurBuffer = SrcMgr.AddNewSourceBuffer(Instantiation, SMLoc());
|
||||
Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
|
||||
|
||||
ActiveRept.push_back(getTok().getLoc());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AsmParser::ParseDirectiveEndRept(SMLoc DirectiveLoc) {
|
||||
if (ActiveRept.empty())
|
||||
return TokError("unexpected '.endr' directive, no current .rept");
|
||||
|
||||
// The only .repl that should get here are the ones created by
|
||||
// ParseDirectiveRept.
|
||||
assert(getLexer().is(AsmToken::EndOfStatement));
|
||||
|
||||
JumpToLoc(ActiveRept.back());
|
||||
ActiveRept.pop_back();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Create an MCAsmParser instance.
|
||||
MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM,
|
||||
|
6
test/MC/AsmParser/macro-rept-err1.s
Normal file
6
test/MC/AsmParser/macro-rept-err1.s
Normal file
@ -0,0 +1,6 @@
|
||||
// RUN: not llvm-mc -triple x86_64-unknown-unknown %s 2> %t
|
||||
// RUN: FileCheck < %t %s
|
||||
|
||||
.endr
|
||||
|
||||
// CHECK: unexpected '.endr' directive, no current .rept
|
7
test/MC/AsmParser/macro-rept-err2.s
Normal file
7
test/MC/AsmParser/macro-rept-err2.s
Normal file
@ -0,0 +1,7 @@
|
||||
// RUN: not llvm-mc -triple x86_64-unknown-unknown %s 2> %t
|
||||
// RUN: FileCheck < %t %s
|
||||
|
||||
.rept 3
|
||||
.long
|
||||
|
||||
// CHECK: no matching '.endr' in definition
|
22
test/MC/AsmParser/macro-rept.s
Normal file
22
test/MC/AsmParser/macro-rept.s
Normal file
@ -0,0 +1,22 @@
|
||||
// RUN: llvm-mc -triple x86_64-unknown-unknown %s | FileCheck %s
|
||||
|
||||
.rept 2
|
||||
.long 1
|
||||
.endr
|
||||
|
||||
.rept 3
|
||||
.rept 2
|
||||
.long 0
|
||||
.endr
|
||||
.endr
|
||||
|
||||
// CHECK: .long 1
|
||||
// CHECK: .long 1
|
||||
|
||||
// CHECK: .long 0
|
||||
// CHECK: .long 0
|
||||
// CHECK: .long 0
|
||||
|
||||
// CHECK: .long 0
|
||||
// CHECK: .long 0
|
||||
// CHECK: .long 0
|
Loading…
Reference in New Issue
Block a user