llvm.org GIT mirror llvm / 2ebca36
[Linker] Provide callback for internalization Differential Revision: https://reviews.llvm.org/D30738 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297649 91177308-0d34-0410-b5e6-96231b3b80d8 Jonas Devlieghere 2 years ago
5 changed file(s) with 69 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
99 #ifndef LLVM_LINKER_LINKER_H
1010 #define LLVM_LINKER_LINKER_H
1111
12 #include "llvm/ADT/StringSet.h"
1213 #include "llvm/Linker/IRMover.h"
1314
1415 namespace llvm {
2829 None = 0,
2930 OverrideFromSrc = (1 << 0),
3031 LinkOnlyNeeded = (1 << 1),
31 InternalizeLinkedSymbols = (1 << 2),
3232 };
3333
3434 Linker(Module &M);
3838 /// Passing OverrideSymbols as true will have symbols from Src
3939 /// shadow those in the Dest.
4040 ///
41 /// Passing InternalizeCallback will have the linker call the function with
42 /// the new module and a list of global value names to be internalized by the
43 /// callback.
44 ///
4145 /// Returns true on error.
42 bool linkInModule(std::unique_ptr Src, unsigned Flags = Flags::None);
46 bool linkInModule(std::unique_ptr Src, unsigned Flags = Flags::None,
47 std::function &)>
48 InternalizeCallback = {});
4349
4450 static bool linkModules(Module &Dest, std::unique_ptr Src,
45 unsigned Flags = Flags::None);
51 unsigned Flags = Flags::None,
52 std::function &)>
53 InternalizeCallback = {});
4654 };
4755
4856 } // End llvm namespace
1313 #include "LinkDiagnosticInfo.h"
1414 #include "llvm-c/Linker.h"
1515 #include "llvm/ADT/SetVector.h"
16 #include "llvm/ADT/StringSet.h"
1716 #include "llvm/IR/Comdat.h"
1817 #include "llvm/IR/DiagnosticPrinter.h"
1918 #include "llvm/IR/GlobalValue.h"
3231 std::unique_ptr SrcM;
3332
3433 SetVector ValuesToLink;
35 StringSet<> Internalize;
3634
3735 /// For symbol clashes, prefer those from Src.
3836 unsigned Flags;
37
38 /// List of global value names that should be internalized.
39 StringSet<> Internalize;
40
41 /// Function that will perform the actual internalization. The reason for a
42 /// callback is that the linker cannot call internalizeModule without
43 /// creating a circular dependency between IPO and the linker.
44 std::function &)> InternalizeCallback;
3945
4046 /// Used as the callback for lazy linking.
4147 /// The mover has just hit GV and we have to decide if it, and other members
4551
4652 bool shouldOverrideFromSrc() { return Flags & Linker::OverrideFromSrc; }
4753 bool shouldLinkOnlyNeeded() { return Flags & Linker::LinkOnlyNeeded; }
48 bool shouldInternalizeLinkedSymbols() {
49 return Flags & Linker::InternalizeLinkedSymbols;
50 }
5154
5255 bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest,
5356 const GlobalValue &Src);
103106 bool linkIfNeeded(GlobalValue &GV);
104107
105108 public:
106 ModuleLinker(IRMover &Mover, std::unique_ptr SrcM, unsigned Flags)
107 : Mover(Mover), SrcM(std::move(SrcM)), Flags(Flags) {}
109 ModuleLinker(IRMover &Mover, std::unique_ptr SrcM, unsigned Flags,
110 std::function &)>
111 InternalizeCallback = {})
112 : Mover(Mover), SrcM(std::move(SrcM)), Flags(Flags),
113 InternalizeCallback(std::move(InternalizeCallback)) {}
108114
109115 bool run();
110116 };
382388 !shouldLinkOnlyNeeded())
383389 return;
384390
385 if (shouldInternalizeLinkedSymbols())
391 if (InternalizeCallback)
386392 Internalize.insert(GV.getName());
387393 Add(GV);
388394
396402 return;
397403 if (!LinkFromSrc)
398404 continue;
399 if (shouldInternalizeLinkedSymbols())
405 if (InternalizeCallback)
400406 Internalize.insert(GV2->getName());
401407 Add(*GV2);
402408 }
525531 }
526532 }
527533
528 if (shouldInternalizeLinkedSymbols()) {
534 if (InternalizeCallback) {
529535 for (GlobalValue *GV : ValuesToLink)
530536 Internalize.insert(GV->getName());
531537 }
546552 if (HasErrors)
547553 return true;
548554
549 for (auto &P : Internalize) {
550 GlobalValue *GV = DstM.getNamedValue(P.first());
551 GV->setLinkage(GlobalValue::InternalLinkage);
552 }
555 if (InternalizeCallback)
556 InternalizeCallback(DstM, Internalize);
553557
554558 return false;
555559 }
556560
557561 Linker::Linker(Module &M) : Mover(M) {}
558562
559 bool Linker::linkInModule(std::unique_ptr Src, unsigned Flags) {
560 ModuleLinker ModLinker(Mover, std::move(Src), Flags);
563 bool Linker::linkInModule(
564 std::unique_ptr Src, unsigned Flags,
565 std::function &)> InternalizeCallback) {
566 ModuleLinker ModLinker(Mover, std::move(Src), Flags,
567 std::move(InternalizeCallback));
561568 return ModLinker.run();
562569 }
563570
570577 /// true is returned and ErrorMsg (if not null) is set to indicate the problem.
571578 /// Upon failure, the Dest module could be in a modified state, and shouldn't be
572579 /// relied on to be consistent.
573 bool Linker::linkModules(Module &Dest, std::unique_ptr Src,
574 unsigned Flags) {
580 bool Linker::linkModules(
581 Module &Dest, std::unique_ptr Src, unsigned Flags,
582 std::function &)> InternalizeCallback) {
575583 Linker L(Dest);
576 return L.linkInModule(std::move(Src), Flags);
584 return L.linkInModule(std::move(Src), Flags, std::move(InternalizeCallback));
577585 }
578586
579587 //===----------------------------------------------------------------------===//
0 @Y = global i8 42
1
2 define i64 @foo() { ret i64 7 }
3
4 @llvm.used = appending global [2 x i8*] [i8* @Y, i8* bitcast (i64 ()* @foo to i8*)], section "llvm.metadata"
11 ; RUN: llvm-link -S -only-needed %S/Inputs/linkage.b.ll %S/Inputs/linkage.c.ll | FileCheck %s -check-prefix=B -check-prefix=C -check-prefix=CN
22 ; RUN: llvm-link -S -internalize %S/Inputs/linkage.b.ll %S/Inputs/linkage.c.ll | FileCheck %s -check-prefix=B -check-prefix=CI
33 ; RUN: llvm-link -S -internalize -only-needed %S/Inputs/linkage.b.ll %S/Inputs/linkage.c.ll | FileCheck %s -check-prefix=B -check-prefix=CN
4 ; RUN: llvm-link -S -internalize %S/Inputs/linkage.b.ll %S/Inputs/linkage.c.ll %S/Inputs/linkage.d.ll | FileCheck %s -check-prefix=B -check-prefix=DI
45
56 C-LABEL: @X = global i32 5
67 CI-LABEL: @X = internal global i32 5
78 CU-LABEL:@U = global i32 6
89 CI-LABEL:@U = internal global i32 6
910 CN-NOT:@U
11 DI-LABEL: @Y = global i8 42
12 DI-LABEL: @llvm.used = appending global [2 x i8*] [i8* @Y, i8* bitcast (i64 ()* @foo to i8*)], section "llvm.metadata"
1013
1114 B-LABEL: define void @bar() {
1215
1619 CU-LABEL:define i32 @unused() {
1720 CI-LABEL:define internal i32 @unused() {
1821 CN-NOT:@unused()
22
23 DI-LABEL: define internal i32 @foo.6()
24 DI-LABEL: define i64 @foo()
3333 #include "llvm/Support/SystemUtils.h"
3434 #include "llvm/Support/ToolOutputFile.h"
3535 #include "llvm/Transforms/IPO/FunctionImport.h"
36 #include "llvm/Transforms/IPO/Internalize.h"
3637 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
3738
3839 #include
271272 unsigned Flags) {
272273 // Filter out flags that don't apply to the first file we load.
273274 unsigned ApplicableFlags = Flags & Linker::Flags::OverrideFromSrc;
275 // Similar to some flags, internalization doesn't apply to the first file.
276 bool InternalizeLinkedSymbols = false;
274277 for (const auto &File : Files) {
275278 std::unique_ptr M = loadFile(argv0, File, Context);
276279 if (!M.get()) {
310313 if (Verbose)
311314 errs() << "Linking in '" << File << "'\n";
312315
313 if (L.linkInModule(std::move(M), ApplicableFlags))
316 bool Err = false;
317 if (InternalizeLinkedSymbols) {
318 Err = L.linkInModule(
319 std::move(M), ApplicableFlags, [](Module &M, const StringSet<> &GVS) {
320 internalizeModule(M, [&M, &GVS](const GlobalValue &GV) {
321 return !GV.hasName() || (GVS.count(GV.getName()) == 0);
322 });
323 });
324 } else {
325 Err = L.linkInModule(std::move(M), ApplicableFlags);
326 }
327
328 if (Err)
314329 return false;
330
331 // Internalization applies to linking of subsequent files.
332 InternalizeLinkedSymbols = Internalize;
333
315334 // All linker flags apply to linking of subsequent files.
316335 ApplicableFlags = Flags;
317336 }
339358 Linker L(*Composite);
340359
341360 unsigned Flags = Linker::Flags::None;
342 if (Internalize)
343 Flags |= Linker::Flags::InternalizeLinkedSymbols;
344361 if (OnlyNeeded)
345362 Flags |= Linker::Flags::LinkOnlyNeeded;
346363