/// Find the llvm.global_ctors list, verifying that all initializers have an /// init priority of 65535. static GlobalVariable *findGlobalCtors(Module &M) { GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors"); if (!GV) return nullptr; // Verify that the initializer is simple enough for us to handle. We are // only allowed to optimize the initializer if it is unique. if (!GV->hasUniqueInitializer()) return nullptr; if (isa<ConstantAggregateZero>(GV->getInitializer())) return GV; ConstantArray *CA = cast<ConstantArray>(GV->getInitializer()); for (auto &V : CA->operands()) { if (isa<ConstantAggregateZero>(V)) continue; ConstantStruct *CS = cast<ConstantStruct>(V); if (isa<ConstantPointerNull>(CS->getOperand(1))) continue; // Must have a function or null ptr. if (!isa<Function>(CS->getOperand(1))) return nullptr; // Init priority must be standard. ConstantInt *CI = cast<ConstantInt>(CS->getOperand(0)); if (CI->getZExtValue() != 65535) return nullptr; } return GV; }
/// Given a llvm.global_ctors list that we can understand, /// return a list of the functions and null terminator as a vector. static std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) { if (GV->getInitializer()->isNullValue()) return std::vector<Function *>(); ConstantArray *CA = cast<ConstantArray>(GV->getInitializer()); std::vector<Function *> Result; Result.reserve(CA->getNumOperands()); for (auto &V : CA->operands()) { ConstantStruct *CS = cast<ConstantStruct>(V); Result.push_back(dyn_cast<Function>(CS->getOperand(1))); } return Result; }
// If a linkonce global is present in the MustPreserveSymbols, we need to make // sure we honor this. To force the compiler to not drop it, we add it to the // "llvm.compiler.used" global. 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()); auto mayPreserveGlobal = [&](GlobalValue &GV) { if (!GV.isDiscardableIfUnused() || GV.isDeclaration()) return; if (!mustPreserveGV(GV)) return; if (GV.hasAvailableExternallyLinkage()) { emitWarning( (Twine("Linker asked to preserve available_externally global: '") + GV.getName() + "'").str()); return; } if (GV.hasInternalLinkage()) { emitWarning((Twine("Linker asked to preserve internal global: '") + GV.getName() + "'").str()); return; } UsedValuesSet.insert(ConstantExpr::getBitCast(&GV, i8PTy)); }; for (auto &GV : TheModule) mayPreserveGlobal(GV); for (auto &GV : TheModule.globals()) mayPreserveGlobal(GV); for (auto &GV : TheModule.aliases()) mayPreserveGlobal(GV); if (UsedValuesSet.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"); }