diff options
Diffstat (limited to 'llvm/lib/MC/MCParser/AsmParser.cpp')
-rw-r--r-- | llvm/lib/MC/MCParser/AsmParser.cpp | 651 |
1 files changed, 414 insertions, 237 deletions
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index c5ff241ead74..d3cb5ca59bf3 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -168,6 +169,8 @@ private: /// List of forward directional labels for diagnosis at the end. SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels; + SmallSet<StringRef, 2> LTODiscardSymbols; + /// AssemblerDialect. ~OU means unset value and use value provided by MAI. unsigned AssemblerDialect = ~0U; @@ -183,6 +186,22 @@ private: // Is alt macro mode enabled. bool AltMacroMode = false; +protected: + virtual bool parseStatement(ParseStatementInfo &Info, + MCAsmParserSemaCallback *SI); + + /// This routine uses the target specific ParseInstruction function to + /// parse an instruction into Operands, and then call the target specific + /// MatchAndEmit function to match and emit the instruction. + bool parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info, + StringRef IDVal, AsmToken ID, + SMLoc IDLoc); + + /// Should we emit DWARF describing this assembler source? (Returns false if + /// the source has .file directives, which means we don't want to generate + /// info describing the assembler source itself.) + bool enabledGenDwarfForAssembly(); + public: AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, const MCAsmInfo &MAI, unsigned CB); @@ -235,9 +254,13 @@ public: } bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; } - bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, - unsigned &NumOutputs, unsigned &NumInputs, - SmallVectorImpl<std::pair<void *,bool>> &OpDecls, + bool discardLTOSymbol(StringRef Name) const override { + return LTODiscardSymbols.contains(Name); + } + + bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs, + unsigned &NumInputs, + SmallVectorImpl<std::pair<void *, bool>> &OpDecls, SmallVectorImpl<std::string> &Constraints, SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, @@ -266,8 +289,6 @@ public: /// } private: - bool parseStatement(ParseStatementInfo &Info, - MCAsmParserSemaCallback *SI); bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites); bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true); @@ -310,11 +331,6 @@ private: } static void DiagHandler(const SMDiagnostic &Diag, void *Context); - /// Should we emit DWARF describing this assembler source? (Returns false if - /// the source has .file directives, which means we don't want to generate - /// info describing the assembler source itself.) - bool enabledGenDwarfForAssembly(); - /// Enter the specified file. This returns true on failure. bool enterIncludeFile(const std::string &Filename); @@ -483,6 +499,7 @@ private: DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER, + DK_CFI_LLVM_DEF_ASPACE_CFA, DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, @@ -516,6 +533,7 @@ private: DK_ADDRSIG, DK_ADDRSIG_SYM, DK_PSEUDO_PROBE, + DK_LTO_DISCARD, DK_END }; @@ -583,6 +601,7 @@ private: bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc); bool parseDirectiveCFIAdjustCfaOffset(); bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc); + bool parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc); bool parseDirectiveCFIOffset(SMLoc DirectiveLoc); bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc); bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality); @@ -682,6 +701,9 @@ private: // .pseudoprobe bool parseDirectivePseudoProbe(); + // ".lto_discard" + bool parseDirectiveLTODiscard(); + // Directives to support address-significance tables. bool parseDirectiveAddrsig(); bool parseDirectiveAddrsigSym(); @@ -690,6 +712,36 @@ private: void initializeCVDefRangeTypeMap(); }; +class HLASMAsmParser final : public AsmParser { +private: + MCAsmLexer &Lexer; + MCStreamer &Out; + + void lexLeadingSpaces() { + while (Lexer.is(AsmToken::Space)) + Lexer.Lex(); + } + + bool parseAsHLASMLabel(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI); + bool parseAsMachineInstruction(ParseStatementInfo &Info, + MCAsmParserSemaCallback *SI); + +public: + HLASMAsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, + const MCAsmInfo &MAI, unsigned CB = 0) + : AsmParser(SM, Ctx, Out, MAI, CB), Lexer(getLexer()), Out(Out) { + Lexer.setSkipSpace(false); + Lexer.setAllowHashInIdentifier(true); + Lexer.setLexHLASMIntegers(true); + Lexer.setLexHLASMStrings(true); + } + + ~HLASMAsmParser() { Lexer.setSkipSpace(true); } + + bool parseStatement(ParseStatementInfo &Info, + MCAsmParserSemaCallback *SI) override; +}; + } // end anonymous namespace namespace llvm { @@ -697,6 +749,7 @@ namespace llvm { extern MCAsmParserExtension *createDarwinAsmParser(); extern MCAsmParserExtension *createELFAsmParser(); extern MCAsmParserExtension *createCOFFAsmParser(); +extern MCAsmParserExtension *createXCOFFAsmParser(); extern MCAsmParserExtension *createWasmAsmParser(); } // end namespace llvm @@ -718,23 +771,24 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, Out.setStartTokLocPtr(&StartTokLoc); // Initialize the platform / file format parser. - switch (Ctx.getObjectFileInfo()->getObjectFileType()) { - case MCObjectFileInfo::IsCOFF: + switch (Ctx.getObjectFileType()) { + case MCContext::IsCOFF: PlatformParser.reset(createCOFFAsmParser()); break; - case MCObjectFileInfo::IsMachO: + case MCContext::IsMachO: PlatformParser.reset(createDarwinAsmParser()); IsDarwin = true; break; - case MCObjectFileInfo::IsELF: + case MCContext::IsELF: PlatformParser.reset(createELFAsmParser()); break; - case MCObjectFileInfo::IsWasm: + case MCContext::IsGOFF: + report_fatal_error("GOFFAsmParser support not implemented yet"); + case MCContext::IsWasm: PlatformParser.reset(createWasmAsmParser()); break; - case MCObjectFileInfo::IsXCOFF: - report_fatal_error( - "Need to implement createXCOFFAsmParser for XCOFF format."); + case MCContext::IsXCOFF: + PlatformParser.reset(createXCOFFAsmParser()); break; } @@ -892,6 +946,8 @@ bool AsmParser::enabledGenDwarfForAssembly() { } bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { + LTODiscardSymbols.clear(); + // Create the initial section, if requested. if (!NoInitialTextSection) Out.InitSections(false); @@ -919,6 +975,8 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { (void)InsertResult; } + getTargetParser().onBeginOfFile(); + // While we have input, parse each statement. while (Lexer.isNot(AsmToken::Eof)) { ParseStatementInfo Info(&AsmStrRewrites); @@ -1095,25 +1153,33 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc); return false; case AsmToken::Dollar: + case AsmToken::Star: case AsmToken::At: case AsmToken::String: case AsmToken::Identifier: { StringRef Identifier; if (parseIdentifier(Identifier)) { - // We may have failed but $ may be a valid token. - if (getTok().is(AsmToken::Dollar)) { - if (Lexer.getMAI().getDollarIsPC()) { - Lex(); - // This is a '$' reference, which references the current PC. Emit a - // temporary label to the streamer and refer to it. - MCSymbol *Sym = Ctx.createTempSymbol(); - Out.emitLabel(Sym); - Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, - getContext()); - EndLoc = FirstTokenLoc; - return false; - } - return Error(FirstTokenLoc, "invalid token in expression"); + // We may have failed but '$'|'*' may be a valid token in context of + // the current PC. + if (getTok().is(AsmToken::Dollar) || getTok().is(AsmToken::Star)) { + bool ShouldGenerateTempSymbol = false; + if ((getTok().is(AsmToken::Dollar) && MAI.getDollarIsPC()) || + (getTok().is(AsmToken::Star) && MAI.getStarIsPC())) + ShouldGenerateTempSymbol = true; + + if (!ShouldGenerateTempSymbol) + return Error(FirstTokenLoc, "invalid token in expression"); + + // Eat the '$'|'*' token. + Lex(); + // This is either a '$'|'*' reference, which references the current PC. + // Emit a temporary label to the streamer and refer to it. + MCSymbol *Sym = Ctx.createTempSymbol(); + Out.emitLabel(Sym); + Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, + getContext()); + EndLoc = FirstTokenLoc; + return false; } } // Parse symbol variant @@ -1167,7 +1233,8 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName); if (!Sym) - Sym = getContext().getOrCreateSymbol(SymbolName); + Sym = getContext().getOrCreateSymbol( + MAI.shouldEmitLabelsInUpperCase() ? SymbolName.upper() : SymbolName); // If this is an absolute variable reference, substitute it now to preserve // semantics in the face of reassignment. @@ -1230,6 +1297,9 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, return false; } case AsmToken::Dot: { + if (!MAI.getDotIsPC()) + return TokError("cannot use . as current PC"); + // This is a '.' reference, which references the current PC. Emit a // temporary label to the streamer and refer to it. MCSymbol *Sym = Ctx.createTempSymbol(); @@ -1770,7 +1840,6 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, StringMap<DirectiveKind>::const_iterator DirKindIt = DirectiveKindMap.find(IDVal.lower()); DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end()) - ? DK_NO_DIRECTIVE : DirKindIt->getValue(); switch (DirKind) { @@ -1868,6 +1937,9 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, Lex(); } + if (discardLTOSymbol(IDVal)) + return false; + getTargetParser().doBeforeLabelEmit(Sym); // Emit the label. @@ -2119,6 +2191,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveCFIAdjustCfaOffset(); case DK_CFI_DEF_CFA_REGISTER: return parseDirectiveCFIDefCfaRegister(IDLoc); + case DK_CFI_LLVM_DEF_ASPACE_CFA: + return parseDirectiveCFILLVMDefAspaceCfa(IDLoc); case DK_CFI_OFFSET: return parseDirectiveCFIOffset(IDLoc); case DK_CFI_REL_OFFSET: @@ -2208,6 +2282,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveAddrsigSym(); case DK_PSEUDO_PROBE: return parseDirectivePseudoProbe(); + case DK_LTO_DISCARD: + return parseDirectiveLTODiscard(); } return Error(IDLoc, "unknown directive"); @@ -2227,6 +2303,13 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, if (checkForValidSection()) return true; + return parseAndMatchAndEmitTargetInstruction(Info, IDVal, ID, IDLoc); +} + +bool AsmParser::parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info, + StringRef IDVal, + AsmToken ID, + SMLoc IDLoc) { // Canonicalize the opcode to lower case. std::string OpcodeStr = IDVal.lower(); ParseInstructionInfo IInfo(Info.AsmRewrites); @@ -2348,7 +2431,7 @@ bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) { /// will use the last parsed cpp hash line filename comment /// for the Filename and LineNo if any in the diagnostic. void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { - const AsmParser *Parser = static_cast<const AsmParser *>(Context); + auto *Parser = static_cast<AsmParser *>(Context); raw_ostream &OS = errs(); const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr(); @@ -2369,12 +2452,11 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { // If we have not parsed a cpp hash line filename comment or the source // manager changed or buffer changed (like in a nested include) then just // print the normal diagnostic using its Filename and LineNo. - if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr || - DiagBuf != CppHashBuf) { + if (!Parser->CppHashInfo.LineNumber || DiagBuf != CppHashBuf) { if (Parser->SavedDiagHandler) Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); else - Diag.print(nullptr, OS); + Parser->getContext().diagnose(Diag); return; } @@ -2394,9 +2476,9 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { Diag.getLineContents(), Diag.getRanges()); if (Parser->SavedDiagHandler) - Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext); + Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); else - NewDiag.print(nullptr, OS); + Parser->getContext().diagnose(NewDiag); } // FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The @@ -2853,6 +2935,9 @@ bool AsmParser::parseAssignment(StringRef Name, bool allow_redef, return false; } + if (discardLTOSymbol(Name)) + return false; + // Do the assignment. Out.emitAssignment(Sym, Value); if (NoDeadStrip) @@ -2910,9 +2995,9 @@ bool AsmParser::parseIdentifier(StringRef &Res) { /// ::= .set identifier ',' expression bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) { StringRef Name; - if (check(parseIdentifier(Name), "expected identifier") || - parseToken(AsmToken::Comma) || parseAssignment(Name, allow_redef, true)) - return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); + if (check(parseIdentifier(Name), "expected identifier") || parseComma() || + parseAssignment(Name, allow_redef, true)) + return true; return false; } @@ -3027,9 +3112,7 @@ bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { return false; }; - if (parseMany(parseOp)) - return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); - return false; + return parseMany(parseOp); } /// parseDirectiveReloc @@ -3041,7 +3124,7 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) { if (parseExpression(Offset)) return true; - if (parseToken(AsmToken::Comma, "expected comma") || + if (parseComma() || check(getTok().isNot(AsmToken::Identifier), "expected relocation name")) return true; @@ -3060,9 +3143,8 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) { return Error(ExprLoc, "expression must be relocatable"); } - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in .reloc directive")) - return true; + if (parseEOL()) + return true; const MCTargetAsmParser &MCT = getTargetParser(); const MCSubtargetInfo &STI = MCT.getSTI(); @@ -3094,9 +3176,7 @@ bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) { return false; }; - if (parseMany(parseOp)) - return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); - return false; + return parseMany(parseOp); } static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) { @@ -3138,9 +3218,7 @@ bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) { return false; }; - if (parseMany(parseOp)) - return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); - return false; + return parseMany(parseOp); } bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) { @@ -3163,9 +3241,10 @@ bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) { APFloat Value(Semantics); StringRef IDVal = getTok().getString(); if (getLexer().is(AsmToken::Identifier)) { - if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf")) + if (!IDVal.compare_insensitive("infinity") || + !IDVal.compare_insensitive("inf")) Value = APFloat::getInf(Semantics); - else if (!IDVal.compare_lower("nan")) + else if (!IDVal.compare_insensitive("nan")) Value = APFloat::getNaN(Semantics, false, ~0); else return TokError("invalid floating point literal"); @@ -3197,9 +3276,7 @@ bool AsmParser::parseDirectiveRealValue(StringRef IDVal, return false; }; - if (parseMany(parseOp)) - return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); - return false; + return parseMany(parseOp); } /// parseDirectiveZero @@ -3217,8 +3294,7 @@ bool AsmParser::parseDirectiveZero() { return true; } - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.zero' directive")) + if (parseEOL()) return true; getStreamer().emitFill(*NumBytes, Val, NumBytesLoc); @@ -3248,8 +3324,7 @@ bool AsmParser::parseDirectiveFill() { return true; } } - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.fill' directive")) + if (parseEOL()) return true; if (FillSize < 0) { @@ -3281,9 +3356,9 @@ bool AsmParser::parseDirectiveOrg() { int64_t FillExpr = 0; if (parseOptionalToken(AsmToken::Comma)) if (parseAbsoluteExpression(FillExpr)) - return addErrorSuffix(" in '.org' directive"); - if (parseToken(AsmToken::EndOfStatement)) - return addErrorSuffix(" in '.org' directive"); + return true; + if (parseEOL()) + return true; getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc); return false; @@ -3316,18 +3391,18 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) { parseAbsoluteExpression(MaxBytesToFill)) return true; } - return parseToken(AsmToken::EndOfStatement); + return parseEOL(); }; if (checkForValidSection()) - return addErrorSuffix(" in directive"); + return true; // Ignore empty '.p2align' directives for GNU-as compatibility if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) { Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored"); - return parseToken(AsmToken::EndOfStatement); + return parseEOL(); } if (parseAlign()) - return addErrorSuffix(" in directive"); + return true; // Always emit an alignment here even if we thrown an error. bool ReturnVal = false; @@ -3404,9 +3479,7 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { // Usually the directory and filename together, otherwise just the directory. // Allow the strings to have escaped octal character sequence. - if (check(getTok().isNot(AsmToken::String), - "unexpected token in '.file' directive") || - parseEscapedString(Path)) + if (parseEscapedString(Path)) return true; StringRef Directory; @@ -3485,8 +3558,9 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { Source = StringRef(SourceBuf, SourceString.size()); } if (FileNumber == 0) { + // Upgrade to Version 5 for assembly actions like clang -c a.s. if (Ctx.getDwarfVersion() < 5) - return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5"); + Ctx.setDwarfVersion(5); getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source); } else { Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective( @@ -3515,11 +3589,7 @@ bool AsmParser::parseDirectiveLine() { (void)LineNumber; // FIXME: Do something with the .line. } - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.line' directive")) - return true; - - return false; + return parseEOL(); } /// parseDirectiveLoc @@ -3841,15 +3911,13 @@ bool AsmParser::parseDirectiveCVLinetable() { int64_t FunctionId; StringRef FnStartName, FnEndName; SMLoc Loc = getTok().getLoc(); - if (parseCVFunctionId(FunctionId, ".cv_linetable") || - parseToken(AsmToken::Comma, - "unexpected token in '.cv_linetable' directive") || - parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, - "expected identifier in directive") || - parseToken(AsmToken::Comma, - "unexpected token in '.cv_linetable' directive") || - parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, - "expected identifier in directive")) + if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() || + parseTokenLoc(Loc) || + check(parseIdentifier(FnStartName), Loc, + "expected identifier in directive") || + parseComma() || parseTokenLoc(Loc) || + check(parseIdentifier(FnEndName), Loc, + "expected identifier in directive")) return true; MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); @@ -4016,7 +4084,7 @@ bool AsmParser::parseDirectiveCVDefRange() { bool AsmParser::parseDirectiveCVString() { std::string Data; if (checkForValidSection() || parseEscapedString(Data)) - return addErrorSuffix(" in '.cv_string' directive"); + return true; // Put the string in the table and emit the offset. std::pair<StringRef, unsigned> Insertion = @@ -4058,8 +4126,8 @@ bool AsmParser::parseDirectiveCVFPOData() { StringRef ProcName; if (parseIdentifier(ProcName)) return TokError("expected symbol name"); - if (parseEOL("unexpected tokens")) - return addErrorSuffix(" in '.cv_fpo_data' directive"); + if (parseEOL()) + return true; MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName); getStreamer().EmitCVFPOData(ProcSym, DirLoc); return false; @@ -4072,29 +4140,20 @@ bool AsmParser::parseDirectiveCFISections() { bool EH = false; bool Debug = false; - if (parseIdentifier(Name)) - return TokError("Expected an identifier"); - - if (Name == ".eh_frame") - EH = true; - else if (Name == ".debug_frame") - Debug = true; - - if (getLexer().is(AsmToken::Comma)) { - Lex(); - - if (parseIdentifier(Name)) - return TokError("Expected an identifier"); - - if (Name == ".eh_frame") - EH = true; - else if (Name == ".debug_frame") - Debug = true; + if (!parseOptionalToken(AsmToken::EndOfStatement)) { + for (;;) { + if (parseIdentifier(Name)) + return TokError("expected .eh_frame or .debug_frame"); + if (Name == ".eh_frame") + EH = true; + else if (Name == ".debug_frame") + Debug = true; + if (parseOptionalToken(AsmToken::EndOfStatement)) + break; + if (parseComma()) + return true; + } } - - if (parseToken(AsmToken::EndOfStatement)) - return addErrorSuffix(" in '.cfi_sections' directive"); - getStreamer().emitCFISections(EH, Debug); return false; } @@ -4106,8 +4165,8 @@ bool AsmParser::parseDirectiveCFIStartProc() { if (!parseOptionalToken(AsmToken::EndOfStatement)) { if (check(parseIdentifier(Simple) || Simple != "simple", "unexpected token") || - parseToken(AsmToken::EndOfStatement)) - return addErrorSuffix(" in '.cfi_startproc' directive"); + parseEOL()) + return true; } // TODO(kristina): Deal with a corner case of incorrect diagnostic context @@ -4122,8 +4181,8 @@ bool AsmParser::parseDirectiveCFIStartProc() { /// parseDirectiveCFIEndProc /// ::= .cfi_endproc bool AsmParser::parseDirectiveCFIEndProc() { - if (parseToken(AsmToken::EndOfStatement)) - return addErrorSuffix(" in '.cfi_endproc' directive"); + if (parseEOL()) + return true; getStreamer().emitCFIEndProc(); return false; } @@ -4147,9 +4206,8 @@ bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register, /// ::= .cfi_def_cfa register, offset bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { int64_t Register = 0, Offset = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || - parseToken(AsmToken::Comma, "unexpected token in directive") || - parseAbsoluteExpression(Offset)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() || + parseAbsoluteExpression(Offset) || parseEOL()) return true; getStreamer().emitCFIDefCfa(Register, Offset); @@ -4160,7 +4218,7 @@ bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { /// ::= .cfi_def_cfa_offset offset bool AsmParser::parseDirectiveCFIDefCfaOffset() { int64_t Offset = 0; - if (parseAbsoluteExpression(Offset)) + if (parseAbsoluteExpression(Offset) || parseEOL()) return true; getStreamer().emitCFIDefCfaOffset(Offset); @@ -4171,9 +4229,8 @@ bool AsmParser::parseDirectiveCFIDefCfaOffset() { /// ::= .cfi_register register, register bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) { int64_t Register1 = 0, Register2 = 0; - if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || - parseToken(AsmToken::Comma, "unexpected token in directive") || - parseRegisterOrRegisterNumber(Register2, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() || + parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL()) return true; getStreamer().emitCFIRegister(Register1, Register2); @@ -4183,6 +4240,8 @@ bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) { /// parseDirectiveCFIWindowSave /// ::= .cfi_window_save bool AsmParser::parseDirectiveCFIWindowSave() { + if (parseEOL()) + return true; getStreamer().emitCFIWindowSave(); return false; } @@ -4191,7 +4250,7 @@ bool AsmParser::parseDirectiveCFIWindowSave() { /// ::= .cfi_adjust_cfa_offset adjustment bool AsmParser::parseDirectiveCFIAdjustCfaOffset() { int64_t Adjustment = 0; - if (parseAbsoluteExpression(Adjustment)) + if (parseAbsoluteExpression(Adjustment) || parseEOL()) return true; getStreamer().emitCFIAdjustCfaOffset(Adjustment); @@ -4202,22 +4261,34 @@ bool AsmParser::parseDirectiveCFIAdjustCfaOffset() { /// ::= .cfi_def_cfa_register register bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) { int64_t Register = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL()) return true; getStreamer().emitCFIDefCfaRegister(Register); return false; } +/// parseDirectiveCFILLVMDefAspaceCfa +/// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space +bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) { + int64_t Register = 0, Offset = 0, AddressSpace = 0; + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() || + parseAbsoluteExpression(Offset) || parseComma() || + parseAbsoluteExpression(AddressSpace) || parseEOL()) + return true; + + getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace); + return false; +} + /// parseDirectiveCFIOffset /// ::= .cfi_offset register, offset bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) { int64_t Register = 0; int64_t Offset = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || - parseToken(AsmToken::Comma, "unexpected token in directive") || - parseAbsoluteExpression(Offset)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() || + parseAbsoluteExpression(Offset) || parseEOL()) return true; getStreamer().emitCFIOffset(Register, Offset); @@ -4229,9 +4300,8 @@ bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) { bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) { int64_t Register = 0, Offset = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || - parseToken(AsmToken::Comma, "unexpected token in directive") || - parseAbsoluteExpression(Offset)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() || + parseAbsoluteExpression(Offset) || parseEOL()) return true; getStreamer().emitCFIRelOffset(Register, Offset); @@ -4273,8 +4343,9 @@ bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { StringRef Name; if (check(!isValidEncoding(Encoding), "unsupported encoding.") || - parseToken(AsmToken::Comma, "unexpected token in directive") || - check(parseIdentifier(Name), "expected identifier in directive")) + parseComma() || + check(parseIdentifier(Name), "expected identifier in directive") || + parseEOL()) return true; MCSymbol *Sym = getContext().getOrCreateSymbol(Name); @@ -4289,6 +4360,8 @@ bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { /// parseDirectiveCFIRememberState /// ::= .cfi_remember_state bool AsmParser::parseDirectiveCFIRememberState() { + if (parseEOL()) + return true; getStreamer().emitCFIRememberState(); return false; } @@ -4296,6 +4369,8 @@ bool AsmParser::parseDirectiveCFIRememberState() { /// parseDirectiveCFIRestoreState /// ::= .cfi_remember_state bool AsmParser::parseDirectiveCFIRestoreState() { + if (parseEOL()) + return true; getStreamer().emitCFIRestoreState(); return false; } @@ -4305,7 +4380,7 @@ bool AsmParser::parseDirectiveCFIRestoreState() { bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) { int64_t Register = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL()) return true; getStreamer().emitCFISameValue(Register); @@ -4316,7 +4391,7 @@ bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) { /// ::= .cfi_restore register bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) { int64_t Register = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL()) return true; getStreamer().emitCFIRestore(Register); @@ -4350,7 +4425,7 @@ bool AsmParser::parseDirectiveCFIEscape() { /// ::= .cfi_return_column register bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) { int64_t Register = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL()) return true; getStreamer().emitCFIReturnColumn(Register); return false; @@ -4359,8 +4434,7 @@ bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) { /// parseDirectiveCFISignalFrame /// ::= .cfi_signal_frame bool AsmParser::parseDirectiveCFISignalFrame() { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.cfi_signal_frame'")) + if (parseEOL()) return true; getStreamer().emitCFISignalFrame(); @@ -4372,7 +4446,7 @@ bool AsmParser::parseDirectiveCFISignalFrame() { bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) { int64_t Register = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL()) return true; getStreamer().emitCFIUndefined(Register); @@ -4383,8 +4457,8 @@ bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) { /// ::= .altmacro /// ::= .noaltmacro bool AsmParser::parseDirectiveAltmacro(StringRef Directive) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '" + Directive + "' directive"); + if (parseEOL()) + return true; AltMacroMode = (Directive == ".altmacro"); return false; } @@ -4393,10 +4467,8 @@ bool AsmParser::parseDirectiveAltmacro(StringRef Directive) { /// ::= .macros_on /// ::= .macros_off bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Directive + "' directive")) + if (parseEOL()) return true; - setMacrosEnabled(Directive == ".macros_on"); return false; } @@ -4635,8 +4707,7 @@ void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, /// parseDirectiveExitMacro /// ::= .exitm bool AsmParser::parseDirectiveExitMacro(StringRef Directive) { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Directive + "' directive")) + if (parseEOL()) return true; if (!isInsideMacroInstantiation()) @@ -4674,15 +4745,14 @@ bool AsmParser::parseDirectiveEndMacro(StringRef Directive) { } /// parseDirectivePurgeMacro -/// ::= .purgem +/// ::= .purgem name bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) { StringRef Name; SMLoc Loc; if (parseTokenLoc(Loc) || check(parseIdentifier(Name), Loc, "expected identifier in '.purgem' directive") || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '.purgem' directive")) + parseEOL()) return true; if (!getContext().lookupMacro(Name)) @@ -4702,9 +4772,7 @@ bool AsmParser::parseDirectiveBundleAlignMode() { SMLoc ExprLoc = getLexer().getLoc(); int64_t AlignSizePow2; if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) || - parseToken(AsmToken::EndOfStatement, "unexpected token after expression " - "in '.bundle_align_mode' " - "directive") || + parseEOL() || check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc, "invalid bundle alignment size (expected between 0 and 30)")) return true; @@ -4729,9 +4797,7 @@ bool AsmParser::parseDirectiveBundleLock() { if (!parseOptionalToken(AsmToken::EndOfStatement)) { if (check(parseIdentifier(Option), Loc, kInvalidOptionError) || - check(Option != "align_to_end", Loc, kInvalidOptionError) || - parseToken(AsmToken::EndOfStatement, - "unexpected token after '.bundle_lock' directive option")) + check(Option != "align_to_end", Loc, kInvalidOptionError) || parseEOL()) return true; AlignToEnd = true; } @@ -4743,9 +4809,7 @@ bool AsmParser::parseDirectiveBundleLock() { /// parseDirectiveBundleLock /// ::= {.bundle_lock} bool AsmParser::parseDirectiveBundleUnlock() { - if (checkForValidSection() || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '.bundle_unlock' directive")) + if (checkForValidSection() || parseEOL()) return true; getStreamer().emitBundleUnlock(); @@ -4763,9 +4827,9 @@ bool AsmParser::parseDirectiveSpace(StringRef IDVal) { int64_t FillExpr = 0; if (parseOptionalToken(AsmToken::Comma)) if (parseAbsoluteExpression(FillExpr)) - return addErrorSuffix("in '" + Twine(IDVal) + "' directive"); - if (parseToken(AsmToken::EndOfStatement)) - return addErrorSuffix("in '" + Twine(IDVal) + "' directive"); + return true; + if (parseEOL()) + return true; // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc); @@ -4786,8 +4850,7 @@ bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) { return false; } - if (parseToken(AsmToken::Comma, - "unexpected token in '" + Twine(IDVal) + "' directive")) + if (parseComma()) return true; const MCExpr *Value; @@ -4808,11 +4871,7 @@ bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) { getStreamer().emitValue(Value, Size, ExprLoc); } - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Twine(IDVal) + "' directive")) - return true; - - return false; + return parseEOL(); } /// parseDirectiveRealDCB @@ -4828,16 +4887,11 @@ bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Seman return false; } - if (parseToken(AsmToken::Comma, - "unexpected token in '" + Twine(IDVal) + "' directive")) + if (parseComma()) return true; APInt AsInt; - if (parseRealValue(Semantics, AsInt)) - return true; - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Twine(IDVal) + "' directive")) + if (parseRealValue(Semantics, AsInt) || parseEOL()) return true; for (uint64_t i = 0, e = NumValues; i != e; ++i) @@ -4852,7 +4906,8 @@ bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Seman bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) { SMLoc NumValuesLoc = Lexer.getLoc(); int64_t NumValues; - if (checkForValidSection() || parseAbsoluteExpression(NumValues)) + if (checkForValidSection() || parseAbsoluteExpression(NumValues) || + parseEOL()) return true; if (NumValues < 0) { @@ -4860,10 +4915,6 @@ bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) { return false; } - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Twine(IDVal) + "' directive")) - return true; - for (uint64_t i = 0, e = NumValues; i != e; ++i) getStreamer().emitFill(Size, 0); @@ -4887,10 +4938,7 @@ bool AsmParser::parseDirectiveLEB128(bool Signed) { return false; }; - if (parseMany(parseOp)) - return addErrorSuffix(" in directive"); - - return false; + return parseMany(parseOp); } /// parseDirectiveSymbolAttribute @@ -4901,6 +4949,10 @@ bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) { SMLoc Loc = getTok().getLoc(); if (parseIdentifier(Name)) return Error(Loc, "expected identifier"); + + if (discardLTOSymbol(Name)) + return false; + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); // Assembler local symbols don't make any sense here. Complain loudly. @@ -4912,9 +4964,7 @@ bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) { return false; }; - if (parseMany(parseOp)) - return addErrorSuffix(" in directive"); - return false; + return parseMany(parseOp); } /// parseDirectiveComm @@ -4931,9 +4981,8 @@ bool AsmParser::parseDirectiveComm(bool IsLocal) { // Handle the identifier as the key symbol. MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); + if (parseComma()) + return true; int64_t Size; SMLoc SizeLoc = getLexer().getLoc(); @@ -4961,8 +5010,7 @@ bool AsmParser::parseDirectiveComm(bool IsLocal) { } } - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.comm' or '.lcomm' directive")) + if (parseEOL()) return true; // NOTE: a size of zero for a .comm should create a undefined symbol @@ -4999,8 +5047,7 @@ bool AsmParser::parseDirectiveAbort() { SMLoc Loc = getLexer().getLoc(); StringRef Str = parseStringToEndOfStatement(); - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.abort' directive")) + if (parseEOL()) return true; if (Str.empty()) @@ -5061,8 +5108,7 @@ bool AsmParser::parseDirectiveIncbin() { } } - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.incbin' directive")) + if (parseEOL()) return true; if (check(Skip < 0, SkipLoc, "skip is negative")) @@ -5083,9 +5129,7 @@ bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) { eatToEndOfStatement(); } else { int64_t ExprValue; - if (parseAbsoluteExpression(ExprValue) || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '.if' directive")) + if (parseAbsoluteExpression(ExprValue) || parseEOL()) return true; switch (DirKind) { @@ -5129,8 +5173,7 @@ bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { } else { StringRef Str = parseStringToEndOfStatement(); - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.ifb' directive")) + if (parseEOL()) return true; TheCondState.CondMet = ExpectBlank == Str.empty(); @@ -5152,13 +5195,12 @@ bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { } else { StringRef Str1 = parseStringToComma(); - if (parseToken(AsmToken::Comma, "unexpected token in '.ifc' directive")) + if (parseComma()) return true; StringRef Str2 = parseStringToEndOfStatement(); - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.ifc' directive")) + if (parseEOL()) return true; TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim()); @@ -5217,7 +5259,7 @@ bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { eatToEndOfStatement(); } else { if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") || - parseToken(AsmToken::EndOfStatement, "unexpected token in '.ifdef'")) + parseEOL()) return true; MCSymbol *Sym = getContext().lookupSymbol(Name); @@ -5252,8 +5294,7 @@ bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) { if (parseAbsoluteExpression(ExprValue)) return true; - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.elseif' directive")) + if (parseEOL()) return true; TheCondState.CondMet = ExprValue; @@ -5266,8 +5307,7 @@ bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) { /// parseDirectiveElse /// ::= .else bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.else' directive")) + if (parseEOL()) return true; if (TheCondState.TheCond != AsmCond::IfCond && @@ -5289,8 +5329,7 @@ bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) { /// parseDirectiveEnd /// ::= .end bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.end' directive")) + if (parseEOL()) return true; while (Lexer.isNot(AsmToken::Eof)) @@ -5343,8 +5382,7 @@ bool AsmParser::parseDirectiveWarning(SMLoc L) { Message = getTok().getStringContents(); Lex(); - if (parseToken(AsmToken::EndOfStatement, - "expected end of statement in '.warning' directive")) + if (parseEOL()) return true; } @@ -5354,8 +5392,7 @@ bool AsmParser::parseDirectiveWarning(SMLoc L) { /// parseDirectiveEndIf /// ::= .endif bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.endif' directive")) + if (parseEOL()) return true; if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty()) @@ -5481,6 +5518,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET; DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET; DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER; + DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA; DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET; DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET; DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY; @@ -5536,6 +5574,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".addrsig"] = DK_ADDRSIG; DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM; DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE; + DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD; } MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { @@ -5617,9 +5656,7 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) { return Error(CountLoc, "unexpected token in '" + Dir + "' directive"); } - if (check(Count < 0, CountLoc, "Count is negative") || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Dir + "' directive")) + if (check(Count < 0, CountLoc, "Count is negative") || parseEOL()) return true; // Lex the rept definition. @@ -5648,9 +5685,7 @@ bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { MCAsmMacroArguments A; if (check(parseIdentifier(Parameter.Name), "expected identifier in '.irp' directive") || - parseToken(AsmToken::Comma, "expected comma in '.irp' directive") || - parseMacroArguments(nullptr, A) || - parseToken(AsmToken::EndOfStatement, "expected End of Statement")) + parseComma() || parseMacroArguments(nullptr, A) || parseEOL()) return true; // Lex the irp definition. @@ -5683,15 +5718,12 @@ bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) { if (check(parseIdentifier(Parameter.Name), "expected identifier in '.irpc' directive") || - parseToken(AsmToken::Comma, "expected comma in '.irpc' directive") || - parseMacroArguments(nullptr, A)) + parseComma() || parseMacroArguments(nullptr, A)) return true; if (A.size() != 1 || A.front().size() != 1) return TokError("unexpected token in '.irpc' directive"); - - // Eat the end of statement. - if (parseToken(AsmToken::EndOfStatement, "expected end of statement")) + if (parseEOL()) return true; // Lex the irpc definition. @@ -5770,21 +5802,22 @@ bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) { Lex(); if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"') return Error(DirectiveLoc, "expected double quoted string after .print"); - if (parseToken(AsmToken::EndOfStatement, "expected end of statement")) + if (parseEOL()) return true; llvm::outs() << StrTok.getStringContents() << '\n'; return false; } bool AsmParser::parseDirectiveAddrsig() { + if (parseEOL()) + return true; getStreamer().emitAddrsig(); return false; } bool AsmParser::parseDirectiveAddrsigSym() { StringRef Name; - if (check(parseIdentifier(Name), - "expected identifier in '.addrsig_sym' directive")) + if (check(parseIdentifier(Name), "expected identifier") || parseEOL()) return true; MCSymbol *Sym = getContext().getOrCreateSymbol(Name); getStreamer().emitAddrsigSym(Sym); @@ -5846,14 +5879,32 @@ bool AsmParser::parseDirectivePseudoProbe() { InlineStack.push_back(Site); } - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.pseudoprobe' directive")) + if (parseEOL()) return true; getStreamer().emitPseudoProbe(Guid, Index, Type, Attr, InlineStack); return false; } +/// parseDirectiveLTODiscard +/// ::= ".lto_discard" [ identifier ( , identifier )* ] +/// The LTO library emits this directive to discard non-prevailing symbols. +/// We ignore symbol assignments and attribute changes for the specified +/// symbols. +bool AsmParser::parseDirectiveLTODiscard() { + auto ParseOp = [&]() -> bool { + StringRef Name; + SMLoc Loc = getTok().getLoc(); + if (parseIdentifier(Name)) + return Error(Loc, "expected identifier"); + LTODiscardSymbols.insert(Name); + return false; + }; + + LTODiscardSymbols.clear(); + return parseMany(ParseOp); +} + // We are comparing pointers, but the pointers are relative to a single string. // Thus, this should always be deterministic. static int rewritesSort(const AsmRewrite *AsmRewriteA, @@ -5878,8 +5929,8 @@ static int rewritesSort(const AsmRewrite *AsmRewriteA, } bool AsmParser::parseMSInlineAsm( - void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, - unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls, + std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, + SmallVectorImpl<std::pair<void *, bool>> &OpDecls, SmallVectorImpl<std::string> &Constraints, SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) { @@ -6141,6 +6192,129 @@ bool AsmParser::parseMSInlineAsm( return false; } +bool HLASMAsmParser::parseAsHLASMLabel(ParseStatementInfo &Info, + MCAsmParserSemaCallback *SI) { + AsmToken LabelTok = getTok(); + SMLoc LabelLoc = LabelTok.getLoc(); + StringRef LabelVal; + + if (parseIdentifier(LabelVal)) + return Error(LabelLoc, "The HLASM Label has to be an Identifier"); + + // We have validated whether the token is an Identifier. + // Now we have to validate whether the token is a + // valid HLASM Label. + if (!getTargetParser().isLabel(LabelTok) || checkForValidSection()) + return true; + + // Lex leading spaces to get to the next operand. + lexLeadingSpaces(); + + // We shouldn't emit the label if there is nothing else after the label. + // i.e asm("<token>\n") + if (getTok().is(AsmToken::EndOfStatement)) + return Error(LabelLoc, + "Cannot have just a label for an HLASM inline asm statement"); + + MCSymbol *Sym = getContext().getOrCreateSymbol( + getContext().getAsmInfo()->shouldEmitLabelsInUpperCase() + ? LabelVal.upper() + : LabelVal); + + getTargetParser().doBeforeLabelEmit(Sym); + + // Emit the label. + Out.emitLabel(Sym, LabelLoc); + + // If we are generating dwarf for assembly source files then gather the + // info to make a dwarf label entry for this label if needed. + if (enabledGenDwarfForAssembly()) + MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(), + LabelLoc); + + getTargetParser().onLabelParsed(Sym); + + return false; +} + +bool HLASMAsmParser::parseAsMachineInstruction(ParseStatementInfo &Info, + MCAsmParserSemaCallback *SI) { + AsmToken OperationEntryTok = Lexer.getTok(); + SMLoc OperationEntryLoc = OperationEntryTok.getLoc(); + StringRef OperationEntryVal; + + // Attempt to parse the first token as an Identifier + if (parseIdentifier(OperationEntryVal)) + return Error(OperationEntryLoc, "unexpected token at start of statement"); + + // Once we've parsed the operation entry successfully, lex + // any spaces to get to the OperandEntries. + lexLeadingSpaces(); + + return parseAndMatchAndEmitTargetInstruction( + Info, OperationEntryVal, OperationEntryTok, OperationEntryLoc); +} + +bool HLASMAsmParser::parseStatement(ParseStatementInfo &Info, + MCAsmParserSemaCallback *SI) { + assert(!hasPendingError() && "parseStatement started with pending error"); + + // Should the first token be interpreted as a HLASM Label. + bool ShouldParseAsHLASMLabel = false; + + // If a Name Entry exists, it should occur at the very + // start of the string. In this case, we should parse the + // first non-space token as a Label. + // If the Name entry is missing (i.e. there's some other + // token), then we attempt to parse the first non-space + // token as a Machine Instruction. + if (getTok().isNot(AsmToken::Space)) + ShouldParseAsHLASMLabel = true; + + // If we have an EndOfStatement (which includes the target's comment + // string) we can appropriately lex it early on) + if (Lexer.is(AsmToken::EndOfStatement)) { + // if this is a line comment we can drop it safely + if (getTok().getString().empty() || getTok().getString().front() == '\r' || + getTok().getString().front() == '\n') + Out.AddBlankLine(); + Lex(); + return false; + } + + // We have established how to parse the inline asm statement. + // Now we can safely lex any leading spaces to get to the + // first token. + lexLeadingSpaces(); + + // If we see a new line or carriage return as the first operand, + // after lexing leading spaces, emit the new line and lex the + // EndOfStatement token. + if (Lexer.is(AsmToken::EndOfStatement)) { + if (getTok().getString().front() == '\n' || + getTok().getString().front() == '\r') { + Out.AddBlankLine(); + Lex(); + return false; + } + } + + // Handle the label first if we have to before processing the rest + // of the tokens as a machine instruction. + if (ShouldParseAsHLASMLabel) { + // If there were any errors while handling and emitting the label, + // early return. + if (parseAsHLASMLabel(Info, SI)) { + // If we know we've failed in parsing, simply eat until end of the + // statement. This ensures that we don't process any other statements. + eatToEndOfStatement(); + return true; + } + } + + return parseAsMachineInstruction(Info, SI); +} + namespace llvm { namespace MCParserUtils { @@ -6184,7 +6358,7 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef, // a = b // b = c - if (Parser.parseToken(AsmToken::EndOfStatement)) + if (Parser.parseEOL()) return true; // Validate that the LHS is allowed to be a variable (either it has not been @@ -6228,5 +6402,8 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef, MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C, MCStreamer &Out, const MCAsmInfo &MAI, unsigned CB) { + if (C.getTargetTriple().isSystemZ() && C.getTargetTriple().isOSzOS()) + return new HLASMAsmParser(SM, C, Out, MAI, CB); + return new AsmParser(SM, C, Out, MAI, CB); } |