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; }
bool SourceEntityWalker::walk(Module &Mod) { SemaAnnotator Annotator(*this); return Mod.walk(Annotator); }
static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) { Mod.print(OS, nullptr); }
// run - Run the transformation on the program. We grab the function // prototypes for longjmp and setjmp. If they are used in the program, // then we can go directly to the places they're at and transform them. bool LowerSetJmp::runOnModule(Module& M) { bool Changed = false; // These are what the functions are called. Function* SetJmp = M.getFunction("llvm.setjmp"); Function* LongJmp = M.getFunction("llvm.longjmp"); // This program doesn't have longjmp and setjmp calls. if ((!LongJmp || LongJmp->use_empty()) && (!SetJmp || SetJmp->use_empty())) return false; // Initialize some values and functions we'll need to transform the // setjmp/longjmp functions. doInitialization(M); if (SetJmp) { for (Value::use_iterator B = SetJmp->use_begin(), E = SetJmp->use_end(); B != E; ++B) { BasicBlock* BB = cast<Instruction>(*B)->getParent(); for (df_ext_iterator<BasicBlock*> I = df_ext_begin(BB, DFSBlocks), E = df_ext_end(BB, DFSBlocks); I != E; ++I) /* empty */; } while (!SetJmp->use_empty()) { assert(isa<CallInst>(SetJmp->use_back()) && "User of setjmp intrinsic not a call?"); TransformSetJmpCall(cast<CallInst>(SetJmp->use_back())); Changed = true; } } if (LongJmp) while (!LongJmp->use_empty()) { assert(isa<CallInst>(LongJmp->use_back()) && "User of longjmp intrinsic not a call?"); TransformLongJmpCall(cast<CallInst>(LongJmp->use_back())); Changed = true; } // Now go through the affected functions and convert calls and invokes // to new invokes... for (std::map<Function*, AllocaInst*>::iterator B = SJMap.begin(), E = SJMap.end(); B != E; ++B) { Function* F = B->first; for (Function::iterator BB = F->begin(), BE = F->end(); BB != BE; ++BB) for (BasicBlock::iterator IB = BB->begin(), IE = BB->end(); IB != IE; ) { visit(*IB++); if (IB != BB->end() && IB->getParent() != BB) break; // The next instruction got moved to a different block! } } DFSBlocks.clear(); SJMap.clear(); RethrowBBMap.clear(); PrelimBBMap.clear(); SwitchValMap.clear(); SetJmpIDMap.clear(); return Changed; }
void compile_module_to_html(const Module &module, std::string filename) { if (filename.empty()) filename = module.name() + ".html"; Internal::print_to_html(filename, module); }
bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { // Clone the program to try hacking it apart... Module *M = CloneModule(BD.getProgram()); // Convert list to set for fast lookup... std::set<BasicBlock*> Blocks; for (unsigned i = 0, e = BBs.size(); i != e; ++i) { // Convert the basic block from the original module to the new module... const Function *F = BBs[i]->getParent(); Function *CMF = M->getFunction(F->getName()); assert(CMF && "Function not in module?!"); assert(CMF->getFunctionType() == F->getFunctionType() && "wrong type?"); // Get the mapped basic block... Function::iterator CBI = CMF->begin(); std::advance(CBI, std::distance(F->begin(), Function::const_iterator(BBs[i]))); Blocks.insert(CBI); } std::cout << "Checking for crash with only these blocks:"; unsigned NumPrint = Blocks.size(); if (NumPrint > 10) NumPrint = 10; for (unsigned i = 0, e = NumPrint; i != e; ++i) std::cout << " " << BBs[i]->getName(); if (NumPrint < Blocks.size()) std::cout << "... <" << Blocks.size() << " total>"; std::cout << ": "; // Loop over and delete any hack up any blocks that are not listed... for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB) if (!Blocks.count(BB) && BB->getTerminator()->getNumSuccessors()) { // Loop over all of the successors of this block, deleting any PHI nodes // that might include it. for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI) (*SI)->removePredecessor(BB); if (BB->getTerminator()->getType() != Type::VoidTy) BB->getTerminator()->replaceAllUsesWith( Constant::getNullValue(BB->getTerminator()->getType())); // Delete the old terminator instruction... BB->getInstList().pop_back(); // Add a new return instruction of the appropriate type... const Type *RetTy = BB->getParent()->getReturnType(); new ReturnInst(RetTy == Type::VoidTy ? 0 : Constant::getNullValue(RetTy), BB); } // The CFG Simplifier pass may delete one of the basic blocks we are // interested in. If it does we need to take the block out of the list. Make // a "persistent mapping" by turning basic blocks into <function, name> pairs. // This won't work well if blocks are unnamed, but that is just the risk we // have to take. std::vector<std::pair<Function*, std::string> > BlockInfo; for (std::set<BasicBlock*>::iterator I = Blocks.begin(), E = Blocks.end(); I != E; ++I) BlockInfo.push_back(std::make_pair((*I)->getParent(), (*I)->getName())); // Now run the CFG simplify pass on the function... PassManager Passes; Passes.add(createCFGSimplificationPass()); Passes.add(createVerifierPass()); Passes.run(*M); // Try running on the hacked up program... if (TestFn(BD, M)) { BD.setNewProgram(M); // It crashed, keep the trimmed version... // Make sure to use basic block pointers that point into the now-current // module, and that they don't include any deleted blocks. BBs.clear(); for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) { ValueSymbolTable &ST = BlockInfo[i].first->getValueSymbolTable(); Value* V = ST.lookup(BlockInfo[i].second); if (V && V->getType() == Type::LabelTy) BBs.push_back(cast<BasicBlock>(V)); } return true; } delete M; // It didn't crash, try something else. return false; }
void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) { // Load argc and argv from the entry point arguments. SILValue argc = F.begin()->getBBArg(0); SILValue argv = F.begin()->getBBArg(1); switch (mainClass->getArtificialMainKind()) { case ArtificialMainKind::UIApplicationMain: { // Emit a UIKit main. // return UIApplicationMain(C_ARGC, C_ARGV, nil, ClassName); CanType NSStringTy = SGM.Types.getNSStringType(); CanType OptNSStringTy = OptionalType::get(NSStringTy)->getCanonicalType(); CanType IUOptNSStringTy = ImplicitlyUnwrappedOptionalType::get(NSStringTy)->getCanonicalType(); // Look up UIApplicationMain. // FIXME: Doing an AST lookup here is gross and not entirely sound; // we're getting away with it because the types are guaranteed to already // be imported. ASTContext &ctx = getASTContext(); Module *UIKit = ctx.getLoadedModule(ctx.getIdentifier("UIKit")); SmallVector<ValueDecl *, 1> results; UIKit->lookupQualified(UIKit->getDeclaredType(), ctx.getIdentifier("UIApplicationMain"), NL_QualifiedDefault, /*resolver*/nullptr, results); assert(!results.empty() && "couldn't find UIApplicationMain in UIKit"); assert(results.size() == 1 && "more than one UIApplicationMain?"); SILDeclRef mainRef{results.front(), ResilienceExpansion::Minimal, SILDeclRef::ConstructAtNaturalUncurryLevel, /*isForeign*/true}; auto UIApplicationMainFn = SGM.M.getOrCreateFunction(mainClass, mainRef, NotForDefinition); auto fnTy = UIApplicationMainFn->getLoweredFunctionType(); // Get the class name as a string using NSStringFromClass. CanType mainClassTy = mainClass->getDeclaredTypeInContext()->getCanonicalType(); CanType mainClassMetaty = CanMetatypeType::get(mainClassTy, MetatypeRepresentation::ObjC); ProtocolDecl *anyObjectProtocol = ctx.getProtocol(KnownProtocolKind::AnyObject); auto mainClassAnyObjectConformance = ProtocolConformanceRef( *SGM.M.getSwiftModule()->lookupConformance(mainClassTy, anyObjectProtocol, nullptr)); CanType anyObjectTy = anyObjectProtocol ->getDeclaredTypeInContext() ->getCanonicalType(); CanType anyObjectMetaTy = CanExistentialMetatypeType::get(anyObjectTy, MetatypeRepresentation::ObjC); auto NSStringFromClassType = SILFunctionType::get(nullptr, SILFunctionType::ExtInfo() .withRepresentation(SILFunctionType::Representation:: CFunctionPointer), ParameterConvention::Direct_Unowned, SILParameterInfo(anyObjectMetaTy, ParameterConvention::Direct_Unowned), SILResultInfo(OptNSStringTy, ResultConvention::Autoreleased), /*error result*/ None, ctx); auto NSStringFromClassFn = SGM.M.getOrCreateFunction(mainClass, "NSStringFromClass", SILLinkage::PublicExternal, NSStringFromClassType, IsBare, IsTransparent, IsNotFragile); auto NSStringFromClass = B.createFunctionRef(mainClass, NSStringFromClassFn); SILValue metaTy = B.createMetatype(mainClass, SILType::getPrimitiveObjectType(mainClassMetaty)); metaTy = B.createInitExistentialMetatype(mainClass, metaTy, SILType::getPrimitiveObjectType(anyObjectMetaTy), ctx.AllocateCopy( llvm::makeArrayRef(mainClassAnyObjectConformance))); SILValue optName = B.createApply(mainClass, NSStringFromClass, NSStringFromClass->getType(), SILType::getPrimitiveObjectType(OptNSStringTy), {}, metaTy); // Fix up the string parameters to have the right type. SILType nameArgTy = fnTy->getSILArgumentType(3); assert(nameArgTy == fnTy->getSILArgumentType(2)); auto managedName = ManagedValue::forUnmanaged(optName); SILValue nilValue; if (optName->getType() == nameArgTy) { nilValue = getOptionalNoneValue(mainClass, getTypeLowering(OptNSStringTy)); } else { assert(nameArgTy.getSwiftRValueType() == IUOptNSStringTy); nilValue = getOptionalNoneValue(mainClass, getTypeLowering(IUOptNSStringTy)); managedName = emitOptionalToOptional( mainClass, managedName, SILType::getPrimitiveObjectType(IUOptNSStringTy), [](SILGenFunction &, SILLocation, ManagedValue input, SILType) { return input; }); } // Fix up argv to have the right type. auto argvTy = fnTy->getSILArgumentType(1); SILType unwrappedTy = argvTy; if (Type innerTy = argvTy.getSwiftRValueType()->getAnyOptionalObjectType()){ auto canInnerTy = innerTy->getCanonicalType(); unwrappedTy = SILType::getPrimitiveObjectType(canInnerTy); } auto managedArgv = ManagedValue::forUnmanaged(argv); if (unwrappedTy != argv->getType()) { auto converted = emitPointerToPointer(mainClass, managedArgv, argv->getType().getSwiftRValueType(), unwrappedTy.getSwiftRValueType()); managedArgv = std::move(converted).getAsSingleValue(*this, mainClass); } if (unwrappedTy != argvTy) { managedArgv = getOptionalSomeValue(mainClass, managedArgv, getTypeLowering(argvTy)); } auto UIApplicationMain = B.createFunctionRef(mainClass, UIApplicationMainFn); SILValue args[] = {argc, managedArgv.getValue(), nilValue, managedName.getValue()}; B.createApply(mainClass, UIApplicationMain, UIApplicationMain->getType(), argc->getType(), {}, args); SILValue r = B.createIntegerLiteral(mainClass, SILType::getBuiltinIntegerType(32, ctx), 0); auto rType = F.getLoweredFunctionType()->getSingleResult().getSILType(); if (r->getType() != rType) r = B.createStruct(mainClass, rType, r); Cleanups.emitCleanupsForReturn(mainClass); B.createReturn(mainClass, r); return; } case ArtificialMainKind::NSApplicationMain: { // Emit an AppKit main. // return NSApplicationMain(C_ARGC, C_ARGV); SILParameterInfo argTypes[] = { SILParameterInfo(argc->getType().getSwiftRValueType(), ParameterConvention::Direct_Unowned), SILParameterInfo(argv->getType().getSwiftRValueType(), ParameterConvention::Direct_Unowned), }; auto NSApplicationMainType = SILFunctionType::get(nullptr, SILFunctionType::ExtInfo() // Should be C calling convention, but NSApplicationMain // has an overlay to fix the type of argv. .withRepresentation(SILFunctionType::Representation::Thin), ParameterConvention::Direct_Unowned, argTypes, SILResultInfo(argc->getType().getSwiftRValueType(), ResultConvention::Unowned), /*error result*/ None, getASTContext()); auto NSApplicationMainFn = SGM.M.getOrCreateFunction(mainClass, "NSApplicationMain", SILLinkage::PublicExternal, NSApplicationMainType, IsBare, IsTransparent, IsNotFragile); auto NSApplicationMain = B.createFunctionRef(mainClass, NSApplicationMainFn); SILValue args[] = { argc, argv }; B.createApply(mainClass, NSApplicationMain, NSApplicationMain->getType(), argc->getType(), {}, args); SILValue r = B.createIntegerLiteral(mainClass, SILType::getBuiltinIntegerType(32, getASTContext()), 0); auto rType = F.getLoweredFunctionType()->getSingleResult().getSILType(); if (r->getType() != rType) r = B.createStruct(mainClass, rType, r); B.createReturn(mainClass, r); return; } } }
static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) { if (I == M.alias_end()) return 3; const GlobalValue *GV = &*I; return reinterpret_cast<uintptr_t>(GV) | 2; }
static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) { if (I == M.end()) return skipEmpty(M.global_begin(), M); const GlobalValue *GV = &*I; return reinterpret_cast<uintptr_t>(GV) | 0; }
llvm::error_code ELFObjectWriter::writeObject(Module& pModule, MemoryArea& pOutput) { bool is_dynobj = m_Config.codeGenType() == LinkerConfig::DynObj; bool is_exec = m_Config.codeGenType() == LinkerConfig::Exec; bool is_binary = m_Config.codeGenType() == LinkerConfig::Binary; bool is_object = m_Config.codeGenType() == LinkerConfig::Object; assert(is_dynobj || is_exec || is_binary || is_object); if (is_dynobj || is_exec) { // Allow backend to sort symbols before emitting target().orderSymbolTable(pModule); // Write out the interpreter section: .interp target().emitInterp(pOutput); // Write out name pool sections: .dynsym, .dynstr, .hash target().emitDynNamePools(pModule, pOutput); } if (is_object || is_dynobj || is_exec) { // Write out name pool sections: .symtab, .strtab target().emitRegNamePools(pModule, pOutput); } if (is_binary) { // Iterate over the loadable segments and write the corresponding sections ELFSegmentFactory::iterator seg, segEnd = target().elfSegmentTable().end(); for (seg = target().elfSegmentTable().begin(); seg != segEnd; ++seg) { if (llvm::ELF::PT_LOAD == (*seg).type()) { ELFSegment::sect_iterator sect, sectEnd = (*seg).end(); for (sect = (*seg).begin(); sect != sectEnd; ++sect) writeSection(pOutput, *sect); } } } else { // Write out regular ELF sections Module::iterator sect, sectEnd = pModule.end(); for (sect = pModule.begin(); sect != sectEnd; ++sect) writeSection(pOutput, *sect); emitShStrTab(target().getOutputFormat()->getShStrTab(), pModule, pOutput); if (m_Config.targets().is32Bits()) { // Write out ELF header // Write out section header table writeELFHeader<32>(m_Config, pModule, pOutput); if (is_dynobj || is_exec) emitProgramHeader<32>(pOutput); emitSectionHeader<32>(pModule, m_Config, pOutput); } else if (m_Config.targets().is64Bits()) { // Write out ELF header // Write out section header table writeELFHeader<64>(m_Config, pModule, pOutput); if (is_dynobj || is_exec) emitProgramHeader<64>(pOutput); emitSectionHeader<64>(pModule, m_Config, pOutput); } else return make_error_code(errc::not_supported); } pOutput.clear(); return llvm::make_error_code(llvm::errc::success); }
uint64_t ELFObjectWriter::getLastStartOffset<64>(const Module& pModule) const { const LDSection* lastSect = pModule.back(); assert(lastSect != NULL); return Align<64>(lastSect->offset() + lastSect->size()); }
// Construct the lowerer base class and initialize its members. coro::LowererBase::LowererBase(Module &M) : TheModule(M), Context(M.getContext()), ResumeFnType(FunctionType::get(Type::getVoidTy(Context), Type::getInt8PtrTy(Context), /*isVarArg=*/false)) {}
void Manager::process_modules( const Tsk::Task< Manager >& task ) { Module* next; Module* current; Lst::Search< Module > sh; Manager& manager = task.GetData(); if ( !manager.control_change ) { return; // nothing to do } manager.control_change = false; next = sh.FirstItem( manager.module_list ); while ( next ) { current = next; next = sh.NextItem(); // get next item before excuting callback switch ( current->state ) { case Module::vSTOPPED : { if (( current->command == Module::vSTART ) || ( current->command == Module::vRESTART )) { #ifndef __PLAT_XBOX__ #ifndef __PLAT_NGC__ #ifdef __NOPT_DEBUG__ Dbg_Notify ( "Starting module %s @ %d", current->GetName(), Tmr::GetTime() ); // should use Game Clock not system clock #endif #endif #endif current->v_start_cb(); current->state = Module::vRUNNING; current->command = Module::vNONE; } break; } case Module::vRUNNING : { if ( current->command == Module::vSTOP ) { #ifndef __PLAT_XBOX__ #ifndef __PLAT_NGC__ #ifdef __NOPT_DEBUG__ Dbg_Notify ( "Stopping module %s @ %d", current->GetName(), Tmr::GetTime() ); // should use Game Clock not system clock #endif #endif #endif current->v_stop_cb(); current->state = Module::vSTOPPED; current->command = Module::vNONE; } else if ( current->command == Module::vRESTART ) { #ifndef __PLAT_XBOX__ #ifndef __PLAT_NGC__ #ifdef __NOPT_DEBUG__ Dbg_Notify ( "Restarting module %s @ %d", current->GetName(), Tmr::GetTime() ); // should use Game Clock not system clock #endif #endif #endif current->v_stop_cb(); current->v_start_cb(); current->command = Module::vNONE; } break; } default: { Dbg_MsgAssert( false,( "Invalid module control state" )); } } } }
Module *Preprocessor::LeaveSubmodule(bool ForPragma) { if (BuildingSubmoduleStack.empty() || BuildingSubmoduleStack.back().IsPragma != ForPragma) { assert(ForPragma && "non-pragma module enter/leave mismatch"); return nullptr; } auto &Info = BuildingSubmoduleStack.back(); Module *LeavingMod = Info.M; SourceLocation ImportLoc = Info.ImportLoc; if (!needModuleMacros() || (!getLangOpts().ModulesLocalVisibility && LeavingMod->getTopLevelModuleName() != getLangOpts().CurrentModule)) { // If we don't need module macros, or this is not a module for which we // are tracking macro visibility, don't build any, and preserve the list // of pending names for the surrounding submodule. BuildingSubmoduleStack.pop_back(); makeModuleVisible(LeavingMod, ImportLoc); return LeavingMod; } // Create ModuleMacros for any macros defined in this submodule. llvm::SmallPtrSet<const IdentifierInfo*, 8> VisitedMacros; for (unsigned I = Info.OuterPendingModuleMacroNames; I != PendingModuleMacroNames.size(); ++I) { auto *II = const_cast<IdentifierInfo*>(PendingModuleMacroNames[I]); if (!VisitedMacros.insert(II).second) continue; auto MacroIt = CurSubmoduleState->Macros.find(II); if (MacroIt == CurSubmoduleState->Macros.end()) continue; auto &Macro = MacroIt->second; // Find the starting point for the MacroDirective chain in this submodule. MacroDirective *OldMD = nullptr; auto *OldState = Info.OuterSubmoduleState; if (getLangOpts().ModulesLocalVisibility) OldState = &NullSubmoduleState; if (OldState && OldState != CurSubmoduleState) { // FIXME: It'd be better to start at the state from when we most recently // entered this submodule, but it doesn't really matter. auto &OldMacros = OldState->Macros; auto OldMacroIt = OldMacros.find(II); if (OldMacroIt == OldMacros.end()) OldMD = nullptr; else OldMD = OldMacroIt->second.getLatest(); } // This module may have exported a new macro. If so, create a ModuleMacro // representing that fact. bool ExplicitlyPublic = false; for (auto *MD = Macro.getLatest(); MD != OldMD; MD = MD->getPrevious()) { assert(MD && "broken macro directive chain"); if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) { // The latest visibility directive for a name in a submodule affects // all the directives that come before it. if (VisMD->isPublic()) ExplicitlyPublic = true; else if (!ExplicitlyPublic) // Private with no following public directive: not exported. break; } else { MacroInfo *Def = nullptr; if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) Def = DefMD->getInfo(); // FIXME: Issue a warning if multiple headers for the same submodule // define a macro, rather than silently ignoring all but the first. bool IsNew; // Don't bother creating a module macro if it would represent a #undef // that doesn't override anything. if (Def || !Macro.getOverriddenMacros().empty()) addModuleMacro(LeavingMod, II, Def, Macro.getOverriddenMacros(), IsNew); if (!getLangOpts().ModulesLocalVisibility) { // This macro is exposed to the rest of this compilation as a // ModuleMacro; we don't need to track its MacroDirective any more. Macro.setLatest(nullptr); Macro.setOverriddenMacros(*this, {}); } break; } } } PendingModuleMacroNames.resize(Info.OuterPendingModuleMacroNames); // FIXME: Before we leave this submodule, we should parse all the other // headers within it. Otherwise, we're left with an inconsistent state // where we've made the module visible but don't yet have its complete // contents. // Put back the outer module's state, if we're tracking it. if (getLangOpts().ModulesLocalVisibility) CurSubmoduleState = Info.OuterSubmoduleState; BuildingSubmoduleStack.pop_back(); // A nested #include makes the included submodule visible. makeModuleVisible(LeavingMod, ImportLoc); return LeavingMod; }
void InitializeSoftBound:: constructMetadataHandlers(Module & module){ Type* VoidTy = Type::getVoidTy(module.getContext()); Type* VoidPtrTy = PointerType::getUnqual(Type::getInt8Ty(module.getContext())); Type* SizeTy = Type::getInt64Ty(module.getContext()); Type* Int32Ty = Type::getInt32Ty(module.getContext()); module.getOrInsertFunction("__softboundcets_introspect_metadata", VoidTy, VoidPtrTy, VoidPtrTy, Int32Ty, NULL); module.getOrInsertFunction("__softboundcets_copy_metadata", VoidTy, VoidPtrTy, VoidPtrTy, SizeTy, NULL); Type* PtrVoidPtrTy = PointerType::getUnqual(VoidPtrTy); Type* PtrSizeTy = PointerType::getUnqual(SizeTy); module.getOrInsertFunction("__softboundcets_metadata_load", VoidTy, VoidPtrTy, PtrVoidPtrTy, PtrVoidPtrTy, PtrSizeTy, PtrVoidPtrTy, NULL); module.getOrInsertFunction("__softboundcets_metadata_store", VoidTy, VoidPtrTy, VoidPtrTy, VoidPtrTy, SizeTy, VoidPtrTy, NULL); module.getOrInsertFunction("__softboundcets_get_global_lock", VoidPtrTy, NULL); module.getOrInsertFunction("__softboundcets_stack_memory_allocation", VoidTy, PtrVoidPtrTy, PtrSizeTy, NULL); module.getOrInsertFunction("__softboundcets_stack_memory_deallocation", VoidTy, SizeTy, NULL); module.getOrInsertFunction("__softboundcets_spatial_call_dereference_check", VoidTy, VoidPtrTy, VoidPtrTy, VoidPtrTy, NULL); }
void StatsTracker::writeIStats() { Module *m = executor.kmodule->module; uint64_t istatsMask = 0; llvm::raw_fd_ostream &of = *istatsFile; // We assume that we didn't move the file pointer unsigned istatsSize = of.tell(); of.seek(0); of << "version: 1\n"; of << "creator: klee\n"; of << "pid: " << getpid() << "\n"; of << "cmd: " << m->getModuleIdentifier() << "\n\n"; of << "\n"; StatisticManager &sm = *theStatisticManager; unsigned nStats = sm.getNumStatistics(); // Max is 13, sadly istatsMask |= 1<<sm.getStatisticID("Queries"); istatsMask |= 1<<sm.getStatisticID("QueriesValid"); istatsMask |= 1<<sm.getStatisticID("QueriesInvalid"); istatsMask |= 1<<sm.getStatisticID("QueryTime"); istatsMask |= 1<<sm.getStatisticID("ResolveTime"); istatsMask |= 1<<sm.getStatisticID("Instructions"); istatsMask |= 1<<sm.getStatisticID("InstructionTimes"); istatsMask |= 1<<sm.getStatisticID("InstructionRealTimes"); istatsMask |= 1<<sm.getStatisticID("Forks"); istatsMask |= 1<<sm.getStatisticID("CoveredInstructions"); istatsMask |= 1<<sm.getStatisticID("UncoveredInstructions"); istatsMask |= 1<<sm.getStatisticID("States"); istatsMask |= 1<<sm.getStatisticID("MinDistToUncovered"); of << "positions: instr line\n"; for (unsigned i=0; i<nStats; i++) { if (istatsMask & (1<<i)) { Statistic &s = sm.getStatistic(i); of << "event: " << s.getShortName() << " : " << s.getName() << "\n"; } } of << "events: "; for (unsigned i=0; i<nStats; i++) { if (istatsMask & (1<<i)) of << sm.getStatistic(i).getShortName() << " "; } of << "\n"; // set state counts, decremented after we process so that we don't // have to zero all records each time. if (istatsMask & (1<<stats::states.getID())) updateStateStatistics(1); std::string sourceFile = ""; CallSiteSummaryTable callSiteStats; if (UseCallPaths) callPathManager.getSummaryStatistics(callSiteStats); of << "ob=" << objectFilename << "\n"; for (Module::iterator fnIt = m->begin(), fn_ie = m->end(); fnIt != fn_ie; ++fnIt) { if (!fnIt->isDeclaration()) { // Always try to write the filename before the function name, as otherwise // KCachegrind can create two entries for the function, one with an // unnamed file and one without. const InstructionInfo &ii = executor.kmodule->infos->getFunctionInfo(fnIt); if (ii.file != sourceFile) { of << "fl=" << ii.file << "\n"; sourceFile = ii.file; } of << "fn=" << fnIt->getName().str() << "\n"; for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end(); bbIt != bb_ie; ++bbIt) { for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); it != ie; ++it) { Instruction *instr = &*it; const InstructionInfo &ii = executor.kmodule->infos->getInfo(instr); unsigned index = ii.id; if (ii.file!=sourceFile) { of << "fl=" << ii.file << "\n"; sourceFile = ii.file; } of << ii.assemblyLine << " "; of << ii.line << " "; for (unsigned i=0; i<nStats; i++) if (istatsMask&(1<<i)) of << sm.getIndexedValue(sm.getStatistic(i), index) << " "; of << "\n"; if (UseCallPaths && (isa<CallInst>(instr) || isa<InvokeInst>(instr))) { CallSiteSummaryTable::iterator it = callSiteStats.find(instr); if (it!=callSiteStats.end()) { for (std::map<llvm::Function*, CallSiteInfo>::iterator fit = it->second.begin(), fie = it->second.end(); fit != fie; ++fit) { Function *f = fit->first; CallSiteInfo &csi = fit->second; const InstructionInfo &fii = executor.kmodule->infos->getFunctionInfo(f); if (fii.file!="" && fii.file!=sourceFile) of << "cfl=" << fii.file << "\n"; of << "cfn=" << f->getName().str() << "\n"; of << "calls=" << csi.count << " "; of << fii.assemblyLine << " "; of << fii.line << "\n"; of << ii.assemblyLine << " "; of << ii.line << " "; for (unsigned i=0; i<nStats; i++) { if (istatsMask&(1<<i)) { Statistic &s = sm.getStatistic(i); uint64_t value; // Hack, ignore things that don't make sense on // call paths. if (&s == &stats::uncoveredInstructions) { value = 0; } else { value = csi.statistics.getValue(s); } of << value << " "; } } of << "\n"; } } } } } } } if (istatsMask & (1<<stats::states.getID())) updateStateStatistics((uint64_t)-1); // Clear then end of the file if necessary (no truncate op?). unsigned pos = of.tell(); for (unsigned i=pos; i<istatsSize; ++i) of << '\n'; of.flush(); }
void sceNpTrophy_init() { sceNpTrophy.AddFunc(0x079f0e87, sceNpTrophyGetGameProgress); sceNpTrophy.AddFunc(0x1197b52c, sceNpTrophyRegisterContext); sceNpTrophy.AddFunc(0x1c25470d, sceNpTrophyCreateHandle); sceNpTrophy.AddFunc(0x27deda93, sceNpTrophySetSoundLevel); sceNpTrophy.AddFunc(0x370136fe, sceNpTrophyGetRequiredDiskSpace); sceNpTrophy.AddFunc(0x3741ecc7, sceNpTrophyDestroyContext); sceNpTrophy.AddFunc(0x39567781, sceNpTrophyInit); sceNpTrophy.AddFunc(0x48bd97c7, sceNpTrophyAbortHandle); sceNpTrophy.AddFunc(0x49d18217, sceNpTrophyGetGameInfo); sceNpTrophy.AddFunc(0x623cd2dc, sceNpTrophyDestroyHandle); sceNpTrophy.AddFunc(0x8ceedd21, sceNpTrophyUnlockTrophy); sceNpTrophy.AddFunc(0xa7fabf4d, sceNpTrophyTerm); sceNpTrophy.AddFunc(0xb3ac3478, sceNpTrophyGetTrophyUnlockState); sceNpTrophy.AddFunc(0xbaedf689, sceNpTrophyGetTrophyIcon); sceNpTrophy.AddFunc(0xe3bf9a28, sceNpTrophyCreateContext); sceNpTrophy.AddFunc(0xfce6d30a, sceNpTrophyGetTrophyInfo); sceNpTrophy.AddFunc(0xff299e03, sceNpTrophyGetGameIcon); }
void StatsTracker::computeReachableUncovered() { KModule *km = executor.kmodule; Module *m = km->module; static bool init = true; const InstructionInfoTable &infos = *km->infos; StatisticManager &sm = *theStatisticManager; if (init) { init = false; // Compute call targets. It would be nice to use alias information // instead of assuming all indirect calls hit all escaping // functions, eh? for (Module::iterator fnIt = m->begin(), fn_ie = m->end(); fnIt != fn_ie; ++fnIt) { for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end(); bbIt != bb_ie; ++bbIt) { for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); it != ie; ++it) { if (isa<CallInst>(it) || isa<InvokeInst>(it)) { CallSite cs(it); if (isa<InlineAsm>(cs.getCalledValue())) { // We can never call through here so assume no targets // (which should be correct anyhow). callTargets.insert(std::make_pair(it, std::vector<Function*>())); } else if (Function *target = getDirectCallTarget(cs)) { callTargets[it].push_back(target); } else { callTargets[it] = std::vector<Function*>(km->escapingFunctions.begin(), km->escapingFunctions.end()); } } } } } // Compute function callers as reflexion of callTargets. for (calltargets_ty::iterator it = callTargets.begin(), ie = callTargets.end(); it != ie; ++it) for (std::vector<Function*>::iterator fit = it->second.begin(), fie = it->second.end(); fit != fie; ++fit) functionCallers[*fit].push_back(it->first); // Initialize minDistToReturn to shortest paths through // functions. 0 is unreachable. std::vector<Instruction *> instructions; for (Module::iterator fnIt = m->begin(), fn_ie = m->end(); fnIt != fn_ie; ++fnIt) { if (fnIt->isDeclaration()) { if (fnIt->doesNotReturn()) { functionShortestPath[fnIt] = 0; } else { functionShortestPath[fnIt] = 1; // whatever } } else { functionShortestPath[fnIt] = 0; } // Not sure if I should bother to preorder here. XXX I should. for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end(); bbIt != bb_ie; ++bbIt) { for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); it != ie; ++it) { instructions.push_back(it); unsigned id = infos.getInfo(it).id; sm.setIndexedValue(stats::minDistToReturn, id, isa<ReturnInst>(it) #if LLVM_VERSION_CODE < LLVM_VERSION(3, 1) || isa<UnwindInst>(it) #endif ); } } } std::reverse(instructions.begin(), instructions.end()); // I'm so lazy it's not even worklisted. bool changed; do { changed = false; for (std::vector<Instruction*>::iterator it = instructions.begin(), ie = instructions.end(); it != ie; ++it) { Instruction *inst = *it; unsigned bestThrough = 0; if (isa<CallInst>(inst) || isa<InvokeInst>(inst)) { std::vector<Function*> &targets = callTargets[inst]; for (std::vector<Function*>::iterator fnIt = targets.begin(), ie = targets.end(); fnIt != ie; ++fnIt) { uint64_t dist = functionShortestPath[*fnIt]; if (dist) { dist = 1+dist; // count instruction itself if (bestThrough==0 || dist<bestThrough) bestThrough = dist; } } } else { bestThrough = 1; } if (bestThrough) { unsigned id = infos.getInfo(*it).id; uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToReturn, id); std::vector<Instruction*> succs = getSuccs(*it); for (std::vector<Instruction*>::iterator it2 = succs.begin(), ie = succs.end(); it2 != ie; ++it2) { uint64_t dist = sm.getIndexedValue(stats::minDistToReturn, infos.getInfo(*it2).id); if (dist) { uint64_t val = bestThrough + dist; if (best==0 || val<best) best = val; } } // there's a corner case here when a function only includes a single // instruction (a ret). in that case, we MUST update // functionShortestPath, or it will remain 0 (erroneously indicating // that no return instructions are reachable) Function *f = inst->getParent()->getParent(); if (best != cur || (inst == f->begin()->begin() && functionShortestPath[f] != best)) { sm.setIndexedValue(stats::minDistToReturn, id, best); changed = true; // Update shortest path if this is the entry point. if (inst==f->begin()->begin()) functionShortestPath[f] = best; } } } } while (changed); } // compute minDistToUncovered, 0 is unreachable std::vector<Instruction *> instructions; for (Module::iterator fnIt = m->begin(), fn_ie = m->end(); fnIt != fn_ie; ++fnIt) { // Not sure if I should bother to preorder here. for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end(); bbIt != bb_ie; ++bbIt) { for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); it != ie; ++it) { unsigned id = infos.getInfo(it).id; instructions.push_back(&*it); sm.setIndexedValue(stats::minDistToUncovered, id, sm.getIndexedValue(stats::uncoveredInstructions, id)); } } } std::reverse(instructions.begin(), instructions.end()); // I'm so lazy it's not even worklisted. bool changed; do { changed = false; for (std::vector<Instruction*>::iterator it = instructions.begin(), ie = instructions.end(); it != ie; ++it) { Instruction *inst = *it; uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToUncovered, infos.getInfo(inst).id); unsigned bestThrough = 0; if (isa<CallInst>(inst) || isa<InvokeInst>(inst)) { std::vector<Function*> &targets = callTargets[inst]; for (std::vector<Function*>::iterator fnIt = targets.begin(), ie = targets.end(); fnIt != ie; ++fnIt) { uint64_t dist = functionShortestPath[*fnIt]; if (dist) { dist = 1+dist; // count instruction itself if (bestThrough==0 || dist<bestThrough) bestThrough = dist; } if (!(*fnIt)->isDeclaration()) { uint64_t calleeDist = sm.getIndexedValue(stats::minDistToUncovered, infos.getFunctionInfo(*fnIt).id); if (calleeDist) { calleeDist = 1+calleeDist; // count instruction itself if (best==0 || calleeDist<best) best = calleeDist; } } } } else { bestThrough = 1; } if (bestThrough) { std::vector<Instruction*> succs = getSuccs(inst); for (std::vector<Instruction*>::iterator it2 = succs.begin(), ie = succs.end(); it2 != ie; ++it2) { uint64_t dist = sm.getIndexedValue(stats::minDistToUncovered, infos.getInfo(*it2).id); if (dist) { uint64_t val = bestThrough + dist; if (best==0 || val<best) best = val; } } } if (best != cur) { sm.setIndexedValue(stats::minDistToUncovered, infos.getInfo(inst).id, best); changed = true; } } } while (changed); for (std::set<ExecutionState*>::iterator it = executor.states.begin(), ie = executor.states.end(); it != ie; ++it) { ExecutionState *es = *it; uint64_t currentFrameMinDist = 0; #if MULTITHREAD for (Thread::stack_ty::iterator sfIt = es->stack().begin(), sf_ie = es->stack().end(); sfIt != sf_ie; ++sfIt) { Thread::stack_ty::iterator next = sfIt + 1; KInstIterator kii; if (next==es->stack().end()) { kii = es->pc(); #else for (ExecutionState::stack_ty::iterator sfIt = es->stack.begin(), sf_ie = es->stack.end(); sfIt != sf_ie; ++sfIt) { ExecutionState::stack_ty::iterator next = sfIt + 1; KInstIterator kii; if (next==es->stack.end()) { kii = es->pc; #endif } else { kii = next->caller; ++kii; } sfIt->minDistToUncoveredOnReturn = currentFrameMinDist; currentFrameMinDist = computeMinDistToUncovered(kii, currentFrameMinDist); } } }
/// DebugACrash - Given a predicate that determines whether a component crashes /// on a program, try to destructively reduce the program while still keeping /// the predicate true. static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { // See if we can get away with nuking some of the global variable initializers // in the program... if (BD.getProgram()->global_begin() != BD.getProgram()->global_end()) { // Now try to reduce the number of global variable initializers in the // module to something small. Module *M = CloneModule(BD.getProgram()); bool DeletedInit = false; for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasInitializer()) { I->setInitializer(0); I->setLinkage(GlobalValue::ExternalLinkage); DeletedInit = true; } if (!DeletedInit) { delete M; // No change made... } else { // See if the program still causes a crash... std::cout << "\nChecking to see if we can delete global inits: "; if (TestFn(BD, M)) { // Still crashes? BD.setNewProgram(M); std::cout << "\n*** Able to remove all global initializers!\n"; } else { // No longer crashes? std::cout << " - Removing all global inits hides problem!\n"; delete M; std::vector<GlobalVariable*> GVs; for (Module::global_iterator I = BD.getProgram()->global_begin(), E = BD.getProgram()->global_end(); I != E; ++I) if (I->hasInitializer()) GVs.push_back(I); if (GVs.size() > 1 && !BugpointIsInterrupted) { std::cout << "\n*** Attempting to reduce the number of global " << "variables in the testcase\n"; unsigned OldSize = GVs.size(); ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs); if (GVs.size() < OldSize) BD.EmitProgressBytecode("reduced-global-variables"); } } } } // Now try to reduce the number of functions in the module to something small. std::vector<Function*> Functions; for (Module::iterator I = BD.getProgram()->begin(), E = BD.getProgram()->end(); I != E; ++I) if (!I->isDeclaration()) Functions.push_back(I); if (Functions.size() > 1 && !BugpointIsInterrupted) { std::cout << "\n*** Attempting to reduce the number of functions " "in the testcase\n"; unsigned OldSize = Functions.size(); ReduceCrashingFunctions(BD, TestFn).reduceList(Functions); if (Functions.size() < OldSize) BD.EmitProgressBytecode("reduced-function"); } // Attempt to delete entire basic blocks at a time to speed up // convergence... this actually works by setting the terminator of the blocks // to a return instruction then running simplifycfg, which can potentially // shrinks the code dramatically quickly // if (!DisableSimplifyCFG && !BugpointIsInterrupted) { std::vector<const BasicBlock*> Blocks; for (Module::const_iterator I = BD.getProgram()->begin(), E = BD.getProgram()->end(); I != E; ++I) for (Function::const_iterator FI = I->begin(), E = I->end(); FI !=E; ++FI) Blocks.push_back(FI); ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks); } // FIXME: This should use the list reducer to converge faster by deleting // larger chunks of instructions at a time! unsigned Simplification = 2; do { if (BugpointIsInterrupted) break; --Simplification; std::cout << "\n*** Attempting to reduce testcase by deleting instruc" << "tions: Simplification Level #" << Simplification << '\n'; // Now that we have deleted the functions that are unnecessary for the // program, try to remove instructions that are not necessary to cause the // crash. To do this, we loop through all of the instructions in the // remaining functions, deleting them (replacing any values produced with // nulls), and then running ADCE and SimplifyCFG. If the transformed input // still triggers failure, keep deleting until we cannot trigger failure // anymore. // unsigned InstructionsToSkipBeforeDeleting = 0; TryAgain: // Loop over all of the (non-terminator) instructions remaining in the // function, attempting to delete them. unsigned CurInstructionNum = 0; for (Module::const_iterator FI = BD.getProgram()->begin(), E = BD.getProgram()->end(); FI != E; ++FI) if (!FI->isDeclaration()) for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E; ++BI) for (BasicBlock::const_iterator I = BI->begin(), E = --BI->end(); I != E; ++I, ++CurInstructionNum) if (InstructionsToSkipBeforeDeleting) { --InstructionsToSkipBeforeDeleting; } else { if (BugpointIsInterrupted) goto ExitLoops; std::cout << "Checking instruction '" << I->getName() << "': "; Module *M = BD.deleteInstructionFromProgram(I, Simplification); // Find out if the pass still crashes on this pass... if (TestFn(BD, M)) { // Yup, it does, we delete the old module, and continue trying // to reduce the testcase... BD.setNewProgram(M); InstructionsToSkipBeforeDeleting = CurInstructionNum; goto TryAgain; // I wish I had a multi-level break here! } // This pass didn't crash without this instruction, try the next // one. delete M; } if (InstructionsToSkipBeforeDeleting) { InstructionsToSkipBeforeDeleting = 0; goto TryAgain; } } while (Simplification); ExitLoops: // Try to clean up the testcase by running funcresolve and globaldce... if (!BugpointIsInterrupted) { std::cout << "\n*** Attempting to perform final cleanups: "; Module *M = CloneModule(BD.getProgram()); M = BD.performFinalCleanups(M, true); // Find out if the pass still crashes on the cleaned up program... if (TestFn(BD, M)) { BD.setNewProgram(M); // Yup, it does, keep the reduced version... } else { delete M; } } BD.EmitProgressBytecode("reduced-simplified"); return false; }
bool AMDGPURewriteOutArguments::doInitialization(Module &M) { DL = &M.getDataLayout(); return false; }
bool GenericToNVVM::runOnModule(Module &M) { // Create a clone of each global variable that has the default address space. // The clone is created with the global address space specifier, and the pair // of original global variable and its clone is placed in the GVMap for later // use. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E;) { GlobalVariable *GV = &*I++; if (GV->getType()->getAddressSpace() == llvm::ADDRESS_SPACE_GENERIC && !llvm::isTexture(*GV) && !llvm::isSurface(*GV) && !llvm::isSampler(*GV) && !GV->getName().startswith("llvm.")) { GlobalVariable *NewGV = new GlobalVariable( M, GV->getType()->getElementType(), GV->isConstant(), GV->getLinkage(), GV->hasInitializer() ? GV->getInitializer() : nullptr, "", GV, GV->getThreadLocalMode(), llvm::ADDRESS_SPACE_GLOBAL); NewGV->copyAttributesFrom(GV); GVMap[GV] = NewGV; } } // Return immediately, if every global variable has a specific address space // specifier. if (GVMap.empty()) { return false; } // Walk through the instructions in function defitinions, and replace any use // of original global variables in GVMap with a use of the corresponding // copies in GVMap. If necessary, promote constants to instructions. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { if (I->isDeclaration()) { continue; } IRBuilder<> Builder(I->getEntryBlock().getFirstNonPHIOrDbg()); for (Function::iterator BBI = I->begin(), BBE = I->end(); BBI != BBE; ++BBI) { for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; ++II) { for (unsigned i = 0, e = II->getNumOperands(); i < e; ++i) { Value *Operand = II->getOperand(i); if (isa<Constant>(Operand)) { II->setOperand( i, remapConstant(&M, &*I, cast<Constant>(Operand), Builder)); } } } } ConstantToValueMap.clear(); } // Copy GVMap over to a standard value map. ValueToValueMapTy VM; for (auto I = GVMap.begin(), E = GVMap.end(); I != E; ++I) VM[I->first] = I->second; // Walk through the metadata section and update the debug information // associated with the global variables in the default address space. for (NamedMDNode &I : M.named_metadata()) { remapNamedMDNode(VM, &I); } // Walk through the global variable initializers, and replace any use of // original global variables in GVMap with a use of the corresponding copies // in GVMap. The copies need to be bitcast to the original global variable // types, as we cannot use cvta in global variable initializers. for (GVMapTy::iterator I = GVMap.begin(), E = GVMap.end(); I != E;) { GlobalVariable *GV = I->first; GlobalVariable *NewGV = I->second; // Remove GV from the map so that it can be RAUWed. Note that // DenseMap::erase() won't invalidate any iterators but this one. auto Next = std::next(I); GVMap.erase(I); I = Next; Constant *BitCastNewGV = ConstantExpr::getPointerCast(NewGV, GV->getType()); // At this point, the remaining uses of GV should be found only in global // variable initializers, as other uses have been already been removed // while walking through the instructions in function definitions. GV->replaceAllUsesWith(BitCastNewGV); std::string Name = GV->getName(); GV->eraseFromParent(); NewGV->setName(Name); } assert(GVMap.empty() && "Expected it to be empty by now"); return true; }
Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident) { Module *m; char *filename; //printf("Module::load(ident = '%s')\n", ident->toChars()); // Build module filename by turning: // foo.bar.baz // into: // foo\bar\baz filename = ident->toChars(); if (packages && packages->dim) { OutBuffer buf; for (size_t i = 0; i < packages->dim; i++) { Identifier *pid = packages->tdata()[i]; buf.writestring(pid->toChars()); #if _WIN32 buf.writeByte('\\'); #else buf.writeByte('/'); #endif } buf.writestring(filename); buf.writeByte(0); filename = (char *)buf.extractData(); } m = new Module(filename, ident, 0, 0); m->loc = loc; /* Search along global.path for .di file, then .d file. */ char *result = NULL; FileName *fdi = FileName::forceExt(filename, global.hdr_ext); FileName *fd = FileName::forceExt(filename, global.mars_ext); char *sdi = fdi->toChars(); char *sd = fd->toChars(); if (FileName::exists(sdi)) result = sdi; else if (FileName::exists(sd)) result = sd; else if (FileName::absolute(filename)) ; else if (!global.path) ; else { for (size_t i = 0; i < global.path->dim; i++) { char *p = (*global.path)[i]; char *n = FileName::combine(p, sdi); if (FileName::exists(n)) { result = n; break; } mem.free(n); n = FileName::combine(p, sd); if (FileName::exists(n)) { result = n; break; } mem.free(n); } } if (result) m->srcfile = new File(result); if (global.params.verbose) { printf("import "); if (packages) { for (size_t i = 0; i < packages->dim; i++) { Identifier *pid = packages->tdata()[i]; printf("%s.", pid->toChars()); } } printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars()); } m->read(loc); m->parse(); #ifdef IN_GCC d_gcc_magic_module(m); #endif return m; }
// doInitialization - For the lower long/setjmp pass, this ensures that a // module contains a declaration for the intrisic functions we are going // to call to convert longjmp and setjmp calls. // // This function is always successful, unless it isn't. bool LowerSetJmp::doInitialization(Module& M) { const Type *SBPTy = Type::getInt8PtrTy(M.getContext()); const Type *SBPPTy = PointerType::getUnqual(SBPTy); // N.B. See llvm/runtime/GCCLibraries/libexception/SJLJ-Exception.h for // a description of the following library functions. // void __llvm_sjljeh_init_setjmpmap(void**) InitSJMap = M.getOrInsertFunction("__llvm_sjljeh_init_setjmpmap", Type::getVoidTy(M.getContext()), SBPPTy, (Type *)0); // void __llvm_sjljeh_destroy_setjmpmap(void**) DestroySJMap = M.getOrInsertFunction("__llvm_sjljeh_destroy_setjmpmap", Type::getVoidTy(M.getContext()), SBPPTy, (Type *)0); // void __llvm_sjljeh_add_setjmp_to_map(void**, void*, unsigned) AddSJToMap = M.getOrInsertFunction("__llvm_sjljeh_add_setjmp_to_map", Type::getVoidTy(M.getContext()), SBPPTy, SBPTy, Type::getInt32Ty(M.getContext()), (Type *)0); // void __llvm_sjljeh_throw_longjmp(int*, int) ThrowLongJmp = M.getOrInsertFunction("__llvm_sjljeh_throw_longjmp", Type::getVoidTy(M.getContext()), SBPTy, Type::getInt32Ty(M.getContext()), (Type *)0); // unsigned __llvm_sjljeh_try_catching_longjmp_exception(void **) TryCatchLJ = M.getOrInsertFunction("__llvm_sjljeh_try_catching_longjmp_exception", Type::getInt32Ty(M.getContext()), SBPPTy, (Type *)0); // bool __llvm_sjljeh_is_longjmp_exception() IsLJException = M.getOrInsertFunction("__llvm_sjljeh_is_longjmp_exception", Type::getInt1Ty(M.getContext()), (Type *)0); // int __llvm_sjljeh_get_longjmp_value() GetLJValue = M.getOrInsertFunction("__llvm_sjljeh_get_longjmp_value", Type::getInt32Ty(M.getContext()), (Type *)0); return true; }
void Module::parse() #endif { char *srcname; unsigned char *buf; unsigned buflen; unsigned le; unsigned bom; //printf("Module::parse()\n"); srcname = srcfile->name->toChars(); //printf("Module::parse(srcname = '%s')\n", srcname); buf = srcfile->buffer; buflen = srcfile->len; if (buflen >= 2) { /* Convert all non-UTF-8 formats to UTF-8. * BOM : http://www.unicode.org/faq/utf_bom.html * 00 00 FE FF UTF-32BE, big-endian * FF FE 00 00 UTF-32LE, little-endian * FE FF UTF-16BE, big-endian * FF FE UTF-16LE, little-endian * EF BB BF UTF-8 */ bom = 1; // assume there's a BOM if (buf[0] == 0xFF && buf[1] == 0xFE) { if (buflen >= 4 && buf[2] == 0 && buf[3] == 0) { // UTF-32LE le = 1; Lutf32: OutBuffer dbuf; unsigned *pu = (unsigned *)(buf); unsigned *pumax = &pu[buflen / 4]; if (buflen & 3) { error("odd length of UTF-32 char source %u", buflen); fatal(); } dbuf.reserve(buflen / 4); for (pu += bom; pu < pumax; pu++) { unsigned u; u = le ? readlongLE(pu) : readlongBE(pu); if (u & ~0x7F) { if (u > 0x10FFFF) { error("UTF-32 value %08x greater than 0x10FFFF", u); fatal(); } dbuf.writeUTF8(u); } else dbuf.writeByte(u); } dbuf.writeByte(0); // add 0 as sentinel for scanner buflen = dbuf.offset - 1; // don't include sentinel in count buf = (unsigned char *) dbuf.extractData(); } else { // UTF-16LE (X86) // Convert it to UTF-8 le = 1; Lutf16: OutBuffer dbuf; unsigned short *pu = (unsigned short *)(buf); unsigned short *pumax = &pu[buflen / 2]; if (buflen & 1) { error("odd length of UTF-16 char source %u", buflen); fatal(); } dbuf.reserve(buflen / 2); for (pu += bom; pu < pumax; pu++) { unsigned u; u = le ? readwordLE(pu) : readwordBE(pu); if (u & ~0x7F) { if (u >= 0xD800 && u <= 0xDBFF) { unsigned u2; if (++pu > pumax) { error("surrogate UTF-16 high value %04x at EOF", u); fatal(); } u2 = le ? readwordLE(pu) : readwordBE(pu); if (u2 < 0xDC00 || u2 > 0xDFFF) { error("surrogate UTF-16 low value %04x out of range", u2); fatal(); } u = (u - 0xD7C0) << 10; u |= (u2 - 0xDC00); } else if (u >= 0xDC00 && u <= 0xDFFF) { error("unpaired surrogate UTF-16 value %04x", u); fatal(); } else if (u == 0xFFFE || u == 0xFFFF) { error("illegal UTF-16 value %04x", u); fatal(); } dbuf.writeUTF8(u); } else dbuf.writeByte(u); } dbuf.writeByte(0); // add 0 as sentinel for scanner buflen = dbuf.offset - 1; // don't include sentinel in count buf = (unsigned char *) dbuf.extractData(); } } else if (buf[0] == 0xFE && buf[1] == 0xFF) { // UTF-16BE le = 0; goto Lutf16; } else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF) { // UTF-32BE le = 0; goto Lutf32; } else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) { // UTF-8 buf += 3; buflen -= 3; } else { /* There is no BOM. Make use of Arcane Jill's insight that * the first char of D source must be ASCII to * figure out the encoding. */ bom = 0; if (buflen >= 4) { if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0) { // UTF-32LE le = 1; goto Lutf32; } else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) { // UTF-32BE le = 0; goto Lutf32; } } if (buflen >= 2) { if (buf[1] == 0) { // UTF-16LE le = 1; goto Lutf16; } else if (buf[0] == 0) { // UTF-16BE le = 0; goto Lutf16; } } // It's UTF-8 if (buf[0] >= 0x80) { error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]); fatal(); } } } #ifdef IN_GCC // dump utf-8 encoded source if (dump_source) { // %% srcname could contain a path ... d_gcc_dump_source(srcname, "utf-8", buf, buflen); } #endif /* If it starts with the string "Ddoc", then it's a documentation * source file. */ if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0) { comment = buf + 4; isDocFile = 1; if (!docfile) setDocfile(); return; } if (isHtml) { OutBuffer *dbuf = new OutBuffer(); Html h(srcname, buf, buflen); h.extractCode(dbuf); buf = dbuf->data; buflen = dbuf->offset; #ifdef IN_GCC // dump extracted source if (dump_source) d_gcc_dump_source(srcname, "d.utf-8", buf, buflen); #endif } Parser p(this, buf, buflen, docfile != NULL); p.nextToken(); members = p.parseModule(); ::free(srcfile->buffer); srcfile->buffer = NULL; srcfile->len = 0; md = p.md; numlines = p.loc.linnum; DsymbolTable *dst; if (md) { this->ident = md->id; this->safe = md->safe; dst = Package::resolve(md->packages, &this->parent, NULL); } else { dst = modules; /* Check to see if module name is a valid identifier */ if (!Lexer::isValidIdentifier(this->ident->toChars())) error("has non-identifier characters in filename, use module declaration instead"); } // Update global list of modules if (!dst->insert(this)) { Dsymbol *prev = dst->lookup(ident); assert(prev); Module *mprev = prev->isModule(); if (mprev) error(loc, "from file %s conflicts with another module %s from file %s", srcname, mprev->toChars(), mprev->srcfile->toChars()); else { Package *pkg = prev->isPackage(); assert(pkg); error(loc, "from file %s conflicts with package name %s", srcname, pkg->toChars()); } } else { amodules.push(this); } }
void compile_module_to_text(const Module &module, std::string filename) { if (filename.empty()) filename = module.name() + ".stmt"; std::ofstream file(filename.c_str()); file << module; }
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 (); } }
/* ** Close an existing SQLite database */ int sqlite3_close(sqlite3 *db){ HashElem *i; int j; if( !db ){ return SQLITE_OK; } if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } #ifdef SQLITE_SSE { extern void sqlite3SseCleanup(sqlite3*); sqlite3SseCleanup(db); } #endif sqlite3ResetInternalSchema(db, 0); /* If a transaction is open, the ResetInternalSchema() call above ** will not have called the xDisconnect() method on any virtual ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() ** call will do so. We need to do this before the check for active ** SQL statements below, as the v-table implementation may be storing ** some prepared statements internally. */ sqlite3VtabRollback(db); /* If there are any outstanding VMs, return SQLITE_BUSY. */ if( db->pVdbe ){ sqlite3Error(db, SQLITE_BUSY, "Unable to close due to unfinalised statements"); return SQLITE_BUSY; } assert( !sqlite3SafetyCheck(db) ); /* FIX ME: db->magic may be set to SQLITE_MAGIC_CLOSED if the database ** cannot be opened for some reason. So this routine needs to run in ** that case. But maybe there should be an extra magic value for the ** "failed to open" state. ** ** TODO: Coverage tests do not test the case where this condition is ** true. It's hard to see how to cause it without messing with threads. */ if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){ /* printf("DID NOT CLOSE\n"); fflush(stdout); */ return SQLITE_ERROR; } for(j=0; j<db->nDb; j++){ struct Db *pDb = &db->aDb[j]; if( pDb->pBt ){ sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; if( j!=1 ){ pDb->pSchema = 0; } } } sqlite3ResetInternalSchema(db, 0); assert( db->nDb<=2 ); assert( db->aDb==db->aDbStatic ); for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ FuncDef *pFunc, *pNext; for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){ pNext = pFunc->pNext; sqliteFree(pFunc); } } for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ CollSeq *pColl = (CollSeq *)sqliteHashData(i); /* Invoke any destructors registered for collation sequence user data. */ for(j=0; j<3; j++){ if( pColl[j].xDel ){ pColl[j].xDel(pColl[j].pUser); } } sqliteFree(pColl); } sqlite3HashClear(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ Module *pMod = (Module *)sqliteHashData(i); if( pMod->xDestroy ){ pMod->xDestroy(pMod->pAux); } sqliteFree(pMod); } sqlite3HashClear(&db->aModule); #endif sqlite3HashClear(&db->aFunc); sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ if( db->pErr ){ sqlite3ValueFree(db->pErr); } sqlite3CloseExtensions(db); db->magic = SQLITE_MAGIC_ERROR; /* The temp-database schema is allocated differently from the other schema ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()). ** So it needs to be freed here. Todo: Why not roll the temp schema into ** the same sqliteMalloc() as the one that allocates the database ** structure? */ sqliteFree(db->aDb[1].pSchema); sqliteFree(db); sqlite3ReleaseThreadData(); return SQLITE_OK; }
void InitializeSoftBound:: constructShadowStackHandlers(Module & module){ Type* VoidTy = Type::getVoidTy(module.getContext()); Type* VoidPtrTy = PointerType::getUnqual(Type::getInt8Ty(module.getContext())); Type* SizeTy = Type::getInt64Ty(module.getContext()); Type* Int32Ty = Type::getInt32Ty(module.getContext()); module.getOrInsertFunction("__softboundcets_allocate_shadow_stack_space", VoidTy, Int32Ty, NULL); module.getOrInsertFunction("__softboundcets_deallocate_shadow_stack_space", VoidTy, NULL); module.getOrInsertFunction("__softboundcets_load_base_shadow_stack", VoidPtrTy, Int32Ty, NULL); module.getOrInsertFunction("__softboundcets_load_bound_shadow_stack", VoidPtrTy, Int32Ty, NULL); module.getOrInsertFunction("__softboundcets_load_key_shadow_stack", SizeTy, Int32Ty, NULL); module.getOrInsertFunction("__softboundcets_load_lock_shadow_stack", VoidPtrTy, Int32Ty, NULL); module.getOrInsertFunction("__softboundcets_store_base_shadow_stack", VoidTy, VoidPtrTy, Int32Ty, NULL); module.getOrInsertFunction("__softboundcets_store_bound_shadow_stack", VoidTy, VoidPtrTy, Int32Ty, NULL); module.getOrInsertFunction("__softboundcets_store_key_shadow_stack", VoidTy, SizeTy, Int32Ty, NULL); module.getOrInsertFunction("__softboundcets_store_lock_shadow_stack", VoidTy, VoidPtrTy, Int32Ty, NULL); }
/// \brief Assign DWARF discriminators. /// /// To assign discriminators, we examine the boundaries of every /// basic block and its successors. Suppose there is a basic block B1 /// with successor B2. The last instruction I1 in B1 and the first /// instruction I2 in B2 are located at the same file and line number. /// This situation is illustrated in the following code snippet: /// /// if (i < 10) x = i; /// /// entry: /// br i1 %cmp, label %if.then, label %if.end, !dbg !10 /// if.then: /// %1 = load i32* %i.addr, align 4, !dbg !10 /// store i32 %1, i32* %x, align 4, !dbg !10 /// br label %if.end, !dbg !10 /// if.end: /// ret void, !dbg !12 /// /// Notice how the branch instruction in block 'entry' and all the /// instructions in block 'if.then' have the exact same debug location /// information (!dbg !10). /// /// To distinguish instructions in block 'entry' from instructions in /// block 'if.then', we generate a new lexical block for all the /// instruction in block 'if.then' that share the same file and line /// location with the last instruction of block 'entry'. /// /// This new lexical block will have the same location information as /// the previous one, but with a new DWARF discriminator value. /// /// One of the main uses of this discriminator value is in runtime /// sample profilers. It allows the profiler to distinguish instructions /// at location !dbg !10 that execute on different basic blocks. This is /// important because while the predicate 'if (x < 10)' may have been /// executed millions of times, the assignment 'x = i' may have only /// executed a handful of times (meaning that the entry->if.then edge is /// seldom taken). /// /// If we did not have discriminator information, the profiler would /// assign the same weight to both blocks 'entry' and 'if.then', which /// in turn will make it conclude that the entry->if.then edge is very /// hot. /// /// To decide where to create new discriminator values, this function /// traverses the CFG and examines instruction at basic block boundaries. /// If the last instruction I1 of a block B1 is at the same file and line /// location as instruction I2 of successor B2, then it creates a new /// lexical block for I2 and all the instruction in B2 that share the same /// file and line location as I2. This new lexical block will have a /// different discriminator number than I1. bool AddDiscriminators::runOnFunction(Function &F) { // If the function has debug information, but the user has disabled // discriminators, do nothing. // Simlarly, if the function has no debug info, do nothing. // Finally, if this module is built with dwarf versions earlier than 4, // do nothing (discriminator support is a DWARF 4 feature). if (NoDiscriminators || !hasDebugInfo(F) || F.getParent()->getDwarfVersion() < 4) return false; bool Changed = false; Module *M = F.getParent(); LLVMContext &Ctx = M->getContext(); DIBuilder Builder(*M, /*AllowUnresolved*/ false); // Traverse all the blocks looking for instructions in different // blocks that are at the same file:line location. for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { BasicBlock *B = I; TerminatorInst *Last = B->getTerminator(); DILocation LastDIL = Last->getDebugLoc().get(); if (!LastDIL) continue; for (unsigned I = 0; I < Last->getNumSuccessors(); ++I) { BasicBlock *Succ = Last->getSuccessor(I); Instruction *First = Succ->getFirstNonPHIOrDbgOrLifetime(); DILocation FirstDIL = First->getDebugLoc().get(); if (!FirstDIL) continue; // If the first instruction (First) of Succ is at the same file // location as B's last instruction (Last), add a new // discriminator for First's location and all the instructions // in Succ that share the same location with First. if (!FirstDIL->canDiscriminate(*LastDIL)) { // Create a new lexical scope and compute a new discriminator // number for it. StringRef Filename = FirstDIL->getFilename(); auto *Scope = FirstDIL->getScope(); auto *File = Builder.createFile(Filename, Scope->getDirectory()); // FIXME: Calculate the discriminator here, based on local information, // and delete MDLocation::computeNewDiscriminator(). The current // solution gives different results depending on other modules in the // same context. All we really need is to discriminate between // FirstDIL and LastDIL -- a local map would suffice. unsigned Discriminator = FirstDIL->computeNewDiscriminator(); auto *NewScope = Builder.createLexicalBlockFile(Scope, File, Discriminator); auto *NewDIL = MDLocation::get(Ctx, FirstDIL->getLine(), FirstDIL->getColumn(), NewScope, FirstDIL->getInlinedAt()); DebugLoc newDebugLoc = NewDIL; // Attach this new debug location to First and every // instruction following First that shares the same location. for (BasicBlock::iterator I1(*First), E1 = Succ->end(); I1 != E1; ++I1) { if (I1->getDebugLoc().get() != FirstDIL) break; I1->setDebugLoc(newDebugLoc); DEBUG(dbgs() << NewDIL->getFilename() << ":" << NewDIL->getLine() << ":" << NewDIL->getColumn() << ":" << NewDIL->getDiscriminator() << *I1 << "\n"); } DEBUG(dbgs() << "\n"); Changed = true; } } } return Changed; }
// Ensure ELF .symver aliases get the same binding as the defined symbol // they alias with. static void handleSymverAliases(const Module &M, RecordStreamer &Streamer) { if (Streamer.symverAliases().empty()) return; // The name in the assembler will be mangled, but the name in the IR // might not, so we first compute a mapping from mangled name to GV. Mangler Mang; SmallString<64> MangledName; StringMap<const GlobalValue *> MangledNameMap; auto GetMangledName = [&](const GlobalValue &GV) { if (!GV.hasName()) return; MangledName.clear(); MangledName.reserve(GV.getName().size() + 1); Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false); MangledNameMap[MangledName] = &GV; }; for (const Function &F : M) GetMangledName(F); for (const GlobalVariable &GV : M.globals()) GetMangledName(GV); for (const GlobalAlias &GA : M.aliases()) GetMangledName(GA); // Walk all the recorded .symver aliases, and set up the binding // for each alias. for (auto &Symver : Streamer.symverAliases()) { const MCSymbol *Aliasee = Symver.first; MCSymbolAttr Attr = MCSA_Invalid; // First check if the aliasee binding was recorded in the asm. RecordStreamer::State state = Streamer.getSymbolState(Aliasee); switch (state) { case RecordStreamer::Global: case RecordStreamer::DefinedGlobal: Attr = MCSA_Global; break; case RecordStreamer::UndefinedWeak: case RecordStreamer::DefinedWeak: Attr = MCSA_Weak; break; default: break; } // If we don't have a symbol attribute from assembly, then check if // the aliasee was defined in the IR. if (Attr == MCSA_Invalid) { const auto *GV = M.getNamedValue(Aliasee->getName()); if (!GV) { auto MI = MangledNameMap.find(Aliasee->getName()); if (MI != MangledNameMap.end()) GV = MI->second; else continue; } if (GV->hasExternalLinkage()) Attr = MCSA_Global; else if (GV->hasLocalLinkage()) Attr = MCSA_Local; else if (GV->isWeakForLinker()) Attr = MCSA_Weak; } if (Attr == MCSA_Invalid) continue; // Set the detected binding on each alias with this aliasee. for (auto &Alias : Symver.second) Streamer.EmitSymbolAttribute(Alias, Attr); } }