1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
//==-LTOInternalize.cpp - LLVM Link Time Optimizer Internalization Utility -==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a helper to run the internalization part of LTO.
//
//===----------------------------------------------------------------------===//
#include "LTOInternalize.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Transforms/IPO.h"
using namespace llvm;
namespace {
class ComputePreserveList {
public:
ComputePreserveList(const StringSet<> &MustPreserveSymbols,
const StringSet<> &AsmUndefinedRefs,
const TargetMachine &TM, const Module &TheModule,
StringMap<GlobalValue::LinkageTypes> *ExternalSymbols,
std::vector<const char *> &MustPreserveList,
SmallPtrSetImpl<const GlobalValue *> &AsmUsed)
: MustPreserveSymbols(MustPreserveSymbols),
AsmUndefinedRefs(AsmUndefinedRefs), TM(TM),
ExternalSymbols(ExternalSymbols), MustPreserveList(MustPreserveList),
AsmUsed(AsmUsed) {
accumulateAndSortLibcalls(TheModule);
for (const Function &F : TheModule)
applyRestriction(F);
for (const GlobalVariable &GV : TheModule.globals())
applyRestriction(GV);
for (const GlobalAlias &GA : TheModule.aliases())
applyRestriction(GA);
}
private:
// Inputs
const StringSet<> &MustPreserveSymbols;
const StringSet<> AsmUndefinedRefs;
const TargetMachine &TM;
// Temps
Mangler Mangler;
std::vector<StringRef> Libcalls;
// Output
StringMap<GlobalValue::LinkageTypes> *ExternalSymbols;
std::vector<const char *> &MustPreserveList;
SmallPtrSetImpl<const GlobalValue *> &AsmUsed;
// Collect names of runtime library functions. User-defined functions with the
// same names are added to llvm.compiler.used to prevent them from being
// deleted by optimizations.
void accumulateAndSortLibcalls(const Module &TheModule) {
TargetLibraryInfoImpl TLII(Triple(TM.getTargetTriple()));
TargetLibraryInfo TLI(TLII);
// TargetLibraryInfo has info on C runtime library calls on the current
// target.
for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs);
I != E; ++I) {
LibFunc::Func F = static_cast<LibFunc::Func>(I);
if (TLI.has(F))
Libcalls.push_back(TLI.getName(F));
}
SmallPtrSet<const TargetLowering *, 1> TLSet;
for (const Function &F : TheModule) {
const TargetLowering *Lowering =
TM.getSubtargetImpl(F)->getTargetLowering();
if (Lowering && TLSet.insert(Lowering).second)
// TargetLowering has info on library calls that CodeGen expects to be
// available, both from the C runtime and compiler-rt.
for (unsigned I = 0, E = static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL);
I != E; ++I)
if (const char *Name =
Lowering->getLibcallName(static_cast<RTLIB::Libcall>(I)))
Libcalls.push_back(Name);
}
array_pod_sort(Libcalls.begin(), Libcalls.end());
Libcalls.erase(std::unique(Libcalls.begin(), Libcalls.end()),
Libcalls.end());
}
void applyRestriction(const GlobalValue &GV) {
// There are no restrictions to apply to declarations.
if (GV.isDeclaration())
return;
// There is nothing more restrictive than private linkage.
if (GV.hasPrivateLinkage())
return;
SmallString<64> Buffer;
TM.getNameWithPrefix(Buffer, &GV, Mangler);
if (MustPreserveSymbols.count(Buffer))
MustPreserveList.push_back(GV.getName().data());
if (AsmUndefinedRefs.count(Buffer))
AsmUsed.insert(&GV);
// Conservatively append user-supplied runtime library functions to
// llvm.compiler.used. These could be internalized and deleted by
// optimizations like -globalopt, causing problems when later optimizations
// add new library calls (e.g., llvm.memset => memset and printf => puts).
// Leave it to the linker to remove any dead code (e.g. with -dead_strip).
if (isa<Function>(GV) &&
std::binary_search(Libcalls.begin(), Libcalls.end(), GV.getName()))
AsmUsed.insert(&GV);
// Record the linkage type of non-local symbols so they can be restored
// prior
// to module splitting.
if (ExternalSymbols && !GV.hasAvailableExternallyLinkage() &&
!GV.hasLocalLinkage() && GV.hasName())
ExternalSymbols->insert(std::make_pair(GV.getName(), GV.getLinkage()));
}
};
} // namespace anonymous
static void findUsedValues(GlobalVariable *LLVMUsed,
SmallPtrSetImpl<const GlobalValue *> &UsedValues) {
if (!LLVMUsed)
return;
ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
if (GlobalValue *GV =
dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
UsedValues.insert(GV);
}
void llvm::LTOInternalize(
Module &TheModule, const TargetMachine &TM,
const StringSet<> &MustPreserveSymbols, const StringSet<> &AsmUndefinedRefs,
StringMap<GlobalValue::LinkageTypes> *ExternalSymbols) {
legacy::PassManager passes;
// mark which symbols can not be internalized
Mangler Mangler;
std::vector<const char *> MustPreserveList;
SmallPtrSet<const GlobalValue *, 8> AsmUsed;
ComputePreserveList(MustPreserveSymbols, AsmUndefinedRefs, TM, TheModule,
ExternalSymbols, MustPreserveList, AsmUsed);
GlobalVariable *LLVMCompilerUsed =
TheModule.getGlobalVariable("llvm.compiler.used");
findUsedValues(LLVMCompilerUsed, AsmUsed);
if (LLVMCompilerUsed)
LLVMCompilerUsed->eraseFromParent();
if (!AsmUsed.empty()) {
llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(TheModule.getContext());
std::vector<Constant *> asmUsed2;
for (const auto *GV : AsmUsed) {
Constant *c =
ConstantExpr::getBitCast(const_cast<GlobalValue *>(GV), i8PTy);
asmUsed2.push_back(c);
}
llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size());
LLVMCompilerUsed = new llvm::GlobalVariable(
TheModule, ATy, false, llvm::GlobalValue::AppendingLinkage,
llvm::ConstantArray::get(ATy, asmUsed2), "llvm.compiler.used");
LLVMCompilerUsed->setSection("llvm.metadata");
}
passes.add(createInternalizePass(MustPreserveList));
// apply scope restrictions
passes.run(TheModule);
}
|