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/CodeGen/TargetLowering.h" 17 #include "llvm/CodeGen/TargetSubtargetInfo.h" 18 #include "llvm/IR/LegacyPassManager.h" 19 #include "llvm/IR/Mangler.h" 20 #include "llvm/Transforms/IPO/Internalize.h" 21 #include "llvm/Transforms/Utils/ModuleUtils.h" 22 23 using namespace llvm; 24 25 namespace { 26 27 // Helper class that collects AsmUsed and user supplied libcalls. 28 class PreserveLibCallsAndAsmUsed { 29 public: 30 PreserveLibCallsAndAsmUsed(const StringSet<> &AsmUndefinedRefs, 31 const TargetMachine &TM, 32 std::vector<GlobalValue *> &LLVMUsed) 33 : AsmUndefinedRefs(AsmUndefinedRefs), TM(TM), LLVMUsed(LLVMUsed) {} 34 35 void findInModule(Module &TheModule) { 36 initializeLibCalls(TheModule); 37 for (Function &F : TheModule) 38 findLibCallsAndAsm(F); 39 for (GlobalVariable &GV : TheModule.globals()) 40 findLibCallsAndAsm(GV); 41 for (GlobalAlias &GA : TheModule.aliases()) 42 findLibCallsAndAsm(GA); 43 } 44 45 private: 46 // Inputs 47 const StringSet<> &AsmUndefinedRefs; 48 const TargetMachine &TM; 49 50 // Temps 51 llvm::Mangler Mangler; 52 StringSet<> Libcalls; 53 54 // Output 55 std::vector<GlobalValue *> &LLVMUsed; 56 57 // Collect names of runtime library functions. User-defined functions with the 58 // same names are added to llvm.compiler.used to prevent them from being 59 // deleted by optimizations. 60 void initializeLibCalls(const Module &TheModule) { 61 TargetLibraryInfoImpl TLII(Triple(TM.getTargetTriple())); 62 TargetLibraryInfo TLI(TLII); 63 64 // TargetLibraryInfo has info on C runtime library calls on the current 65 // target. 66 for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs); 67 I != E; ++I) { 68 LibFunc F = static_cast<LibFunc>(I); 69 if (TLI.has(F)) 70 Libcalls.insert(TLI.getName(F)); 71 } 72 73 SmallPtrSet<const TargetLowering *, 1> TLSet; 74 75 for (const Function &F : TheModule) { 76 const TargetLowering *Lowering = 77 TM.getSubtargetImpl(F)->getTargetLowering(); 78 79 if (Lowering && TLSet.insert(Lowering).second) 80 // TargetLowering has info on library calls that CodeGen expects to be 81 // available, both from the C runtime and compiler-rt. 82 for (unsigned I = 0, E = static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL); 83 I != E; ++I) 84 if (const char *Name = 85 Lowering->getLibcallName(static_cast<RTLIB::Libcall>(I))) 86 Libcalls.insert(Name); 87 } 88 } 89 90 void findLibCallsAndAsm(GlobalValue &GV) { 91 // There are no restrictions to apply to declarations. 92 if (GV.isDeclaration()) 93 return; 94 95 // There is nothing more restrictive than private linkage. 96 if (GV.hasPrivateLinkage()) 97 return; 98 99 // Conservatively append user-supplied runtime library functions to 100 // llvm.compiler.used. These could be internalized and deleted by 101 // optimizations like -globalopt, causing problems when later optimizations 102 // add new library calls (e.g., llvm.memset => memset and printf => puts). 103 // Leave it to the linker to remove any dead code (e.g. with -dead_strip). 104 if (isa<Function>(GV) && Libcalls.count(GV.getName())) { 105 LLVMUsed.push_back(&GV); 106 return; 107 } 108 109 SmallString<64> Buffer; 110 TM.getNameWithPrefix(Buffer, &GV, Mangler); 111 if (AsmUndefinedRefs.count(Buffer)) 112 LLVMUsed.push_back(&GV); 113 } 114 }; 115 116 } // namespace anonymous 117 118 void llvm::updateCompilerUsed(Module &TheModule, const TargetMachine &TM, 119 const StringSet<> &AsmUndefinedRefs) { 120 std::vector<GlobalValue *> UsedValues; 121 PreserveLibCallsAndAsmUsed(AsmUndefinedRefs, TM, UsedValues) 122 .findInModule(TheModule); 123 124 if (UsedValues.empty()) 125 return; 126 127 appendToCompilerUsed(TheModule, UsedValues); 128 } 129