void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // Check to see if this is a special global used by LLVM, if so, emit it. if (!GV->hasInitializer() || EmitSpecialLLVMGlobal(GV)) return; const TargetData *TD = TM.getTargetData(); OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM)); MCSymbol *GVSym = Mang->getSymbol(GV); Constant *C = GV->getInitializer(); unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); // Mark the start of the global OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," + GVSym->getName()); switch (GV->getLinkage()) { case GlobalValue::AppendingLinkage: report_fatal_error("AppendingLinkage is not supported by this target!"); case GlobalValue::LinkOnceAnyLinkage: case GlobalValue::LinkOnceODRLinkage: case GlobalValue::WeakAnyLinkage: case GlobalValue::WeakODRLinkage: case GlobalValue::ExternalLinkage: emitArrayBound(GVSym, GV); OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); // TODO Use COMDAT groups for LinkOnceLinkage if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); // FALL THROUGH case GlobalValue::InternalLinkage: case GlobalValue::PrivateLinkage: case GlobalValue::LinkerPrivateLinkage: break; case GlobalValue::DLLImportLinkage: llvm_unreachable("DLLImport linkage is not supported by this target!"); case GlobalValue::DLLExportLinkage: llvm_unreachable("DLLExport linkage is not supported by this target!"); default: llvm_unreachable("Unknown linkage type!"); } EmitAlignment(Align > 2 ? Align : 2, GV); unsigned Size = TD->getTypeAllocSize(C->getType()); if (GV->isThreadLocal()) { Size *= MaxThreads; } if (MAI->hasDotTypeDotSizeDirective()) { OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," + Twine(Size)); } OutStreamer.EmitLabel(GVSym); EmitGlobalConstant(C); if (GV->isThreadLocal()) { for (unsigned i = 1; i < MaxThreads; ++i) EmitGlobalConstant(C); } // The ABI requires that unsigned scalar types smaller than 32 bits // are padded to 32 bits. if (Size < 4) OutStreamer.EmitZeros(4 - Size, 0); // Mark the end of the global OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data"); }
// llvm_asm_file_end - Finish the .s file. void llvm_asm_file_end(void) { timevar_push(TV_LLVM_PERFILE); llvm_shutdown_obj X; // Call llvm_shutdown() on exit. if (flag_pch_file) { writeLLVMTypesStringTable(); writeLLVMValues(); } // Add an llvm.global_ctors global if needed. if (!StaticCtors.empty()) CreateStructorsList(StaticCtors, "llvm.global_ctors"); // Add an llvm.global_dtors global if needed. if (!StaticDtors.empty()) CreateStructorsList(StaticDtors, "llvm.global_dtors"); if (!AttributeUsedGlobals.empty()) { const Type *SBP = PointerType::get(Type::Int8Ty); ArrayType *AT = ArrayType::get(SBP, AttributeUsedGlobals.size()); Constant *Init = ConstantArray::get(AT, AttributeUsedGlobals); GlobalValue* gv = new GlobalVariable(AT, false, GlobalValue::AppendingLinkage, Init, "llvm.used", TheModule); gv->setSection("llvm.metadata"); AttributeUsedGlobals.clear(); } // Add llvm.noinline if (!AttributeNoinlineFunctions.empty()) { const Type *SBP= PointerType::get(Type::Int8Ty); ArrayType *AT = ArrayType::get(SBP, AttributeNoinlineFunctions.size()); Constant *Init = ConstantArray::get(AT, AttributeNoinlineFunctions); GlobalValue *gv = new GlobalVariable(AT, false, GlobalValue::AppendingLinkage, Init, "llvm.noinline", TheModule); gv->setSection("llvm.metadata"); // Clear vector AttributeNoinlineFunctions.clear(); } // Add llvm.global.annotations if (!AttributeAnnotateGlobals.empty()) { Constant *Array = ConstantArray::get(ArrayType::get(AttributeAnnotateGlobals[0]->getType(), AttributeAnnotateGlobals.size()), AttributeAnnotateGlobals); GlobalValue *gv = new GlobalVariable(Array->getType(), false, GlobalValue::AppendingLinkage, Array, "llvm.global.annotations", TheModule); gv->setSection("llvm.metadata"); AttributeAnnotateGlobals.clear(); } // Finish off the per-function pass. if (PerFunctionPasses) PerFunctionPasses->doFinalization(); // Run module-level optimizers, if any are present. if (PerModulePasses) PerModulePasses->run(*TheModule); // Run the code generator, if present. if (CodeGenPasses) { CodeGenPasses->doInitialization(); for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E; ++I) if (!I->isDeclaration()) CodeGenPasses->run(*I); CodeGenPasses->doFinalization(); } AsmOutStream->flush(); fflush(asm_out_file); delete AsmOutStream; AsmOutStream = 0; delete AsmOutFile; AsmOutFile = 0; timevar_pop(TV_LLVM_PERFILE); }
/// emit_global_to_llvm - Emit the specified VAR_DECL or aggregate CONST_DECL to /// LLVM as a global variable. This function implements the end of /// assemble_variable. void emit_global_to_llvm(tree decl) { if (errorcount || sorrycount) return; // FIXME: Support alignment on globals: DECL_ALIGN. // FIXME: DECL_PRESERVE_P indicates the var is marked with attribute 'used'. // Global register variables don't turn into LLVM GlobalVariables. if (TREE_CODE(decl) == VAR_DECL && DECL_REGISTER(decl)) return; timevar_push(TV_LLVM_GLOBALS); // Get or create the global variable now. GlobalVariable *GV = cast<GlobalVariable>(DECL_LLVM(decl)); // Convert the initializer over. Constant *Init; if (DECL_INITIAL(decl) == 0 || DECL_INITIAL(decl) == error_mark_node) { // This global should be zero initialized. Reconvert the type in case the // forward def of the global and the real def differ in type (e.g. declared // as 'int A[]', and defined as 'int A[100]'). Init = Constant::getNullValue(ConvertType(TREE_TYPE(decl))); } else { assert((TREE_CONSTANT(DECL_INITIAL(decl)) || TREE_CODE(DECL_INITIAL(decl)) == STRING_CST) && "Global initializer should be constant!"); // Temporarily set an initializer for the global, so we don't infinitely // recurse. If we don't do this, we can hit cases where we see "oh a global // with an initializer hasn't been initialized yet, call emit_global_to_llvm // on it". When constructing the initializer it might refer to itself. // this can happen for things like void *G = &G; // GV->setInitializer(UndefValue::get(GV->getType()->getElementType())); Init = TreeConstantToLLVM::Convert(DECL_INITIAL(decl)); } // If we had a forward definition that has a type that disagrees with our // initializer, insert a cast now. This sort of thing occurs when we have a // global union, and the LLVM type followed a union initializer that is // different from the union element used for the type. if (GV->getType()->getElementType() != Init->getType()) { GV->removeFromParent(); GlobalVariable *NGV = new GlobalVariable(Init->getType(), GV->isConstant(), GlobalValue::ExternalLinkage, 0, GV->getName(), TheModule); GV->replaceAllUsesWith(ConstantExpr::getBitCast(NGV, GV->getType())); delete GV; SET_DECL_LLVM(decl, NGV); GV = NGV; } // Set the initializer. GV->setInitializer(Init); // Set thread local (TLS) if (TREE_CODE(decl) == VAR_DECL && DECL_THREAD_LOCAL(decl)) GV->setThreadLocal(true); // Set the linkage. if (!TREE_PUBLIC(decl)) { GV->setLinkage(GlobalValue::InternalLinkage); } else if (DECL_WEAK(decl) || DECL_ONE_ONLY(decl) || (DECL_COMMON(decl) && // DECL_COMMON is only meaningful if no init (!DECL_INITIAL(decl) || DECL_INITIAL(decl) == error_mark_node))) { // llvm-gcc also includes DECL_VIRTUAL_P here. GV->setLinkage(GlobalValue::WeakLinkage); } else if (DECL_COMDAT(decl)) { GV->setLinkage(GlobalValue::LinkOnceLinkage); } #ifdef TARGET_ADJUST_LLVM_LINKAGE TARGET_ADJUST_LLVM_LINKAGE(GV,decl); #endif /* TARGET_ADJUST_LLVM_LINKAGE */ // Handle visibility style if (TREE_PUBLIC(decl)) { if (DECL_VISIBILITY(decl) == VISIBILITY_HIDDEN) GV->setVisibility(GlobalValue::HiddenVisibility); else if (DECL_VISIBILITY(decl) == VISIBILITY_PROTECTED) GV->setVisibility(GlobalValue::ProtectedVisibility); } // Set the section for the global. if (TREE_CODE(decl) == VAR_DECL || TREE_CODE(decl) == CONST_DECL) { if (DECL_SECTION_NAME(decl)) { GV->setSection(TREE_STRING_POINTER(DECL_SECTION_NAME(decl))); #ifdef LLVM_IMPLICIT_TARGET_GLOBAL_VAR_SECTION } else if (const char *Section = LLVM_IMPLICIT_TARGET_GLOBAL_VAR_SECTION(decl)) { GV->setSection(Section); #endif } // Set the alignment for the global if one of the following condition is met // 1) DECL_ALIGN_UNIT does not match alignment as per ABI specification // 2) DECL_ALIGN is set by user. if (DECL_ALIGN_UNIT(decl)) { unsigned TargetAlign = getTargetData().getABITypeAlignment(GV->getType()->getElementType()); if (DECL_USER_ALIGN(decl) || TargetAlign != DECL_ALIGN_UNIT(decl)) GV->setAlignment(DECL_ALIGN_UNIT(decl)); } // Handle used decls if (DECL_PRESERVE_P (decl)) { const Type *SBP= PointerType::get(Type::Int8Ty); AttributeUsedGlobals.push_back(ConstantExpr::getBitCast(GV, SBP)); } // Add annotate attributes for globals if (DECL_ATTRIBUTES(decl)) AddAnnotateAttrsToGlobal(GV, decl); } if (TheDebugInfo) TheDebugInfo->EmitGlobalVariable(GV, decl); timevar_pop(TV_LLVM_GLOBALS); }
bool SanitizerCoverageModule::runOnModule(Module &M) { if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false; C = &(M.getContext()); DL = &M.getDataLayout(); CurModule = &M; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); Type *VoidTy = Type::getVoidTy(*C); IRBuilder<> IRB(*C); Type *Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty()); Int64Ty = IRB.getInt64Ty(); SanCovFunction = checkSanitizerInterfaceFunction( M.getOrInsertFunction(kSanCovName, VoidTy, Int32PtrTy, nullptr)); SanCovWithCheckFunction = checkSanitizerInterfaceFunction( M.getOrInsertFunction(kSanCovWithCheckName, VoidTy, Int32PtrTy, nullptr)); SanCovIndirCallFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr)); SanCovTraceCmpFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( kSanCovTraceCmp, VoidTy, Int64Ty, Int64Ty, Int64Ty, nullptr)); SanCovTraceSwitchFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( kSanCovTraceSwitch, VoidTy, Int64Ty, Int64PtrTy, nullptr)); // We insert an empty inline asm after cov callbacks to avoid callback merge. EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false), StringRef(""), StringRef(""), /*hasSideEffects=*/true); SanCovTraceEnter = checkSanitizerInterfaceFunction( M.getOrInsertFunction(kSanCovTraceEnter, VoidTy, Int32PtrTy, nullptr)); SanCovTraceBB = checkSanitizerInterfaceFunction( M.getOrInsertFunction(kSanCovTraceBB, VoidTy, Int32PtrTy, nullptr)); // At this point we create a dummy array of guards because we don't // know how many elements we will need. Type *Int32Ty = IRB.getInt32Ty(); Type *Int8Ty = IRB.getInt8Ty(); GuardArray = new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage, nullptr, "__sancov_gen_cov_tmp"); if (Options.Use8bitCounters) EightBitCounterArray = new GlobalVariable(M, Int8Ty, false, GlobalVariable::ExternalLinkage, nullptr, "__sancov_gen_cov_tmp"); for (auto &F : M) runOnFunction(F); auto N = NumberOfInstrumentedBlocks(); // Now we know how many elements we need. Create an array of guards // with one extra element at the beginning for the size. Type *Int32ArrayNTy = ArrayType::get(Int32Ty, N + 1); GlobalVariable *RealGuardArray = new GlobalVariable( M, Int32ArrayNTy, false, GlobalValue::PrivateLinkage, Constant::getNullValue(Int32ArrayNTy), "__sancov_gen_cov"); // Replace the dummy array with the real one. GuardArray->replaceAllUsesWith( IRB.CreatePointerCast(RealGuardArray, Int32PtrTy)); GuardArray->eraseFromParent(); GlobalVariable *RealEightBitCounterArray; if (Options.Use8bitCounters) { // Make sure the array is 16-aligned. static const int kCounterAlignment = 16; Type *Int8ArrayNTy = ArrayType::get(Int8Ty, RoundUpToAlignment(N, kCounterAlignment)); RealEightBitCounterArray = new GlobalVariable( M, Int8ArrayNTy, false, GlobalValue::PrivateLinkage, Constant::getNullValue(Int8ArrayNTy), "__sancov_gen_cov_counter"); RealEightBitCounterArray->setAlignment(kCounterAlignment); EightBitCounterArray->replaceAllUsesWith( IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy)); EightBitCounterArray->eraseFromParent(); } // Create variable for module (compilation unit) name Constant *ModNameStrConst = ConstantDataArray::getString(M.getContext(), M.getName(), true); GlobalVariable *ModuleName = new GlobalVariable(M, ModNameStrConst->getType(), true, GlobalValue::PrivateLinkage, ModNameStrConst); Function *CtorFunc; std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( M, kSanCovModuleCtorName, kSanCovModuleInitName, {Int32PtrTy, IntptrTy, Int8PtrTy, Int8PtrTy}, {IRB.CreatePointerCast(RealGuardArray, Int32PtrTy), ConstantInt::get(IntptrTy, N), Options.Use8bitCounters ? IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy) : Constant::getNullValue(Int8PtrTy), IRB.CreatePointerCast(ModuleName, Int8PtrTy)}); appendToGlobalCtors(M, CtorFunc, kSanCtorAndDtorPriority); return true; }
void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char *obj_fname, const char *sysimg_data, size_t sysimg_len) { JL_TIMING(NATIVE_DUMP); // We don't want to use MCJIT's target machine because // it uses the large code model and we may potentially // want less optimizations there. Triple TheTriple = Triple(jl_TargetMachine->getTargetTriple()); // make sure to emit the native object format, even if FORCE_ELF was set in codegen #if defined(_OS_WINDOWS_) TheTriple.setObjectFormat(Triple::COFF); #elif defined(_OS_DARWIN_) TheTriple.setObjectFormat(Triple::MachO); TheTriple.setOS(llvm::Triple::MacOSX); #endif std::unique_ptr<TargetMachine> TM(jl_TargetMachine->getTarget().createTargetMachine( TheTriple.getTriple(), jl_TargetMachine->getTargetCPU(), jl_TargetMachine->getTargetFeatureString(), jl_TargetMachine->Options, #if defined(_OS_LINUX_) || defined(_OS_FREEBSD_) Reloc::PIC_, #else Optional<Reloc::Model>(), #endif #if defined(_CPU_PPC_) || defined(_CPU_PPC64_) // On PPC the small model is limited to 16bit offsets CodeModel::Medium, #else // Use small model so that we can use signed 32bits offset in the function and GV tables CodeModel::Small, #endif CodeGenOpt::Aggressive // -O3 TODO: respect command -O0 flag? )); legacy::PassManager PM; addTargetPasses(&PM, TM.get()); // set up optimization passes SmallVector<char, 128> bc_Buffer; SmallVector<char, 128> obj_Buffer; SmallVector<char, 128> unopt_bc_Buffer; raw_svector_ostream bc_OS(bc_Buffer); raw_svector_ostream obj_OS(obj_Buffer); raw_svector_ostream unopt_bc_OS(unopt_bc_Buffer); std::vector<NewArchiveMember> bc_Archive; std::vector<NewArchiveMember> obj_Archive; std::vector<NewArchiveMember> unopt_bc_Archive; std::vector<std::string> outputs; if (unopt_bc_fname) PM.add(createBitcodeWriterPass(unopt_bc_OS)); if (bc_fname || obj_fname) addOptimizationPasses(&PM, jl_options.opt_level, true); if (bc_fname) PM.add(createBitcodeWriterPass(bc_OS)); if (obj_fname) if (TM->addPassesToEmitFile(PM, obj_OS, TargetMachine::CGFT_ObjectFile, false)) jl_safe_printf("ERROR: target does not support generation of object files\n"); // Reset the target triple to make sure it matches the new target machine shadow_output->setTargetTriple(TM->getTargetTriple().str()); #if JL_LLVM_VERSION >= 40000 DataLayout DL = TM->createDataLayout(); DL.reset(DL.getStringRepresentation() + "-ni:10:11:12"); shadow_output->setDataLayout(DL); #else shadow_output->setDataLayout(TM->createDataLayout()); #endif // add metadata information if (imaging_mode) { emit_offset_table(shadow_output, jl_sysimg_gvars, "jl_sysimg_gvars"); emit_offset_table(shadow_output, jl_sysimg_fvars, "jl_sysimg_fvars"); // reflect the address of the jl_RTLD_DEFAULT_handle variable // back to the caller, so that we can check for consistency issues GlobalValue *jlRTLD_DEFAULT_var = shadow_output->getNamedValue("jl_RTLD_DEFAULT_handle"); addComdat(new GlobalVariable(*shadow_output, jlRTLD_DEFAULT_var->getType(), true, GlobalVariable::ExternalLinkage, jlRTLD_DEFAULT_var, "jl_RTLD_DEFAULT_handle_pointer")); } // do the actual work auto add_output = [&] (Module &M, StringRef unopt_bc_Name, StringRef bc_Name, StringRef obj_Name) { PM.run(M); if (unopt_bc_fname) emit_result(unopt_bc_Archive, unopt_bc_Buffer, unopt_bc_Name, outputs); if (bc_fname) emit_result(bc_Archive, bc_Buffer, bc_Name, outputs); if (obj_fname) emit_result(obj_Archive, obj_Buffer, obj_Name, outputs); }; add_output(*shadow_output, "unopt.bc", "text.bc", "text.o"); LLVMContext &Context = shadow_output->getContext(); std::unique_ptr<Module> sysimage(new Module("sysimage", Context)); sysimage->setTargetTriple(shadow_output->getTargetTriple()); sysimage->setDataLayout(shadow_output->getDataLayout()); addComdat(new GlobalVariable(*sysimage, T_size, true, GlobalVariable::ExternalLinkage, ConstantInt::get(T_size, globalUnique + 1), "jl_globalUnique")); if (sysimg_data) { Constant *data = ConstantDataArray::get(Context, ArrayRef<uint8_t>((const unsigned char*)sysimg_data, sysimg_len)); addComdat(new GlobalVariable(*sysimage, data->getType(), false, GlobalVariable::ExternalLinkage, data, "jl_system_image_data"))->setAlignment(64); Constant *len = ConstantInt::get(T_size, sysimg_len); addComdat(new GlobalVariable(*sysimage, len->getType(), true, GlobalVariable::ExternalLinkage, len, "jl_system_image_size")); } add_output(*sysimage, "data.bc", "data.bc", "data.o"); object::Archive::Kind Kind = getDefaultForHost(TheTriple); if (unopt_bc_fname) handleAllErrors(writeArchive(unopt_bc_fname, unopt_bc_Archive, true, Kind, true, false), reportWriterError); if (bc_fname) handleAllErrors(writeArchive(bc_fname, bc_Archive, true, Kind, true, false), reportWriterError); if (obj_fname) handleAllErrors(writeArchive(obj_fname, obj_Archive, true, Kind, true, false), reportWriterError); imaging_mode = false; }
/// Replace direct callers of Old with New. Also add parameters to the call to /// \p New, which are defined by the FuncIdx's value in \p Params. bool SwiftMergeFunctions::replaceDirectCallers(Function *Old, Function *New, const ParamInfos &Params, unsigned FuncIdx) { bool AllReplaced = true; SmallVector<CallInst *, 8> Callers; for (Use &U : Old->uses()) { auto *I = dyn_cast<Instruction>(U.getUser()); if (!I) { AllReplaced = false; continue; } FunctionEntry *FE = getEntry(I->getFunction()); if (FE) removeEquivalenceClassFromTree(FE); auto *CI = dyn_cast<CallInst>(I); if (!CI || CI->getCalledValue() != Old) { AllReplaced = false; continue; } Callers.push_back(CI); } if (!AllReplaced) return false; for (CallInst *CI : Callers) { auto &Context = New->getContext(); auto NewPAL = New->getAttributes(); SmallVector<Type *, 8> OldParamTypes; SmallVector<Value *, 16> NewArgs; SmallVector<AttributeSet, 8> NewArgAttrs; IRBuilder<> Builder(CI); FunctionType *NewFuncTy = New->getFunctionType(); (void) NewFuncTy; unsigned ParamIdx = 0; // Add the existing parameters. for (Value *OldArg : CI->arg_operands()) { NewArgAttrs.push_back(NewPAL.getParamAttributes(ParamIdx)); NewArgs.push_back(OldArg); OldParamTypes.push_back(OldArg->getType()); ++ParamIdx; } // Add the new parameters. for (const ParamInfo &PI : Params) { assert(ParamIdx < NewFuncTy->getNumParams()); Constant *ArgValue = PI.Values[FuncIdx]; assert(ArgValue != Old && "should not try to replace all callers of self referencing functions"); NewArgs.push_back(ArgValue); OldParamTypes.push_back(ArgValue->getType()); ++ParamIdx; } auto *FType = FunctionType::get(Old->getFunctionType()->getReturnType(), OldParamTypes, false); auto *FPtrType = PointerType::get(FType, cast<PointerType>(New->getType())->getAddressSpace()); Value *Callee = ConstantExpr::getBitCast(New, FPtrType); CallInst *NewCI = Builder.CreateCall(Callee, NewArgs); NewCI->setCallingConv(CI->getCallingConv()); // Don't transfer attributes from the function to the callee. Function // attributes typically aren't relevant to the calling convention or ABI. NewCI->setAttributes(AttributeList::get(Context, /*FnAttrs=*/AttributeSet(), NewPAL.getRetAttributes(), NewArgAttrs)); CI->replaceAllUsesWith(NewCI); CI->eraseFromParent(); } assert(Old->use_empty() && "should have replaced all uses of old function"); return Old->hasLocalLinkage(); }
ConstantExpression::ConstantExpression(Constant constant) : constant { constant } { auto type = constant.getType(); setType(*type); }
// Create a constant for Str so that we can pass it to the run-time lib. static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str) { Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str); return new GlobalVariable(M, StrConst->getType(), true, GlobalValue::PrivateLinkage, StrConst, ""); }
bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals, Module &M, bool isConst, unsigned AddrSpace) const { const TargetLowering *TLI = TM->getTargetLowering(); const DataLayout *DL = TLI->getDataLayout(); // FIXME: Infer the maximum possible offset depending on the actual users // (these max offsets are different for the users inside Thumb or ARM // functions) unsigned MaxOffset = TLI->getMaximalGlobalOffset(); // FIXME: Find better heuristics std::stable_sort(Globals.begin(), Globals.end(), [DL](const GlobalVariable *GV1, const GlobalVariable *GV2) { Type *Ty1 = cast<PointerType>(GV1->getType())->getElementType(); Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType(); return (DL->getTypeAllocSize(Ty1) < DL->getTypeAllocSize(Ty2)); }); Type *Int32Ty = Type::getInt32Ty(M.getContext()); assert(Globals.size() > 1); // FIXME: This simple solution merges globals all together as maximum as // possible. However, with this solution it would be hard to remove dead // global symbols at link-time. An alternative solution could be checking // global symbols references function by function, and make the symbols // being referred in the same function merged and we would probably need // to introduce heuristic algorithm to solve the merge conflict from // different functions. for (size_t i = 0, e = Globals.size(); i != e; ) { size_t j = 0; uint64_t MergedSize = 0; std::vector<Type*> Tys; std::vector<Constant*> Inits; bool HasExternal = false; GlobalVariable *TheFirstExternal = 0; for (j = i; j != e; ++j) { Type *Ty = Globals[j]->getType()->getElementType(); MergedSize += DL->getTypeAllocSize(Ty); if (MergedSize > MaxOffset) { break; } Tys.push_back(Ty); Inits.push_back(Globals[j]->getInitializer()); if (Globals[j]->hasExternalLinkage() && !HasExternal) { HasExternal = true; TheFirstExternal = Globals[j]; } } // If merged variables doesn't have external linkage, we needn't to expose // the symbol after merging. GlobalValue::LinkageTypes Linkage = HasExternal ? GlobalValue::ExternalLinkage : GlobalValue::InternalLinkage; // If merged variables have external linkage, we use symbol name of the // first variable merged as the suffix of global symbol name. This would // be able to avoid the link-time naming conflict for globalm symbols. Twine MergedGVName = HasExternal ? "_MergedGlobals_" + TheFirstExternal->getName() : "_MergedGlobals"; StructType *MergedTy = StructType::get(M.getContext(), Tys); Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); GlobalVariable *MergedGV = new GlobalVariable( M, MergedTy, isConst, Linkage, MergedInit, MergedGVName, nullptr, GlobalVariable::NotThreadLocal, AddrSpace); for (size_t k = i; k < j; ++k) { GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage(); std::string Name = Globals[k]->getName(); Constant *Idx[2] = { ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, k-i) }; Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedGV, Idx); Globals[k]->replaceAllUsesWith(GEP); Globals[k]->eraseFromParent(); if (Linkage != GlobalValue::InternalLinkage) { // Generate a new alias... auto *PTy = cast<PointerType>(GEP->getType()); GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(), Linkage, Name, GEP, &M); } NumMerged++; } i = j; } return true; }
bool ProfilingPass::doInitialization(Module &M) { LLVMContext& context = M.getContext(); Function* mainFunc = M.getFunction("main"); const string moduleName = M.getModuleIdentifier(); if (mainFunc!=NULL) { //BasicBlock* entryBlock = &mainFunc->front(); Constant* Init = ConstantArray::get(context,moduleName,true); // Convert it to an LLVM Type GlobalVariable* nameStr = new GlobalVariable(Init->getType(), true, GlobalValue::InternalLinkage, Init, "NameStr" ); M.getGlobalList().push_back( nameStr ); // Insert it into the list of globals for module std::vector<Constant*>IndicesC(2); IndicesC[0] = Constant::getNullValue(Type::getInt32Ty(context)); IndicesC[1] = ConstantInt::get(Type::getInt32Ty(context),0); Constant *getElemExpr = ConstantExpr::getGetElementPtr(nameStr, &IndicesC[0], IndicesC.size()); vector<Value*> initInjectArgs; initInjectArgs.push_back( getElemExpr ); FunctionType* initInjectionFuncType = FunctionType::get(Type::getVoidTy(context), vector<const Type*>(1, PointerType::get(Type::getInt8Ty(context),0)),0); //BasicBlock *exitBlock = &mainFunc->back(); Instruction *I; for (inst_iterator fi = inst_begin(mainFunc), fe = inst_end(mainFunc); fi!=fe; ++fi){ I = &*fi; if(isa<ReturnInst>(I)) break; } BasicBlock *retblock = I->getParent(); //*retpred = retblock->getSinglePredecessor(); Instruction *term = retblock->getTerminator(); Constant *endFunc = M.getOrInsertFunction("endProfiling", initInjectionFuncType); vector<Value*> countArgs(1); //const IntegerType* itype = IntegerType::get(context,32); //Value* branchVal = ConstantInt::get(itype, BRANCH ); CallInst::Create(endFunc, initInjectArgs.begin(), initInjectArgs.end(), "", term); } else { Constant* Init = ConstantArray::get(context,moduleName,true); // Convert it to an LLVM Type GlobalVariable* nameStr = new GlobalVariable(Init->getType(), true, GlobalValue::InternalLinkage, Init, "NameStr" ); M.getGlobalList().push_back( nameStr ); } //*********************************************************************************************************** //code for loading configure file should be here ifstream config ("llfi_configure.txt"); if (config.is_open()) { // we need to extract information from config file here Qining // this loop is used to know if the file is end while ( config.good() ) { string line; getline (config,line); if(line.empty()) continue; //if the line is empty, just skip. //Any block of configure is started with one specific function unsigned found = line.find("FUNCTION_NAME:"); if (found < line.length()) { //std::cout << "\nfound FUNCTION_NAME at " << found << '\n'; std::string func_name = line.substr (found + string("FUNCTION_NAME:").length(),line.length() - found - string("FUNCTION_NAME:").length()); //first, I need to trim it while(func_name[0] == ' ') { func_name.erase(0, 1); } while(func_name[func_name.length() - 1] == ' ') { func_name.erase(func_name.length() - 1, 0); } //so now I've got the name of the function if(func_name.empty()) continue; std::cout << "The func_name is " << func_name << "\n"; map_func_argu[func_name] = set<unsigned int>(); // create entry //map_func_fault_type[func_name] = set<unsigned int>(); //second, I need to load argument set and type set do { line.clear(); getline(config,line); // get the next line if(!config.good()) break; // if the new line is the end of file, our job is done. if(line.find("ARGUMENT:") < line.length()) { //insert argument id to argument set std::string arg_set = line.substr(line.find("ARGUMENT:")+string("ARGUMENT:").length(), line.length() - line.find("ARGUMENT:")-string("ARGUMENT:").length()); std::string arg; while(!arg_set.empty()) { while(arg_set[0] <= '9' && arg_set[0] >= '0') { arg.append(arg_set.substr(0,1)); if(!arg_set.empty()) arg_set.erase(0,1); } if(!arg.empty()) { unsigned int arg_num = atoi(arg.c_str()) - 1; map_func_argu[func_name].insert(arg_num); std::cout << "\tinclude arg: " << arg_num+1 << "\n"; } arg.clear(); if(!arg_set.empty()) arg_set.erase(0,1); } } }while(line.find("FUNC_DEF_END") != 0); } } // The file is end, we should have already finished our work, now close the file config.close(); } else errs()<<"Unable to open config file, use default config: all instructions, one bit flip\n"; //*********************************************************************************************************** return FunctionPass::doInitialization(M); }
bool SanitizerCoverageModule::runOnModule(Module &M) { if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false; C = &(M.getContext()); DL = &M.getDataLayout(); CurModule = &M; TargetTriple = Triple(M.getTargetTriple()); HasSancovGuardsSection = false; IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); IntptrPtrTy = PointerType::getUnqual(IntptrTy); Type *VoidTy = Type::getVoidTy(*C); IRBuilder<> IRB(*C); Type *Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty()); Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); Int64Ty = IRB.getInt64Ty(); Int32Ty = IRB.getInt32Ty(); SanCovFunction = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovName, VoidTy, Int32PtrTy, nullptr)); SanCovWithCheckFunction = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovWithCheckName, VoidTy, Int32PtrTy, nullptr)); SanCovTracePCIndir = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy, nullptr)); SanCovIndirCallFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( SanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr)); SanCovTraceCmpFunction[0] = checkSanitizerInterfaceFunction(M.getOrInsertFunction( SanCovTraceCmp1, VoidTy, IRB.getInt8Ty(), IRB.getInt8Ty(), nullptr)); SanCovTraceCmpFunction[1] = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovTraceCmp2, VoidTy, IRB.getInt16Ty(), IRB.getInt16Ty(), nullptr)); SanCovTraceCmpFunction[2] = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovTraceCmp4, VoidTy, IRB.getInt32Ty(), IRB.getInt32Ty(), nullptr)); SanCovTraceCmpFunction[3] = checkSanitizerInterfaceFunction(M.getOrInsertFunction( SanCovTraceCmp8, VoidTy, Int64Ty, Int64Ty, nullptr)); SanCovTraceDivFunction[0] = checkSanitizerInterfaceFunction(M.getOrInsertFunction( SanCovTraceDiv4, VoidTy, IRB.getInt32Ty(), nullptr)); SanCovTraceDivFunction[1] = checkSanitizerInterfaceFunction(M.getOrInsertFunction( SanCovTraceDiv8, VoidTy, Int64Ty, nullptr)); SanCovTraceGepFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( SanCovTraceGep, VoidTy, IntptrTy, nullptr)); SanCovTraceSwitchFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( SanCovTraceSwitchName, VoidTy, Int64Ty, Int64PtrTy, nullptr)); // We insert an empty inline asm after cov callbacks to avoid callback merge. EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false), StringRef(""), StringRef(""), /*hasSideEffects=*/true); SanCovTracePC = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovTracePCName, VoidTy, nullptr)); SanCovTracePCGuard = checkSanitizerInterfaceFunction(M.getOrInsertFunction( SanCovTracePCGuardName, VoidTy, Int32PtrTy, nullptr)); SanCovTraceEnter = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovTraceEnterName, VoidTy, Int32PtrTy, nullptr)); SanCovTraceBB = checkSanitizerInterfaceFunction( M.getOrInsertFunction(SanCovTraceBBName, VoidTy, Int32PtrTy, nullptr)); // At this point we create a dummy array of guards because we don't // know how many elements we will need. Type *Int32Ty = IRB.getInt32Ty(); Type *Int8Ty = IRB.getInt8Ty(); if (!Options.TracePCGuard) GuardArray = new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage, nullptr, "__sancov_gen_cov_tmp"); if (Options.Use8bitCounters) EightBitCounterArray = new GlobalVariable(M, Int8Ty, false, GlobalVariable::ExternalLinkage, nullptr, "__sancov_gen_cov_tmp"); for (auto &F : M) runOnFunction(F); auto N = NumberOfInstrumentedBlocks(); GlobalVariable *RealGuardArray = nullptr; if (!Options.TracePCGuard) { // Now we know how many elements we need. Create an array of guards // with one extra element at the beginning for the size. Type *Int32ArrayNTy = ArrayType::get(Int32Ty, N + 1); RealGuardArray = new GlobalVariable( M, Int32ArrayNTy, false, GlobalValue::PrivateLinkage, Constant::getNullValue(Int32ArrayNTy), "__sancov_gen_cov"); // Replace the dummy array with the real one. GuardArray->replaceAllUsesWith( IRB.CreatePointerCast(RealGuardArray, Int32PtrTy)); GuardArray->eraseFromParent(); } GlobalVariable *RealEightBitCounterArray; if (Options.Use8bitCounters) { // Make sure the array is 16-aligned. static const int CounterAlignment = 16; Type *Int8ArrayNTy = ArrayType::get(Int8Ty, alignTo(N, CounterAlignment)); RealEightBitCounterArray = new GlobalVariable( M, Int8ArrayNTy, false, GlobalValue::PrivateLinkage, Constant::getNullValue(Int8ArrayNTy), "__sancov_gen_cov_counter"); RealEightBitCounterArray->setAlignment(CounterAlignment); EightBitCounterArray->replaceAllUsesWith( IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy)); EightBitCounterArray->eraseFromParent(); } // Create variable for module (compilation unit) name Constant *ModNameStrConst = ConstantDataArray::getString(M.getContext(), M.getName(), true); GlobalVariable *ModuleName = new GlobalVariable( M, ModNameStrConst->getType(), true, GlobalValue::PrivateLinkage, ModNameStrConst, "__sancov_gen_modname"); if (Options.TracePCGuard) { if (HasSancovGuardsSection) { Function *CtorFunc; GlobalVariable *SecStart = new GlobalVariable( M, Int32PtrTy, false, GlobalVariable::ExternalLinkage, nullptr, getSanCovTracePCGuardSectionStart()); SecStart->setVisibility(GlobalValue::HiddenVisibility); GlobalVariable *SecEnd = new GlobalVariable( M, Int32PtrTy, false, GlobalVariable::ExternalLinkage, nullptr, getSanCovTracePCGuardSectionEnd()); SecEnd->setVisibility(GlobalValue::HiddenVisibility); std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( M, SanCovModuleCtorName, SanCovTracePCGuardInitName, {Int32PtrTy, Int32PtrTy}, {IRB.CreatePointerCast(SecStart, Int32PtrTy), IRB.CreatePointerCast(SecEnd, Int32PtrTy)}); if (TargetTriple.supportsCOMDAT()) { // Use comdat to dedup CtorFunc. CtorFunc->setComdat(M.getOrInsertComdat(SanCovModuleCtorName)); appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority, CtorFunc); } else { appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority); } } } else if (!Options.TracePC) { Function *CtorFunc; std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( M, SanCovModuleCtorName, SanCovModuleInitName, {Int32PtrTy, IntptrTy, Int8PtrTy, Int8PtrTy}, {IRB.CreatePointerCast(RealGuardArray, Int32PtrTy), ConstantInt::get(IntptrTy, N), Options.Use8bitCounters ? IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy) : Constant::getNullValue(Int8PtrTy), IRB.CreatePointerCast(ModuleName, Int8PtrTy)}); appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority); } return true; }
/// Evaluate all instructions in block BB, returning true if successful, false /// if we can't evaluate it. NewBB returns the next BB that control flows into, /// or null upon return. bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB) { // This is the main evaluation loop. while (1) { Constant *InstResult = nullptr; DEBUG(dbgs() << "Evaluating Instruction: " << *CurInst << "\n"); if (StoreInst *SI = dyn_cast<StoreInst>(CurInst)) { if (!SI->isSimple()) { DEBUG(dbgs() << "Store is not simple! Can not evaluate.\n"); return false; // no volatile/atomic accesses. } Constant *Ptr = getVal(SI->getOperand(1)); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) { DEBUG(dbgs() << "Folding constant ptr expression: " << *Ptr); Ptr = ConstantFoldConstantExpression(CE, DL, TLI); DEBUG(dbgs() << "; To: " << *Ptr << "\n"); } if (!isSimpleEnoughPointerToCommit(Ptr)) { // If this is too complex for us to commit, reject it. DEBUG(dbgs() << "Pointer is too complex for us to evaluate store."); return false; } Constant *Val = getVal(SI->getOperand(0)); // If this might be too difficult for the backend to handle (e.g. the addr // of one global variable divided by another) then we can't commit it. if (!isSimpleEnoughValueToCommit(Val, SimpleConstants, DL)) { DEBUG(dbgs() << "Store value is too complex to evaluate store. " << *Val << "\n"); return false; } if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) { if (CE->getOpcode() == Instruction::BitCast) { DEBUG(dbgs() << "Attempting to resolve bitcast on constant ptr.\n"); // If we're evaluating a store through a bitcast, then we need // to pull the bitcast off the pointer type and push it onto the // stored value. Ptr = CE->getOperand(0); Type *NewTy = cast<PointerType>(Ptr->getType())->getElementType(); // In order to push the bitcast onto the stored value, a bitcast // from NewTy to Val's type must be legal. If it's not, we can try // introspecting NewTy to find a legal conversion. while (!Val->getType()->canLosslesslyBitCastTo(NewTy)) { // If NewTy is a struct, we can convert the pointer to the struct // into a pointer to its first member. // FIXME: This could be extended to support arrays as well. if (StructType *STy = dyn_cast<StructType>(NewTy)) { NewTy = STy->getTypeAtIndex(0U); IntegerType *IdxTy = IntegerType::get(NewTy->getContext(), 32); Constant *IdxZero = ConstantInt::get(IdxTy, 0, false); Constant * const IdxList[] = {IdxZero, IdxZero}; Ptr = ConstantExpr::getGetElementPtr(nullptr, Ptr, IdxList); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) Ptr = ConstantFoldConstantExpression(CE, DL, TLI); // If we can't improve the situation by introspecting NewTy, // we have to give up. } else { DEBUG(dbgs() << "Failed to bitcast constant ptr, can not " "evaluate.\n"); return false; } } // If we found compatible types, go ahead and push the bitcast // onto the stored value. Val = ConstantExpr::getBitCast(Val, NewTy); DEBUG(dbgs() << "Evaluated bitcast: " << *Val << "\n"); } } MutatedMemory[Ptr] = Val; } else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CurInst)) { InstResult = ConstantExpr::get(BO->getOpcode(), getVal(BO->getOperand(0)), getVal(BO->getOperand(1))); DEBUG(dbgs() << "Found a BinaryOperator! Simplifying: " << *InstResult << "\n"); } else if (CmpInst *CI = dyn_cast<CmpInst>(CurInst)) { InstResult = ConstantExpr::getCompare(CI->getPredicate(), getVal(CI->getOperand(0)), getVal(CI->getOperand(1))); DEBUG(dbgs() << "Found a CmpInst! Simplifying: " << *InstResult << "\n"); } else if (CastInst *CI = dyn_cast<CastInst>(CurInst)) { InstResult = ConstantExpr::getCast(CI->getOpcode(), getVal(CI->getOperand(0)), CI->getType()); DEBUG(dbgs() << "Found a Cast! Simplifying: " << *InstResult << "\n"); } else if (SelectInst *SI = dyn_cast<SelectInst>(CurInst)) { InstResult = ConstantExpr::getSelect(getVal(SI->getOperand(0)), getVal(SI->getOperand(1)), getVal(SI->getOperand(2))); DEBUG(dbgs() << "Found a Select! Simplifying: " << *InstResult << "\n"); } else if (auto *EVI = dyn_cast<ExtractValueInst>(CurInst)) { InstResult = ConstantExpr::getExtractValue( getVal(EVI->getAggregateOperand()), EVI->getIndices()); DEBUG(dbgs() << "Found an ExtractValueInst! Simplifying: " << *InstResult << "\n"); } else if (auto *IVI = dyn_cast<InsertValueInst>(CurInst)) { InstResult = ConstantExpr::getInsertValue( getVal(IVI->getAggregateOperand()), getVal(IVI->getInsertedValueOperand()), IVI->getIndices()); DEBUG(dbgs() << "Found an InsertValueInst! Simplifying: " << *InstResult << "\n"); } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(CurInst)) { Constant *P = getVal(GEP->getOperand(0)); SmallVector<Constant*, 8> GEPOps; for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e; ++i) GEPOps.push_back(getVal(*i)); InstResult = ConstantExpr::getGetElementPtr(GEP->getSourceElementType(), P, GEPOps, cast<GEPOperator>(GEP)->isInBounds()); DEBUG(dbgs() << "Found a GEP! Simplifying: " << *InstResult << "\n"); } else if (LoadInst *LI = dyn_cast<LoadInst>(CurInst)) { if (!LI->isSimple()) { DEBUG(dbgs() << "Found a Load! Not a simple load, can not evaluate.\n"); return false; // no volatile/atomic accesses. } Constant *Ptr = getVal(LI->getOperand(0)); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) { Ptr = ConstantFoldConstantExpression(CE, DL, TLI); DEBUG(dbgs() << "Found a constant pointer expression, constant " "folding: " << *Ptr << "\n"); } InstResult = ComputeLoadResult(Ptr); if (!InstResult) { DEBUG(dbgs() << "Failed to compute load result. Can not evaluate load." "\n"); return false; // Could not evaluate load. } DEBUG(dbgs() << "Evaluated load: " << *InstResult << "\n"); } else if (AllocaInst *AI = dyn_cast<AllocaInst>(CurInst)) { if (AI->isArrayAllocation()) { DEBUG(dbgs() << "Found an array alloca. Can not evaluate.\n"); return false; // Cannot handle array allocs. } Type *Ty = AI->getAllocatedType(); AllocaTmps.push_back( make_unique<GlobalVariable>(Ty, false, GlobalValue::InternalLinkage, UndefValue::get(Ty), AI->getName())); InstResult = AllocaTmps.back().get(); DEBUG(dbgs() << "Found an alloca. Result: " << *InstResult << "\n"); } else if (isa<CallInst>(CurInst) || isa<InvokeInst>(CurInst)) { CallSite CS(&*CurInst); // Debug info can safely be ignored here. if (isa<DbgInfoIntrinsic>(CS.getInstruction())) { DEBUG(dbgs() << "Ignoring debug info.\n"); ++CurInst; continue; } // Cannot handle inline asm. if (isa<InlineAsm>(CS.getCalledValue())) { DEBUG(dbgs() << "Found inline asm, can not evaluate.\n"); return false; } if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction())) { if (MemSetInst *MSI = dyn_cast<MemSetInst>(II)) { if (MSI->isVolatile()) { DEBUG(dbgs() << "Can not optimize a volatile memset " << "intrinsic.\n"); return false; } Constant *Ptr = getVal(MSI->getDest()); Constant *Val = getVal(MSI->getValue()); Constant *DestVal = ComputeLoadResult(getVal(Ptr)); if (Val->isNullValue() && DestVal && DestVal->isNullValue()) { // This memset is a no-op. DEBUG(dbgs() << "Ignoring no-op memset.\n"); ++CurInst; continue; } } if (II->getIntrinsicID() == Intrinsic::lifetime_start || II->getIntrinsicID() == Intrinsic::lifetime_end) { DEBUG(dbgs() << "Ignoring lifetime intrinsic.\n"); ++CurInst; continue; } if (II->getIntrinsicID() == Intrinsic::invariant_start) { // We don't insert an entry into Values, as it doesn't have a // meaningful return value. if (!II->use_empty()) { DEBUG(dbgs() << "Found unused invariant_start. Can't evaluate.\n"); return false; } ConstantInt *Size = cast<ConstantInt>(II->getArgOperand(0)); Value *PtrArg = getVal(II->getArgOperand(1)); Value *Ptr = PtrArg->stripPointerCasts(); if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr)) { Type *ElemTy = GV->getValueType(); if (!Size->isAllOnesValue() && Size->getValue().getLimitedValue() >= DL.getTypeStoreSize(ElemTy)) { Invariants.insert(GV); DEBUG(dbgs() << "Found a global var that is an invariant: " << *GV << "\n"); } else { DEBUG(dbgs() << "Found a global var, but can not treat it as an " "invariant.\n"); } } // Continue even if we do nothing. ++CurInst; continue; } else if (II->getIntrinsicID() == Intrinsic::assume) { DEBUG(dbgs() << "Skipping assume intrinsic.\n"); ++CurInst; continue; } DEBUG(dbgs() << "Unknown intrinsic. Can not evaluate.\n"); return false; } // Resolve function pointers. Function *Callee = dyn_cast<Function>(getVal(CS.getCalledValue())); if (!Callee || Callee->mayBeOverridden()) { DEBUG(dbgs() << "Can not resolve function pointer.\n"); return false; // Cannot resolve. } SmallVector<Constant*, 8> Formals; for (User::op_iterator i = CS.arg_begin(), e = CS.arg_end(); i != e; ++i) Formals.push_back(getVal(*i)); if (Callee->isDeclaration()) { // If this is a function we can constant fold, do it. if (Constant *C = ConstantFoldCall(Callee, Formals, TLI)) { InstResult = C; DEBUG(dbgs() << "Constant folded function call. Result: " << *InstResult << "\n"); } else { DEBUG(dbgs() << "Can not constant fold function call.\n"); return false; } } else { if (Callee->getFunctionType()->isVarArg()) { DEBUG(dbgs() << "Can not constant fold vararg function call.\n"); return false; } Constant *RetVal = nullptr; // Execute the call, if successful, use the return value. ValueStack.emplace_back(); if (!EvaluateFunction(Callee, RetVal, Formals)) { DEBUG(dbgs() << "Failed to evaluate function.\n"); return false; } ValueStack.pop_back(); InstResult = RetVal; if (InstResult) { DEBUG(dbgs() << "Successfully evaluated function. Result: " << *InstResult << "\n\n"); } else { DEBUG(dbgs() << "Successfully evaluated function. Result: 0\n\n"); } } } else if (isa<TerminatorInst>(CurInst)) { DEBUG(dbgs() << "Found a terminator instruction.\n"); if (BranchInst *BI = dyn_cast<BranchInst>(CurInst)) { if (BI->isUnconditional()) { NextBB = BI->getSuccessor(0); } else { ConstantInt *Cond = dyn_cast<ConstantInt>(getVal(BI->getCondition())); if (!Cond) return false; // Cannot determine. NextBB = BI->getSuccessor(!Cond->getZExtValue()); } } else if (SwitchInst *SI = dyn_cast<SwitchInst>(CurInst)) { ConstantInt *Val = dyn_cast<ConstantInt>(getVal(SI->getCondition())); if (!Val) return false; // Cannot determine. NextBB = SI->findCaseValue(Val).getCaseSuccessor(); } else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(CurInst)) { Value *Val = getVal(IBI->getAddress())->stripPointerCasts(); if (BlockAddress *BA = dyn_cast<BlockAddress>(Val)) NextBB = BA->getBasicBlock(); else return false; // Cannot determine. } else if (isa<ReturnInst>(CurInst)) { NextBB = nullptr; } else { // invoke, unwind, resume, unreachable. DEBUG(dbgs() << "Can not handle terminator."); return false; // Cannot handle this terminator. } // We succeeded at evaluating this block! DEBUG(dbgs() << "Successfully evaluated block.\n"); return true; } else { // Did not know how to evaluate this! DEBUG(dbgs() << "Failed to evaluate block due to unhandled instruction." "\n"); return false; } if (!CurInst->use_empty()) { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(InstResult)) InstResult = ConstantFoldConstantExpression(CE, DL, TLI); setVal(&*CurInst, InstResult); } // If we just processed an invoke, we finished evaluating the block. if (InvokeInst *II = dyn_cast<InvokeInst>(CurInst)) { NextBB = II->getNormalDest(); DEBUG(dbgs() << "Found an invoke instruction. Finished Block.\n\n"); return true; } // Advance program counter. ++CurInst; } }
void InitializeSoftBound:: constructCheckHandlers(Module & module){ Type* void_ty = Type::getVoidTy(module.getContext()); Type* void_ptr_ty = PointerType::getUnqual(Type::getInt8Ty(module.getContext())); Type* size_ty = Type::getInt64Ty(module.getContext()); module.getOrInsertFunction("__softboundcets_spatial_load_dereference_check", void_ty, void_ptr_ty, void_ptr_ty, void_ptr_ty, size_ty, NULL); module.getOrInsertFunction("__softboundcets_spatial_store_dereference_check", void_ty, void_ptr_ty, void_ptr_ty, void_ptr_ty, size_ty, NULL); module.getOrInsertFunction("__softboundcets_temporal_load_dereference_check", void_ty, void_ptr_ty, size_ty, void_ptr_ty, void_ptr_ty, NULL); module.getOrInsertFunction("__softboundcets_temporal_store_dereference_check", void_ty, void_ptr_ty, size_ty, void_ptr_ty, void_ptr_ty, NULL); Function* global_init = (Function *) module.getOrInsertFunction("__softboundcets_global_init", void_ty, NULL); global_init->setDoesNotThrow(); global_init->setLinkage(GlobalValue::InternalLinkage); BasicBlock* BB = BasicBlock::Create(module.getContext(), "entry", global_init); Function* softboundcets_init = (Function*) module.getOrInsertFunction("__softboundcets_init", void_ty, Type::getInt32Ty(module.getContext()), NULL); SmallVector<Value*, 8> args; Constant * const_one = ConstantInt::get(Type::getInt32Ty(module.getContext()), 1); args.push_back(const_one); Instruction* ret = ReturnInst::Create(module.getContext(), BB); CallInst::Create(softboundcets_init, args, "", ret); Type * Int32Type = IntegerType::getInt32Ty(module.getContext()); std::vector<Constant *> CtorInits; CtorInits.push_back(ConstantInt::get(Int32Type, 0)); CtorInits.push_back(global_init); StructType * ST = ConstantStruct::getTypeForElements(CtorInits, false); Constant * RuntimeCtorInit = ConstantStruct::get(ST, CtorInits); // // Get the current set of static global constructors and add the new ctor // to the list. // std::vector<Constant *> CurrentCtors; GlobalVariable * GVCtor = module.getNamedGlobal ("llvm.global_ctors"); if (GVCtor) { if (Constant * C = GVCtor->getInitializer()) { for (unsigned index = 0; index < C->getNumOperands(); ++index) { CurrentCtors.push_back (dyn_cast<Constant>(C->getOperand (index))); } } } CurrentCtors.push_back(RuntimeCtorInit); // // Create a new initializer. // ArrayType * AT = ArrayType::get (RuntimeCtorInit-> getType(), CurrentCtors.size()); Constant * NewInit = ConstantArray::get (AT, CurrentCtors); // // Create the new llvm.global_ctors global variable and remove the old one // if it existed. // Value * newGVCtor = new GlobalVariable (module, NewInit->getType(), false, GlobalValue::AppendingLinkage, NewInit, "llvm.global_ctors"); if (GVCtor) { newGVCtor->takeName (GVCtor); GVCtor->eraseFromParent (); } }
virtual bool runOnModule(Module &M) { LLVMContext &C = M.getContext(); Function *printError_func = (Function*)M.getOrInsertFunction("printErrorMessage", Type::getVoidTy(C), NULL); BasicBlock* entryBlock = BasicBlock::Create(C, "", printError_func); IRBuilder<> builder(entryBlock); Constant *msg = ConstantArray::get(C, "ERROR! Array Index Out of Bounds", true); Constant *zero_32 = Constant::getNullValue(IntegerType::getInt32Ty(C)); Constant *gep_params[] = {zero_32, zero_32}; GlobalVariable *errorMsg = new GlobalVariable(M, msg->getType(), true, GlobalValue::InternalLinkage, msg, "errorMsg"); Function *puts_func = (Function*)(M.getOrInsertFunction("puts", IntegerType::getInt32Ty(C), PointerType::getUnqual(IntegerType::getInt8Ty(C)), NULL)); Constant *msgptr = ConstantExpr::getGetElementPtr(errorMsg, gep_params); Value *puts_params[] = {msgptr}; CallInst *puts_call = builder.CreateCall(puts_func, puts_params); puts_call->setTailCall(false); Function *exit_func = cast<Function>(M.getOrInsertFunction("exit", IntegerType::getVoidTy(C), Type::getInt32Ty(C),NULL)); Value *exit_val = ConstantInt::get(IntegerType::getInt32Ty(C), 1); //create exit block. This block prints the error and calls exit system function BasicBlock* exitBlock = BasicBlock::Create(C, "exitBlock", printError_func); builder.CreateBr(exitBlock); builder.SetInsertPoint(exitBlock); builder.CreateCall(exit_func,exit_val); builder.CreateBr(exitBlock); int checksInserted = 0; for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) { //leave func defs alone if (!MI->isDeclaration()) { for (inst_iterator I = inst_begin(*MI), E = inst_end(*MI); I != E; ++I) { Instruction *inst = &*I; if(GetElementPtrInst *gep = dyn_cast<GetElementPtrInst>(inst)) { if (const ArrayType *ar = dyn_cast<ArrayType>(gep->getPointerOperandType()->getElementType())) { //increment checks inserted counter checksInserted++; //create split in basic block for function call insertion (branch) Instruction* next = inst->getNextNode(); BasicBlock* oldBlock = inst->getParent(); BasicBlock* newBlock = SplitBlock(oldBlock, next, this); //get upper limit and index used unsigned upperLim = ar->getNumElements(); int index = gep->getNumOperands() - 1; Value *vIndexUsed = gep->getOperand(index); Value *vUpperLimit = ConstantInt::get(vIndexUsed->getType(), upperLim); BasicBlock* checkUpperBlock = BasicBlock::Create(C, "checkUpperBlock", MI, newBlock); BasicBlock* checkLowerBlock = BasicBlock::Create(C, "checkLowerBlock", MI, checkUpperBlock); builder.SetInsertPoint(oldBlock); //remove old terminator TerminatorInst* term = oldBlock->getTerminator(); term->eraseFromParent(); //insert new one builder.CreateBr(checkUpperBlock); //configure uppper bound test builder.SetInsertPoint(checkUpperBlock); Value* condUpperInst = builder.CreateICmpSLT(vIndexUsed, vUpperLimit, "checkUpperBounds"); BasicBlock* errorBlock = BasicBlock::Create(C, "errorBlock", MI, newBlock); builder.CreateCondBr(condUpperInst, checkLowerBlock, errorBlock); //configure lower bound test builder.SetInsertPoint(checkLowerBlock); Value *vLowerLimit = ConstantInt::get(vIndexUsed->getType(), -1); Value *condLowerInst = builder.CreateICmpSGT(vIndexUsed, vLowerLimit, "checkLowerBounds"); builder.CreateCondBr(condLowerInst, newBlock, errorBlock); //setup error block. All this block does is call func to print error and exit builder.SetInsertPoint(errorBlock); builder.CreateCall(printError_func); builder.CreateBr(errorBlock); } } } } } errs() << "This pass has inserted " << checksInserted << " checks\n"; return true; }
Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags, ValueMapTypeRemapper *TypeMapper) { ValueToValueMapTy::iterator I = VM.find(V); // If the value already exists in the map, use it. if (I != VM.end() && I->second) return I->second; // Global values do not need to be seeded into the VM if they // are using the identity mapping. if (isa<GlobalValue>(V) || isa<MDString>(V)) return VM[V] = const_cast<Value*>(V); if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) { // Inline asm may need *type* remapping. FunctionType *NewTy = IA->getFunctionType(); if (TypeMapper) { NewTy = cast<FunctionType>(TypeMapper->remapType(NewTy)); if (NewTy != IA->getFunctionType()) V = InlineAsm::get(NewTy, IA->getAsmString(), IA->getConstraintString(), IA->hasSideEffects(), IA->isAlignStack()); } return VM[V] = const_cast<Value*>(V); } if (const MDNode *MD = dyn_cast<MDNode>(V)) { // If this is a module-level metadata and we know that nothing at the module // level is changing, then use an identity mapping. if (!MD->isFunctionLocal() && (Flags & RF_NoModuleLevelChanges)) return VM[V] = const_cast<Value*>(V); // Create a dummy node in case we have a metadata cycle. MDNode *Dummy = MDNode::getTemporary(V->getContext(), ArrayRef<Value*>()); VM[V] = Dummy; // Check all operands to see if any need to be remapped. for (unsigned i = 0, e = MD->getNumOperands(); i != e; ++i) { Value *OP = MD->getOperand(i); if (OP == 0 || MapValue(OP, VM, Flags, TypeMapper) == OP) continue; // Ok, at least one operand needs remapping. SmallVector<Value*, 4> Elts; Elts.reserve(MD->getNumOperands()); for (i = 0; i != e; ++i) { Value *Op = MD->getOperand(i); Elts.push_back(Op ? MapValue(Op, VM, Flags, TypeMapper) : 0); } MDNode *NewMD = MDNode::get(V->getContext(), Elts); Dummy->replaceAllUsesWith(NewMD); VM[V] = NewMD; MDNode::deleteTemporary(Dummy); return NewMD; } VM[V] = const_cast<Value*>(V); MDNode::deleteTemporary(Dummy); // No operands needed remapping. Use an identity mapping. return const_cast<Value*>(V); } // Okay, this either must be a constant (which may or may not be mappable) or // is something that is not in the mapping table. Constant *C = const_cast<Constant*>(dyn_cast<Constant>(V)); if (C == 0) return 0; if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) { Function *F = cast<Function>(MapValue(BA->getFunction(), VM, Flags, TypeMapper)); BasicBlock *BB = cast_or_null<BasicBlock>(MapValue(BA->getBasicBlock(), VM, Flags, TypeMapper)); return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock()); } // Otherwise, we have some other constant to remap. Start by checking to see // if all operands have an identity remapping. unsigned OpNo = 0, NumOperands = C->getNumOperands(); Value *Mapped = 0; for (; OpNo != NumOperands; ++OpNo) { Value *Op = C->getOperand(OpNo); Mapped = MapValue(Op, VM, Flags, TypeMapper); if (Mapped != C) break; } // See if the type mapper wants to remap the type as well. Type *NewTy = C->getType(); if (TypeMapper) NewTy = TypeMapper->remapType(NewTy); // If the result type and all operands match up, then just insert an identity // mapping. if (OpNo == NumOperands && NewTy == C->getType()) return VM[V] = C; // Okay, we need to create a new constant. We've already processed some or // all of the operands, set them all up now. SmallVector<Constant*, 8> Ops; Ops.reserve(NumOperands); for (unsigned j = 0; j != OpNo; ++j) Ops.push_back(cast<Constant>(C->getOperand(j))); // If one of the operands mismatch, push it and the other mapped operands. if (OpNo != NumOperands) { Ops.push_back(cast<Constant>(Mapped)); // Map the rest of the operands that aren't processed yet. for (++OpNo; OpNo != NumOperands; ++OpNo) Ops.push_back(MapValue(cast<Constant>(C->getOperand(OpNo)), VM, Flags, TypeMapper)); } if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) return VM[V] = CE->getWithOperands(Ops, NewTy); if (isa<ConstantArray>(C)) return VM[V] = ConstantArray::get(cast<ArrayType>(NewTy), Ops); if (isa<ConstantStruct>(C)) return VM[V] = ConstantStruct::get(cast<StructType>(NewTy), Ops); if (isa<ConstantVector>(C)) return VM[V] = ConstantVector::get(Ops); // If this is a no-operand constant, it must be because the type was remapped. if (isa<UndefValue>(C)) return VM[V] = UndefValue::get(NewTy); if (isa<ConstantAggregateZero>(C)) return VM[V] = ConstantAggregateZero::get(NewTy); assert(isa<ConstantPointerNull>(C)); return VM[V] = ConstantPointerNull::get(cast<PointerType>(NewTy)); }
// ResolveConstantExpr - Resolve the constant expression until it stop // yielding other constant expressions. CstExprResTy ELFWriter::ResolveConstantExpr(const Constant *CV) { const TargetData *TD = TM.getTargetData(); // There ins't constant expression inside others anymore if (!isa<ConstantExpr>(CV)) return std::make_pair(CV, 0); const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV); switch (CE->getOpcode()) { case Instruction::BitCast: return ResolveConstantExpr(CE->getOperand(0)); case Instruction::GetElementPtr: { const Constant *ptrVal = CE->getOperand(0); SmallVector<Value*, 8> idxVec(CE->op_begin()+1, CE->op_end()); int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0], idxVec.size()); return std::make_pair(ptrVal, Offset); } case Instruction::IntToPtr: { Constant *Op = CE->getOperand(0); Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(CV->getContext()), false/*ZExt*/); return ResolveConstantExpr(Op); } case Instruction::PtrToInt: { Constant *Op = CE->getOperand(0); const Type *Ty = CE->getType(); // We can emit the pointer value into this slot if the slot is an // integer slot greater or equal to the size of the pointer. if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType())) return ResolveConstantExpr(Op); llvm_unreachable("Integer size less then pointer size"); } case Instruction::Add: case Instruction::Sub: { // Only handle cases where there's a constant expression with GlobalValue // as first operand and ConstantInt as second, which are the cases we can // solve direclty using a relocation entry. GlobalValue=Op0, CstInt=Op1 // 1) Instruction::Add => (global) + CstInt // 2) Instruction::Sub => (global) + -CstInt const Constant *Op0 = CE->getOperand(0); const Constant *Op1 = CE->getOperand(1); assert(isa<ConstantInt>(Op1) && "Op1 must be a ConstantInt"); CstExprResTy Res = ResolveConstantExpr(Op0); assert(isa<GlobalValue>(Res.first) && "Op0 must be a GlobalValue"); const APInt &RHS = cast<ConstantInt>(Op1)->getValue(); switch (CE->getOpcode()) { case Instruction::Add: return std::make_pair(Res.first, RHS.getSExtValue()); case Instruction::Sub: return std::make_pair(Res.first, (-RHS).getSExtValue()); } } } report_fatal_error(CE->getOpcodeName() + StringRef(": Unsupported ConstantExpr type")); return std::make_pair(CV, 0); // silence warning }
/// CleanupAndPrepareModules - Get the specified modules ready for code /// generator testing. /// static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, Module *Safe) { // Clean up the modules, removing extra cruft that we don't need anymore... Test = BD.performFinalCleanups(Test); // If we are executing the JIT, we have several nasty issues to take care of. if (!BD.isExecutingJIT()) return; // First, if the main function is in the Safe module, we must add a stub to // the Test module to call into it. Thus, we create a new function `main' // which just calls the old one. if (Function *oldMain = Safe->getFunction("main")) if (!oldMain->isDeclaration()) { // Rename it oldMain->setName("llvm_bugpoint_old_main"); // Create a NEW `main' function with same type in the test module. Function *newMain = Function::Create(oldMain->getFunctionType(), GlobalValue::ExternalLinkage, "main", Test); // Create an `oldmain' prototype in the test module, which will // corresponds to the real main function in the same module. Function *oldMainProto = Function::Create(oldMain->getFunctionType(), GlobalValue::ExternalLinkage, oldMain->getName(), Test); // Set up and remember the argument list for the main function. std::vector<Value*> args; for (Function::arg_iterator I = newMain->arg_begin(), E = newMain->arg_end(), OI = oldMain->arg_begin(); I != E; ++I, ++OI) { I->setName(OI->getName()); // Copy argument names from oldMain args.push_back(I); } // Call the old main function and return its result BasicBlock *BB = BasicBlock::Create(Safe->getContext(), "entry", newMain); CallInst *call = CallInst::Create(oldMainProto, args, "", BB); // If the type of old function wasn't void, return value of call ReturnInst::Create(Safe->getContext(), call, BB); } // The second nasty issue we must deal with in the JIT is that the Safe // module cannot directly reference any functions defined in the test // module. Instead, we use a JIT API call to dynamically resolve the // symbol. // Add the resolver to the Safe module. // Prototype: void *getPointerToNamedFunction(const char* Name) Constant *resolverFunc = Safe->getOrInsertFunction("getPointerToNamedFunction", Type::getInt8PtrTy(Safe->getContext()), Type::getInt8PtrTy(Safe->getContext()), (Type *)0); // Use the function we just added to get addresses of functions we need. for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) { if (F->isDeclaration() && !F->use_empty() && &*F != resolverFunc && !F->isIntrinsic() /* ignore intrinsics */) { Function *TestFn = Test->getFunction(F->getName()); // Don't forward functions which are external in the test module too. if (TestFn && !TestFn->isDeclaration()) { // 1. Add a string constant with its name to the global file Constant *InitArray = ConstantDataArray::getString(F->getContext(), F->getName()); GlobalVariable *funcName = new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/, GlobalValue::InternalLinkage, InitArray, F->getName() + "_name"); // 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an // sbyte* so it matches the signature of the resolver function. // GetElementPtr *funcName, ulong 0, ulong 0 std::vector<Constant*> GEPargs(2, Constant::getNullValue(Type::getInt32Ty(F->getContext()))); Value *GEP = ConstantExpr::getGetElementPtr(funcName, GEPargs); std::vector<Value*> ResolverArgs; ResolverArgs.push_back(GEP); // Rewrite uses of F in global initializers, etc. to uses of a wrapper // function that dynamically resolves the calls to F via our JIT API if (!F->use_empty()) { // Create a new global to hold the cached function pointer. Constant *NullPtr = ConstantPointerNull::get(F->getType()); GlobalVariable *Cache = new GlobalVariable(*F->getParent(), F->getType(), false, GlobalValue::InternalLinkage, NullPtr,F->getName()+".fpcache"); // Construct a new stub function that will re-route calls to F FunctionType *FuncTy = F->getFunctionType(); Function *FuncWrapper = Function::Create(FuncTy, GlobalValue::InternalLinkage, F->getName() + "_wrapper", F->getParent()); BasicBlock *EntryBB = BasicBlock::Create(F->getContext(), "entry", FuncWrapper); BasicBlock *DoCallBB = BasicBlock::Create(F->getContext(), "usecache", FuncWrapper); BasicBlock *LookupBB = BasicBlock::Create(F->getContext(), "lookupfp", FuncWrapper); // Check to see if we already looked up the value. Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB); Value *IsNull = new ICmpInst(*EntryBB, ICmpInst::ICMP_EQ, CachedVal, NullPtr, "isNull"); BranchInst::Create(LookupBB, DoCallBB, IsNull, EntryBB); // Resolve the call to function F via the JIT API: // // call resolver(GetElementPtr...) CallInst *Resolver = CallInst::Create(resolverFunc, ResolverArgs, "resolver", LookupBB); // Cast the result from the resolver to correctly-typed function. CastInst *CastedResolver = new BitCastInst(Resolver, PointerType::getUnqual(F->getFunctionType()), "resolverCast", LookupBB); // Save the value in our cache. new StoreInst(CastedResolver, Cache, LookupBB); BranchInst::Create(DoCallBB, LookupBB); PHINode *FuncPtr = PHINode::Create(NullPtr->getType(), 2, "fp", DoCallBB); FuncPtr->addIncoming(CastedResolver, LookupBB); FuncPtr->addIncoming(CachedVal, EntryBB); // Save the argument list. std::vector<Value*> Args; for (Function::arg_iterator i = FuncWrapper->arg_begin(), e = FuncWrapper->arg_end(); i != e; ++i) Args.push_back(i); // Pass on the arguments to the real function, return its result if (F->getReturnType()->isVoidTy()) { CallInst::Create(FuncPtr, Args, "", DoCallBB); ReturnInst::Create(F->getContext(), DoCallBB); } else { CallInst *Call = CallInst::Create(FuncPtr, Args, "retval", DoCallBB); ReturnInst::Create(F->getContext(),Call, DoCallBB); } // Use the wrapper function instead of the old function F->replaceAllUsesWith(FuncWrapper); } } } } if (verifyModule(*Test) || verifyModule(*Safe)) { errs() << "Bugpoint has a bug, which corrupted a module!!\n"; abort(); } }
Instruction *InstCombiner::visitSRem(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); if (Value *V = SimplifyVectorOp(I)) return ReplaceInstUsesWith(I, V); if (Value *V = SimplifySRemInst(Op0, Op1, DL)) return ReplaceInstUsesWith(I, V); // Handle the integer rem common cases if (Instruction *Common = commonIRemTransforms(I)) return Common; if (Value *RHSNeg = dyn_castNegVal(Op1)) if (!isa<Constant>(RHSNeg) || (isa<ConstantInt>(RHSNeg) && cast<ConstantInt>(RHSNeg)->getValue().isStrictlyPositive())) { // X % -Y -> X % Y Worklist.AddValue(I.getOperand(1)); I.setOperand(1, RHSNeg); return &I; } // If the sign bits of both operands are zero (i.e. we can prove they are // unsigned inputs), turn this into a urem. if (I.getType()->isIntegerTy()) { APInt Mask(APInt::getSignBit(I.getType()->getPrimitiveSizeInBits())); if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) { // X srem Y -> X urem Y, iff X and Y don't have sign bit set return BinaryOperator::CreateURem(Op0, Op1, I.getName()); } } // If it's a constant vector, flip any negative values positive. if (isa<ConstantVector>(Op1) || isa<ConstantDataVector>(Op1)) { Constant *C = cast<Constant>(Op1); unsigned VWidth = C->getType()->getVectorNumElements(); bool hasNegative = false; bool hasMissing = false; for (unsigned i = 0; i != VWidth; ++i) { Constant *Elt = C->getAggregateElement(i); if (!Elt) { hasMissing = true; break; } if (ConstantInt *RHS = dyn_cast<ConstantInt>(Elt)) if (RHS->isNegative()) hasNegative = true; } if (hasNegative && !hasMissing) { SmallVector<Constant *, 16> Elts(VWidth); for (unsigned i = 0; i != VWidth; ++i) { Elts[i] = C->getAggregateElement(i); // Handle undef, etc. if (ConstantInt *RHS = dyn_cast<ConstantInt>(Elts[i])) { if (RHS->isNegative()) Elts[i] = cast<ConstantInt>(ConstantExpr::getNeg(RHS)); } } Constant *NewRHSV = ConstantVector::get(Elts); if (NewRHSV != C) { // Don't loop on -MININT Worklist.AddValue(I.getOperand(1)); I.setOperand(1, NewRHSV); return &I; } } } return nullptr; }
Value *Mapper::mapValue(const Value *V) { ValueToValueMapTy::iterator I = getVM().find(V); // If the value already exists in the map, use it. if (I != getVM().end()) { assert(I->second && "Unexpected null mapping"); return I->second; } // If we have a materializer and it can materialize a value, use that. if (auto *Materializer = getMaterializer()) { if (Value *NewV = Materializer->materialize(const_cast<Value *>(V))) { getVM()[V] = NewV; return NewV; } } // Global values do not need to be seeded into the VM if they // are using the identity mapping. if (isa<GlobalValue>(V)) { if (Flags & RF_NullMapMissingGlobalValues) return nullptr; return getVM()[V] = const_cast<Value *>(V); } if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) { // Inline asm may need *type* remapping. FunctionType *NewTy = IA->getFunctionType(); if (TypeMapper) { NewTy = cast<FunctionType>(TypeMapper->remapType(NewTy)); if (NewTy != IA->getFunctionType()) V = InlineAsm::get(NewTy, IA->getAsmString(), IA->getConstraintString(), IA->hasSideEffects(), IA->isAlignStack()); } return getVM()[V] = const_cast<Value *>(V); } if (const auto *MDV = dyn_cast<MetadataAsValue>(V)) { const Metadata *MD = MDV->getMetadata(); if (auto *LAM = dyn_cast<LocalAsMetadata>(MD)) { // Look through to grab the local value. if (Value *LV = mapValue(LAM->getValue())) { if (V == LAM->getValue()) return const_cast<Value *>(V); return MetadataAsValue::get(V->getContext(), ValueAsMetadata::get(LV)); } // FIXME: always return nullptr once Verifier::verifyDominatesUse() // ensures metadata operands only reference defined SSA values. return (Flags & RF_IgnoreMissingLocals) ? nullptr : MetadataAsValue::get(V->getContext(), MDTuple::get(V->getContext(), None)); } // If this is a module-level metadata and we know that nothing at the module // level is changing, then use an identity mapping. if (Flags & RF_NoModuleLevelChanges) return getVM()[V] = const_cast<Value *>(V); // Map the metadata and turn it into a value. auto *MappedMD = mapMetadata(MD); if (MD == MappedMD) return getVM()[V] = const_cast<Value *>(V); return getVM()[V] = MetadataAsValue::get(V->getContext(), MappedMD); } // Okay, this either must be a constant (which may or may not be mappable) or // is something that is not in the mapping table. Constant *C = const_cast<Constant*>(dyn_cast<Constant>(V)); if (!C) return nullptr; if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) return mapBlockAddress(*BA); auto mapValueOrNull = [this](Value *V) { auto Mapped = mapValue(V); assert((Mapped || (Flags & RF_NullMapMissingGlobalValues)) && "Unexpected null mapping for constant operand without " "NullMapMissingGlobalValues flag"); return Mapped; }; // Otherwise, we have some other constant to remap. Start by checking to see // if all operands have an identity remapping. unsigned OpNo = 0, NumOperands = C->getNumOperands(); Value *Mapped = nullptr; for (; OpNo != NumOperands; ++OpNo) { Value *Op = C->getOperand(OpNo); Mapped = mapValueOrNull(Op); if (!Mapped) return nullptr; if (Mapped != Op) break; } // See if the type mapper wants to remap the type as well. Type *NewTy = C->getType(); if (TypeMapper) NewTy = TypeMapper->remapType(NewTy); // If the result type and all operands match up, then just insert an identity // mapping. if (OpNo == NumOperands && NewTy == C->getType()) return getVM()[V] = C; // Okay, we need to create a new constant. We've already processed some or // all of the operands, set them all up now. SmallVector<Constant*, 8> Ops; Ops.reserve(NumOperands); for (unsigned j = 0; j != OpNo; ++j) Ops.push_back(cast<Constant>(C->getOperand(j))); // If one of the operands mismatch, push it and the other mapped operands. if (OpNo != NumOperands) { Ops.push_back(cast<Constant>(Mapped)); // Map the rest of the operands that aren't processed yet. for (++OpNo; OpNo != NumOperands; ++OpNo) { Mapped = mapValueOrNull(C->getOperand(OpNo)); if (!Mapped) return nullptr; Ops.push_back(cast<Constant>(Mapped)); } } Type *NewSrcTy = nullptr; if (TypeMapper) if (auto *GEPO = dyn_cast<GEPOperator>(C)) NewSrcTy = TypeMapper->remapType(GEPO->getSourceElementType()); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) return getVM()[V] = CE->getWithOperands(Ops, NewTy, false, NewSrcTy); if (isa<ConstantArray>(C)) return getVM()[V] = ConstantArray::get(cast<ArrayType>(NewTy), Ops); if (isa<ConstantStruct>(C)) return getVM()[V] = ConstantStruct::get(cast<StructType>(NewTy), Ops); if (isa<ConstantVector>(C)) return getVM()[V] = ConstantVector::get(Ops); // If this is a no-operand constant, it must be because the type was remapped. if (isa<UndefValue>(C)) return getVM()[V] = UndefValue::get(NewTy); if (isa<ConstantAggregateZero>(C)) return getVM()[V] = ConstantAggregateZero::get(NewTy); assert(isa<ConstantPointerNull>(C)); return getVM()[V] = ConstantPointerNull::get(cast<PointerType>(NewTy)); }
bool SparcAsmPrinter::doFinalization(Module &M) { const TargetData *TD = TM.getTargetData(); // Print out module-level global variables here. for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (I->hasInitializer()) { // External global require no code // Check to see if this is a special global used by LLVM, if so, emit it. if (EmitSpecialLLVMGlobal(I)) continue; O << "\n\n"; std::string name = Mang->getValueName(I); Constant *C = I->getInitializer(); unsigned Size = TD->getTypeSize(C->getType()); unsigned Align = TD->getPrefTypeAlignment(C->getType()); if (C->isNullValue() && (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || I->hasWeakLinkage() /* FIXME: Verify correct */)) { SwitchToDataSection(".data", I); if (I->hasInternalLinkage()) O << "\t.local " << name << "\n"; O << "\t.comm " << name << "," << TD->getTypeSize(C->getType()) << "," << Align; O << "\n"; } else { switch (I->getLinkage()) { case GlobalValue::LinkOnceLinkage: case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. // Nonnull linkonce -> weak O << "\t.weak " << name << "\n"; SwitchToDataSection("", I); O << "\t.section\t\".llvm.linkonce.d." << name << "\",\"aw\",@progbits\n"; break; case GlobalValue::AppendingLinkage: // FIXME: appending linkage variables should go into a section of // their name or something. For now, just emit them as external. case GlobalValue::ExternalLinkage: // If external or appending, declare as a global symbol O << "\t.globl " << name << "\n"; // FALL THROUGH case GlobalValue::InternalLinkage: if (C->isNullValue()) SwitchToDataSection(".bss", I); else SwitchToDataSection(".data", I); break; case GlobalValue::GhostLinkage: cerr << "Should not have any unmaterialized functions!\n"; abort(); case GlobalValue::DLLImportLinkage: cerr << "DLLImport linkage is not supported by this target!\n"; abort(); case GlobalValue::DLLExportLinkage: cerr << "DLLExport linkage is not supported by this target!\n"; abort(); default: assert(0 && "Unknown linkage type!"); } O << "\t.align " << Align << "\n"; O << "\t.type " << name << ",#object\n"; O << "\t.size " << name << "," << Size << "\n"; O << name << ":\n"; EmitGlobalConstant(C); } } AsmPrinter::doFinalization(M); return false; // success }