From 2ec304c0bf308c5c304412c56ca8f6d69c0b94fc Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 12 May 2012 16:31:10 +0000 Subject: [PATCH] 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 --- lib/MC/MCParser/AsmParser.cpp | 91 +++++++++++++++++++++++++++++ test/MC/AsmParser/macro-rept-err1.s | 6 ++ test/MC/AsmParser/macro-rept-err2.s | 7 +++ test/MC/AsmParser/macro-rept.s | 22 +++++++ 4 files changed, 126 insertions(+) create mode 100644 test/MC/AsmParser/macro-rept-err1.s create mode 100644 test/MC/AsmParser/macro-rept-err2.s create mode 100644 test/MC/AsmParser/macro-rept.s diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 109ce5b4f24..3a29336dc24 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 ActiveMacros; + /// ActiveRept - Stack of active .rept directives. + std::vector 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 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(), ""); + + 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, diff --git a/test/MC/AsmParser/macro-rept-err1.s b/test/MC/AsmParser/macro-rept-err1.s new file mode 100644 index 00000000000..db92856a1d6 --- /dev/null +++ b/test/MC/AsmParser/macro-rept-err1.s @@ -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 diff --git a/test/MC/AsmParser/macro-rept-err2.s b/test/MC/AsmParser/macro-rept-err2.s new file mode 100644 index 00000000000..678b4c7eeee --- /dev/null +++ b/test/MC/AsmParser/macro-rept-err2.s @@ -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 diff --git a/test/MC/AsmParser/macro-rept.s b/test/MC/AsmParser/macro-rept.s new file mode 100644 index 00000000000..1dc8060e1d8 --- /dev/null +++ b/test/MC/AsmParser/macro-rept.s @@ -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 -- 2.34.1