Index: llvm/include/llvm/MC/MCContext.h =================================================================== --- llvm/include/llvm/MC/MCContext.h +++ llvm/include/llvm/MC/MCContext.h @@ -310,7 +310,7 @@ MCSectionELF *createELFSectionImpl(StringRef Section, unsigned Type, unsigned Flags, SectionKind K, unsigned EntrySize, - const MCSymbolELF *Group, + const MCSymbolELF *Group, bool IsComdat, unsigned UniqueID, const MCSymbolELF *LinkedToSym); @@ -487,19 +487,21 @@ MCSectionELF *getELFSection(const Twine &Section, unsigned Type, unsigned Flags, unsigned EntrySize, - const Twine &Group) { - return getELFSection(Section, Type, Flags, EntrySize, Group, + const Twine &Group, bool IsComdat = true) { + return getELFSection(Section, Type, Flags, EntrySize, Group, IsComdat, MCSection::NonUniqueID, nullptr); } MCSectionELF *getELFSection(const Twine &Section, unsigned Type, unsigned Flags, unsigned EntrySize, - const Twine &Group, unsigned UniqueID, + const Twine &Group, bool IsComdat, + unsigned UniqueID, const MCSymbolELF *LinkedToSym); MCSectionELF *getELFSection(const Twine &Section, unsigned Type, unsigned Flags, unsigned EntrySize, - const MCSymbolELF *Group, unsigned UniqueID, + const MCSymbolELF *Group, bool IsComdat, + unsigned UniqueID, const MCSymbolELF *LinkedToSym); /// Get a section with the provided group identifier. This section is @@ -517,7 +519,8 @@ void renameELFSection(MCSectionELF *Section, StringRef Name); - MCSectionELF *createELFGroupSection(const MCSymbolELF *Group); + MCSectionELF *createELFGroupSection(const MCSymbolELF *Group, + bool IsComdat); void recordELFMergeableSectionInfo(StringRef SectionName, unsigned Flags, unsigned UniqueID, unsigned EntrySize); Index: llvm/include/llvm/MC/MCSectionELF.h =================================================================== --- llvm/include/llvm/MC/MCSectionELF.h +++ llvm/include/llvm/MC/MCSectionELF.h @@ -13,6 +13,7 @@ #ifndef LLVM_MC_MCSECTIONELF_H #define LLVM_MC_MCSECTIONELF_H +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbolELF.h" @@ -38,7 +39,7 @@ /// fixed-sized entries 'EntrySize' will be 0. unsigned EntrySize; - const MCSymbolELF *Group; + const PointerIntPair Group; /// Used by SHF_LINK_ORDER. If non-null, the sh_link field will be set to the /// section header index of the section where LinkedToSym is defined. @@ -49,13 +50,14 @@ // The storage of Name is owned by MCContext's ELFUniquingMap. MCSectionELF(StringRef Name, unsigned type, unsigned flags, SectionKind K, - unsigned entrySize, const MCSymbolELF *group, unsigned UniqueID, - MCSymbol *Begin, const MCSymbolELF *LinkedToSym) + unsigned entrySize, const MCSymbolELF *group, bool IsComdat, + unsigned UniqueID, MCSymbol *Begin, + const MCSymbolELF *LinkedToSym) : MCSection(SV_ELF, Name, K, Begin), Type(type), Flags(flags), - UniqueID(UniqueID), EntrySize(entrySize), Group(group), + UniqueID(UniqueID), EntrySize(entrySize), Group(group, IsComdat), LinkedToSym(LinkedToSym) { - if (Group) - Group->setIsSignature(); + if (Group.getPointer()) + Group.getPointer()->setIsSignature(); } // TODO Delete after we stop supporting generation of GNU-style .zdebug_* @@ -71,7 +73,8 @@ unsigned getFlags() const { return Flags; } unsigned getEntrySize() const { return EntrySize; } void setFlags(unsigned F) { Flags = F; } - const MCSymbolELF *getGroup() const { return Group; } + const MCSymbolELF *getGroup() const { return Group.getPointer(); } + bool isComdat() const { return Group.getInt(); } void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, raw_ostream &OS, Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1827,7 +1827,7 @@ OutStreamer->SwitchSection( OutContext.getELFSection(".llvm_sympart", ELF::SHT_LLVM_SYMPART, 0, 0, - "", ++UniqueID, nullptr)); + "", false, ++UniqueID, nullptr)); OutStreamer->emitBytes(GV.getPartition()); OutStreamer->emitZeros(1); OutStreamer->emitValue( @@ -3374,13 +3374,13 @@ GroupName = F.getComdat()->getName(); } InstMap = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS, - Flags, 0, GroupName, + Flags, 0, GroupName, F.hasComdat(), MCSection::NonUniqueID, LinkedToSym); if (!TM.Options.XRayOmitFunctionIndex) FnSledIndex = OutContext.getELFSection( "xray_fn_idx", ELF::SHT_PROGBITS, Flags | ELF::SHF_WRITE, 0, - GroupName, MCSection::NonUniqueID, LinkedToSym); + GroupName, F.hasComdat(), MCSection::NonUniqueID, LinkedToSym); } else if (MF->getSubtarget().getTargetTriple().isOSBinFormatMachO()) { InstMap = OutContext.getMachOSection("__DATA", "xray_instr_map", 0, SectionKind::getReadOnlyWithRel()); @@ -3476,7 +3476,7 @@ } OutStreamer->SwitchSection(OutContext.getELFSection( "__patchable_function_entries", ELF::SHT_PROGBITS, Flags, 0, GroupName, - MCSection::NonUniqueID, LinkedToSym)); + F.hasComdat(), MCSection::NonUniqueID, LinkedToSym)); emitAlignment(Align(PointerSize)); OutStreamer->emitSymbolValue(CurrentPatchableFunctionEntrySym, PointerSize); } Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -522,9 +522,11 @@ if (!C) return nullptr; - if (C->getSelectionKind() != Comdat::Any) - report_fatal_error("ELF COMDATs only support SelectionKind::Any, '" + - C->getName() + "' cannot be lowered."); + if (C->getSelectionKind() != Comdat::Any && + C->getSelectionKind() != Comdat::NoDuplicates) + report_fatal_error("ELF COMDATs only support SelectionKind::Any and " + "SelectionKind::NoDuplicates, '" + C->getName() + + "' cannot be lowered."); return C; } @@ -669,9 +671,11 @@ Kind = getELFKindForNamedSection(SectionName, Kind); StringRef Group = ""; + bool IsComdat = false; unsigned Flags = getELFSectionFlags(Kind); if (const Comdat *C = getELFComdat(GO)) { Group = C->getName(); + IsComdat = C->getSelectionKind() == Comdat::Any; Flags |= ELF::SHF_GROUP; } @@ -730,8 +734,8 @@ } MCSectionELF *Section = getContext().getELFSection( - SectionName, getELFSectionType(SectionName, Kind), Flags, - EntrySize, Group, UniqueID, LinkedToSym); + SectionName, getELFSectionType(SectionName, Kind), Flags, EntrySize, + Group, IsComdat, UniqueID, LinkedToSym); // Make sure that we did not get some other section with incompatible sh_link. // This should not be possible due to UniqueID code above. assert(Section->getLinkedToSymbol() == LinkedToSym && @@ -763,9 +767,11 @@ unsigned *NextUniqueID, const MCSymbolELF *AssociatedSymbol) { StringRef Group = ""; + bool IsComdat = false; if (const Comdat *C = getELFComdat(GO)) { Flags |= ELF::SHF_GROUP; Group = C->getName(); + IsComdat = C->getSelectionKind() == Comdat::Any; } // Get the section entry size based on the kind. @@ -788,7 +794,8 @@ if (Kind.isExecuteOnly()) UniqueID = 0; return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), Flags, - EntrySize, Group, UniqueID, AssociatedSymbol); + EntrySize, Group, IsComdat, UniqueID, + AssociatedSymbol); } MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal( @@ -843,11 +850,13 @@ const auto *LSDA = cast(LSDASection); unsigned Flags = LSDA->getFlags(); - StringRef Group; const MCSymbolELF *LinkedToSym = nullptr; - if (F.hasComdat()) { - Group = F.getComdat()->getName(); + StringRef Group = ""; + bool IsComdat = false; + if (const Comdat *C = getELFComdat(&F)) { Flags |= ELF::SHF_GROUP; + Group = C->getName(); + IsComdat = C->getSelectionKind() == Comdat::Any; } // Use SHF_LINK_ORDER to facilitate --gc-sections if we can use GNU ld>=2.36 // or LLD, which support mixed SHF_LINK_ORDER & non-SHF_LINK_ORDER. @@ -863,7 +872,8 @@ return getContext().getELFSection( (TM.getUniqueSectionNames() ? LSDA->getName() + "." + F.getName() : LSDA->getName()), - LSDA->getType(), Flags, 0, Group, MCSection::NonUniqueID, LinkedToSym); + LSDA->getType(), Flags, 0, Group, F.hasComdat(), MCSection::NonUniqueID, + LinkedToSym); } bool TargetLoweringObjectFileELF::shouldPutJumpTableInFunctionSection( @@ -929,8 +939,8 @@ GroupName = F.getComdat()->getName().str(); } return getContext().getELFSection(Name, ELF::SHT_PROGBITS, Flags, - 0 /* Entry Size */, GroupName, UniqueID, - nullptr); + 0 /* Entry Size */, GroupName, + F.hasComdat(), UniqueID, nullptr); } static MCSectionELF *getStaticStructorSection(MCContext &Ctx, bool UseInitArray, Index: llvm/lib/MC/ELFObjectWriter.cpp =================================================================== --- llvm/lib/MC/ELFObjectWriter.cpp +++ llvm/lib/MC/ELFObjectWriter.cpp @@ -1125,7 +1125,8 @@ Asm.registerSymbol(*SignatureSymbol); unsigned &GroupIdx = RevGroupMap[SignatureSymbol]; if (!GroupIdx) { - MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol); + MCSectionELF *Group = + Ctx.createELFGroupSection(SignatureSymbol, Section.isComdat()); GroupIdx = addToSectionTable(Group); Group->setAlignment(Align(4)); Groups.push_back(Group); @@ -1162,7 +1163,7 @@ const MCSymbol *SignatureSymbol = Group->getGroup(); assert(SignatureSymbol); - write(uint32_t(ELF::GRP_COMDAT)); + write(uint32_t(Group->isComdat() ? ELF::GRP_COMDAT : 0)); for (const MCSectionELF *Member : GroupMembers[SignatureSymbol]) { uint32_t SecIndex = SectionIndexMap.lookup(Member); write(SecIndex); Index: llvm/lib/MC/MCContext.cpp =================================================================== --- llvm/lib/MC/MCContext.cpp +++ llvm/lib/MC/MCContext.cpp @@ -419,7 +419,7 @@ unsigned Flags, SectionKind K, unsigned EntrySize, const MCSymbolELF *Group, - unsigned UniqueID, + bool Comdat, unsigned UniqueID, const MCSymbolELF *LinkedToSym) { MCSymbolELF *R; MCSymbol *&Sym = Symbols[Section]; @@ -439,8 +439,9 @@ R->setBinding(ELF::STB_LOCAL); R->setType(ELF::STT_SECTION); - auto *Ret = new (ELFAllocator.Allocate()) MCSectionELF( - Section, Type, Flags, K, EntrySize, Group, UniqueID, R, LinkedToSym); + auto *Ret = new (ELFAllocator.Allocate()) + MCSectionELF(Section, Type, Flags, K, EntrySize, Group, Comdat, UniqueID, + R, LinkedToSym); auto *F = new MCDataFragment(); Ret->getFragmentList().insert(Ret->begin(), F); @@ -461,7 +462,7 @@ return createELFSectionImpl( I->getKey(), Type, Flags, SectionKind::getReadOnly(), EntrySize, Group, - true, cast(RelInfoSection->getBeginSymbol())); + true, true, cast(RelInfoSection->getBeginSymbol())); } MCSectionELF *MCContext::getELFNamedSection(const Twine &Prefix, @@ -473,20 +474,21 @@ MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, unsigned Flags, unsigned EntrySize, - const Twine &Group, unsigned UniqueID, + const Twine &Group, bool IsComdat, + unsigned UniqueID, const MCSymbolELF *LinkedToSym) { MCSymbolELF *GroupSym = nullptr; if (!Group.isTriviallyEmpty() && !Group.str().empty()) GroupSym = cast(getOrCreateSymbol(Group)); - return getELFSection(Section, Type, Flags, EntrySize, GroupSym, UniqueID, - LinkedToSym); + return getELFSection(Section, Type, Flags, EntrySize, GroupSym, IsComdat, + UniqueID, LinkedToSym); } MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, unsigned Flags, unsigned EntrySize, const MCSymbolELF *GroupSym, - unsigned UniqueID, + bool IsComdat, unsigned UniqueID, const MCSymbolELF *LinkedToSym) { StringRef Group = ""; if (GroupSym) @@ -513,7 +515,7 @@ MCSectionELF *Result = createELFSectionImpl(CachedName, Type, Flags, Kind, EntrySize, GroupSym, - UniqueID, LinkedToSym); + IsComdat, UniqueID, LinkedToSym); Entry.second = Result; recordELFMergeableSectionInfo(Result->getName(), Result->getFlags(), @@ -522,9 +524,10 @@ return Result; } -MCSectionELF *MCContext::createELFGroupSection(const MCSymbolELF *Group) { +MCSectionELF *MCContext::createELFGroupSection(const MCSymbolELF *Group, + bool IsComdat) { return createELFSectionImpl(".group", ELF::SHT_GROUP, 0, - SectionKind::getReadOnly(), 4, Group, + SectionKind::getReadOnly(), 4, Group, IsComdat, MCSection::NonUniqueID, nullptr); } Index: llvm/lib/MC/MCObjectFileInfo.cpp =================================================================== --- llvm/lib/MC/MCObjectFileInfo.cpp +++ llvm/lib/MC/MCObjectFileInfo.cpp @@ -1006,7 +1006,7 @@ } return Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, Flags, 0, - GroupName, ElfSec.getUniqueID(), + GroupName, true, ElfSec.getUniqueID(), cast(TextSec.getBeginSymbol())); } @@ -1026,7 +1026,7 @@ // Use the text section's begin symbol and unique ID to create a separate // .llvm_bb_addr_map section associated with every unique text section. return Ctx->getELFSection(".llvm_bb_addr_map", ELF::SHT_LLVM_BB_ADDR_MAP, - Flags, 0, GroupName, ElfSec.getUniqueID(), + Flags, 0, GroupName, true, ElfSec.getUniqueID(), cast(TextSec.getBeginSymbol())); } Index: llvm/lib/MC/MCParser/ELFAsmParser.cpp =================================================================== --- llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -157,7 +157,7 @@ unsigned parseSunStyleSectionFlags(); bool maybeParseSectionType(StringRef &TypeName); bool parseMergeSize(int64_t &Size); - bool parseGroup(StringRef &GroupName); + bool parseGroup(StringRef &GroupName, bool &IsComdat); bool parseLinkedToSym(MCSymbolELF *&LinkedToSym); bool maybeParseUniqueID(int64_t &UniqueID); }; @@ -424,7 +424,7 @@ return false; } -bool ELFAsmParser::parseGroup(StringRef &GroupName) { +bool ELFAsmParser::parseGroup(StringRef &GroupName, bool &IsComdat) { MCAsmLexer &L = getLexer(); if (L.isNot(AsmToken::Comma)) return TokError("expected group name"); @@ -442,6 +442,7 @@ return TokError("invalid linkage"); if (Linkage != "comdat") return TokError("Linkage must be 'comdat'"); + IsComdat = true; } return false; } @@ -502,6 +503,7 @@ StringRef TypeName; int64_t Size = 0; StringRef GroupName; + bool IsComdat = false; unsigned Flags = 0; unsigned extraFlags = 0; const MCExpr *Subsection = nullptr; @@ -574,7 +576,7 @@ if (parseMergeSize(Size)) return true; if (Group) - if (parseGroup(GroupName)) + if (parseGroup(GroupName, IsComdat)) return true; if (Flags & ELF::SHF_LINK_ORDER) if (parseLinkedToSym(LinkedToSym)) @@ -640,12 +642,14 @@ cast_or_null(CurrentSection.first)) if (const MCSymbol *Group = Section->getGroup()) { GroupName = Group->getName(); + IsComdat = Section->isComdat(); Flags |= ELF::SHF_GROUP; } } - MCSectionELF *Section = getContext().getELFSection( - SectionName, Type, Flags, Size, GroupName, UniqueID, LinkedToSym); + MCSectionELF *Section = + getContext().getELFSection(SectionName, Type, Flags, Size, GroupName, + IsComdat, UniqueID, LinkedToSym); getStreamer().SwitchSection(Section, Subsection); // x86-64 psABI names SHT_X86_64_UNWIND as the canonical type for .eh_frame, // but GNU as emits SHT_PROGBITS .eh_frame for .cfi_* directives. Don't error Index: llvm/lib/MC/MCSectionELF.cpp =================================================================== --- llvm/lib/MC/MCSectionELF.cpp +++ llvm/lib/MC/MCSectionELF.cpp @@ -171,8 +171,9 @@ if (Flags & ELF::SHF_GROUP) { OS << ","; - printName(OS, Group->getName()); - OS << ",comdat"; + printName(OS, Group.getPointer()->getName()); + if (isComdat()) + OS << ",comdat"; } if (Flags & ELF::SHF_LINK_ORDER) { Index: llvm/lib/Target/ARM/ARMTargetObjectFile.cpp =================================================================== --- llvm/lib/Target/ARM/ARMTargetObjectFile.cpp +++ llvm/lib/Target/ARM/ARMTargetObjectFile.cpp @@ -49,7 +49,8 @@ // Since we cannot modify flags for an existing section, we create a new // section with the right flags, and use 0 as the unique ID for // execute-only text - TextSection = Ctx.getELFSection(".text", Type, Flags, 0, "", 0U, nullptr); + TextSection = + Ctx.getELFSection(".text", Type, Flags, 0, "", false, 0U, nullptr); } } Index: llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp =================================================================== --- llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -1203,7 +1203,7 @@ if (Group) Flags |= ELF::SHF_GROUP; MCSectionELF *EHSection = getContext().getELFSection( - EHSecName, Type, Flags, 0, Group, FnSection.getUniqueID(), + EHSecName, Type, Flags, 0, Group, false, FnSection.getUniqueID(), static_cast(FnSection.getBeginSymbol())); assert(EHSection && "Failed to get the required EH section"); Index: llvm/test/CodeGen/X86/group.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/group.ll @@ -0,0 +1,17 @@ +; RUN: llc < %s -mtriple=x86_64-unknown-linux | FileCheck %s + +; CHECK: .section .text.f1,"axG",@progbits,f1 +; CHECK: .section .text.f2,"axG",@progbits,f1 +; CHECK: .section .bss.g1,"aGw",@nobits,f1 + +$f1 = comdat noduplicates + +define void @f1() comdat { + unreachable +} + +define hidden void @f2() comdat($f1) { + unreachable +} + +@g1 = global i32 0, comdat($f1)