llvm.org GIT mirror llvm / 4ef7eaf
Respect llvm.used in Internalize. The language reference says that: "If a symbol appears in the @llvm.used list, then the compiler, assembler, and linker are required to treat the symbol as if there is a reference to the symbol that it cannot see" Since even the linker cannot see the reference, we must assume that the reference can be using the symbol table. For example, a user can add __attribute__((used)) to a debug helper function like dump and use it from a debugger. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187103 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 6 years ago
5 changed file(s) with 69 addition(s) and 21 deletion(s). Raw diff Collapse all Expand all
1717
1818 class Module;
1919 class Function;
20 class GlobalValue;
21 class GlobalVariable;
22 template class SmallPtrSet;
2023
2124 /// Append F to the list of global ctors of module M with the given Priority.
2225 /// This wraps the function in the appropriate structure and stores it along
2730 /// Same as appendToGlobalCtors(), but for global dtors.
2831 void appendToGlobalDtors(Module &M, Function *F, int Priority);
2932
33 /// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect
34 /// the initializer elements of that global in Set and return the global itself.
35 GlobalVariable *collectUsedGlobalVariables(Module &M,
36 SmallPtrSet &Set,
37 bool CompilerUsed);
3038 } // End llvm namespace
3139
3240 #endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
3737 #include "llvm/Support/MathExtras.h"
3838 #include "llvm/Support/raw_ostream.h"
3939 #include "llvm/Target/TargetLibraryInfo.h"
40 #include "llvm/Transforms/Utils/ModuleUtils.h"
4041 #include
4142 using namespace llvm;
4243
30393040 return true;
30403041 }
30413042
3042 /// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect
3043 /// the initializer elements of that global in Set and return the global itself.
3044 static GlobalVariable *
3045 collectUsedGlobalVariables(Module &M, const char *Name,
3046 SmallPtrSet &Set) {
3047 GlobalVariable *GV = M.getGlobalVariable(Name);
3048 if (!GV || !GV->hasInitializer())
3049 return GV;
3050
3051 const ConstantArray *Init = cast(GV->getInitializer());
3052 for (unsigned I = 0, E = Init->getNumOperands(); I != E; ++I) {
3053 Value *Op = Init->getOperand(I);
3054 GlobalValue *G = cast(Op->stripPointerCastsNoFollowAliases());
3055 Set.insert(G);
3056 }
3057 return GV;
3058 }
3059
30603043 static int compareNames(const void *A, const void *B) {
30613044 const GlobalValue *VA = *reinterpret_cast(A);
30623045 const GlobalValue *VB = *reinterpret_cast(B);
31063089
31073090 public:
31083091 LLVMUsed(Module &M) {
3109 UsedV = collectUsedGlobalVariables(M, "llvm.used", Used);
3110 CompilerUsedV =
3111 collectUsedGlobalVariables(M, "llvm.compiler.used", CompilerUsed);
3092 UsedV = collectUsedGlobalVariables(M, Used, false);
3093 CompilerUsedV = collectUsedGlobalVariables(M, CompilerUsed, true);
31123094 }
31133095 typedef SmallPtrSet::iterator iterator;
31143096 iterator usedBegin() { return Used.begin(); }
1414
1515 #define DEBUG_TYPE "internalize"
1616 #include "llvm/Transforms/IPO.h"
17 #include "llvm/ADT/SmallPtrSet.h"
1718 #include "llvm/ADT/Statistic.h"
1819 #include "llvm/Analysis/CallGraph.h"
1920 #include "llvm/IR/Module.h"
2122 #include "llvm/Support/CommandLine.h"
2223 #include "llvm/Support/Debug.h"
2324 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/Transforms/Utils/ModuleUtils.h"
2426 #include
2527 #include
2628 using namespace llvm;
115117 // FIXME: We should probably add this (and the __stack_chk_guard) via some
116118 // type of call-back in CodeGen.
117119 ExternalNames.insert("__stack_chk_fail");
120
121 SmallPtrSet Used;
122 collectUsedGlobalVariables(M, Used, false);
123
124 // We must assume that globals in llvm.used have a reference that not even
125 // the linker can see, so we don't internalize them.
126 // For llvm.compiler.used the situation is a bit fuzzy. The assembler and
127 // linker can drop those symbols. If this pass is running as part of LTO,
128 // one might think that it could just drop llvm.compiler.used. The problem
129 // is that even in LTO llvm doesn't see every reference. For example,
130 // we don't see references from function local inline assembly. To be
131 // conservative, we internalize symbols in llvm.compiler.used, but we
132 // keep llvm.compiler.used so that the symbol is not deleted by llvm.
133 for (SmallPtrSet::iterator I = Used.begin(), E = Used.end();
134 I != E; ++I) {
135 GlobalValue *V = *I;
136 ExternalNames.insert(V->getName());
137 }
118138
119139 // Mark all functions not in the api as internal.
120140 // FIXME: maybe use private linkage?
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "llvm/Transforms/Utils/ModuleUtils.h"
14 #include "llvm/ADT/SmallPtrSet.h"
1415 #include "llvm/IR/DerivedTypes.h"
1516 #include "llvm/IR/Function.h"
1617 #include "llvm/IR/IRBuilder.h"
6162 void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority) {
6263 appendToGlobalArray("llvm.global_dtors", M, F, Priority);
6364 }
65
66 GlobalVariable *
67 llvm::collectUsedGlobalVariables(Module &M, SmallPtrSet &Set,
68 bool CompilerUsed) {
69 const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used";
70 GlobalVariable *GV = M.getGlobalVariable(Name);
71 if (!GV || !GV->hasInitializer())
72 return GV;
73
74 const ConstantArray *Init = cast(GV->getInitializer());
75 for (unsigned I = 0, E = Init->getNumOperands(); I != E; ++I) {
76 Value *Op = Init->getOperand(I);
77 GlobalValue *G = cast(Op->stripPointerCastsNoFollowAliases());
78 Set.insert(G);
79 }
80 return GV;
81 }
0 ; RUN: opt < %s -internalize -S | FileCheck %s
1
2 @llvm.used = appending global [1 x void ()*] [void ()* @f], section "llvm.metadata"
3
4 @llvm.compiler.used = appending global [1 x void ()*] [void ()* @g], section "llvm.metadata"
5
6 ; CHECK: define void @f()
7 define void @f() {
8 ret void
9 }
10
11 ; CHECK: define internal void @g()
12 define void @g() {
13 ret void
14 }
15
16 ; CHECK: define internal void @h()
17 define void @h() {
18 ret void
19 }