Index: include/llvm/Transforms/InstrProfiling.h =================================================================== --- include/llvm/Transforms/InstrProfiling.h +++ include/llvm/Transforms/InstrProfiling.h @@ -44,7 +44,7 @@ } }; DenseMap ProfileDataMap; - std::vector UsedVars; + std::vector UsedVars; std::vector ReferencedNames; GlobalVariable *NamesVar; size_t NamesSize; Index: include/llvm/Transforms/Utils/ModuleUtils.h =================================================================== --- include/llvm/Transforms/Utils/ModuleUtils.h +++ include/llvm/Transforms/Utils/ModuleUtils.h @@ -59,6 +59,12 @@ /// the list of public globals in the module. bool nameUnamedGlobals(Module &M); +/// \brief Adds global values to the llvm.used list. +void appendToUsed(Module &M, ArrayRef Values); + +/// \brief Adds global values to the llvm.compiler.used list. +void appendToCompilerUsed(Module &M, ArrayRef Values); + } // End llvm namespace #endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H Index: lib/LTO/LTOCodeGenerator.cpp =================================================================== --- lib/LTO/LTOCodeGenerator.cpp +++ lib/LTO/LTOCodeGenerator.cpp @@ -58,6 +58,7 @@ #include "llvm/Transforms/IPO/Internalize.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/ObjCARC.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" #include using namespace llvm; @@ -364,18 +365,10 @@ void LTOCodeGenerator::preserveDiscardableGVs( Module &TheModule, llvm::function_ref mustPreserveGV) { - SetVector UsedValuesSet; - if (GlobalVariable *LLVMUsed = - TheModule.getGlobalVariable("llvm.compiler.used")) { - ConstantArray *Inits = cast(LLVMUsed->getInitializer()); - for (auto &V : Inits->operands()) - UsedValuesSet.insert(cast(&V)); - LLVMUsed->eraseFromParent(); - } - llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(TheModule.getContext()); + std::vector Used; auto mayPreserveGlobal = [&](GlobalValue &GV) { if (!GV.isDiscardableIfUnused() || GV.isDeclaration() || - !mustPreserveGV(GV)) + !mustPreserveGV(GV)) return; if (GV.hasAvailableExternallyLinkage()) return emitWarning( @@ -384,7 +377,7 @@ if (GV.hasInternalLinkage()) return emitWarning((Twine("Linker asked to preserve internal global: '") + GV.getName() + "'").str()); - UsedValuesSet.insert(ConstantExpr::getBitCast(&GV, i8PTy)); + Used.push_back(&GV); }; for (auto &GV : TheModule) mayPreserveGlobal(GV); @@ -393,15 +386,10 @@ for (auto &GV : TheModule.aliases()) mayPreserveGlobal(GV); - if (UsedValuesSet.empty()) + if (Used.empty()) return; - llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, UsedValuesSet.size()); - auto *LLVMUsed = new llvm::GlobalVariable( - TheModule, ATy, false, llvm::GlobalValue::AppendingLinkage, - llvm::ConstantArray::get(ATy, UsedValuesSet.getArrayRef()), - "llvm.compiler.used"); - LLVMUsed->setSection("llvm.metadata"); + appendToCompilerUsed(TheModule, Used); } void LTOCodeGenerator::applyScopeRestrictions() { Index: lib/LTO/UpdateCompilerUsed.cpp =================================================================== --- lib/LTO/UpdateCompilerUsed.cpp +++ lib/LTO/UpdateCompilerUsed.cpp @@ -18,6 +18,7 @@ #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Transforms/IPO/Internalize.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; @@ -28,16 +29,16 @@ public: PreserveLibCallsAndAsmUsed(const StringSet<> &AsmUndefinedRefs, const TargetMachine &TM, - SmallPtrSetImpl &LLVMUsed) + std::vector &LLVMUsed) : AsmUndefinedRefs(AsmUndefinedRefs), TM(TM), LLVMUsed(LLVMUsed) {} - void findInModule(const Module &TheModule) { + void findInModule(Module &TheModule) { initializeLibCalls(TheModule); - for (const Function &F : TheModule) + for (Function &F : TheModule) findLibCallsAndAsm(F); - for (const GlobalVariable &GV : TheModule.globals()) + for (GlobalVariable &GV : TheModule.globals()) findLibCallsAndAsm(GV); - for (const GlobalAlias &GA : TheModule.aliases()) + for (GlobalAlias &GA : TheModule.aliases()) findLibCallsAndAsm(GA); } @@ -51,7 +52,7 @@ StringSet<> Libcalls; // Output - SmallPtrSetImpl &LLVMUsed; + std::vector &LLVMUsed; // Collect names of runtime library functions. User-defined functions with the // same names are added to llvm.compiler.used to prevent them from being @@ -86,7 +87,7 @@ } } - void findLibCallsAndAsm(const GlobalValue &GV) { + void findLibCallsAndAsm(GlobalValue &GV) { // There are no restrictions to apply to declarations. if (GV.isDeclaration()) return; @@ -100,13 +101,15 @@ // 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(GV) && Libcalls.count(GV.getName())) - LLVMUsed.insert(&GV); + if (isa(GV) && Libcalls.count(GV.getName())) { + LLVMUsed.push_back(&GV); + return; + } SmallString<64> Buffer; TM.getNameWithPrefix(Buffer, &GV, Mangler); if (AsmUndefinedRefs.count(Buffer)) - LLVMUsed.insert(&GV); + LLVMUsed.push_back(&GV); } }; @@ -114,33 +117,12 @@ void llvm::updateCompilerUsed(Module &TheModule, const TargetMachine &TM, const StringSet<> &AsmUndefinedRefs) { - SmallPtrSet UsedValues; + std::vector UsedValues; PreserveLibCallsAndAsmUsed(AsmUndefinedRefs, TM, UsedValues) .findInModule(TheModule); if (UsedValues.empty()) return; - llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(TheModule.getContext()); - std::vector UsedValuesList; - for (const auto *GV : UsedValues) { - Constant *c = - ConstantExpr::getBitCast(const_cast(GV), i8PTy); - UsedValuesList.push_back(c); - } - - GlobalVariable *LLVMUsed = TheModule.getGlobalVariable("llvm.compiler.used"); - if (LLVMUsed) { - ConstantArray *Inits = cast(LLVMUsed->getInitializer()); - for (auto &V : Inits->operands()) - UsedValuesList.push_back(cast(&V)); - LLVMUsed->eraseFromParent(); - } - - llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, UsedValuesList.size()); - LLVMUsed = new llvm::GlobalVariable( - TheModule, ATy, false, llvm::GlobalValue::AppendingLinkage, - llvm::ConstantArray::get(ATy, UsedValuesList), "llvm.compiler.used"); - - LLVMUsed->setSection("llvm.metadata"); + appendToCompilerUsed(TheModule, UsedValues); } Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -1624,7 +1624,7 @@ StructType *LivenessTy = StructType::get(IntptrTy, IntptrTy, nullptr); // Keep the list of "Liveness" GV created to be added to llvm.compiler.used - SmallVector LivenessGlobals; + SmallVector LivenessGlobals; LivenessGlobals.reserve(n); for (size_t i = 0; i < n; i++) { @@ -1647,30 +1647,15 @@ M, LivenessTy, false, GlobalVariable::InternalLinkage, LivenessBinder, Twine("__asan_binder_") + GVName); Liveness->setSection("__DATA,__asan_liveness,regular,live_support"); - LivenessGlobals.push_back( - ConstantExpr::getBitCast(Liveness, IRB.getInt8PtrTy())); + LivenessGlobals.push_back(Liveness); } - if (!LivenessGlobals.empty()) { - // Update llvm.compiler.used, adding the new liveness globals. This is - // needed so that during LTO these variables stay alive. The alternative - // would be to have the linker handling the LTO symbols, but libLTO - // current - // API does not expose access to the section for each symbol. - if (GlobalVariable *LLVMUsed = - M.getGlobalVariable("llvm.compiler.used")) { - ConstantArray *Inits = cast(LLVMUsed->getInitializer()); - for (auto &V : Inits->operands()) - LivenessGlobals.push_back(cast(&V)); - LLVMUsed->eraseFromParent(); - } - llvm::ArrayType *ATy = - llvm::ArrayType::get(IRB.getInt8PtrTy(), LivenessGlobals.size()); - auto *LLVMUsed = new llvm::GlobalVariable( - M, ATy, false, llvm::GlobalValue::AppendingLinkage, - llvm::ConstantArray::get(ATy, LivenessGlobals), "llvm.compiler.used"); - LLVMUsed->setSection("llvm.metadata"); - } + // Update llvm.compiler.used, adding the new liveness globals. This is + // needed so that during LTO these variables stay alive. The alternative + // would be to have the linker handling the LTO symbols, but libLTO + // current API does not expose access to the section for each symbol. + if (!LivenessGlobals.empty()) + appendToCompilerUsed(M, LivenessGlobals); } else { // On all other platfoms, we just emit an array of global metadata // structures. Index: lib/Transforms/Instrumentation/InstrProfiling.cpp =================================================================== --- lib/Transforms/Instrumentation/InstrProfiling.cpp +++ lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -553,31 +553,8 @@ } void InstrProfiling::emitUses() { - if (UsedVars.empty()) - return; - - GlobalVariable *LLVMUsed = M->getGlobalVariable("llvm.used"); - std::vector MergedVars; - if (LLVMUsed) { - // Collect the existing members of llvm.used. - ConstantArray *Inits = cast(LLVMUsed->getInitializer()); - for (unsigned I = 0, E = Inits->getNumOperands(); I != E; ++I) - MergedVars.push_back(Inits->getOperand(I)); - LLVMUsed->eraseFromParent(); - } - - Type *i8PTy = Type::getInt8PtrTy(M->getContext()); - // Add uses for our data. - for (auto *Value : UsedVars) - MergedVars.push_back( - ConstantExpr::getBitCast(cast(Value), i8PTy)); - - // Recreate llvm.used. - ArrayType *ATy = ArrayType::get(i8PTy, MergedVars.size()); - LLVMUsed = - new GlobalVariable(*M, ATy, false, GlobalValue::AppendingLinkage, - ConstantArray::get(ATy, MergedVars), "llvm.used"); - LLVMUsed->setSection("llvm.metadata"); + if (!UsedVars.empty()) + appendToUsed(*M, UsedVars); } void InstrProfiling::emitInitialization() { Index: lib/Transforms/Utils/ModuleUtils.cpp =================================================================== --- lib/Transforms/Utils/ModuleUtils.cpp +++ lib/Transforms/Utils/ModuleUtils.cpp @@ -89,6 +89,44 @@ appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data); } +static void appendToUsedList(Module &M, StringRef Name, ArrayRef Values) { + GlobalVariable *GV = M.getGlobalVariable(Name); + SmallPtrSet InitAsSet; + SmallVector Init; + if (GV) { + ConstantArray *CA = dyn_cast(GV->getInitializer()); + for (auto &Op : CA->operands()) { + Constant *C = cast_or_null(Op); + if (InitAsSet.insert(C).second) + Init.push_back(C); + } + GV->eraseFromParent(); + } + + Type *Int8PtrTy = llvm::Type::getInt8PtrTy(M.getContext()); + for (auto *V : Values) { + Constant *C = ConstantExpr::getBitCast(V, Int8PtrTy); + if (InitAsSet.insert(C).second) + Init.push_back(C); + } + + if (Init.empty()) + return; + + ArrayType *ATy = ArrayType::get(Int8PtrTy, Init.size()); + GV = new llvm::GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage, + ConstantArray::get(ATy, Init), Name); + GV->setSection("llvm.metadata"); +} + +void llvm::appendToUsed(Module &M, ArrayRef Values) { + appendToUsedList(M, "llvm.used", Values); +} + +void llvm::appendToCompilerUsed(Module &M, ArrayRef Values) { + appendToUsedList(M, "llvm.compiler.used", Values); +} + Function *llvm::checkSanitizerInterfaceFunction(Constant *FuncOrBitcast) { if (isa(FuncOrBitcast)) return cast(FuncOrBitcast);