diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2012-05-12 16:31:10 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2012-05-12 16:31:10 +0000 |
commit | 2ec304c0bf308c5c304412c56ca8f6d69c0b94fc (patch) | |
tree | da83d35577cc44cb16b6730d9831dbd9be9d21b7 /lib/MC | |
parent | 6a80f9da8c2cb2cbf931ec8cf2a72b5f288c1bc6 (diff) | |
download | external_llvm-2ec304c0bf308c5c304412c56ca8f6d69c0b94fc.zip external_llvm-2ec304c0bf308c5c304412c56ca8f6d69c0b94fc.tar.gz external_llvm-2ec304c0bf308c5c304412c56ca8f6d69c0b94fc.tar.bz2 |
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
Diffstat (limited to 'lib/MC')
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 109ce5b..3a29336 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -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, |