1 //==-LTOInternalize.cpp - LLVM Link Time Optimizer Internalization Utility -==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines a helper to run the internalization part of LTO. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/LTO/legacy/UpdateCompilerUsed.h" 15 #include "llvm/Analysis/TargetLibraryInfo.h" 16 #include "llvm/IR/LegacyPassManager.h" 17 #include "llvm/IR/Mangler.h" 18 #include "llvm/Target/TargetLowering.h" 19 #include "llvm/Target/TargetSubtargetInfo.h" 20 #include "llvm/Transforms/IPO/Internalize.h" 21 22 using namespace llvm; 23 24 namespace { 25 26 // Helper class that collects AsmUsed and user supplied libcalls. 27 class PreserveLibCallsAndAsmUsed { 28 public: 29 PreserveLibCallsAndAsmUsed(const StringSet<> &AsmUndefinedRefs, 30 const TargetMachine &TM, 31 SmallPtrSetImpl<const GlobalValue *> &LLVMUsed) 32 : AsmUndefinedRefs(AsmUndefinedRefs), TM(TM), LLVMUsed(LLVMUsed) {} 33 34 void findInModule(const Module &TheModule) { 35 initializeLibCalls(TheModule); 36 for (const Function &F : TheModule) 37 findLibCallsAndAsm(F); 38 for (const GlobalVariable &GV : TheModule.globals()) 39 findLibCallsAndAsm(GV); 40 for (const GlobalAlias &GA : TheModule.aliases()) 41 findLibCallsAndAsm(GA); 42 } 43 44 private: 45 // Inputs 46 const StringSet<> &AsmUndefinedRefs; 47 const TargetMachine &TM; 48 49 // Temps 50 llvm::Mangler Mangler; 51 StringSet<> Libcalls; 52 53 // Output 54 SmallPtrSetImpl<const GlobalValue *> &LLVMUsed; 55 56 // Collect names of runtime library functions. User-defined functions with the 57 // same names are added to llvm.compiler.used to prevent them from being 58 // deleted by optimizations. 59 void initializeLibCalls(const Module &TheModule) { 60 TargetLibraryInfoImpl TLII(Triple(TM.getTargetTriple())); 61 TargetLibraryInfo TLI(TLII); 62 63 // TargetLibraryInfo has info on C runtime library calls on the current 64 // target. 65 for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs); 66 I != E; ++I) { 67 LibFunc::Func F = static_cast<LibFunc::Func>(I); 68 if (TLI.has(F)) 69 Libcalls.insert(TLI.getName(F)); 70 } 71 72 SmallPtrSet<const TargetLowering *, 1> TLSet; 73 74 for (const Function &F : TheModule) { 75 const TargetLowering *Lowering = 76 TM.getSubtargetImpl(F)->getTargetLowering(); 77 78 if (Lowering && TLSet.insert(Lowering).second) 79 // TargetLowering has info on library calls that CodeGen expects to be 80 // available, both from the C runtime and compiler-rt. 81 for (unsigned I = 0, E = static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL); 82 I != E; ++I) 83 if (const char *Name = 84 Lowering->getLibcallName(static_cast<RTLIB::Libcall>(I))) 85 Libcalls.insert(Name); 86 } 87 } 88 89 void findLibCallsAndAsm(const GlobalValue &GV) { 90 // There are no restrictions to apply to declarations. 91 if (GV.isDeclaration()) 92 return; 93 94 // There is nothing more restrictive than private linkage. 95 if (GV.hasPrivateLinkage()) 96 return; 97 98 // Conservatively append user-supplied runtime library functions to 99 // llvm.compiler.used. These could be internalized and deleted by 100 // optimizations like -globalopt, causing problems when later optimizations 101 // add new library calls (e.g., llvm.memset => memset and printf => puts). 102 // Leave it to the linker to remove any dead code (e.g. with -dead_strip). 103 if (isa<Function>(GV) && Libcalls.count(GV.getName())) 104 LLVMUsed.insert(&GV); 105 106 SmallString<64> Buffer; 107 TM.getNameWithPrefix(Buffer, &GV, Mangler); 108 if (AsmUndefinedRefs.count(Buffer)) 109 LLVMUsed.insert(&GV); 110 } 111 }; 112 113 } // namespace anonymous 114 115 void llvm::updateCompilerUsed(Module &TheModule, const TargetMachine &TM, 116 const StringSet<> &AsmUndefinedRefs) { 117 SmallPtrSet<const GlobalValue *, 8> UsedValues; 118 PreserveLibCallsAndAsmUsed(AsmUndefinedRefs, TM, UsedValues) 119 .findInModule(TheModule); 120 121 if (UsedValues.empty()) 122 return; 123 124 llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(TheModule.getContext()); 125 std::vector<Constant *> UsedValuesList; 126 for (const auto *GV : UsedValues) { 127 Constant *c = 128 ConstantExpr::getBitCast(const_cast<GlobalValue *>(GV), i8PTy); 129 UsedValuesList.push_back(c); 130 } 131 132 GlobalVariable *LLVMUsed = TheModule.getGlobalVariable("llvm.compiler.used"); 133 if (LLVMUsed) { 134 ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer()); 135 for (auto &V : Inits->operands()) 136 UsedValuesList.push_back(cast<Constant>(&V)); 137 LLVMUsed->eraseFromParent(); 138 } 139 140 llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, UsedValuesList.size()); 141 LLVMUsed = new llvm::GlobalVariable( 142 TheModule, ATy, false, llvm::GlobalValue::AppendingLinkage, 143 llvm::ConstantArray::get(ATy, UsedValuesList), "llvm.compiler.used"); 144 145 LLVMUsed->setSection("llvm.metadata"); 146 } 147