llvm.org GIT mirror llvm / 9b16aa5
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@361923 91177308-0d34-0410-b5e6-96231b3b80d8 Peter Collingbourne 2 months ago
19 changed file(s) with 220 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
378378
379379 This marks ``sym`` as address-significant.
380380
381 ``SHT_LLVM_SYMPART`` Section (symbol partition specification)
382 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
383
384 This section is used to mark symbols with the `partition`_ that they
385 belong to. An ``.llvm_sympart`` section consists of a null-terminated string
386 specifying the name of the partition followed by a relocation referring to
387 the symbol that belongs to the partition. It may be constructed as follows:
388
389 .. code-block:: gas
390
391 .section ".llvm_sympart","",@llvm_sympart
392 .asciz "libpartition.so"
393 .word symbol_in_partition
394
395 .. _partition: https://lld.llvm.org/Partitions.html
396
381397 CodeView-Dependent
382398 ------------------
383399
841841 SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols
842842 // for safe ICF.
843843 SHT_LLVM_DEPENDENT_LIBRARIES = 0x6fff4c04, // LLVM Dependent Library Specifiers.
844 SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification.
844845 // Android's experimental support for SHT_RELR sections.
845846 // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512
846847 SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets.
7878 ValueType(Ty), Visibility(DefaultVisibility),
7979 UnnamedAddrVal(unsigned(UnnamedAddr::None)),
8080 DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal),
81 HasLLVMReservedName(false), IsDSOLocal(false), IntID((Intrinsic::ID)0U),
82 Parent(nullptr) {
81 HasLLVMReservedName(false), IsDSOLocal(false), HasPartition(false),
82 IntID((Intrinsic::ID)0U), Parent(nullptr) {
8383 setLinkage(Linkage);
8484 setName(Name);
8585 }
8686
8787 Type *ValueType;
8888
89 static const unsigned GlobalValueSubClassDataBits = 17;
89 static const unsigned GlobalValueSubClassDataBits = 16;
9090
9191 // All bitfields use unsigned as the underlying type so that MSVC will pack
9292 // them.
107107 /// definition cannot be runtime preempted.
108108 unsigned IsDSOLocal : 1;
109109
110 /// True if this symbol has a partition name assigned (see
111 /// https://lld.llvm.org/Partitions.html).
112 unsigned HasPartition : 1;
113
110114 private:
111115 // Give subclasses access to what otherwise would be wasted padding.
112 // (17 + 4 + 2 + 2 + 2 + 3 + 1 + 1) == 32.
116 // (16 + 4 + 2 + 2 + 2 + 3 + 1 + 1 + 1) == 32.
113117 unsigned SubClassData : GlobalValueSubClassDataBits;
114118
115119 friend class Constant;
279283 return IsDSOLocal;
280284 }
281285
286 bool hasPartition() const {
287 return HasPartition;
288 }
289 StringRef getPartition() const;
290 void setPartition(StringRef Part);
291
282292 static LinkageTypes getLinkOnceLinkage(bool ODR) {
283293 return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage;
284294 }
569569 KEYWORD(align);
570570 KEYWORD(addrspace);
571571 KEYWORD(section);
572 KEYWORD(partition);
572573 KEYWORD(alias);
573574 KEYWORD(ifunc);
574575 KEYWORD(module);
855855 /// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier
856856 /// OptionalVisibility OptionalDLLStorageClass
857857 /// OptionalThreadLocal OptionalUnnamedAddr
858 // 'alias|ifunc' IndirectSymbol
858 /// 'alias|ifunc' IndirectSymbol IndirectSymbolAttr*
859859 ///
860860 /// IndirectSymbol
861861 /// ::= TypeAndValue
862 ///
863 /// IndirectSymbolAttr
864 /// ::= ',' 'partition' StringConstant
862865 ///
863866 /// Everything through OptionalUnnamedAddr has already been parsed.
864867 ///
958961 GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass);
959962 GA->setUnnamedAddr(UnnamedAddr);
960963 maybeSetDSOLocal(DSOLocal, *GA);
964
965 // At this point we've parsed everything except for the IndirectSymbolAttrs.
966 // Now parse them if there are any.
967 while (Lex.getKind() == lltok::comma) {
968 Lex.Lex();
969
970 if (Lex.getKind() == lltok::kw_partition) {
971 Lex.Lex();
972 GA->setPartition(Lex.getStrVal());
973 if (ParseToken(lltok::StringConstant, "expected partition string"))
974 return true;
975 } else {
976 return TokError("unknown alias or ifunc property!");
977 }
978 }
961979
962980 if (Name.empty())
963981 NumberedVals.push_back(GA.get());
10931111 Lex.Lex();
10941112 GV->setSection(Lex.getStrVal());
10951113 if (ParseToken(lltok::StringConstant, "expected global section string"))
1114 return true;
1115 } else if (Lex.getKind() == lltok::kw_partition) {
1116 Lex.Lex();
1117 GV->setPartition(Lex.getStrVal());
1118 if (ParseToken(lltok::StringConstant, "expected partition string"))
10961119 return true;
10971120 } else if (Lex.getKind() == lltok::kw_align) {
10981121 unsigned Alignment;
52865309 std::vector FwdRefAttrGrps;
52875310 LocTy BuiltinLoc;
52885311 std::string Section;
5312 std::string Partition;
52895313 unsigned Alignment;
52905314 std::string GC;
52915315 GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None;
53025326 BuiltinLoc) ||
53035327 (EatIfPresent(lltok::kw_section) &&
53045328 ParseStringConstant(Section)) ||
5329 (EatIfPresent(lltok::kw_partition) &&
5330 ParseStringConstant(Partition)) ||
53055331 parseOptionalComdat(FunctionName, C) ||
53065332 ParseOptionalAlignment(Alignment) ||
53075333 (EatIfPresent(lltok::kw_gc) &&
54035429 Fn->setUnnamedAddr(UnnamedAddr);
54045430 Fn->setAlignment(Alignment);
54055431 Fn->setSection(Section);
5432 Fn->setPartition(Partition);
54065433 Fn->setComdat(C);
54075434 Fn->setPersonalityFn(PersonalityFn);
54085435 if (!GC.empty()) Fn->setGC(GC);
112112 kw_align,
113113 kw_addrspace,
114114 kw_section,
115 kw_partition,
115116 kw_alias,
116117 kw_ifunc,
117118 kw_module,
28912891 Error BitcodeReader::parseGlobalVarRecord(ArrayRef Record) {
28922892 // v1: [pointer type, isconst, initid, linkage, alignment, section,
28932893 // visibility, threadlocal, unnamed_addr, externally_initialized,
2894 // dllstorageclass, comdat, attributes, preemption specifier] (name in VST)
2894 // dllstorageclass, comdat, attributes, preemption specifier,
2895 // partition strtab offset, partition strtab size] (name in VST)
28952896 // v2: [strtab_offset, strtab_size, v1]
28962897 StringRef Name;
28972898 std::tie(Name, Record) = readNameFromStrtab(Record);
29822983 }
29832984 inferDSOLocal(NewGV);
29842985
2986 // Check whether we have enough values to read a partition name.
2987 if (Record.size() > 15)
2988 NewGV->setPartition(StringRef(Strtab.data() + Record[14], Record[15]));
2989
29852990 return Error::success();
29862991 }
29872992
30703075 Func->setDSOLocal(getDecodedDSOLocal(Record[15]));
30713076 }
30723077 inferDSOLocal(Func);
3078
3079 // Record[16] is the address space number.
3080
3081 // Check whether we have enough values to read a partition name.
3082 if (Record.size() > 18)
3083 Func->setPartition(StringRef(Strtab.data() + Record[17], Record[18]));
30733084
30743085 ValueList.push_back(Func);
30753086
31473158 if (OpNum != Record.size())
31483159 NewGA->setDSOLocal(getDecodedDSOLocal(Record[OpNum++]));
31493160 inferDSOLocal(NewGA);
3161
3162 // Check whether we have enough values to read a partition name.
3163 if (OpNum + 1 < Record.size()) {
3164 NewGA->setPartition(
3165 StringRef(Strtab.data() + Record[OpNum], Record[OpNum + 1]));
3166 OpNum += 2;
3167 }
31503168
31513169 ValueList.push_back(NewGA);
31523170 IndirectSymbolInits.push_back(std::make_pair(NewGA, Val));
12611261 GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass ||
12621262 GV.hasComdat() ||
12631263 GV.hasAttributes() ||
1264 GV.isDSOLocal()) {
1264 GV.isDSOLocal() ||
1265 GV.hasPartition()) {
12651266 Vals.push_back(getEncodedVisibility(GV));
12661267 Vals.push_back(getEncodedThreadLocalMode(GV));
12671268 Vals.push_back(getEncodedUnnamedAddr(GV));
12731274 Vals.push_back(VE.getAttributeListID(AL));
12741275
12751276 Vals.push_back(GV.isDSOLocal());
1277 Vals.push_back(addToStrtab(GV.getPartition()));
1278 Vals.push_back(GV.getPartition().size());
12761279 } else {
12771280 AbbrevToUse = SimpleGVarAbbrev;
12781281 }
13101313
13111314 Vals.push_back(F.isDSOLocal());
13121315 Vals.push_back(F.getAddressSpace());
1316 Vals.push_back(addToStrtab(F.getPartition()));
1317 Vals.push_back(F.getPartition().size());
13131318
13141319 unsigned AbbrevToUse = 0;
13151320 Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
13321337 Vals.push_back(getEncodedThreadLocalMode(A));
13331338 Vals.push_back(getEncodedUnnamedAddr(A));
13341339 Vals.push_back(A.isDSOLocal());
1340 Vals.push_back(addToStrtab(A.getPartition()));
1341 Vals.push_back(A.getPartition().size());
13351342
13361343 unsigned AbbrevToUse = 0;
13371344 Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse);
13501357 Vals.push_back(getEncodedLinkage(I));
13511358 Vals.push_back(getEncodedVisibility(I));
13521359 Vals.push_back(I.isDSOLocal());
1360 Vals.push_back(addToStrtab(I.getPartition()));
1361 Vals.push_back(I.getPartition().size());
13531362 Stream.EmitRecord(bitc::MODULE_CODE_IFUNC, Vals);
13541363 Vals.clear();
13551364 }
16311631 OutStreamer->EmitAddrsigSym(getSymbol(&GV));
16321632 }
16331633
1634 // Emit symbol partition specifications (ELF only).
1635 if (TM.getTargetTriple().isOSBinFormatELF()) {
1636 unsigned UniqueID = 0;
1637 for (const GlobalValue &GV : M.global_values()) {
1638 if (!GV.hasPartition() || GV.isDeclarationForLinker() ||
1639 GV.getVisibility() != GlobalValue::DefaultVisibility)
1640 continue;
1641
1642 OutStreamer->SwitchSection(OutContext.getELFSection(
1643 ".llvm_sympart", ELF::SHT_LLVM_SYMPART, 0, 0, "", ++UniqueID));
1644 OutStreamer->EmitBytes(GV.getPartition());
1645 OutStreamer->EmitZeros(1);
1646 OutStreamer->EmitValue(
1647 MCSymbolRefExpr::create(getSymbol(&GV), OutContext),
1648 MAI->getCodePointerSize());
1649 }
1650 }
1651
16341652 // Allow the target to emit any magic that it wants at the end of the file,
16351653 // after everything else has gone out.
16361654 EmitEndOfAsmFile(M);
32463246 printEscapedString(GV->getSection(), Out);
32473247 Out << '"';
32483248 }
3249 if (GV->hasPartition()) {
3250 Out << ", partition \"";
3251 printEscapedString(GV->getPartition(), Out);
3252 Out << '"';
3253 }
3254
32493255 maybePrintComdat(Out, *GV);
32503256 if (GV->getAlignment())
32513257 Out << ", align " << GV->getAlignment();
32953301 Out << " <>";
32963302 } else {
32973303 writeOperand(IS, !isa(IS));
3304 }
3305
3306 if (GIS->hasPartition()) {
3307 Out << ", partition \"";
3308 printEscapedString(GIS->getPartition(), Out);
3309 Out << '"';
32983310 }
32993311
33003312 printInfoComment(*GIS);
34353447 if (F->hasSection()) {
34363448 Out << " section \"";
34373449 printEscapedString(F->getSection(), Out);
3450 Out << '"';
3451 }
3452 if (F->hasPartition()) {
3453 Out << " partition \"";
3454 printEscapedString(F->getPartition(), Out);
34383455 Out << '"';
34393456 }
34403457 maybePrintComdat(Out, *F);
6666 setUnnamedAddr(Src->getUnnamedAddr());
6767 setDLLStorageClass(Src->getDLLStorageClass());
6868 setDSOLocal(Src->isDSOLocal());
69 setPartition(Src->getPartition());
6970 }
7071
7172 void GlobalValue::removeFromParent() {
177178 if (isa(this))
178179 return nullptr;
179180 return cast(this)->getComdat();
181 }
182
183 StringRef GlobalValue::getPartition() const {
184 if (!hasPartition())
185 return "";
186 return getContext().pImpl->GlobalValuePartitions[this];
187 }
188
189 void GlobalValue::setPartition(StringRef S) {
190 // Do nothing if we're clearing the partition and it is already empty.
191 if (!hasPartition() && S.empty())
192 return;
193
194 // Get or create a stable partition name string and put it in the table in the
195 // context.
196 if (!S.empty())
197 S = getContext().pImpl->Saver.save(S);
198 getContext().pImpl->GlobalValuePartitions[this] = S;
199
200 // Update the HasPartition field. Setting the partition to the empty string
201 // means this global no longer has a partition.
202 HasPartition = !S.empty();
180203 }
181204
182205 StringRef GlobalObject::getSectionImpl() const {
13551355 /// Collection of per-GlobalObject sections used in this context.
13561356 DenseMap GlobalObjectSections;
13571357
1358 /// Collection of per-GlobalValue partitions used in this context.
1359 DenseMap GlobalValuePartitions;
1360
13581361 /// DiscriminatorTable - This table maps file:line locations to an
13591362 /// integer representing the next DWARF path discriminator to assign to
13601363 /// instructions in different blocks at the same location.
616616 Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
617617 else if (TypeName == "llvm_dependent_libraries")
618618 Type = ELF::SHT_LLVM_DEPENDENT_LIBRARIES;
619 else if (TypeName == "llvm_sympart")
620 Type = ELF::SHT_LLVM_SYMPART;
619621 else if (TypeName.getAsInteger(0, Type))
620622 return TokError("unknown section type");
621623 }
153153 OS << "llvm_call_graph_profile";
154154 else if (Type == ELF::SHT_LLVM_DEPENDENT_LIBRARIES)
155155 OS << "llvm_dependent_libraries";
156 else if (Type == ELF::SHT_LLVM_SYMPART)
157 OS << "llvm_sympart";
156158 else
157159 report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) +
158160 " for section " + getSectionName());
253253 STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_CALL_GRAPH_PROFILE);
254254 STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ADDRSIG);
255255 STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_DEPENDENT_LIBRARIES);
256 STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_SYMPART);
256257 STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES);
257258 STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH);
258259 STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef);
159159 @g.section = global i32 0, section "_DATA"
160160 ; CHECK: @g.section = global i32 0, section "_DATA"
161161
162 ; Global Variables -- partition
163 @g.partition = global i32 0, partition "part"
164 ; CHECK: @g.partition = global i32 0, partition "part"
165
162166 ; Global Variables -- comdat
163167 @comdat.any = global i32 0, comdat
164168 ; CHECK: @comdat.any = global i32 0, comdat
250254 @a.local_unnamed_addr = local_unnamed_addr alias i32, i32* @g.local_unnamed_addr
251255 ; CHECK: @a.local_unnamed_addr = local_unnamed_addr alias i32, i32* @g.local_unnamed_addr
252256
257 ; Aliases -- partition
258 ; CHECK: @alias.partition = alias i32, i32* @g.partition, partition "part"
259 @alias.partition = alias i32, i32* @g.partition, partition "part"
260
253261 ;; IFunc
254262 ; Format @ = [Linkage] [Visibility] ifunc ,
255263 ; * @
269277 ; CHECK: @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver
270278 @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
271279 ; CHECK: @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
280
281 ; IFunc -- partition
282 ; CHECK: @ifunc.partition = ifunc void (), i8* ()* @ifunc_resolver, partition "part"
283 @ifunc.partition = ifunc void (), i8* ()* @ifunc_resolver, partition "part"
272284
273285 define i8* @ifunc_resolver() {
274286 entry:
619631 declare void @f.section() section "80"
620632 ; CHECK: declare void @f.section() section "80"
621633
634 ; Functions -- partition
635 define void @f.partition() partition "part" {
636 ; CHECK: define void @f.partition() partition "part"
637 ret void
638 }
639
622640 ; Functions -- comdat
623641 define void @f.comdat_any() comdat($comdat.any) {
624642 ; CHECK: define void @f.comdat_any() comdat($comdat.any)
0 ; RUN: llc < %s -mtriple=x86_64-unknown-linux | FileCheck %s
1
2 ; CHECK: .section .llvm_sympart,"",@llvm_sympart,unique,1
3 ; CHECK-NEXT: .ascii "part1"
4 ; CHECK-NEXT: .zero 1
5 ; CHECK-NEXT: .quad f1
6 ; CHECK-NEXT: .section .llvm_sympart,"",@llvm_sympart,unique,2
7 ; CHECK-NEXT: .ascii "part4"
8 ; CHECK-NEXT: .zero 1
9 ; CHECK-NEXT: .quad g1
10 ; CHECK-NEXT: .section .llvm_sympart,"",@llvm_sympart,unique,3
11 ; CHECK-NEXT: .ascii "part5"
12 ; CHECK-NEXT: .zero 1
13 ; CHECK-NEXT: .quad a1
14 ; CHECK-NEXT: .section .llvm_sympart,"",@llvm_sympart,unique,4
15 ; CHECK-NEXT: .ascii "part6"
16 ; CHECK-NEXT: .zero 1
17 ; CHECK-NEXT: .quad i1
18
19 define void @f1() partition "part1" {
20 unreachable
21 }
22
23 define hidden void @f2() partition "part2" {
24 unreachable
25 }
26
27 declare void @f3() partition "part3"
28
29 @g1 = global i32 0, partition "part4"
30
31 @a1 = alias i32, i32* @g1, partition "part5"
32 @i1 = ifunc void(), void()* @f1, partition "part6"
305305 // CHECK-NEXT: SHF_STRINGS
306306 // CHECK-NEXT: ]
307307 // CHECK: }
308
309 // Test SHT_LLVM_SYMPART
310
311 .section .llvm_sympart,"",@llvm_sympart
312 // ASM: .section .llvm_sympart,"",@llvm_sympart
313
314 // CHECK: Section {
315 // CHECK: Name: .llvm_sympart
316 // CHECK-NEXT: Type: SHT_LLVM_SYMPART
317 // CHECK-NEXT: Flags [
318 // CHECK-NEXT: ]
319 // CHECK: }
88
99 ; BCA:
1010 ; Version stored at offset 0.
11 ; 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\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'
11 ; 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'
1212 ; BCA-NEXT:
1313 ; BCA-NEXT:
1414 ; BCA-NEXT: blob data = 'foobarproducerx86_64-unknown-linux-gnuirsymtab.ll'