Utility functions for appending to llvm.used/llvm.compiler.used.

llvm-svn: 285143
This commit is contained in:
Evgeniy Stepanov 2016-10-25 23:53:31 +00:00
parent d64a9f9f9d
commit 2be3986f95
7 changed files with 76 additions and 100 deletions

View File

@ -44,7 +44,7 @@ private:
}
};
DenseMap<GlobalVariable *, PerFunctionProfileData> ProfileDataMap;
std::vector<Value *> UsedVars;
std::vector<GlobalValue *> UsedVars;
std::vector<GlobalVariable *> ReferencedNames;
GlobalVariable *NamesVar;
size_t NamesSize;

View File

@ -59,6 +59,12 @@ std::pair<Function *, Function *> createSanitizerCtorAndInitFunctions(
/// 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<GlobalValue *> Values);
/// \brief Adds global values to the llvm.compiler.used list.
void appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values);
} // End llvm namespace
#endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H

View File

@ -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 <system_error>
using namespace llvm;
@ -364,18 +365,10 @@ std::unique_ptr<TargetMachine> LTOCodeGenerator::createTargetMachine() {
void LTOCodeGenerator::preserveDiscardableGVs(
Module &TheModule,
llvm::function_ref<bool(const GlobalValue &)> mustPreserveGV) {
SetVector<Constant *> UsedValuesSet;
if (GlobalVariable *LLVMUsed =
TheModule.getGlobalVariable("llvm.compiler.used")) {
ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
for (auto &V : Inits->operands())
UsedValuesSet.insert(cast<Constant>(&V));
LLVMUsed->eraseFromParent();
}
llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(TheModule.getContext());
std::vector<GlobalValue *> Used;
auto mayPreserveGlobal = [&](GlobalValue &GV) {
if (!GV.isDiscardableIfUnused() || GV.isDeclaration() ||
!mustPreserveGV(GV))
!mustPreserveGV(GV))
return;
if (GV.hasAvailableExternallyLinkage())
return emitWarning(
@ -384,7 +377,7 @@ void LTOCodeGenerator::preserveDiscardableGVs(
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 @@ void LTOCodeGenerator::preserveDiscardableGVs(
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() {

View File

@ -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 @@ class PreserveLibCallsAndAsmUsed {
public:
PreserveLibCallsAndAsmUsed(const StringSet<> &AsmUndefinedRefs,
const TargetMachine &TM,
SmallPtrSetImpl<const GlobalValue *> &LLVMUsed)
std::vector<GlobalValue *> &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 @@ private:
StringSet<> Libcalls;
// Output
SmallPtrSetImpl<const GlobalValue *> &LLVMUsed;
std::vector<GlobalValue *> &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 @@ private:
}
}
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 @@ private:
// 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<Function>(GV) && Libcalls.count(GV.getName()))
LLVMUsed.insert(&GV);
if (isa<Function>(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 @@ private:
void llvm::updateCompilerUsed(Module &TheModule, const TargetMachine &TM,
const StringSet<> &AsmUndefinedRefs) {
SmallPtrSet<const GlobalValue *, 8> UsedValues;
std::vector<GlobalValue *> UsedValues;
PreserveLibCallsAndAsmUsed(AsmUndefinedRefs, TM, UsedValues)
.findInModule(TheModule);
if (UsedValues.empty())
return;
llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(TheModule.getContext());
std::vector<Constant *> UsedValuesList;
for (const auto *GV : UsedValues) {
Constant *c =
ConstantExpr::getBitCast(const_cast<GlobalValue *>(GV), i8PTy);
UsedValuesList.push_back(c);
}
GlobalVariable *LLVMUsed = TheModule.getGlobalVariable("llvm.compiler.used");
if (LLVMUsed) {
ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
for (auto &V : Inits->operands())
UsedValuesList.push_back(cast<Constant>(&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);
}

View File

@ -1624,7 +1624,7 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
StructType *LivenessTy = StructType::get(IntptrTy, IntptrTy, nullptr);
// Keep the list of "Liveness" GV created to be added to llvm.compiler.used
SmallVector<Constant *, 16> LivenessGlobals;
SmallVector<GlobalValue *, 16> LivenessGlobals;
LivenessGlobals.reserve(n);
for (size_t i = 0; i < n; i++) {
@ -1647,30 +1647,15 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
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<ConstantArray>(LLVMUsed->getInitializer());
for (auto &V : Inits->operands())
LivenessGlobals.push_back(cast<Constant>(&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.

View File

@ -553,31 +553,8 @@ void InstrProfiling::emitRuntimeHook() {
}
void InstrProfiling::emitUses() {
if (UsedVars.empty())
return;
GlobalVariable *LLVMUsed = M->getGlobalVariable("llvm.used");
std::vector<Constant *> MergedVars;
if (LLVMUsed) {
// Collect the existing members of llvm.used.
ConstantArray *Inits = cast<ConstantArray>(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<Constant>(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() {

View File

@ -89,6 +89,44 @@ void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *D
appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data);
}
static void appendToUsedList(Module &M, StringRef Name, ArrayRef<GlobalValue *> Values) {
GlobalVariable *GV = M.getGlobalVariable(Name);
SmallPtrSet<Constant *, 16> InitAsSet;
SmallVector<Constant *, 16> Init;
if (GV) {
ConstantArray *CA = dyn_cast<ConstantArray>(GV->getInitializer());
for (auto &Op : CA->operands()) {
Constant *C = cast_or_null<Constant>(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<GlobalValue *> Values) {
appendToUsedList(M, "llvm.used", Values);
}
void llvm::appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values) {
appendToUsedList(M, "llvm.compiler.used", Values);
}
Function *llvm::checkSanitizerInterfaceFunction(Constant *FuncOrBitcast) {
if (isa<Function>(FuncOrBitcast))
return cast<Function>(FuncOrBitcast);