From 519212bf695693266c853588743d814b1f289c4c Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 24 Jul 2014 17:08:39 +0000 Subject: [PATCH] Let the integrated assembler understand .exitm, PR20426. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213876 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCParser/AsmParser.cpp | 48 ++++++++++++++++++++----- test/MC/AsmParser/macro-exitm.s | 64 +++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 test/MC/AsmParser/macro-exitm.s diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 46225f1b33b..897999c461f 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -92,8 +92,12 @@ struct MacroInstantiation { /// The location where parsing should resume upon instantiation completion. SMLoc ExitLoc; + /// The depth of TheCondStack at the start of the instantiation. + size_t CondStackDepth; + public: - MacroInstantiation(SMLoc IL, int EB, SMLoc EL, MemoryBuffer *I); + MacroInstantiation(SMLoc IL, int EB, SMLoc EL, MemoryBuffer *I, + size_t CondStackDepth); }; struct ParseStatementInfo { @@ -351,7 +355,8 @@ private: DK_CFI_REMEMBER_STATE, DK_CFI_RESTORE_STATE, DK_CFI_SAME_VALUE, DK_CFI_RESTORE, DK_CFI_ESCAPE, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED, DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE, - DK_MACROS_ON, DK_MACROS_OFF, DK_MACRO, DK_ENDM, DK_ENDMACRO, DK_PURGEM, + DK_MACROS_ON, DK_MACROS_OFF, + DK_MACRO, DK_EXITM, DK_ENDM, DK_ENDMACRO, DK_PURGEM, DK_SLEB128, DK_ULEB128, DK_ERR, DK_ERROR, DK_WARNING, DK_END @@ -403,6 +408,7 @@ private: // macro directives bool parseDirectivePurgeMacro(SMLoc DirectiveLoc); + bool parseDirectiveExitMacro(StringRef Directive); bool parseDirectiveEndMacro(StringRef Directive); bool parseDirectiveMacro(SMLoc DirectiveLoc); bool parseDirectiveMacrosOnOff(StringRef Directive); @@ -1541,6 +1547,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { return parseDirectiveMacrosOnOff(IDVal); case DK_MACRO: return parseDirectiveMacro(IDLoc); + case DK_EXITM: + return parseDirectiveExitMacro(IDVal); case DK_ENDM: case DK_ENDMACRO: return parseDirectiveEndMacro(IDVal); @@ -1858,8 +1866,9 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, } MacroInstantiation::MacroInstantiation(SMLoc IL, int EB, SMLoc EL, - MemoryBuffer *I) - : Instantiation(I), InstantiationLoc(IL), ExitBuffer(EB), ExitLoc(EL) {} + MemoryBuffer *I, size_t CondStackDepth) + : Instantiation(I), InstantiationLoc(IL), ExitBuffer(EB), ExitLoc(EL), + CondStackDepth(CondStackDepth) {} static bool isOperator(AsmToken::TokenKind kind) { switch (kind) { @@ -2122,8 +2131,9 @@ bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { // Create the macro instantiation object and add to the current macro // instantiation stack. - MacroInstantiation *MI = new MacroInstantiation( - NameLoc, CurBuffer, getTok().getLoc(), Instantiation); + MacroInstantiation *MI = + new MacroInstantiation(NameLoc, CurBuffer, getTok().getLoc(), + Instantiation, TheCondStack.size()); ActiveMacros.push_back(MI); // Jump to the macro instantiation and prime the lexer. @@ -3471,6 +3481,26 @@ void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, "found in body which will have no effect"); } +/// parseDirectiveExitMacro +/// ::= .exitm +bool AsmParser::parseDirectiveExitMacro(StringRef Directive) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '" + Directive + "' directive"); + + if (!isInsideMacroInstantiation()) + return TokError("unexpected '" + Directive + "' in file, " + "no current macro definition"); + + // Exit all conditionals that are active in the current macro. + while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) { + TheCondState = TheCondStack.back(); + TheCondStack.pop_back(); + } + + handleMacroExit(); + return false; +} + /// parseDirectiveEndMacro /// ::= .endm /// ::= .endmacro @@ -4226,6 +4256,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".macros_on"] = DK_MACROS_ON; DirectiveKindMap[".macros_off"] = DK_MACROS_OFF; DirectiveKindMap[".macro"] = DK_MACRO; + DirectiveKindMap[".exitm"] = DK_EXITM; DirectiveKindMap[".endm"] = DK_ENDM; DirectiveKindMap[".endmacro"] = DK_ENDMACRO; DirectiveKindMap[".purgem"] = DK_PURGEM; @@ -4286,8 +4317,9 @@ void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, // Create the macro instantiation object and add to the current macro // instantiation stack. - MacroInstantiation *MI = new MacroInstantiation( - DirectiveLoc, CurBuffer, getTok().getLoc(), Instantiation); + MacroInstantiation *MI = + new MacroInstantiation(DirectiveLoc, CurBuffer, getTok().getLoc(), + Instantiation, TheCondStack.size()); ActiveMacros.push_back(MI); // Jump to the macro instantiation and prime the lexer. diff --git a/test/MC/AsmParser/macro-exitm.s b/test/MC/AsmParser/macro-exitm.s new file mode 100644 index 00000000000..66a0597288a --- /dev/null +++ b/test/MC/AsmParser/macro-exitm.s @@ -0,0 +1,64 @@ +// RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s + +// .exitm is encountered in a normal macro expansion +.macro REP +.rept 3 +.long 0 +.exitm +.endr +.endm +REP +// Only the output from the first rept expansion should make it through: +// CHECK: .long 0 +// CHECK-NOT: .long 0 + +// .exitm is in a true branch +.macro A +.if 1 +.long 1 +.exitm +.endif +.long 1 +.endm +A +// CHECK: .long 1 +// CHECK-NOT: .long 1 + +// .exitm is in a false branch +.macro B +.if 1 +.long 2 +.else +.exitm +.endif +.long 2 +.endm +B +// CHECK: .long 2 +// CHECK: .long 2 + + +// .exitm is in a false branch that is encountered prior to the true branch +.macro C +.if 0 +.exitm +.else +.long 3 +.endif +.long 3 +.endm +C +// CHECK: .long 3 +// CHECK: .long 3 + +// .exitm is in a macro that's expanded in a conditional block. +.macro D +.long 4 +.exitm +.long 4 +.endm +.if 1 +D +.endif +// CHECK: .long 4 +// CHECK-NOT: .long 4