diff options
Diffstat (limited to 'lib/MC/MCParser/COFFAsmParser.cpp')
-rw-r--r-- | lib/MC/MCParser/COFFAsmParser.cpp | 106 |
1 files changed, 76 insertions, 30 deletions
diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index df1794c..d8343a3 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -35,6 +35,10 @@ class COFFAsmParser : public MCAsmParserExtension { unsigned Characteristics, SectionKind Kind); + bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, + SectionKind Kind, StringRef COMDATSymName, + COFF::COMDATType Type, const MCSectionCOFF *Assoc); + bool ParseSectionName(StringRef &SectionName); bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags); @@ -111,6 +115,8 @@ class COFFAsmParser : public MCAsmParserExtension { bool ParseDirectiveType(StringRef, SMLoc); bool ParseDirectiveEndef(StringRef, SMLoc); bool ParseDirectiveSecRel32(StringRef, SMLoc); + bool parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, + const MCSectionCOFF *&Assoc); bool ParseDirectiveLinkOnce(StringRef, SMLoc); // Win64 EH directives. @@ -284,12 +290,22 @@ bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { bool COFFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Characteristics, SectionKind Kind) { + return ParseSectionSwitch(Section, Characteristics, Kind, "", + COFF::IMAGE_COMDAT_SELECT_ANY, 0); +} + +bool COFFAsmParser::ParseSectionSwitch(StringRef Section, + unsigned Characteristics, + SectionKind Kind, + StringRef COMDATSymName, + COFF::COMDATType Type, + const MCSectionCOFF *Assoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in section switching directive"); Lex(); getStreamer().SwitchSection(getContext().getCOFFSection( - Section, Characteristics, Kind)); + Section, Characteristics, Kind, COMDATSymName, Type, Assoc)); return false; } @@ -303,7 +319,7 @@ bool COFFAsmParser::ParseSectionName(StringRef &SectionName) { return false; } -// .section name [, "flags"] +// .section name [, "flags"] [, identifier [ identifier ], identifier] // // Supported flags: // a: Ignored. @@ -340,11 +356,30 @@ bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { return true; } + COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; + const MCSectionCOFF *Assoc = 0; + StringRef COMDATSymName; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + + Flags |= COFF::IMAGE_SCN_LNK_COMDAT; + + if (parseCOMDATTypeAndAssoc(Type, Assoc)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected comma in directive"); + Lex(); + + if (getParser().parseIdentifier(COMDATSymName)) + return TokError("expected identifier in directive"); + } + if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); SectionKind Kind = computeSectionKind(Flags); - ParseSectionSwitch(SectionName, Flags, Kind); + ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type, Assoc); return false; } @@ -409,37 +444,29 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { return false; } -/// ParseDirectiveLinkOnce -/// ::= .linkonce [ identifier [ identifier ] ] -bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { - COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; - - if (getLexer().is(AsmToken::Identifier)) { - StringRef TypeId = getTok().getIdentifier(); +/// ::= [ identifier [ identifier ] ] +bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, + const MCSectionCOFF *&Assoc) { + StringRef TypeId = getTok().getIdentifier(); - Type = StringSwitch<COFF::COMDATType>(TypeId) - .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) - .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY) - .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE) - .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH) - .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) - .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST) - .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST) - .Default((COFF::COMDATType)0); + Type = StringSwitch<COFF::COMDATType>(TypeId) + .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) + .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY) + .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE) + .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH) + .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) + .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST) + .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST) + .Default((COFF::COMDATType)0); - if (Type == 0) - return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'")); + if (Type == 0) + return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'")); - Lex(); - } - - const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>( - getStreamer().getCurrentSection().first); + Lex(); - const MCSectionCOFF *Assoc = 0; if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { - StringRef AssocName; SMLoc Loc = getTok().getLoc(); + StringRef AssocName; if (ParseSectionName(AssocName)) return TokError("expected associated section name"); @@ -447,14 +474,33 @@ bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { getContext().getCOFFSection(AssocName)); if (!Assoc) return Error(Loc, "cannot associate unknown section '" + AssocName + "'"); - if (Assoc == Current) - return Error(Loc, "cannot associate a section with itself"); if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)) return Error(Loc, "associated section must be a COMDAT section"); if (Assoc->getSelection() == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) return Error(Loc, "associated section cannot be itself associative"); } + return false; +} + +/// ParseDirectiveLinkOnce +/// ::= .linkonce [ identifier [ identifier ] ] +bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { + COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; + const MCSectionCOFF *Assoc = 0; + if (getLexer().is(AsmToken::Identifier)) + if (parseCOMDATTypeAndAssoc(Type, Assoc)) + return true; + + const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>( + getStreamer().getCurrentSection().first); + + + if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { + if (Assoc == Current) + return Error(Loc, "cannot associate a section with itself"); + } + if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) return Error(Loc, Twine("section '") + Current->getSectionName() + "' is already linkonce"); |