diff options
Diffstat (limited to 'contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp')
-rw-r--r-- | contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp | 121 |
1 files changed, 73 insertions, 48 deletions
diff --git a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp index 3134fc3..8807975 100644 --- a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -16,6 +16,7 @@ #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/ELF.h" using namespace llvm; @@ -30,14 +31,11 @@ class ELFAsmParser : public MCAsmParserExtension { getParser().addDirectiveHandler(Directive, Handler); } - bool ParseSectionSwitch(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind); - bool SeenIdent; + bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind); public: - ELFAsmParser() : SeenIdent(false) { - BracketExpressionsSupported = true; - } + ELFAsmParser() { BracketExpressionsSupported = true; } virtual void Initialize(MCAsmParser &Parser) { // Call the base implementation. @@ -241,7 +239,6 @@ bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { } for (;;) { - StringRef Tmp; unsigned CurSize; SMLoc PrevLoc = getLexer().getLoc(); @@ -279,14 +276,17 @@ static SectionKind computeSectionKind(unsigned Flags) { return SectionKind::getDataRel(); } -static int parseSectionFlags(StringRef flagsStr) { - int flags = 0; +static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) { + unsigned flags = 0; for (unsigned i = 0; i < flagsStr.size(); i++) { switch (flagsStr[i]) { case 'a': flags |= ELF::SHF_ALLOC; break; + case 'e': + flags |= ELF::SHF_EXCLUDE; + break; case 'x': flags |= ELF::SHF_EXECINSTR; break; @@ -311,8 +311,11 @@ static int parseSectionFlags(StringRef flagsStr) { case 'G': flags |= ELF::SHF_GROUP; break; + case '?': + *UseLastGroup = true; + break; default: - return -1; + return -1U; } } @@ -352,6 +355,7 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush) { StringRef GroupName; unsigned Flags = 0; const MCExpr *Subsection = 0; + bool UseLastGroup = false; // Set the defaults first. if (SectionName == ".fini" || SectionName == ".init" || @@ -377,13 +381,16 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush) { StringRef FlagsStr = getTok().getStringContents(); Lex(); - int extraFlags = parseSectionFlags(FlagsStr); - if (extraFlags < 0) + unsigned extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup); + if (extraFlags == -1U) return TokError("unknown flag"); Flags |= extraFlags; bool Mergeable = Flags & ELF::SHF_MERGE; bool Group = Flags & ELF::SHF_GROUP; + if (Group && UseLastGroup) + return TokError("Section cannot specifiy a group name while also acting " + "as a member of the last group"); if (getLexer().isNot(AsmToken::Comma)) { if (Mergeable) @@ -392,10 +399,13 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush) { return TokError("Group section must specify the type"); } else { Lex(); - if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At)) - return TokError("expected '@' or '%' before type"); + if (getLexer().is(AsmToken::At) || getLexer().is(AsmToken::Percent) || + getLexer().is(AsmToken::String)) { + if (!getLexer().is(AsmToken::String)) + Lex(); + } else + return TokError("expected '@<type>', '%<type>' or \"<type>\""); - Lex(); if (getParser().parseIdentifier(TypeName)) return TokError("expected identifier in directive"); @@ -461,6 +471,16 @@ EndStmt: return TokError("unknown section type"); } + if (UseLastGroup) { + MCSectionSubPair CurrentSection = getStreamer().getCurrentSection(); + if (const MCSectionELF *Section = + cast_or_null<MCSectionELF>(CurrentSection.first)) + if (const MCSymbol *Group = Section->getGroup()) { + GroupName = Group->getName(); + Flags |= ELF::SHF_GROUP; + } + } + SectionKind Kind = computeSectionKind(Flags); getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, Flags, Kind, Size, @@ -479,7 +499,11 @@ bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { } /// ParseDirectiveELFType +/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE> +/// ::= .type identifier , #attribute /// ::= .type identifier , @attribute +/// ::= .type identifier , %attribute +/// ::= .type identifier , "attribute" bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { StringRef Name; if (getParser().parseIdentifier(Name)) @@ -492,26 +516,42 @@ bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { return TokError("unexpected token in '.type' directive"); Lex(); - if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At)) - return TokError("expected '@' or '%' before type"); - Lex(); - StringRef Type; SMLoc TypeLoc; + MCSymbolAttr Attr; + if (getLexer().is(AsmToken::Identifier)) { + TypeLoc = getLexer().getLoc(); + if (getParser().parseIdentifier(Type)) + return TokError("expected symbol type in directive"); + Attr = StringSwitch<MCSymbolAttr>(Type) + .Case("STT_FUNC", MCSA_ELF_TypeFunction) + .Case("STT_OBJECT", MCSA_ELF_TypeObject) + .Case("STT_TLS", MCSA_ELF_TypeTLS) + .Case("STT_COMMON", MCSA_ELF_TypeCommon) + .Case("STT_NOTYPE", MCSA_ELF_TypeNoType) + .Case("STT_GNU_IFUNC", MCSA_ELF_TypeIndFunction) + .Default(MCSA_Invalid); + } else if (getLexer().is(AsmToken::Hash) || getLexer().is(AsmToken::At) || + getLexer().is(AsmToken::Percent) || + getLexer().is(AsmToken::String)) { + if (!getLexer().is(AsmToken::String)) + Lex(); - TypeLoc = getLexer().getLoc(); - if (getParser().parseIdentifier(Type)) - return TokError("expected symbol type in directive"); - - MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Type) - .Case("function", MCSA_ELF_TypeFunction) - .Case("object", MCSA_ELF_TypeObject) - .Case("tls_object", MCSA_ELF_TypeTLS) - .Case("common", MCSA_ELF_TypeCommon) - .Case("notype", MCSA_ELF_TypeNoType) - .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) - .Case("gnu_indirect_function", MCSA_ELF_TypeIndFunction) - .Default(MCSA_Invalid); + TypeLoc = getLexer().getLoc(); + if (getParser().parseIdentifier(Type)) + return TokError("expected symbol type in directive"); + Attr = StringSwitch<MCSymbolAttr>(Type) + .Case("function", MCSA_ELF_TypeFunction) + .Case("object", MCSA_ELF_TypeObject) + .Case("tls_object", MCSA_ELF_TypeTLS) + .Case("common", MCSA_ELF_TypeCommon) + .Case("notype", MCSA_ELF_TypeNoType) + .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) + .Case("gnu_indirect_function", MCSA_ELF_TypeIndFunction) + .Default(MCSA_Invalid); + } else + return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', " + "'%<type>' or \"<type>\""); if (Attr == MCSA_Invalid) return Error(TypeLoc, "unsupported attribute in '.type' directive"); @@ -536,22 +576,7 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { Lex(); - const MCSection *Comment = - getContext().getELFSection(".comment", ELF::SHT_PROGBITS, - ELF::SHF_MERGE | - ELF::SHF_STRINGS, - SectionKind::getReadOnly(), - 1, ""); - - getStreamer().PushSection(); - getStreamer().SwitchSection(Comment); - if (!SeenIdent) { - getStreamer().EmitIntValue(0, 1); - SeenIdent = true; - } - getStreamer().EmitBytes(Data); - getStreamer().EmitIntValue(0, 1); - getStreamer().PopSection(); + getStreamer().EmitIdent(Data); return false; } |