1 //===-- ExtractGV.cpp - Global Value extraction pass ----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This pass extracts global values
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Transforms/IPO/ExtractGV.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/IR/PassManager.h"
19 /// Make sure GV is visible from both modules. Delete is true if it is
20 /// being deleted from this module.
21 /// This also makes sure GV cannot be dropped so that references from
22 /// the split module remain valid.
23 static void makeVisible(GlobalValue
&GV
, bool Delete
) {
24 bool Local
= GV
.hasLocalLinkage();
25 if (Local
|| Delete
) {
26 GV
.setLinkage(GlobalValue::ExternalLinkage
);
28 GV
.setVisibility(GlobalValue::HiddenVisibility
);
32 if (!GV
.hasLinkOnceLinkage()) {
33 assert(!GV
.isDiscardableIfUnused());
37 // Map linkonce* to weak* so that llvm doesn't drop this GV.
38 switch (GV
.getLinkage()) {
40 llvm_unreachable("Unexpected linkage");
41 case GlobalValue::LinkOnceAnyLinkage
:
42 GV
.setLinkage(GlobalValue::WeakAnyLinkage
);
44 case GlobalValue::LinkOnceODRLinkage
:
45 GV
.setLinkage(GlobalValue::WeakODRLinkage
);
50 /// If deleteS is true, this pass deletes the specified global values.
51 /// Otherwise, it deletes as much of the module as possible, except for the
52 /// global values specified.
53 ExtractGVPass::ExtractGVPass(std::vector
<GlobalValue
*> &GVs
, bool deleteS
,
55 : Named(GVs
.begin(), GVs
.end()), deleteStuff(deleteS
),
56 keepConstInit(keepConstInit
) {}
58 PreservedAnalyses
ExtractGVPass::run(Module
&M
, ModuleAnalysisManager
&) {
59 // Visit the global inline asm.
61 M
.setModuleInlineAsm("");
63 // For simplicity, just give all GlobalValues ExternalLinkage. A trickier
64 // implementation could figure out which GlobalValues are actually
65 // referenced by the Named set, and which GlobalValues in the rest of
66 // the module are referenced by the NamedSet, and get away with leaving
67 // more internal and private things internal and private. But for now,
68 // be conservative and simple.
70 // Visit the GlobalVariables.
71 for (GlobalVariable
&GV
: M
.globals()) {
72 bool Delete
= deleteStuff
== (bool)Named
.count(&GV
) &&
73 !GV
.isDeclaration() && (!GV
.isConstant() || !keepConstInit
);
75 if (GV
.hasAvailableExternallyLinkage())
77 if (GV
.getName() == "llvm.global_ctors")
81 makeVisible(GV
, Delete
);
84 // Make this a declaration and drop it's comdat.
85 GV
.setInitializer(nullptr);
86 GV
.setComdat(nullptr);
90 // Visit the Functions.
91 for (Function
&F
: M
) {
92 bool Delete
= deleteStuff
== (bool)Named
.count(&F
) && !F
.isDeclaration();
94 if (F
.hasAvailableExternallyLinkage())
98 makeVisible(F
, Delete
);
101 // Make this a declaration and drop it's comdat.
103 F
.setComdat(nullptr);
107 // Visit the Aliases.
108 for (GlobalAlias
&GA
: llvm::make_early_inc_range(M
.aliases())) {
109 bool Delete
= deleteStuff
== (bool)Named
.count(&GA
);
110 makeVisible(GA
, Delete
);
113 Type
*Ty
= GA
.getValueType();
115 GA
.removeFromParent();
116 llvm::Value
*Declaration
;
117 if (FunctionType
*FTy
= dyn_cast
<FunctionType
>(Ty
)) {
118 Declaration
= Function::Create(FTy
, GlobalValue::ExternalLinkage
,
119 GA
.getAddressSpace(), GA
.getName(), &M
);
122 Declaration
= new GlobalVariable(
123 M
, Ty
, false, GlobalValue::ExternalLinkage
, nullptr, GA
.getName());
125 GA
.replaceAllUsesWith(Declaration
);
131 for (GlobalIFunc
&IF
: llvm::make_early_inc_range(M
.ifuncs())) {
132 bool Delete
= deleteStuff
== (bool)Named
.count(&IF
);
133 makeVisible(IF
, Delete
);
138 auto *FuncType
= dyn_cast
<FunctionType
>(IF
.getValueType());
139 IF
.removeFromParent();
140 llvm::Value
*Declaration
=
141 Function::Create(FuncType
, GlobalValue::ExternalLinkage
,
142 IF
.getAddressSpace(), IF
.getName(), &M
);
143 IF
.replaceAllUsesWith(Declaration
);
147 return PreservedAnalyses::none();