xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/IPO/ExtractGV.cpp (revision 9f23cbd6cae82fd77edfad7173432fa8dccd0a95)
1 //===-- ExtractGV.cpp - Global Value extraction pass ----------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass extracts global values
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/Transforms/IPO/ExtractGV.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/IR/PassManager.h"
16 #include <algorithm>
17 
18 using namespace llvm;
19 
20 /// Make sure GV is visible from both modules. Delete is true if it is
21 /// being deleted from this module.
22 /// This also makes sure GV cannot be dropped so that references from
23 /// the split module remain valid.
24 static void makeVisible(GlobalValue &GV, bool Delete) {
25   bool Local = GV.hasLocalLinkage();
26   if (Local || Delete) {
27     GV.setLinkage(GlobalValue::ExternalLinkage);
28     if (Local)
29       GV.setVisibility(GlobalValue::HiddenVisibility);
30     return;
31   }
32 
33   if (!GV.hasLinkOnceLinkage()) {
34     assert(!GV.isDiscardableIfUnused());
35     return;
36   }
37 
38   // Map linkonce* to weak* so that llvm doesn't drop this GV.
39   switch(GV.getLinkage()) {
40   default:
41     llvm_unreachable("Unexpected linkage");
42   case GlobalValue::LinkOnceAnyLinkage:
43     GV.setLinkage(GlobalValue::WeakAnyLinkage);
44     return;
45   case GlobalValue::LinkOnceODRLinkage:
46     GV.setLinkage(GlobalValue::WeakODRLinkage);
47     return;
48   }
49 }
50 
51 
52     /// If deleteS is true, this pass deletes the specified global values.
53     /// Otherwise, it deletes as much of the module as possible, except for the
54     /// global values specified.
55 ExtractGVPass::ExtractGVPass(std::vector<GlobalValue *> &GVs, bool deleteS,
56                              bool keepConstInit)
57     : Named(GVs.begin(), GVs.end()), deleteStuff(deleteS),
58       keepConstInit(keepConstInit) {}
59 
60 PreservedAnalyses ExtractGVPass::run(Module &M, ModuleAnalysisManager &) {
61   // Visit the global inline asm.
62   if (!deleteStuff)
63     M.setModuleInlineAsm("");
64 
65   // For simplicity, just give all GlobalValues ExternalLinkage. A trickier
66   // implementation could figure out which GlobalValues are actually
67   // referenced by the Named set, and which GlobalValues in the rest of
68   // the module are referenced by the NamedSet, and get away with leaving
69   // more internal and private things internal and private. But for now,
70   // be conservative and simple.
71 
72   // Visit the GlobalVariables.
73   for (GlobalVariable &GV : M.globals()) {
74     bool Delete = deleteStuff == (bool)Named.count(&GV) &&
75                   !GV.isDeclaration() && (!GV.isConstant() || !keepConstInit);
76     if (!Delete) {
77       if (GV.hasAvailableExternallyLinkage())
78         continue;
79       if (GV.getName() == "llvm.global_ctors")
80         continue;
81     }
82 
83     makeVisible(GV, Delete);
84 
85     if (Delete) {
86       // Make this a declaration and drop it's comdat.
87       GV.setInitializer(nullptr);
88       GV.setComdat(nullptr);
89     }
90   }
91 
92   // Visit the Functions.
93   for (Function &F : M) {
94     bool Delete = deleteStuff == (bool)Named.count(&F) && !F.isDeclaration();
95     if (!Delete) {
96       if (F.hasAvailableExternallyLinkage())
97         continue;
98     }
99 
100     makeVisible(F, Delete);
101 
102     if (Delete) {
103       // Make this a declaration and drop it's comdat.
104       F.deleteBody();
105       F.setComdat(nullptr);
106     }
107   }
108 
109   // Visit the Aliases.
110   for (GlobalAlias &GA : llvm::make_early_inc_range(M.aliases())) {
111     bool Delete = deleteStuff == (bool)Named.count(&GA);
112     makeVisible(GA, Delete);
113 
114     if (Delete) {
115       Type *Ty = GA.getValueType();
116 
117       GA.removeFromParent();
118       llvm::Value *Declaration;
119       if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
120         Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage,
121                                        GA.getAddressSpace(), GA.getName(), &M);
122 
123       } else {
124         Declaration = new GlobalVariable(
125             M, Ty, false, GlobalValue::ExternalLinkage, nullptr, GA.getName());
126       }
127       GA.replaceAllUsesWith(Declaration);
128       delete &GA;
129     }
130   }
131 
132   return PreservedAnalyses::none();
133 }
134