diff options
Diffstat (limited to 'lib/MC/MCParser/AsmParser.cpp')
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 327 |
1 files changed, 265 insertions, 62 deletions
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 09c92b8..bbd6635 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -27,6 +27,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCDwarf.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" @@ -36,15 +37,21 @@ #include <vector> using namespace llvm; +static cl::opt<bool> +FatalAssemblerWarnings("fatal-assembler-warnings", + cl::desc("Consider warnings as error")); + namespace { /// \brief Helper class for tracking macro definitions. struct Macro { StringRef Name; StringRef Body; + std::vector<StringRef> Parameters; public: - Macro(StringRef N, StringRef B) : Name(N), Body(B) {} + Macro(StringRef N, StringRef B, const std::vector<StringRef> &P) : + Name(N), Body(B), Parameters(P) {} }; /// \brief Helper class for storing information about an active macro @@ -64,7 +71,7 @@ struct MacroInstantiation { public: MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL, - const std::vector<std::vector<AsmToken> > &A); + MemoryBuffer *I); }; /// \brief The concrete assembly parser instance. @@ -77,6 +84,7 @@ private: AsmLexer Lexer; MCContext &Ctx; MCStreamer &Out; + const MCAsmInfo &MAI; SourceMgr &SrcMgr; MCAsmParserExtension *GenericParser; MCAsmParserExtension *PlatformParser; @@ -128,7 +136,7 @@ public: virtual MCContext &getContext() { return Ctx; } virtual MCStreamer &getStreamer() { return Out; } - virtual void Warning(SMLoc L, const Twine &Meg); + virtual bool Warning(SMLoc L, const Twine &Msg); virtual bool Error(SMLoc L, const Twine &Msg); const AsmToken &Lex(); @@ -146,11 +154,16 @@ private: bool ParseStatement(); bool HandleMacroEntry(StringRef Name, SMLoc NameLoc, const Macro *M); + bool expandMacro(SmallString<256> &Buf, StringRef Body, + const std::vector<StringRef> &Parameters, + const std::vector<std::vector<AsmToken> > &A, + const SMLoc &L); void HandleMacroExit(); void PrintMacroInstantiations(); - void PrintMessage(SMLoc Loc, const Twine &Msg, const char *Type) const { - SrcMgr.PrintMessage(Loc, Msg, Type); + void PrintMessage(SMLoc Loc, const Twine &Msg, const char *Type, + bool ShowLine = true) const { + SrcMgr.PrintMessage(Loc, Msg, Type, ShowLine); } /// EnterIncludeFile - Enter the specified file. This returns true on failure. @@ -243,6 +256,8 @@ public: AddDirectiveHandler<&GenericAsmParser::ParseDirectiveStabs>(".stabs"); // CFI directives. + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFISections>( + ".cfi_sections"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIStartProc>( ".cfi_startproc"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIEndProc>( @@ -251,10 +266,14 @@ public: ".cfi_def_cfa"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaOffset>( ".cfi_def_cfa_offset"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset>( + ".cfi_adjust_cfa_offset"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaRegister>( ".cfi_def_cfa_register"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIOffset>( ".cfi_offset"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIRelOffset>( + ".cfi_rel_offset"); AddDirectiveHandler< &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_personality"); AddDirectiveHandler< @@ -263,6 +282,8 @@ public: &GenericAsmParser::ParseDirectiveCFIRememberState>(".cfi_remember_state"); AddDirectiveHandler< &GenericAsmParser::ParseDirectiveCFIRestoreState>(".cfi_restore_state"); + AddDirectiveHandler< + &GenericAsmParser::ParseDirectiveCFISameValue>(".cfi_same_value"); // Macro directives. AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>( @@ -283,15 +304,19 @@ public: bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveStabs(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFISections(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIStartProc(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfa(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfaOffset(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIAdjustCfaOffset(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfaRegister(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIRelOffset(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIPersonalityOrLsda(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIRememberState(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIRestoreState(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFISameValue(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveMacrosOnOff(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc); @@ -314,7 +339,7 @@ enum { DEFAULT_ADDRSPACE = 0 }; AsmParser::AsmParser(const Target &T, SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, const MCAsmInfo &_MAI) - : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM), + : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM), GenericParser(new GenericAsmParser), PlatformParser(0), CurBuffer(0), MacrosEnabled(true) { Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); @@ -358,9 +383,12 @@ void AsmParser::PrintMacroInstantiations() { "note"); } -void AsmParser::Warning(SMLoc L, const Twine &Msg) { +bool AsmParser::Warning(SMLoc L, const Twine &Msg) { + if (FatalAssemblerWarnings) + return Error(L, Msg); PrintMessage(L, Msg, "warning"); PrintMacroInstantiations(); + return false; } bool AsmParser::Error(SMLoc L, const Twine &Msg) { @@ -371,7 +399,8 @@ bool AsmParser::Error(SMLoc L, const Twine &Msg) { } bool AsmParser::EnterIncludeFile(const std::string &Filename) { - int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc()); + std::string IncludedFile; + int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); if (NewBuf == -1) return true; @@ -439,6 +468,29 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { TokError("unassigned file number: " + Twine(i) + " for .file directives"); } + // Check to see that all assembler local symbols were actually defined. + // Targets that don't do subsections via symbols may not want this, though, + // so conservatively exclude them. Only do this if we're finalizing, though, + // as otherwise we won't necessarilly have seen everything yet. + if (!NoFinalize && MAI.hasSubsectionsViaSymbols()) { + const MCContext::SymbolTable &Symbols = getContext().getSymbols(); + for (MCContext::SymbolTable::const_iterator i = Symbols.begin(), + e = Symbols.end(); + i != e; ++i) { + MCSymbol *Sym = i->getValue(); + // Variable symbols may not be marked as defined, so check those + // explicitly. If we know it's a variable, we have a definition for + // the purposes of this check. + if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined()) + // FIXME: We would really like to refer back to where the symbol was + // first referenced for a source location. We need to add something + // to track that. Currently, we just point to the end of the file. + PrintMessage(getLexer().getLoc(), "assembler local symbol '" + + Sym->getName() + "' not defined", "error", false); + } + } + + // Finalize the output stream if there are no errors and if the client wants // us to. if (!HadError && !NoFinalize) @@ -517,6 +569,9 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { switch (Lexer.getKind()) { default: return TokError("unknown token in expression"); + // If we have an error assume that we've already handled it. + case AsmToken::Error: + return true; case AsmToken::Exclaim: Lex(); // Eat the operator. if (ParsePrimaryExpr(Res, EndLoc)) @@ -530,7 +585,7 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { StringRef Identifier; if (ParseIdentifier(Identifier)) - return false; + return true; // This is a symbol reference. std::pair<StringRef, StringRef> Split = Identifier.split('@'); @@ -1114,9 +1169,9 @@ bool AsmParser::ParseStatement() { if (!getTargetParser().ParseDirective(ID)) return false; - Warning(IDLoc, "ignoring directive for now"); + bool retval = Warning(IDLoc, "ignoring directive for now"); EatToEndOfStatement(); - return false; + return retval; } CheckForValidSection(); @@ -1159,27 +1214,33 @@ bool AsmParser::ParseStatement() { return false; } -MacroInstantiation::MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL, - const std::vector<std::vector<AsmToken> > &A) - : TheMacro(M), InstantiationLoc(IL), ExitLoc(EL) -{ - // Macro instantiation is lexical, unfortunately. We construct a new buffer - // to hold the macro body with substitutions. - SmallString<256> Buf; +bool AsmParser::expandMacro(SmallString<256> &Buf, StringRef Body, + const std::vector<StringRef> &Parameters, + const std::vector<std::vector<AsmToken> > &A, + const SMLoc &L) { raw_svector_ostream OS(Buf); + unsigned NParameters = Parameters.size(); + if (NParameters != 0 && NParameters != A.size()) + return Error(L, "Wrong number of arguments"); - StringRef Body = M->Body; while (!Body.empty()) { // Scan for the next substitution. std::size_t End = Body.size(), Pos = 0; for (; Pos != End; ++Pos) { // Check for a substitution or escape. - if (Body[Pos] != '$' || Pos + 1 == End) - continue; - - char Next = Body[Pos + 1]; - if (Next == '$' || Next == 'n' || isdigit(Next)) - break; + if (!NParameters) { + // This macro has no parameters, look for $0, $1, etc. + if (Body[Pos] != '$' || Pos + 1 == End) + continue; + + char Next = Body[Pos + 1]; + if (Next == '$' || Next == 'n' || isdigit(Next)) + break; + } else { + // This macro has parameters, look for \foo, \bar, etc. + if (Body[Pos] == '\\' && Pos + 1 != End) + break; + } } // Add the prefix. @@ -1189,41 +1250,69 @@ MacroInstantiation::MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL, if (Pos == End) break; - switch (Body[Pos+1]) { - // $$ => $ - case '$': - OS << '$'; - break; + if (!NParameters) { + switch (Body[Pos+1]) { + // $$ => $ + case '$': + OS << '$'; + break; - // $n => number of arguments - case 'n': - OS << A.size(); - break; + // $n => number of arguments + case 'n': + OS << A.size(); + break; - // $[0-9] => argument - default: { - // Missing arguments are ignored. - unsigned Index = Body[Pos+1] - '0'; - if (Index >= A.size()) + // $[0-9] => argument + default: { + // Missing arguments are ignored. + unsigned Index = Body[Pos+1] - '0'; + if (Index >= A.size()) + break; + + // Otherwise substitute with the token values, with spaces eliminated. + for (std::vector<AsmToken>::const_iterator it = A[Index].begin(), + ie = A[Index].end(); it != ie; ++it) + OS << it->getString(); break; + } + } + Pos += 2; + } else { + unsigned I = Pos + 1; + while (isalnum(Body[I]) && I + 1 != End) + ++I; + + const char *Begin = Body.data() + Pos +1; + StringRef Argument(Begin, I - (Pos +1)); + unsigned Index = 0; + for (; Index < NParameters; ++Index) + if (Parameters[Index] == Argument) + break; + + // FIXME: We should error at the macro definition. + if (Index == NParameters) + return Error(L, "Parameter not found"); - // Otherwise substitute with the token values, with spaces eliminated. for (std::vector<AsmToken>::const_iterator it = A[Index].begin(), ie = A[Index].end(); it != ie; ++it) OS << it->getString(); - break; - } - } + Pos += 1 + Argument.size(); + } // Update the scan point. - Body = Body.substr(Pos + 2); + Body = Body.substr(Pos); } // We include the .endmacro in the buffer as our queue to exit the macro // instantiation. OS << ".endmacro\n"; + return false; +} - Instantiation = MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); +MacroInstantiation::MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL, + MemoryBuffer *I) + : TheMacro(M), Instantiation(I), InstantiationLoc(IL), ExitLoc(EL) +{ } bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc, @@ -1260,11 +1349,22 @@ bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc, Lex(); } + // Macro instantiation is lexical, unfortunately. We construct a new buffer + // to hold the macro body with substitutions. + SmallString<256> Buf; + StringRef Body = M->Body; + + if (expandMacro(Buf, Body, M->Parameters, MacroArguments, getTok().getLoc())) + return true; + + MemoryBuffer *Instantiation = + MemoryBuffer::getMemBufferCopy(Buf.str(), "<instantiation>"); + // Create the macro instantiation object and add to the current macro // instantiation stack. MacroInstantiation *MI = new MacroInstantiation(M, NameLoc, getTok().getLoc(), - MacroArguments); + Instantiation); ActiveMacros.push_back(MI); // Jump to the macro instantiation and prime the lexer. @@ -1336,7 +1436,7 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef) { // FIXME: Diagnose assignment to protected identifier (e.g., register name). if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable()) ; // Allow redefinitions of undefined symbols only used in directives. - else if (!Sym->isUndefined() && (!Sym->isAbsolute() || !allow_redef)) + else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef)) return Error(EqualLoc, "redefinition of '" + Name + "'"); else if (!Sym->isVariable()) return Error(EqualLoc, "invalid assignment to '" + Name + "'"); @@ -2241,7 +2341,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { } getStreamer().EmitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags, - Isa, Discriminator); + Isa, Discriminator, StringRef()); return false; } @@ -2253,17 +2353,52 @@ bool GenericAsmParser::ParseDirectiveStabs(StringRef Directive, return TokError("unsupported directive '" + Directive + "'"); } +/// ParseDirectiveCFISections +/// ::= .cfi_sections section [, section] +bool GenericAsmParser::ParseDirectiveCFISections(StringRef, + SMLoc DirectiveLoc) { + StringRef Name; + bool EH = false; + bool Debug = false; + + if (getParser().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 (getParser().ParseIdentifier(Name)) + return TokError("Expected an identifier"); + + if (Name == ".eh_frame") + EH = true; + else if (Name == ".debug_frame") + Debug = true; + } + + getStreamer().EmitCFISections(EH, Debug); + + return false; +} + /// ParseDirectiveCFIStartProc /// ::= .cfi_startproc bool GenericAsmParser::ParseDirectiveCFIStartProc(StringRef, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIStartProc(); + getStreamer().EmitCFIStartProc(); + return false; } /// ParseDirectiveCFIEndProc /// ::= .cfi_endproc bool GenericAsmParser::ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIEndProc(); + getStreamer().EmitCFIEndProc(); + return false; } /// ParseRegisterOrRegisterNumber - parse register name or number. @@ -2271,7 +2406,7 @@ bool GenericAsmParser::ParseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc) { unsigned RegNo; - if (getLexer().is(AsmToken::Percent)) { + if (getLexer().isNot(AsmToken::Integer)) { if (getParser().getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc)) return true; @@ -2298,7 +2433,8 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfa(StringRef, if (getParser().ParseAbsoluteExpression(Offset)) return true; - return getStreamer().EmitCFIDefCfa(Register, Offset); + getStreamer().EmitCFIDefCfa(Register, Offset); + return false; } /// ParseDirectiveCFIDefCfaOffset @@ -2309,7 +2445,20 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfaOffset(StringRef, if (getParser().ParseAbsoluteExpression(Offset)) return true; - return getStreamer().EmitCFIDefCfaOffset(Offset); + getStreamer().EmitCFIDefCfaOffset(Offset); + return false; +} + +/// ParseDirectiveCFIAdjustCfaOffset +/// ::= .cfi_adjust_cfa_offset adjustment +bool GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset(StringRef, + SMLoc DirectiveLoc) { + int64_t Adjustment = 0; + if (getParser().ParseAbsoluteExpression(Adjustment)) + return true; + + getStreamer().EmitCFIAdjustCfaOffset(Adjustment); + return false; } /// ParseDirectiveCFIDefCfaRegister @@ -2320,11 +2469,12 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfaRegister(StringRef, if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; - return getStreamer().EmitCFIDefCfaRegister(Register); + getStreamer().EmitCFIDefCfaRegister(Register); + return false; } /// ParseDirectiveCFIOffset -/// ::= .cfi_off register, offset +/// ::= .cfi_offset register, offset bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { int64_t Register = 0; int64_t Offset = 0; @@ -2339,7 +2489,29 @@ bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { if (getParser().ParseAbsoluteExpression(Offset)) return true; - return getStreamer().EmitCFIOffset(Register, Offset); + getStreamer().EmitCFIOffset(Register, Offset); + return false; +} + +/// ParseDirectiveCFIRelOffset +/// ::= .cfi_rel_offset register, offset +bool GenericAsmParser::ParseDirectiveCFIRelOffset(StringRef, + SMLoc DirectiveLoc) { + int64_t Register = 0; + + if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Offset = 0; + if (getParser().ParseAbsoluteExpression(Offset)) + return true; + + getStreamer().EmitCFIRelOffset(Register, Offset); + return false; } static bool isValidEncoding(int64_t Encoding) { @@ -2389,25 +2561,42 @@ bool GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda(StringRef IDVal, MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); if (IDVal == ".cfi_personality") - return getStreamer().EmitCFIPersonality(Sym, Encoding); + getStreamer().EmitCFIPersonality(Sym, Encoding); else { assert(IDVal == ".cfi_lsda"); - return getStreamer().EmitCFILsda(Sym, Encoding); + getStreamer().EmitCFILsda(Sym, Encoding); } + return false; } /// ParseDirectiveCFIRememberState /// ::= .cfi_remember_state bool GenericAsmParser::ParseDirectiveCFIRememberState(StringRef IDVal, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIRememberState(); + getStreamer().EmitCFIRememberState(); + return false; } /// ParseDirectiveCFIRestoreState /// ::= .cfi_remember_state bool GenericAsmParser::ParseDirectiveCFIRestoreState(StringRef IDVal, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIRestoreState(); + getStreamer().EmitCFIRestoreState(); + return false; +} + +/// ParseDirectiveCFISameValue +/// ::= .cfi_same_value register +bool GenericAsmParser::ParseDirectiveCFISameValue(StringRef IDVal, + SMLoc DirectiveLoc) { + int64_t Register = 0; + + if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + return true; + + getStreamer().EmitCFISameValue(Register); + + return false; } /// ParseDirectiveMacrosOnOff @@ -2425,13 +2614,27 @@ bool GenericAsmParser::ParseDirectiveMacrosOnOff(StringRef Directive, } /// ParseDirectiveMacro -/// ::= .macro name +/// ::= .macro name [parameters] bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive, SMLoc DirectiveLoc) { StringRef Name; if (getParser().ParseIdentifier(Name)) return TokError("expected identifier in directive"); + std::vector<StringRef> Parameters; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for(;;) { + StringRef Parameter; + if (getParser().ParseIdentifier(Parameter)) + return TokError("expected identifier in directive"); + Parameters.push_back(Parameter); + + if (getLexer().isNot(AsmToken::Comma)) + break; + Lex(); + } + } + if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.macro' directive"); @@ -2469,7 +2672,7 @@ bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive, const char *BodyStart = StartToken.getLoc().getPointer(); const char *BodyEnd = EndToken.getLoc().getPointer(); StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); - getParser().MacroMap[Name] = new Macro(Name, Body); + getParser().MacroMap[Name] = new Macro(Name, Body, Parameters); return false; } |