diff options
author | Bill Wendling <isanbard@gmail.com> | 2013-11-27 06:44:18 +0000 |
---|---|---|
committer | Bill Wendling <isanbard@gmail.com> | 2013-11-27 06:44:18 +0000 |
commit | 0ae07098f7d2ad5a1868d448d0b1b4eef2a3b091 (patch) | |
tree | e8e00fbae3c35abdbcfe8f7aacd1df44a0fe00b7 /lib/MC | |
parent | b1df5b013a38ab7381630af8b3142c56f604d85b (diff) | |
download | external_llvm-0ae07098f7d2ad5a1868d448d0b1b4eef2a3b091.zip external_llvm-0ae07098f7d2ad5a1868d448d0b1b4eef2a3b091.tar.gz external_llvm-0ae07098f7d2ad5a1868d448d0b1b4eef2a3b091.tar.bz2 |
Merging r195148:
------------------------------------------------------------------------
r195148 | rafael | 2013-11-19 11:52:52 -0800 (Tue, 19 Nov 2013) | 15 lines
Support multiple COFF sections with the same name but different COMDAT.
This is the first step to fix pr17918.
It extends the .section directive a bit, inspired by what the ELF one looks
like. The problem with using linkonce is that given
.section foo
.linkonce....
.section foo
.linkonce
we would already have switched sections when getting to .linkonce. The cleanest
solution seems to be to add the comdat information in the .section itself.
------------------------------------------------------------------------
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_34@195822 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC')
-rw-r--r-- | lib/MC/MCContext.cpp | 44 | ||||
-rw-r--r-- | lib/MC/MCParser/COFFAsmParser.cpp | 106 | ||||
-rw-r--r-- | lib/MC/WinCOFFStreamer.cpp | 3 |
3 files changed, 109 insertions, 44 deletions
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index 67904f6..3b45d16 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -34,8 +34,7 @@ typedef std::pair<std::string, std::string> SectionGroupPair; typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy; typedef std::map<SectionGroupPair, const MCSectionELF *> ELFUniqueMapTy; -typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy; - +typedef std::map<SectionGroupPair, const MCSectionCOFF *> COFFUniqueMapTy; MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri, const MCObjectFileInfo *mofi, const SourceMgr *mgr, @@ -280,32 +279,51 @@ const MCSectionELF *MCContext::CreateELFGroupSection() { return Result; } -const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, - unsigned Characteristics, - SectionKind Kind, int Selection, - const MCSectionCOFF *Assoc) { +const MCSectionCOFF * +MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind, StringRef COMDATSymName, + int Selection, const MCSectionCOFF *Assoc) { if (COFFUniquingMap == 0) COFFUniquingMap = new COFFUniqueMapTy(); COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap; // Do the lookup, if we have a hit, return it. - StringMapEntry<const MCSectionCOFF*> &Entry = Map.GetOrCreateValue(Section); - if (Entry.getValue()) return Entry.getValue(); - MCSectionCOFF *Result = new (*this) MCSectionCOFF(Entry.getKey(), - Characteristics, - Selection, Assoc, Kind); + SectionGroupPair P(Section, COMDATSymName); + std::pair<COFFUniqueMapTy::iterator, bool> Entry = + Map.insert(std::make_pair(P, (MCSectionCOFF *)0)); + COFFUniqueMapTy::iterator Iter = Entry.first; + if (!Entry.second) + return Iter->second; + + const MCSymbol *COMDATSymbol = NULL; + if (!COMDATSymName.empty()) + COMDATSymbol = GetOrCreateSymbol(COMDATSymName); + + MCSectionCOFF *Result = + new (*this) MCSectionCOFF(Iter->first.first, Characteristics, + COMDATSymbol, Selection, Assoc, Kind); - Entry.setValue(Result); + Iter->second = Result; return Result; } +const MCSectionCOFF * +MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind) { + return getCOFFSection(Section, Characteristics, Kind, "", 0); +} + const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) { if (COFFUniquingMap == 0) COFFUniquingMap = new COFFUniqueMapTy(); COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap; - return Map.lookup(Section); + SectionGroupPair P(Section, ""); + COFFUniqueMapTy::iterator Iter = Map.find(P); + if (Iter == Map.end()) + return 0; + return Iter->second; } //===----------------------------------------------------------------------===// 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"); diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index 6744df5..7fc114c 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -151,7 +151,8 @@ void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, int Selection = COFF::IMAGE_COMDAT_SELECT_LARGEST; const MCSection *Section = MCStreamer::getContext().getCOFFSection( - SectionName, Characteristics, SectionKind::getBSS(), Selection); + SectionName, Characteristics, SectionKind::getBSS(), Symbol->getName(), + Selection); MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section); |