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