From dd1ef1f3418982af265c4cb897c1156c7e4110a2 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 29 May 2019 03:29:01 +0000 Subject: [PATCH] Add IR support, ELF section and user documentation for partitioning feature. The partitioning feature was proposed here: http://lists.llvm.org/pipermail/llvm-dev/2019-February/130583.html This is mostly just documentation. The feature itself will be contributed in subsequent patches. Differential Revision: https://reviews.llvm.org/D60242 llvm-svn: 361923 --- docs/Extensions.rst | 16 +++++++++++++ include/llvm/BinaryFormat/ELF.h | 1 + include/llvm/IR/GlobalValue.h | 18 +++++++++++---- lib/AsmParser/LLLexer.cpp | 1 + lib/AsmParser/LLParser.cpp | 29 ++++++++++++++++++++++- lib/AsmParser/LLToken.h | 1 + lib/Bitcode/Reader/BitcodeReader.cpp | 20 +++++++++++++++- lib/Bitcode/Writer/BitcodeWriter.cpp | 11 ++++++++- lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 18 +++++++++++++++ lib/IR/AsmWriter.cpp | 17 ++++++++++++++ lib/IR/Globals.cpp | 23 +++++++++++++++++++ lib/IR/LLVMContextImpl.h | 3 +++ lib/MC/MCParser/ELFAsmParser.cpp | 2 ++ lib/MC/MCSectionELF.cpp | 2 ++ lib/Object/ELF.cpp | 1 + test/Bitcode/compatibility.ll | 18 +++++++++++++++ test/CodeGen/X86/partition.ll | 33 +++++++++++++++++++++++++++ test/MC/ELF/section.s | 12 ++++++++++ test/Object/X86/irsymtab.ll | 2 +- 19 files changed, 220 insertions(+), 8 deletions(-) create mode 100644 test/CodeGen/X86/partition.ll diff --git a/docs/Extensions.rst b/docs/Extensions.rst index 8543ac61185..e6f7fdd5044 100644 --- a/docs/Extensions.rst +++ b/docs/Extensions.rst @@ -379,6 +379,22 @@ this directive, all symbols are considered address-significant. This marks ``sym`` as address-significant. +``SHT_LLVM_SYMPART`` Section (symbol partition specification) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This section is used to mark symbols with the `partition`_ that they +belong to. An ``.llvm_sympart`` section consists of a null-terminated string +specifying the name of the partition followed by a relocation referring to +the symbol that belongs to the partition. It may be constructed as follows: + +.. code-block:: gas + + .section ".llvm_sympart","",@llvm_sympart + .asciz "libpartition.so" + .word symbol_in_partition + +.. _partition: https://lld.llvm.org/Partitions.html + CodeView-Dependent ------------------ diff --git a/include/llvm/BinaryFormat/ELF.h b/include/llvm/BinaryFormat/ELF.h index 6ec924d08d1..8258bb3711b 100644 --- a/include/llvm/BinaryFormat/ELF.h +++ b/include/llvm/BinaryFormat/ELF.h @@ -842,6 +842,7 @@ enum : unsigned { SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols // for safe ICF. SHT_LLVM_DEPENDENT_LIBRARIES = 0x6fff4c04, // LLVM Dependent Library Specifiers. + SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification. // Android's experimental support for SHT_RELR sections. // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512 SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets. diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index d78ce622bc5..2209881dbda 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -79,15 +79,15 @@ protected: ValueType(Ty), Visibility(DefaultVisibility), UnnamedAddrVal(unsigned(UnnamedAddr::None)), DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal), - HasLLVMReservedName(false), IsDSOLocal(false), IntID((Intrinsic::ID)0U), - Parent(nullptr) { + HasLLVMReservedName(false), IsDSOLocal(false), HasPartition(false), + IntID((Intrinsic::ID)0U), Parent(nullptr) { setLinkage(Linkage); setName(Name); } Type *ValueType; - static const unsigned GlobalValueSubClassDataBits = 17; + static const unsigned GlobalValueSubClassDataBits = 16; // All bitfields use unsigned as the underlying type so that MSVC will pack // them. @@ -108,9 +108,13 @@ protected: /// definition cannot be runtime preempted. unsigned IsDSOLocal : 1; + /// True if this symbol has a partition name assigned (see + /// https://lld.llvm.org/Partitions.html). + unsigned HasPartition : 1; + private: // Give subclasses access to what otherwise would be wasted padding. - // (17 + 4 + 2 + 2 + 2 + 3 + 1 + 1) == 32. + // (16 + 4 + 2 + 2 + 2 + 3 + 1 + 1 + 1) == 32. unsigned SubClassData : GlobalValueSubClassDataBits; friend class Constant; @@ -280,6 +284,12 @@ public: return IsDSOLocal; } + bool hasPartition() const { + return HasPartition; + } + StringRef getPartition() const; + void setPartition(StringRef Part); + static LinkageTypes getLinkOnceLinkage(bool ODR) { return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; } diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index c0b9cd12d0c..dc8ff7f1315 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -570,6 +570,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(align); KEYWORD(addrspace); KEYWORD(section); + KEYWORD(partition); KEYWORD(alias); KEYWORD(ifunc); KEYWORD(module); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 6af084edbd8..28a8480e7d3 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -856,11 +856,14 @@ static void maybeSetDSOLocal(bool DSOLocal, GlobalValue &GV) { /// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier /// OptionalVisibility OptionalDLLStorageClass /// OptionalThreadLocal OptionalUnnamedAddr -// 'alias|ifunc' IndirectSymbol +/// 'alias|ifunc' IndirectSymbol IndirectSymbolAttr* /// /// IndirectSymbol /// ::= TypeAndValue /// +/// IndirectSymbolAttr +/// ::= ',' 'partition' StringConstant +/// /// Everything through OptionalUnnamedAddr has already been parsed. /// bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc, @@ -960,6 +963,21 @@ bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc, GA->setUnnamedAddr(UnnamedAddr); maybeSetDSOLocal(DSOLocal, *GA); + // At this point we've parsed everything except for the IndirectSymbolAttrs. + // Now parse them if there are any. + while (Lex.getKind() == lltok::comma) { + Lex.Lex(); + + if (Lex.getKind() == lltok::kw_partition) { + Lex.Lex(); + GA->setPartition(Lex.getStrVal()); + if (ParseToken(lltok::StringConstant, "expected partition string")) + return true; + } else { + return TokError("unknown alias or ifunc property!"); + } + } + if (Name.empty()) NumberedVals.push_back(GA.get()); @@ -1095,6 +1113,11 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, GV->setSection(Lex.getStrVal()); if (ParseToken(lltok::StringConstant, "expected global section string")) return true; + } else if (Lex.getKind() == lltok::kw_partition) { + Lex.Lex(); + GV->setPartition(Lex.getStrVal()); + if (ParseToken(lltok::StringConstant, "expected partition string")) + return true; } else if (Lex.getKind() == lltok::kw_align) { unsigned Alignment; if (ParseOptionalAlignment(Alignment)) return true; @@ -5287,6 +5310,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { std::vector FwdRefAttrGrps; LocTy BuiltinLoc; std::string Section; + std::string Partition; unsigned Alignment; std::string GC; GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None; @@ -5303,6 +5327,8 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { BuiltinLoc) || (EatIfPresent(lltok::kw_section) && ParseStringConstant(Section)) || + (EatIfPresent(lltok::kw_partition) && + ParseStringConstant(Partition)) || parseOptionalComdat(FunctionName, C) || ParseOptionalAlignment(Alignment) || (EatIfPresent(lltok::kw_gc) && @@ -5404,6 +5430,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { Fn->setUnnamedAddr(UnnamedAddr); Fn->setAlignment(Alignment); Fn->setSection(Section); + Fn->setPartition(Partition); Fn->setComdat(C); Fn->setPersonalityFn(PersonalityFn); if (!GC.empty()) Fn->setGC(GC); diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 33ea28bb10e..a1e70932178 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -113,6 +113,7 @@ enum Kind { kw_align, kw_addrspace, kw_section, + kw_partition, kw_alias, kw_ifunc, kw_module, diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 412f99d5e62..b23115ba31d 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2892,7 +2892,8 @@ static void inferDSOLocal(GlobalValue *GV) { Error BitcodeReader::parseGlobalVarRecord(ArrayRef Record) { // v1: [pointer type, isconst, initid, linkage, alignment, section, // visibility, threadlocal, unnamed_addr, externally_initialized, - // dllstorageclass, comdat, attributes, preemption specifier] (name in VST) + // dllstorageclass, comdat, attributes, preemption specifier, + // partition strtab offset, partition strtab size] (name in VST) // v2: [strtab_offset, strtab_size, v1] StringRef Name; std::tie(Name, Record) = readNameFromStrtab(Record); @@ -2983,6 +2984,10 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef Record) { } inferDSOLocal(NewGV); + // Check whether we have enough values to read a partition name. + if (Record.size() > 15) + NewGV->setPartition(StringRef(Strtab.data() + Record[14], Record[15])); + return Error::success(); } @@ -3072,6 +3077,12 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef Record) { } inferDSOLocal(Func); + // Record[16] is the address space number. + + // Check whether we have enough values to read a partition name. + if (Record.size() > 18) + Func->setPartition(StringRef(Strtab.data() + Record[17], Record[18])); + ValueList.push_back(Func); // If this is a function with a body, remember the prototype we are @@ -3149,6 +3160,13 @@ Error BitcodeReader::parseGlobalIndirectSymbolRecord( NewGA->setDSOLocal(getDecodedDSOLocal(Record[OpNum++])); inferDSOLocal(NewGA); + // Check whether we have enough values to read a partition name. + if (OpNum + 1 < Record.size()) { + NewGA->setPartition( + StringRef(Strtab.data() + Record[OpNum], Record[OpNum + 1])); + OpNum += 2; + } + ValueList.push_back(NewGA); IndirectSymbolInits.push_back(std::make_pair(NewGA, Val)); return Error::success(); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 7d9b0583d1e..00d6fe8e27c 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1262,7 +1262,8 @@ void ModuleBitcodeWriter::writeModuleInfo() { GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass || GV.hasComdat() || GV.hasAttributes() || - GV.isDSOLocal()) { + GV.isDSOLocal() || + GV.hasPartition()) { Vals.push_back(getEncodedVisibility(GV)); Vals.push_back(getEncodedThreadLocalMode(GV)); Vals.push_back(getEncodedUnnamedAddr(GV)); @@ -1274,6 +1275,8 @@ void ModuleBitcodeWriter::writeModuleInfo() { Vals.push_back(VE.getAttributeListID(AL)); Vals.push_back(GV.isDSOLocal()); + Vals.push_back(addToStrtab(GV.getPartition())); + Vals.push_back(GV.getPartition().size()); } else { AbbrevToUse = SimpleGVarAbbrev; } @@ -1311,6 +1314,8 @@ void ModuleBitcodeWriter::writeModuleInfo() { Vals.push_back(F.isDSOLocal()); Vals.push_back(F.getAddressSpace()); + Vals.push_back(addToStrtab(F.getPartition())); + Vals.push_back(F.getPartition().size()); unsigned AbbrevToUse = 0; Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse); @@ -1333,6 +1338,8 @@ void ModuleBitcodeWriter::writeModuleInfo() { Vals.push_back(getEncodedThreadLocalMode(A)); Vals.push_back(getEncodedUnnamedAddr(A)); Vals.push_back(A.isDSOLocal()); + Vals.push_back(addToStrtab(A.getPartition())); + Vals.push_back(A.getPartition().size()); unsigned AbbrevToUse = 0; Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse); @@ -1351,6 +1358,8 @@ void ModuleBitcodeWriter::writeModuleInfo() { Vals.push_back(getEncodedLinkage(I)); Vals.push_back(getEncodedVisibility(I)); Vals.push_back(I.isDSOLocal()); + Vals.push_back(addToStrtab(I.getPartition())); + Vals.push_back(I.getPartition().size()); Stream.EmitRecord(bitc::MODULE_CODE_IFUNC, Vals); Vals.clear(); } diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index bf7776b1dc0..3317952d05d 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1632,6 +1632,24 @@ bool AsmPrinter::doFinalization(Module &M) { OutStreamer->EmitAddrsigSym(getSymbol(&GV)); } + // Emit symbol partition specifications (ELF only). + if (TM.getTargetTriple().isOSBinFormatELF()) { + unsigned UniqueID = 0; + for (const GlobalValue &GV : M.global_values()) { + if (!GV.hasPartition() || GV.isDeclarationForLinker() || + GV.getVisibility() != GlobalValue::DefaultVisibility) + continue; + + OutStreamer->SwitchSection(OutContext.getELFSection( + ".llvm_sympart", ELF::SHT_LLVM_SYMPART, 0, 0, "", ++UniqueID)); + OutStreamer->EmitBytes(GV.getPartition()); + OutStreamer->EmitZeros(1); + OutStreamer->EmitValue( + MCSymbolRefExpr::create(getSymbol(&GV), OutContext), + MAI->getCodePointerSize()); + } + } + // Allow the target to emit any magic that it wants at the end of the file, // after everything else has gone out. EmitEndOfAsmFile(M); diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index b5db8bdeb22..ca7afd0d81a 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -3247,6 +3247,12 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { printEscapedString(GV->getSection(), Out); Out << '"'; } + if (GV->hasPartition()) { + Out << ", partition \""; + printEscapedString(GV->getPartition(), Out); + Out << '"'; + } + maybePrintComdat(Out, *GV); if (GV->getAlignment()) Out << ", align " << GV->getAlignment(); @@ -3298,6 +3304,12 @@ void AssemblyWriter::printIndirectSymbol(const GlobalIndirectSymbol *GIS) { writeOperand(IS, !isa(IS)); } + if (GIS->hasPartition()) { + Out << ", partition \""; + printEscapedString(GIS->getPartition(), Out); + Out << '"'; + } + printInfoComment(*GIS); Out << '\n'; } @@ -3438,6 +3450,11 @@ void AssemblyWriter::printFunction(const Function *F) { printEscapedString(F->getSection(), Out); Out << '"'; } + if (F->hasPartition()) { + Out << " partition \""; + printEscapedString(F->getPartition(), Out); + Out << '"'; + } maybePrintComdat(Out, *F); if (F->getAlignment()) Out << " align " << F->getAlignment(); diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index b3fdcc6a5fc..e2bfc0420bc 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -67,6 +67,7 @@ void GlobalValue::copyAttributesFrom(const GlobalValue *Src) { setUnnamedAddr(Src->getUnnamedAddr()); setDLLStorageClass(Src->getDLLStorageClass()); setDSOLocal(Src->isDSOLocal()); + setPartition(Src->getPartition()); } void GlobalValue::removeFromParent() { @@ -180,6 +181,28 @@ const Comdat *GlobalValue::getComdat() const { return cast(this)->getComdat(); } +StringRef GlobalValue::getPartition() const { + if (!hasPartition()) + return ""; + return getContext().pImpl->GlobalValuePartitions[this]; +} + +void GlobalValue::setPartition(StringRef S) { + // Do nothing if we're clearing the partition and it is already empty. + if (!hasPartition() && S.empty()) + return; + + // Get or create a stable partition name string and put it in the table in the + // context. + if (!S.empty()) + S = getContext().pImpl->Saver.save(S); + getContext().pImpl->GlobalValuePartitions[this] = S; + + // Update the HasPartition field. Setting the partition to the empty string + // means this global no longer has a partition. + HasPartition = !S.empty(); +} + StringRef GlobalObject::getSectionImpl() const { assert(hasSection()); return getContext().pImpl->GlobalObjectSections[this]; diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index e977f051109..4560617624e 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -1356,6 +1356,9 @@ public: /// Collection of per-GlobalObject sections used in this context. DenseMap GlobalObjectSections; + /// Collection of per-GlobalValue partitions used in this context. + DenseMap GlobalValuePartitions; + /// DiscriminatorTable - This table maps file:line locations to an /// integer representing the next DWARF path discriminator to assign to /// instructions in different blocks at the same location. diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 48ced8d3dfa..a55bdd5364c 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -617,6 +617,8 @@ EndStmt: Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE; else if (TypeName == "llvm_dependent_libraries") Type = ELF::SHT_LLVM_DEPENDENT_LIBRARIES; + else if (TypeName == "llvm_sympart") + Type = ELF::SHT_LLVM_SYMPART; else if (TypeName.getAsInteger(0, Type)) return TokError("unknown section type"); } diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp index 569b6ba0997..efe504b2024 100644 --- a/lib/MC/MCSectionELF.cpp +++ b/lib/MC/MCSectionELF.cpp @@ -154,6 +154,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, OS << "llvm_call_graph_profile"; else if (Type == ELF::SHT_LLVM_DEPENDENT_LIBRARIES) OS << "llvm_dependent_libraries"; + else if (Type == ELF::SHT_LLVM_SYMPART) + OS << "llvm_sympart"; else report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) + " for section " + getSectionName()); diff --git a/lib/Object/ELF.cpp b/lib/Object/ELF.cpp index 951f4ae8f7e..a9c90e01551 100644 --- a/lib/Object/ELF.cpp +++ b/lib/Object/ELF.cpp @@ -254,6 +254,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_CALL_GRAPH_PROFILE); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ADDRSIG); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_DEPENDENT_LIBRARIES); + STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_SYMPART); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef); diff --git a/test/Bitcode/compatibility.ll b/test/Bitcode/compatibility.ll index a1474df6d94..6c3a6887346 100644 --- a/test/Bitcode/compatibility.ll +++ b/test/Bitcode/compatibility.ll @@ -160,6 +160,10 @@ $comdat.samesize = comdat samesize @g.section = global i32 0, section "_DATA" ; CHECK: @g.section = global i32 0, section "_DATA" +; Global Variables -- partition +@g.partition = global i32 0, partition "part" +; CHECK: @g.partition = global i32 0, partition "part" + ; Global Variables -- comdat @comdat.any = global i32 0, comdat ; CHECK: @comdat.any = global i32 0, comdat @@ -251,6 +255,10 @@ declare void @g.f1() @a.local_unnamed_addr = local_unnamed_addr alias i32, i32* @g.local_unnamed_addr ; CHECK: @a.local_unnamed_addr = local_unnamed_addr alias i32, i32* @g.local_unnamed_addr +; Aliases -- partition +; CHECK: @alias.partition = alias i32, i32* @g.partition, partition "part" +@alias.partition = alias i32, i32* @g.partition, partition "part" + ;; IFunc ; Format @ = [Linkage] [Visibility] ifunc , ; * @ @@ -271,6 +279,10 @@ declare void @g.f1() @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver ; CHECK: @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver +; IFunc -- partition +; CHECK: @ifunc.partition = ifunc void (), i8* ()* @ifunc_resolver, partition "part" +@ifunc.partition = ifunc void (), i8* ()* @ifunc_resolver, partition "part" + define i8* @ifunc_resolver() { entry: ret i8* null @@ -620,6 +632,12 @@ declare void @f.strictfp() #35 declare void @f.section() section "80" ; CHECK: declare void @f.section() section "80" +; Functions -- partition +define void @f.partition() partition "part" { +; CHECK: define void @f.partition() partition "part" + ret void +} + ; Functions -- comdat define void @f.comdat_any() comdat($comdat.any) { ; CHECK: define void @f.comdat_any() comdat($comdat.any) diff --git a/test/CodeGen/X86/partition.ll b/test/CodeGen/X86/partition.ll new file mode 100644 index 00000000000..cc8d44e399e --- /dev/null +++ b/test/CodeGen/X86/partition.ll @@ -0,0 +1,33 @@ +; RUN: llc < %s -mtriple=x86_64-unknown-linux | FileCheck %s + +; CHECK: .section .llvm_sympart,"",@llvm_sympart,unique,1 +; CHECK-NEXT: .ascii "part1" +; CHECK-NEXT: .zero 1 +; CHECK-NEXT: .quad f1 +; CHECK-NEXT: .section .llvm_sympart,"",@llvm_sympart,unique,2 +; CHECK-NEXT: .ascii "part4" +; CHECK-NEXT: .zero 1 +; CHECK-NEXT: .quad g1 +; CHECK-NEXT: .section .llvm_sympart,"",@llvm_sympart,unique,3 +; CHECK-NEXT: .ascii "part5" +; CHECK-NEXT: .zero 1 +; CHECK-NEXT: .quad a1 +; CHECK-NEXT: .section .llvm_sympart,"",@llvm_sympart,unique,4 +; CHECK-NEXT: .ascii "part6" +; CHECK-NEXT: .zero 1 +; CHECK-NEXT: .quad i1 + +define void @f1() partition "part1" { + unreachable +} + +define hidden void @f2() partition "part2" { + unreachable +} + +declare void @f3() partition "part3" + +@g1 = global i32 0, partition "part4" + +@a1 = alias i32, i32* @g1, partition "part5" +@i1 = ifunc void(), void()* @f1, partition "part6" diff --git a/test/MC/ELF/section.s b/test/MC/ELF/section.s index 7c9bb7915d1..f4ed666bfc7 100644 --- a/test/MC/ELF/section.s +++ b/test/MC/ELF/section.s @@ -306,3 +306,15 @@ bar: // CHECK-NEXT: SHF_STRINGS // CHECK-NEXT: ] // CHECK: } + +// Test SHT_LLVM_SYMPART + +.section .llvm_sympart,"",@llvm_sympart +// ASM: .section .llvm_sympart,"",@llvm_sympart + +// CHECK: Section { +// CHECK: Name: .llvm_sympart +// CHECK-NEXT: Type: SHT_LLVM_SYMPART +// CHECK-NEXT: Flags [ +// CHECK-NEXT: ] +// CHECK: } diff --git a/test/Object/X86/irsymtab.ll b/test/Object/X86/irsymtab.ll index 1b9915a2b74..2e7b189572f 100644 --- a/test/Object/X86/irsymtab.ll +++ b/test/Object/X86/irsymtab.ll @@ -9,7 +9,7 @@ ; BCA: blob data = '\x02\x00\x00\x00\x06\x00\x00\x00\x08\x00\x00\x00L\x00\x00\x00\x01\x00\x00\x00X\x00\x00\x00\x00\x00\x00\x00X\x00\x00\x00\x02\x00\x00\x00\x88\x00\x00\x00\x00\x00\x00\x00\x0E\x00\x00\x00\x18\x00\x00\x00&\x00\x00\x00\x0B\x00\x00\x001\x00\x00\x00\x00\x00\x00\x00\x88\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xFF\xFF\xFF\xFF\x00$\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\xFF\xFF\xFF\xFF\x08$\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00' +; BCA-NEXT: blob data = '\x02\x00\x00\x00\x06\x00\x00\x00\x08\x00\x00\x00L\x00\x00\x00\x01\x00\x00\x00X\x00\x00\x00\x00\x00\x00\x00X\x00\x00\x00\x02\x00\x00\x00\x88\x00\x00\x00\x00\x00\x00\x00\x0E\x00\x00\x00\x18\x00\x00\x00&\x00\x00\x00\x0B\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x88\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xFF\xFF\xFF\xFF\x00$\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\xFF\xFF\xFF\xFF\x08$\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00' ; BCA-NEXT: ; BCA-NEXT: blob data = 'foobarproducerx86_64-unknown-linux-gnuirsymtab.ll'