Index: include/llvm/MC/MCParser/AsmLexer.h =================================================================== --- include/llvm/MC/MCParser/AsmLexer.h +++ include/llvm/MC/MCParser/AsmLexer.h @@ -55,6 +55,12 @@ const MCAsmInfo &getMAI() const { return MAI; } private: + /// This function check if the next token is type or arithmetic. + /// string that begin with char '<' must end with char '>'. + /// Else the token is not a string. + /// True - + /// false- a and '...' string. + AsmToken LexQuote(char FirstChar = '"'); + AsmToken lexStringHandle(char FirstChar = '"'); AsmToken LexSingleQuote(); AsmToken LexQuote(); AsmToken LexFloatLiteral(); Index: include/llvm/MC/MCParser/MCAsmLexer.h =================================================================== --- include/llvm/MC/MCParser/MCAsmLexer.h +++ include/llvm/MC/MCParser/MCAsmLexer.h @@ -117,6 +117,14 @@ /// Generic assembler lexer interface, for use by target specific assembly /// lexers. class MCAsmLexer { + +public: + enum MacroMode{ + Normal, + Alternate + }; + +private: /// The current token, stored in the base class for faster access. AsmToken CurTok; @@ -132,7 +140,7 @@ bool AllowAtInIdentifier; MCAsmLexer(); - + int MacroValue = MacroMode::Normal; virtual AsmToken LexToken() = 0; void SetError(const SMLoc &errLoc, const std::string &err) { @@ -143,14 +151,19 @@ public: virtual ~MCAsmLexer(); + int GetMacroMode(){ + return MacroValue; + } /// Consume the next token from the input stream and return it. - /// /// The lexer will continuosly return the end-of-file token once the end of /// the main input file has been reached. const AsmToken &Lex() { return CurTok = LexToken(); } + void SetMacroMode(int MacroSet){ + MacroValue = MacroSet; + } virtual StringRef LexUntilEndOfStatement() = 0; /// Get the current source location. Index: lib/MC/MCParser/AsmLexer.cpp =================================================================== --- lib/MC/MCParser/AsmLexer.cpp +++ lib/MC/MCParser/AsmLexer.cpp @@ -359,8 +359,12 @@ return intToken(Result, Value); } -/// LexSingleQuote: Integer: 'b' +/// LexSingleQuote: +/// If AltMacro = true 'string' +/// Else only one character Integer: 'b' AsmToken AsmLexer::LexSingleQuote() { + if (MacroValue==MacroMode::Alternate) + return lexStringHandle('\''); int CurChar = getNextChar(); if (CurChar == '\\') @@ -394,21 +398,35 @@ return AsmToken(AsmToken::Integer, Res, Value); } - -/// LexQuote: String: "..." -AsmToken AsmLexer::LexQuote() { +AsmToken AsmLexer::lexStringHandle(char FirstChar) { + char lastChar; + if (FirstChar == '<') + lastChar = '>'; + else + lastChar = FirstChar; int CurChar = getNextChar(); // TODO: does gas allow multiline string constants? - while (CurChar != '"') { + while (CurChar != lastChar) { if (CurChar == '\\') { // Allow \", etc. CurChar = getNextChar(); } - - if (CurChar == EOF) - return ReturnError(TokStart, "unterminated string constant"); - + if (CurChar == EOF) { + std::string StrError = + "unterminated string constant - missing" + lastChar; + StrError += " at the end"; + return ReturnError(TokStart, StrError); + } CurChar = getNextChar(); + if ((CurChar == '>') && (lastChar == '>')) { + CurChar = getNextChar(); + if (CurChar == EOF) + break; + if ((CurChar == ',') || (CurChar == '\n')) { + CurPtr--; + break; + } + } } return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart)); @@ -476,6 +494,18 @@ strlen(MAI.getSeparatorString())) == 0; } +bool AsmLexer::isAtString(const char *currentPtr) { + while ((*currentPtr != ',') && (*currentPtr != '\n') && + ( currentPtr != CurBuf.end()) && (*currentPtr != '\0')) + currentPtr++; + while (*(currentPtr - 1) == ' ') + currentPtr--; + if (*(currentPtr - 1) == '>') + return true; + else + return false; +} + AsmToken AsmLexer::LexToken() { TokStart = CurPtr; // This always consumes at least one character. @@ -566,21 +596,27 @@ case '%': return AsmToken(AsmToken::Percent, StringRef(TokStart, 1)); case '/': return LexSlash(); case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1)); - case '\'': return LexSingleQuote(); - case '"': return LexQuote(); + case '\'': + return LexSingleQuote(); + case '"': + return lexStringHandle(); // LexQuote(); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return LexDigit(); - case '<': + case '<': { + if (isAtString(CurPtr) && MacroValue==MacroMode::Alternate) + return lexStringHandle('<'); switch (*CurPtr) { - case '<': return ++CurPtr, AsmToken(AsmToken::LessLess, - StringRef(TokStart, 2)); - case '=': return ++CurPtr, AsmToken(AsmToken::LessEqual, - StringRef(TokStart, 2)); - case '>': return ++CurPtr, AsmToken(AsmToken::LessGreater, - StringRef(TokStart, 2)); - default: return AsmToken(AsmToken::Less, StringRef(TokStart, 1)); + case '<': + return ++CurPtr, AsmToken(AsmToken::LessLess, StringRef(TokStart, 2)); + case '=': + return ++CurPtr, AsmToken(AsmToken::LessEqual, StringRef(TokStart, 2)); + case '>': + return ++CurPtr, AsmToken(AsmToken::LessGreater, StringRef(TokStart, 2)); + default: + return AsmToken(AsmToken::Less, StringRef(TokStart, 1)); } + } case '>': switch (*CurPtr) { case '>': return ++CurPtr, AsmToken(AsmToken::GreaterGreater, Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -175,6 +175,10 @@ /// \brief Are we parsing ms-style inline assembly? bool ParsingInlineAsm; + /// \ this is for the .altmode use. + bool AltMacroMode = false; + bool AltMacroPresent = false; + int64_t valueForTheAltMacro; public: AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, @@ -361,7 +365,7 @@ 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_MACROS_ON, DK_MACROS_OFF, DK_ALTMACRO_ON, DK_NOALTMACRO, DK_MACRO, DK_EXITM, DK_ENDM, DK_ENDMACRO, DK_PURGEM, DK_SLEB128, DK_ULEB128, DK_ERR, DK_ERROR, DK_WARNING, @@ -418,7 +422,8 @@ bool parseDirectiveEndMacro(StringRef Directive); bool parseDirectiveMacro(SMLoc DirectiveLoc); bool parseDirectiveMacrosOnOff(StringRef Directive); - + // AltMacros + bool parseDirectiveAltMacrosOnOff(StringRef Directive); // ".bundle_align_mode" bool parseDirectiveBundleAlignMode(); // ".bundle_lock" @@ -779,6 +784,7 @@ /// primaryexpr ::= number /// primaryexpr ::= '.' /// primaryexpr ::= ~,+,- primaryexpr +/// primaryezpr ::= '%' bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { SMLoc FirstTokenLoc = getLexer().getLoc(); AsmToken::TokenKind FirstTokenKind = Lexer.getKind(); @@ -794,6 +800,12 @@ return true; Res = MCUnaryExpr::createLNot(Res, getContext()); return false; + case AsmToken::Percent: { + if (AltMacroMode) + return false; + else + return true; + } case AsmToken::Dollar: case AsmToken::At: case AsmToken::String: @@ -1584,6 +1596,10 @@ return parseDirectiveMacrosOnOff(IDVal); case DK_MACRO: return parseDirectiveMacro(IDLoc); + case DK_ALTMACRO_ON: + return parseDirectiveAltMacrosOnOff(IDVal); + case DK_NOALTMACRO: + return parseDirectiveAltMacrosOnOff(IDVal); case DK_EXITM: return parseDirectiveExitMacro(IDVal); case DK_ENDM: @@ -1804,6 +1820,7 @@ ArrayRef A, bool EnableAtPseudoVariable, const SMLoc &L) { unsigned NParameters = Parameters.size(); + bool Percent = false; bool HasVararg = NParameters ? Parameters.back().Vararg : false; if ((!IsDarwin || NParameters != 0) && NParameters != A.size()) return Error(L, "Wrong number of arguments"); @@ -1828,6 +1845,10 @@ // This macro has parameters, look for \foo, \bar, etc. if (Body[Pos] == '\\' && Pos + 1 != End) break; + if (Body[Pos] == '%' && Pos + 1 != End && AltMacroMode) { + Percent = true; + break; + } } } @@ -1897,6 +1918,11 @@ } } else { bool VarargParameter = HasVararg && Index == (NParameters - 1); + if (Percent && AltMacroPresent) { + AltMacroPresent = false; + OS << valueForTheAltMacro; + } + else { for (MCAsmMacroArgument::const_iterator it = A[Index].begin(), ie = A[Index].end(); it != ie; ++it) @@ -1906,7 +1932,7 @@ OS << it->getString(); else OS << it->getStringContents(); - + } Pos += 1 + Argument.size(); } } @@ -2072,7 +2098,10 @@ NamedParametersFound = true; } - + if (Lexer.is(AsmToken::LParen) && AltMacroMode) { + AltMacroPresent = true; + parseAbsoluteExpression(valueForTheAltMacro); + } if (NamedParametersFound && FA.Name.empty()) { Error(IDLoc, "cannot mix positional and keyword arguments"); eatToEndOfStatement(); @@ -3245,6 +3274,20 @@ return false; } +/// parseDirectiveAltMacrosOnOff +/// ::= .altmacro_on +/// ::= .altmacro_off +bool AsmParser::parseDirectiveAltMacrosOnOff(StringRef Directive) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '" + Directive + "' directive"); + AltMacroMode = (Directive == ".altmacro"); + if (AltMacroMode) + getLexer().SetMacroMode(AsmLexer::MacroMode::Alternate); + else + getLexer().SetMacroMode(AsmLexer::MacroMode::Normal); + return false; +} + /// parseDirectiveMacrosOnOff /// ::= .macros_on /// ::= .macros_off @@ -4269,6 +4312,8 @@ DirectiveKindMap[".err"] = DK_ERR; DirectiveKindMap[".error"] = DK_ERROR; DirectiveKindMap[".warning"] = DK_WARNING; + DirectiveKindMap[".altmacro"] = DK_ALTMACRO_ON; + DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO; } MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { Index: test/MC/AsmParser/altMacroTest.s =================================================================== --- test/MC/AsmParser/altMacroTest.s +++ test/MC/AsmParser/altMacroTest.s @@ -0,0 +1,165 @@ +# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s + +.altmacro +.macro test1 name num + \name\num\(): + .long \name\num +.endm +test1 'b',1 +test1 'ab',1 +test1 "a",1 +test1 "ba",1 +test1 ,1 +.noaltmacro +# CHECK: b1 +# CHECK: .long b1 +# CHECK: ab1: +# CHECK: .long ab1 +# CHECK: a1: +# CHECK: .long a1 +# CHECK: ba1: +# CHECK: .long ba1 +# CHECK: bac1: +# CHECK: .long bac1 + +.altmacro +.macro test2 name, number +__mksym \name, %number +.endm + +.macro __mksym, name, number +\name\number\(): + .long \number +.endm + +.section .rodata + +/* now define symbols by hand... */ +test2 bar, 1 +test2 bar, (9/3 + (7-1)) + +/* ...or use other pseudo ops to do it in a loop */ +.irp i, 3, 2, 1 +test2 foobar, (\i * 2 + 1) +.endr + +# CHECK: bar1: +# CHECK: .long 1 +# CHECK: bar9: +# CHECK: .long 9 +# CHECK: foobar7: +# CHECK: .long 7 +# CHECK: foobar5: +# CHECK: .long 5 +# CHECK: foobar3: +# CHECK: .long 3 +# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s + +.altmacro +.macro test1 name num + \name\num\(): + .long \name\num +.endm +test1 'b',1 +test1 'ab',1 +test1 "a",1 +test1 "ba",1 +test1 ,1 +.noaltmacro +# CHECK: b1 +# CHECK: .long b1 +# CHECK: ab1: +# CHECK: .long ab1 +# CHECK: a1: +# CHECK: .long a1 +# CHECK: ba1: +# CHECK: .long ba1 +# CHECK: bac1: +# CHECK: .long bac1 + +.altmacro +.macro test2 name, number +__mksym \name, %number +.endm + +.macro __mksym, name, number +\name\number\(): + .long \number +.endm + +.section .rodata + +/* now define symbols by hand... */ +test2 bar, 1 +test2 bar, (9/3 + (7-1)) + +/* ...or use other pseudo ops to do it in a loop */ +.irp i, 3, 2, 1 +test2 foobar, (\i * 2 + 1) +.endr + +# CHECK: bar1: +# CHECK: .long 1 +# CHECK: bar9: +# CHECK: .long 9 +# CHECK: foobar7: +# CHECK: .long 7 +# CHECK: foobar5: +# CHECK: .long 5 +# CHECK: foobar3: +# CHECK: .long 3 +# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s + +.altmacro +.macro test1 name num + \name\num\(): + .long \name\num +.endm +test1 'b',1 +test1 'ab',1 +test1 "a",1 +test1 "ba",1 +test1 ,1 +.noaltmacro +# CHECK: b1 +# CHECK: .long b1 +# CHECK: ab1: +# CHECK: .long ab1 +# CHECK: a1: +# CHECK: .long a1 +# CHECK: ba1: +# CHECK: .long ba1 +# CHECK: bac1: +# CHECK: .long bac1 + +.altmacro +.macro test2 name, number +__mksym \name, %number +.endm + +.macro __mksym, name, number +\name\number\(): + .long \number +.endm + +.section .rodata + +/* now define symbols by hand... */ +test2 bar, 1 +test2 bar, (9/3 + (7-1)) + +/* ...or use other pseudo ops to do it in a loop */ +.irp i, 3, 2, 1 +test2 foobar, (\i * 2 + 1) +.endr + +# CHECK: bar1: +# CHECK: .long 1 +# CHECK: bar9: +# CHECK: .long 9 +# CHECK: foobar7: +# CHECK: .long 7 +# CHECK: foobar5: +# CHECK: .long 5 +# CHECK: foobar3: +# CHECK: .long 3 \ No newline at end of file Index: test/MC/AsmParser/altMacroTestFail.s =================================================================== --- test/MC/AsmParser/altMacroTestFail.s +++ test/MC/AsmParser/altMacroTestFail.s @@ -0,0 +1,30 @@ +# RUN: not llvm-mc -triple i386 -o /dev/null %s 2>&1 | FileCheck %s + +.macro lableRun name num + \name\num\(): + .long \name\num +.endm +.altmacro +.noaltmacro +lableRun 'bc',1 +# CHECK: error: single quote way too long +# RUN: not llvm-mc -triple i386 -o /dev/null %s 2>&1 | FileCheck %s + +.macro lableRun name num + \name\num\(): + .long \name\num +.endm +.altmacro +.noaltmacro +lableRun 'bc',1 +# CHECK: error: single quote way too long +# RUN: not llvm-mc -triple i386 -o /dev/null %s 2>&1 | FileCheck %s + +.macro lableRun name num + \name\num\(): + .long \name\num +.endm +.altmacro +.noaltmacro +lableRun 'bc',1 +# CHECK: error: single quote way too long \ No newline at end of file