// 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, ""); }
void StrPrinter::bvisit(const Constant &x) { str_ = x.get_name(); }
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->getABITypeSize(C->getType()); unsigned Align = TD->getPreferredAlignment(I); 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->getABITypeSize(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); } } return AsmPrinter::doFinalization(M); }
/// 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.begin(), args.end(), "", 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 = ConstantArray::get(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[0], 2); 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 const 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.begin(), ResolverArgs.end(), "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(), "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.begin(), Args.end(), "", DoCallBB); ReturnInst::Create(F->getContext(), DoCallBB); } else { CallInst *Call = CallInst::Create(FuncPtr, Args.begin(), Args.end(), "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(); } }
inline Value::Value(const Type& aType, const Constant& val, const char* name) : fpImpl( SFun_Value_ctor_T_C_d_c(aType.getImpl(), val.getImpl(), name) ) { verify(fpImpl); }
Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags, ValueMapTypeRemapper *TypeMapper, ValueMaterializer *Materializer) { 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; // If we have a materializer and it can materialize a value, use that. if (Materializer) { if (Value *NewV = Materializer->materializeValueFor(const_cast<Value*>(V))) return VM[V] = NewV; } // Global values do not need to be seeded into the VM if they // are using the identity mapping. if (isa<GlobalValue>(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 auto *MDV = dyn_cast<MetadataAsValue>(V)) { const Metadata *MD = MDV->getMetadata(); // If this is a module-level metadata and we know that nothing at the module // level is changing, then use an identity mapping. if (!isa<LocalAsMetadata>(MD) && (Flags & RF_NoModuleLevelChanges)) return VM[V] = const_cast<Value *>(V); auto *MappedMD = MapMetadata(MD, VM, Flags, TypeMapper, Materializer); if (MD == MappedMD || (!MappedMD && (Flags & RF_IgnoreMissingEntries))) return VM[V] = const_cast<Value *>(V); // FIXME: This assert crashes during bootstrap, but I think it should be // correct. For now, just match behaviour from before the metadata/value // split. // // assert(MappedMD && "Referenced metadata value not in value map"); return VM[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)) { Function *F = cast<Function>(MapValue(BA->getFunction(), VM, Flags, TypeMapper, Materializer)); BasicBlock *BB = cast_or_null<BasicBlock>(MapValue(BA->getBasicBlock(), VM, Flags, TypeMapper, Materializer)); 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 = nullptr; for (; OpNo != NumOperands; ++OpNo) { Value *Op = C->getOperand(OpNo); Mapped = MapValue(Op, VM, Flags, TypeMapper, Materializer); 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, Materializer)); } 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)); }
static bool match_index_and_scale(Instruction* instr, Instruction** index, int* log2_scale, Instruction** instr_to_unpin) { *instr_to_unpin = NULL; // Skip conversion ops Convert* convert = instr->as_Convert(); if (convert != NULL) { instr = convert->value(); } ShiftOp* shift = instr->as_ShiftOp(); if (shift != NULL) { if (shift->is_pinned()) { *instr_to_unpin = shift; } // Constant shift value? Constant* con = shift->y()->as_Constant(); if (con == NULL) return false; // Well-known type and value? IntConstant* val = con->type()->as_IntConstant(); if (val == NULL) return false; if (shift->x()->type() != intType) return false; *index = shift->x(); int tmp_scale = val->value(); if (tmp_scale >= 0 && tmp_scale < 4) { *log2_scale = tmp_scale; return true; } else { return false; } } ArithmeticOp* arith = instr->as_ArithmeticOp(); if (arith != NULL) { if (arith->is_pinned()) { *instr_to_unpin = arith; } // Check for integer multiply if (arith->op() == Bytecodes::_imul) { // See if either arg is a known constant Constant* con = arith->x()->as_Constant(); if (con != NULL) { *index = arith->y(); } else { con = arith->y()->as_Constant(); if (con == NULL) return false; *index = arith->x(); } if ((*index)->type() != intType) return false; // Well-known type and value? IntConstant* val = con->type()->as_IntConstant(); if (val == NULL) return false; switch (val->value()) { case 1: *log2_scale = 0; return true; case 2: *log2_scale = 1; return true; case 4: *log2_scale = 2; return true; case 8: *log2_scale = 3; return true; default: return false; } } } // Unknown instruction sequence; don't touch it return false; }
Function* TranslationContext::createFunction(Executable& executable, uint64_t baseAddress) { Function* fn = functionMap->createFunction(baseAddress); assert(fn != nullptr); auto targetInfo = TargetInfo::getTargetInfo(*module); AddressToBlock blockMap(*fn); BasicBlock* entry = &fn->back(); TranslationCloningDirector director(*module, *functionMap, blockMap); Argument* registers = fn->arg_begin(); auto flags = new AllocaInst(irgen->getFlagsTy(), "flags", entry); ArrayRef<Value*> ipGepIndices = irgen->getIpOffset(); auto ipPointer = GetElementPtrInst::CreateInBounds(registers, ipGepIndices, "", entry); Type* ipType = GetElementPtrInst::getIndexedType(irgen->getRegisterTy(), ipGepIndices); Function* prologue = irgen->implementationForPrologue(); inlineFunction(fn, prologue, { configVariable, registers }, director, baseAddress); uint64_t addressToDisassemble; auto end = executable.end(); auto inst = cs->alloc(); SmallVector<Value*, 4> inliningParameters = { configVariable, nullptr, registers, flags }; while (blockMap.getOneStub(addressToDisassemble)) { if (auto begin = executable.map(addressToDisassemble)) if (cs->disassemble(inst.get(), begin, end, addressToDisassemble)) if (BasicBlock* thisBlock = blockMap.implementInstruction(inst->address)) // already implemented? { // store instruction pointer // (this needs to be the IP of the next instruction) auto nextInstAddress = inst->address + inst->size; auto ipValue = ConstantInt::get(ipType, nextInstAddress); new StoreInst(ipValue, ipPointer, false, thisBlock); if (Function* implementation = irgen->implementationFor(inst->id)) { // We have an implementation: inline it Constant* detailAsConstant = irgen->constantForDetail(*inst->detail); inliningParameters[1] = new GlobalVariable(*module, detailAsConstant->getType(), true, GlobalValue::PrivateLinkage, detailAsConstant); inlineFunction(fn, implementation, inliningParameters, director, nextInstAddress); } else { createAsmCall(*targetInfo, *inst, registers, *thisBlock); BasicBlock* target = blockMap.blockToInstruction(nextInstAddress); BranchInst::Create(target, thisBlock); } continue; } break; } #if DEBUG && 0 // check that it still works if (verifyModule(*module, &errs())) { module->dump(); abort(); } #endif return fn; }
/// getKindForGlobal - This is a top-level target-independent classifier for /// a global variable. Given an global variable and information from TM, it /// classifies the global in a variety of ways that make various target /// implementations simpler. The target implementation is free to ignore this /// extra info of course. SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV, const TargetMachine &TM){ assert(!GV->isDeclaration() && !GV->hasAvailableExternallyLinkage() && "Can only be used for global definitions"); Reloc::Model ReloModel = TM.getRelocationModel(); // Early exit - functions should be always in text sections. const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); if (GVar == 0) return SectionKind::getText(); // Handle thread-local data first. if (GVar->isThreadLocal()) { if (isSuitableForBSS(GVar)) return SectionKind::getThreadBSS(); return SectionKind::getThreadData(); } // Variables with common linkage always get classified as common. if (GVar->hasCommonLinkage()) return SectionKind::getCommon(); // Variable can be easily put to BSS section. if (isSuitableForBSS(GVar)) { if (GVar->hasLocalLinkage()) return SectionKind::getBSSLocal(); else if (GVar->hasExternalLinkage()) return SectionKind::getBSSExtern(); return SectionKind::getBSS(); } Constant *C = GVar->getInitializer(); // If the global is marked constant, we can put it into a mergable section, // a mergable string section, or general .data if it contains relocations. if (GVar->isConstant()) { // If the initializer for the global contains something that requires a // relocation, then we may have to drop this into a wriable data section // even though it is marked const. switch (C->getRelocationInfo()) { default: assert(0 && "unknown relocation info kind"); case Constant::NoRelocation: // If initializer is a null-terminated string, put it in a "cstring" // section of the right width. if (const ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) { if (const IntegerType *ITy = dyn_cast<IntegerType>(ATy->getElementType())) { if ((ITy->getBitWidth() == 8 || ITy->getBitWidth() == 16 || ITy->getBitWidth() == 32) && IsNullTerminatedString(C)) { if (ITy->getBitWidth() == 8) return SectionKind::getMergeable1ByteCString(); if (ITy->getBitWidth() == 16) return SectionKind::getMergeable2ByteCString(); assert(ITy->getBitWidth() == 32 && "Unknown width"); return SectionKind::getMergeable4ByteCString(); } } } // Otherwise, just drop it into a mergable constant section. If we have // a section for this size, use it, otherwise use the arbitrary sized // mergable section. switch (TM.getTargetData()->getTypeAllocSize(C->getType())) { case 4: return SectionKind::getMergeableConst4(); case 8: return SectionKind::getMergeableConst8(); case 16: return SectionKind::getMergeableConst16(); default: return SectionKind::getMergeableConst(); } case Constant::LocalRelocation: // In static relocation model, the linker will resolve all addresses, so // the relocation entries will actually be constants by the time the app // starts up. However, we can't put this into a mergable section, because // the linker doesn't take relocations into consideration when it tries to // merge entries in the section. if (ReloModel == Reloc::Static) return SectionKind::getReadOnly(); // Otherwise, the dynamic linker needs to fix it up, put it in the // writable data.rel.local section. return SectionKind::getReadOnlyWithRelLocal(); case Constant::GlobalRelocations: // In static relocation model, the linker will resolve all addresses, so // the relocation entries will actually be constants by the time the app // starts up. However, we can't put this into a mergable section, because // the linker doesn't take relocations into consideration when it tries to // merge entries in the section. if (ReloModel == Reloc::Static) return SectionKind::getReadOnly(); // Otherwise, the dynamic linker needs to fix it up, put it in the // writable data.rel section. return SectionKind::getReadOnlyWithRel(); } } // Okay, this isn't a constant. If the initializer for the global is going // to require a runtime relocation by the dynamic linker, put it into a more // specific section to improve startup time of the app. This coalesces these // globals together onto fewer pages, improving the locality of the dynamic // linker. if (ReloModel == Reloc::Static) return SectionKind::getDataNoRel(); switch (C->getRelocationInfo()) { default: assert(0 && "unknown relocation info kind"); case Constant::NoRelocation: return SectionKind::getDataNoRel(); case Constant::LocalRelocation: return SectionKind::getDataRelLocal(); case Constant::GlobalRelocations: return SectionKind::getDataRel(); } }
// // Method: postOrderInline() // // Description: // This methods does a post order traversal of the call graph and performs // bottom-up inlining of the DSGraphs. // void BUDataStructures::postOrderInline (Module & M) { // Variables used for Tarjan SCC-finding algorithm. These are passed into // the recursive function used to find SCCs. std::vector<const Function*> Stack; std::map<const Function*, unsigned> ValMap; unsigned NextID = 1; // Do post order traversal on the global ctors. Use this information to update // the globals graph. const char *Name = "llvm.global_ctors"; GlobalVariable *GV = M.getNamedGlobal(Name); if (GV && !(GV->isDeclaration()) && !(GV->hasLocalLinkage())) { // Should be an array of '{ int, void ()* }' structs. The first value is // the init priority, which we ignore. ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); if (InitList) { for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))) { if (CS->getNumOperands() != 2) break; // Not array of 2-element structs. Constant *FP = CS->getOperand(1); if (FP->isNullValue()) break; // Found a null terminator, exit. if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP)) if (CE->isCast()) FP = CE->getOperand(0); Function *F = dyn_cast<Function>(FP); if (F && !F->isDeclaration() && !ValMap.count(F)) { calculateGraphs(F, Stack, NextID, ValMap); CloneAuxIntoGlobal(getDSGraph(*F)); } } GlobalsGraph->removeTriviallyDeadNodes(); GlobalsGraph->maskIncompleteMarkers(); // Mark external globals incomplete. GlobalsGraph->markIncompleteNodes(DSGraph::IgnoreGlobals); GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal); GlobalsGraph->computeIntPtrFlags(); // // Create equivalence classes for aliasing globals so that we only need to // record one global per DSNode. // formGlobalECs(); // propogte information calculated // from the globals graph to the other graphs. for (Module::iterator F = M.begin(); F != M.end(); ++F) { if (!(F->isDeclaration())){ DSGraph *Graph = getDSGraph(*F); cloneGlobalsInto(Graph, DSGraph::DontCloneCallNodes | DSGraph::DontCloneAuxCallNodes); Graph->buildCallGraph(callgraph, GlobalFunctionList, filterCallees); Graph->maskIncompleteMarkers(); Graph->markIncompleteNodes(DSGraph::MarkFormalArgs | DSGraph::IgnoreGlobals); Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal); Graph->computeIntPtrFlags(); } } } } // // Start the post order traversal with the main() function. If there is no // main() function, don't worry; we'll have a separate traversal for inlining // graphs for functions not reachable from main(). // Function *MainFunc = M.getFunction ("main"); if (MainFunc && !MainFunc->isDeclaration()) { calculateGraphs(MainFunc, Stack, NextID, ValMap); CloneAuxIntoGlobal(getDSGraph(*MainFunc)); } // // Calculate the graphs for any functions that are unreachable from main... // for (Function &F : M) if (!F.isDeclaration() && !ValMap.count(&F)) { if (MainFunc) DEBUG(errs() << debugname << ": Function unreachable from main: " << F.getName() << "\n"); calculateGraphs(&F, Stack, NextID, ValMap); // Calculate all graphs. CloneAuxIntoGlobal(getDSGraph(F)); // Mark this graph as processed. Do this by finding all functions // in the graph that map to it, and mark them visited. // Note that this really should be handled neatly by calculateGraphs // itself, not here. However this catches the worst offenders. DSGraph *G = getDSGraph(F); for(DSGraph::retnodes_iterator RI = G->retnodes_begin(), RE = G->retnodes_end(); RI != RE; ++RI) { if (getDSGraph(*RI->first) == G) { if (!ValMap.count(RI->first)) ValMap[RI->first] = ~0U; else assert(ValMap[RI->first] == ~0U); } } } return; }
/// getPredicateOnEdge - Determine whether the specified value comparison /// with a constant is known to be true or false on the specified CFG edge. /// Pred is a CmpInst predicate. LazyValueInfo::Tristate LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, BasicBlock *FromBB, BasicBlock *ToBB) { LVILatticeVal Result = getCache(PImpl).getValueOnEdge(V, FromBB, ToBB); // If we know the value is a constant, evaluate the conditional. Constant *Res = 0; if (Result.isConstant()) { Res = ConstantFoldCompareInstOperands(Pred, Result.getConstant(), C, TD, TLI); if (ConstantInt *ResCI = dyn_cast<ConstantInt>(Res)) return ResCI->isZero() ? False : True; return Unknown; } if (Result.isConstantRange()) { ConstantInt *CI = dyn_cast<ConstantInt>(C); if (!CI) return Unknown; ConstantRange CR = Result.getConstantRange(); if (Pred == ICmpInst::ICMP_EQ) { if (!CR.contains(CI->getValue())) return False; if (CR.isSingleElement() && CR.contains(CI->getValue())) return True; } else if (Pred == ICmpInst::ICMP_NE) { if (!CR.contains(CI->getValue())) return True; if (CR.isSingleElement() && CR.contains(CI->getValue())) return False; } // Handle more complex predicates. ConstantRange TrueValues = ICmpInst::makeConstantRange((ICmpInst::Predicate)Pred, CI->getValue()); if (TrueValues.contains(CR)) return True; if (TrueValues.inverse().contains(CR)) return False; return Unknown; } if (Result.isNotConstant()) { // If this is an equality comparison, we can try to fold it knowing that // "V != C1". if (Pred == ICmpInst::ICMP_EQ) { // !C1 == C -> false iff C1 == C. Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE, Result.getNotConstant(), C, TD, TLI); if (Res->isNullValue()) return False; } else if (Pred == ICmpInst::ICMP_NE) { // !C1 != C -> true iff C1 == C. Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE, Result.getNotConstant(), C, TD, TLI); if (Res->isNullValue()) return True; } return Unknown; } return Unknown; }
PreservedAnalyses GlobalDCEPass::run(Module &M, ModuleAnalysisManager &) { bool Changed = false; // Remove empty functions from the global ctors list. Changed |= optimizeGlobalCtorsList(M, isEmptyFunction); // Collect the set of members for each comdat. for (Function &F : M) if (Comdat *C = F.getComdat()) ComdatMembers.insert(std::make_pair(C, &F)); for (GlobalVariable &GV : M.globals()) if (Comdat *C = GV.getComdat()) ComdatMembers.insert(std::make_pair(C, &GV)); for (GlobalAlias &GA : M.aliases()) if (Comdat *C = GA.getComdat()) ComdatMembers.insert(std::make_pair(C, &GA)); // Loop over the module, adding globals which are obviously necessary. for (GlobalObject &GO : M.global_objects()) { Changed |= RemoveUnusedGlobalValue(GO); // Functions with external linkage are needed if they have a body. // Externally visible & appending globals are needed, if they have an // initializer. if (!GO.isDeclaration() && !GO.hasAvailableExternallyLinkage()) if (!GO.isDiscardableIfUnused()) GlobalIsNeeded(&GO); } for (GlobalAlias &GA : M.aliases()) { Changed |= RemoveUnusedGlobalValue(GA); // Externally visible aliases are needed. if (!GA.isDiscardableIfUnused()) GlobalIsNeeded(&GA); } for (GlobalIFunc &GIF : M.ifuncs()) { Changed |= RemoveUnusedGlobalValue(GIF); // Externally visible ifuncs are needed. if (!GIF.isDiscardableIfUnused()) GlobalIsNeeded(&GIF); } // Now that all globals which are needed are in the AliveGlobals set, we loop // through the program, deleting those which are not alive. // // The first pass is to drop initializers of global variables which are dead. std::vector<GlobalVariable *> DeadGlobalVars; // Keep track of dead globals for (GlobalVariable &GV : M.globals()) if (!AliveGlobals.count(&GV)) { DeadGlobalVars.push_back(&GV); // Keep track of dead globals if (GV.hasInitializer()) { Constant *Init = GV.getInitializer(); GV.setInitializer(nullptr); if (isSafeToDestroyConstant(Init)) Init->destroyConstant(); } } // The second pass drops the bodies of functions which are dead... std::vector<Function *> DeadFunctions; for (Function &F : M) if (!AliveGlobals.count(&F)) { DeadFunctions.push_back(&F); // Keep track of dead globals if (!F.isDeclaration()) F.deleteBody(); } // The third pass drops targets of aliases which are dead... std::vector<GlobalAlias*> DeadAliases; for (GlobalAlias &GA : M.aliases()) if (!AliveGlobals.count(&GA)) { DeadAliases.push_back(&GA); GA.setAliasee(nullptr); } // The third pass drops targets of ifuncs which are dead... std::vector<GlobalIFunc*> DeadIFuncs; for (GlobalIFunc &GIF : M.ifuncs()) if (!AliveGlobals.count(&GIF)) { DeadIFuncs.push_back(&GIF); GIF.setResolver(nullptr); } // Now that all interferences have been dropped, delete the actual objects // themselves. auto EraseUnusedGlobalValue = [&](GlobalValue *GV) { RemoveUnusedGlobalValue(*GV); GV->eraseFromParent(); Changed = true; }; NumFunctions += DeadFunctions.size(); for (Function *F : DeadFunctions) EraseUnusedGlobalValue(F); NumVariables += DeadGlobalVars.size(); for (GlobalVariable *GV : DeadGlobalVars) EraseUnusedGlobalValue(GV); NumAliases += DeadAliases.size(); for (GlobalAlias *GA : DeadAliases) EraseUnusedGlobalValue(GA); NumIFuncs += DeadIFuncs.size(); for (GlobalIFunc *GIF : DeadIFuncs) EraseUnusedGlobalValue(GIF); // Make sure that all memory is released AliveGlobals.clear(); SeenConstants.clear(); ComdatMembers.clear(); if (Changed) return PreservedAnalyses::none(); return PreservedAnalyses::all(); }
bool GlobalDCE::runOnModule(Module &M) { bool Changed = false; // Remove empty functions from the global ctors list. Changed |= optimizeGlobalCtorsList(M, isEmptyFunction); // Loop over the module, adding globals which are obviously necessary. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Functions with external linkage are needed if they have a body if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage()) { if (!I->isDiscardableIfUnused()) GlobalIsNeeded(I); } } for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Externally visible & appending globals are needed, if they have an // initializer. if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage()) { if (!I->isDiscardableIfUnused()) GlobalIsNeeded(I); } } for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Externally visible aliases are needed. if (!I->isDiscardableIfUnused()) { GlobalIsNeeded(I); } } // Now that all globals which are needed are in the AliveGlobals set, we loop // through the program, deleting those which are not alive. // // The first pass is to drop initializers of global variables which are dead. std::vector<GlobalVariable*> DeadGlobalVars; // Keep track of dead globals for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadGlobalVars.push_back(I); // Keep track of dead globals if (I->hasInitializer()) { Constant *Init = I->getInitializer(); I->setInitializer(nullptr); if (isSafeToDestroyConstant(Init)) Init->destroyConstant(); } } // The second pass drops the bodies of functions which are dead... std::vector<Function*> DeadFunctions; for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadFunctions.push_back(I); // Keep track of dead globals if (!I->isDeclaration()) I->deleteBody(); } // The third pass drops targets of aliases which are dead... std::vector<GlobalAlias*> DeadAliases; for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadAliases.push_back(I); I->setAliasee(nullptr); } if (!DeadFunctions.empty()) { // Now that all interferences have been dropped, delete the actual objects // themselves. for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadFunctions[i]); M.getFunctionList().erase(DeadFunctions[i]); } NumFunctions += DeadFunctions.size(); Changed = true; } if (!DeadGlobalVars.empty()) { for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadGlobalVars[i]); M.getGlobalList().erase(DeadGlobalVars[i]); } NumVariables += DeadGlobalVars.size(); Changed = true; } // Now delete any dead aliases. if (!DeadAliases.empty()) { for (unsigned i = 0, e = DeadAliases.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadAliases[i]); M.getAliasList().erase(DeadAliases[i]); } NumAliases += DeadAliases.size(); Changed = true; } // Make sure that all memory is released AliveGlobals.clear(); SeenConstants.clear(); return Changed; }
bool WebAssemblyLowerEmscriptenEHSjLj::runEHOnFunction(Function &F) { Module &M = *F.getParent(); LLVMContext &C = F.getContext(); IRBuilder<> IRB(C); bool Changed = false; SmallVector<Instruction *, 64> ToErase; SmallPtrSet<LandingPadInst *, 32> LandingPads; bool AllowExceptions = areAllExceptionsAllowed() || EHWhitelistSet.count(F.getName()); for (BasicBlock &BB : F) { auto *II = dyn_cast<InvokeInst>(BB.getTerminator()); if (!II) continue; Changed = true; LandingPads.insert(II->getLandingPadInst()); IRB.SetInsertPoint(II); bool NeedInvoke = AllowExceptions && canThrow(II->getCalledValue()); if (NeedInvoke) { // Wrap invoke with invoke wrapper and generate preamble/postamble Value *Threw = wrapInvoke(II); ToErase.push_back(II); // Insert a branch based on __THREW__ variable Value *Cmp = IRB.CreateICmpEQ(Threw, IRB.getInt32(1), "cmp"); IRB.CreateCondBr(Cmp, II->getUnwindDest(), II->getNormalDest()); } else { // This can't throw, and we don't need this invoke, just replace it with a // call+branch SmallVector<Value *, 16> Args(II->arg_begin(), II->arg_end()); CallInst *NewCall = IRB.CreateCall(II->getCalledValue(), Args); NewCall->takeName(II); NewCall->setCallingConv(II->getCallingConv()); NewCall->setDebugLoc(II->getDebugLoc()); NewCall->setAttributes(II->getAttributes()); II->replaceAllUsesWith(NewCall); ToErase.push_back(II); IRB.CreateBr(II->getNormalDest()); // Remove any PHI node entries from the exception destination II->getUnwindDest()->removePredecessor(&BB); } } // Process resume instructions for (BasicBlock &BB : F) { // Scan the body of the basic block for resumes for (Instruction &I : BB) { auto *RI = dyn_cast<ResumeInst>(&I); if (!RI) continue; // Split the input into legal values Value *Input = RI->getValue(); IRB.SetInsertPoint(RI); Value *Low = IRB.CreateExtractValue(Input, 0, "low"); // Create a call to __resumeException function IRB.CreateCall(ResumeF, {Low}); // Add a terminator to the block IRB.CreateUnreachable(); ToErase.push_back(RI); } } // Process llvm.eh.typeid.for intrinsics for (BasicBlock &BB : F) { for (Instruction &I : BB) { auto *CI = dyn_cast<CallInst>(&I); if (!CI) continue; const Function *Callee = CI->getCalledFunction(); if (!Callee) continue; if (Callee->getIntrinsicID() != Intrinsic::eh_typeid_for) continue; IRB.SetInsertPoint(CI); CallInst *NewCI = IRB.CreateCall(EHTypeIDF, CI->getArgOperand(0), "typeid"); CI->replaceAllUsesWith(NewCI); ToErase.push_back(CI); } } // Look for orphan landingpads, can occur in blocks with no predecessors for (BasicBlock &BB : F) { Instruction *I = BB.getFirstNonPHI(); if (auto *LPI = dyn_cast<LandingPadInst>(I)) LandingPads.insert(LPI); } // Handle all the landingpad for this function together, as multiple invokes // may share a single lp for (LandingPadInst *LPI : LandingPads) { IRB.SetInsertPoint(LPI); SmallVector<Value *, 16> FMCArgs; for (unsigned i = 0, e = LPI->getNumClauses(); i < e; ++i) { Constant *Clause = LPI->getClause(i); // As a temporary workaround for the lack of aggregate varargs support // in the interface between JS and wasm, break out filter operands into // their component elements. if (LPI->isFilter(i)) { auto *ATy = cast<ArrayType>(Clause->getType()); for (unsigned j = 0, e = ATy->getNumElements(); j < e; ++j) { Value *EV = IRB.CreateExtractValue(Clause, makeArrayRef(j), "filter"); FMCArgs.push_back(EV); } } else FMCArgs.push_back(Clause); } // Create a call to __cxa_find_matching_catch_N function Function *FMCF = getFindMatchingCatch(M, FMCArgs.size()); CallInst *FMCI = IRB.CreateCall(FMCF, FMCArgs, "fmc"); Value *Undef = UndefValue::get(LPI->getType()); Value *Pair0 = IRB.CreateInsertValue(Undef, FMCI, 0, "pair0"); Value *TempRet0 = IRB.CreateLoad(TempRet0GV, TempRet0GV->getName() + ".val"); Value *Pair1 = IRB.CreateInsertValue(Pair0, TempRet0, 1, "pair1"); LPI->replaceAllUsesWith(Pair1); ToErase.push_back(LPI); } // Erase everything we no longer need in this function for (Instruction *I : ToErase) I->eraseFromParent(); return Changed; }
bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable *> &Globals, const BitVector &GlobalSet, Module &M, bool isConst, unsigned AddrSpace) const { Type *Int32Ty = Type::getInt32Ty(M.getContext()); auto &DL = M.getDataLayout(); assert(Globals.size() > 1); DEBUG(dbgs() << " Trying to merge set, starts with #" << GlobalSet.find_first() << "\n"); ssize_t i = GlobalSet.find_first(); while (i != -1) { ssize_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 != -1; j = GlobalSet.find_next(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; StructType *MergedTy = StructType::get(M.getContext(), Tys); Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); // 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. GlobalVariable *MergedGV = new GlobalVariable( M, MergedTy, isConst, Linkage, MergedInit, HasExternal ? "_MergedGlobals_" + TheFirstExternal->getName() : "_MergedGlobals", nullptr, GlobalVariable::NotThreadLocal, AddrSpace); for (ssize_t k = i, idx = 0; k != j; k = GlobalSet.find_next(k)) { GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage(); std::string Name = Globals[k]->getName(); Constant *Idx[2] = { ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, idx++) }; Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedTy, 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, Linkage, Name, GEP, &M); } NumMerged++; } i = j; } return true; }
void VisitConstant(const Constant& c) { value_map_[&c] = c.GetValue(); }
bool SDFix::fixDestructors() { bool replaced = false; for (GlobalVariable& gv : module->getGlobalList()) { if (! sd_isVtableName_ref(gv.getName())) continue; else if (! gv.hasInitializer()) continue; Constant* init = gv.getInitializer(); assert(init); ConstantArray* vtable = dyn_cast<ConstantArray>(init); assert(vtable); // get an idea about the virtual function regions std::vector<vtbl_pair_t> vtblRegions = findSubVtables(vtable); // for each subvtable for(unsigned vtblInd = 0; vtblInd < vtblRegions.size(); vtblInd++) { // record the destructors used in the vtable std::vector<DestructorInfo> destructors(3); vtbl_pair_t p = vtblRegions[vtblInd]; for(unsigned i=p.first; i<p.second; i++) { Constant* destructor = sd_getDestructorFunction(vtable->getOperand(i)); if (destructor == NULL) continue; // get the type from its name unsigned s = destructor->getName().size(); char type = destructor->getName()[s-3]; assert('0' <= type && type <= '2'); unsigned typeInt = type - '0'; // store it temporarily destructors[typeInt] = DestructorInfo(destructor, i); } // deleting destructor should always be defined assert(! destructors[0].needsReplacement()); DestructorInfo* d1 = &destructors[1]; DestructorInfo* d2 = &destructors[2]; // only one of the rest could be undefined assert(! d1->needsReplacement() || ! d2->needsReplacement()); // if complete object destructor is missing... if (d1->needsReplacement()) { std::string gv2Name = d1->function->getName(); unsigned l = gv2Name.length(); gv2Name = gv2Name.replace(l-3, 1, "2"); Function* f1 = d1->getFunction(); assert(f1); Function* f2 = module->getFunction(gv2Name); assert(f2); sd_print("Replacing %s with %s inside %s\n", d1->function->getName().data(), gv2Name.c_str(), gv.getName().data()); f1->replaceAllUsesWith(f2); replaced = true; // if base object destructor is missing... } else if (d2->needsReplacement()) { std::string gv1Name = d2->function->getName(); unsigned l = gv1Name.length(); gv1Name = gv1Name.replace(l-3, 1, "1"); Function* f2 = d2->getFunction(); assert(f2); Function* f1 = module->getFunction(gv1Name); assert(f1); sd_print("Replacing %s with %s inside %s\n", d2->function->getName().data(), gv1Name.c_str(), gv.getName().data()); f2->replaceAllUsesWith(f1); replaced = true; } } } return replaced; }
void VisitConstant(const Constant& c) { std::ostringstream ss; ss << c.GetValue(); value_map_[&c] = ss.str(); }
/// Given a disjoint set of bitsets and globals, layout the globals, build the /// bit sets and lower the llvm.bitset.test calls. void LowerBitSets::buildBitSetsFromGlobalVariables( ArrayRef<Metadata *> BitSets, ArrayRef<GlobalVariable *> Globals) { // Build a new global with the combined contents of the referenced globals. // This global is a struct whose even-indexed elements contain the original // contents of the referenced globals and whose odd-indexed elements contain // any padding required to align the next element to the next power of 2. std::vector<Constant *> GlobalInits; const DataLayout &DL = M->getDataLayout(); for (GlobalVariable *G : Globals) { GlobalInits.push_back(G->getInitializer()); uint64_t InitSize = DL.getTypeAllocSize(G->getValueType()); // Compute the amount of padding required. uint64_t Padding = NextPowerOf2(InitSize - 1) - InitSize; // Cap at 128 was found experimentally to have a good data/instruction // overhead tradeoff. if (Padding > 128) Padding = RoundUpToAlignment(InitSize, 128) - InitSize; GlobalInits.push_back( ConstantAggregateZero::get(ArrayType::get(Int8Ty, Padding))); } if (!GlobalInits.empty()) GlobalInits.pop_back(); Constant *NewInit = ConstantStruct::getAnon(M->getContext(), GlobalInits); auto *CombinedGlobal = new GlobalVariable(*M, NewInit->getType(), /*isConstant=*/true, GlobalValue::PrivateLinkage, NewInit); StructType *NewTy = cast<StructType>(NewInit->getType()); const StructLayout *CombinedGlobalLayout = DL.getStructLayout(NewTy); // Compute the offsets of the original globals within the new global. DenseMap<GlobalObject *, uint64_t> GlobalLayout; for (unsigned I = 0; I != Globals.size(); ++I) // Multiply by 2 to account for padding elements. GlobalLayout[Globals[I]] = CombinedGlobalLayout->getElementOffset(I * 2); lowerBitSetCalls(BitSets, CombinedGlobal, GlobalLayout); // Build aliases pointing to offsets into the combined global for each // global from which we built the combined global, and replace references // to the original globals with references to the aliases. for (unsigned I = 0; I != Globals.size(); ++I) { // Multiply by 2 to account for padding elements. Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, I * 2)}; Constant *CombinedGlobalElemPtr = ConstantExpr::getGetElementPtr( NewInit->getType(), CombinedGlobal, CombinedGlobalIdxs); if (LinkerSubsectionsViaSymbols) { Globals[I]->replaceAllUsesWith(CombinedGlobalElemPtr); } else { assert(Globals[I]->getType()->getAddressSpace() == 0); GlobalAlias *GAlias = GlobalAlias::create(NewTy->getElementType(I * 2), 0, Globals[I]->getLinkage(), "", CombinedGlobalElemPtr, M); GAlias->setVisibility(Globals[I]->getVisibility()); GAlias->takeName(Globals[I]); Globals[I]->replaceAllUsesWith(GAlias); } Globals[I]->eraseFromParent(); } }
INLINE Constant *Constant::dispatchMarshal(Stream &stream, JVM_U1 tag) { Constant *constant = NULL; switch(tag) { case 7: constant = new ConstantClass(); break; case 9: constant = new ConstantFieldRef(); break; case 10: constant = new ConstantMethodRef(); break; case 11: constant = new ConstantInterfaceMethodRef(); break; case 8: constant = new ConstantString(); break; case 3: constant = new ConstantInteger(); break; case 4: constant = new ConstantFloat(); break; case 5: constant = new ConstantLong(); break; case 6: constant = new ConstantDouble(); break; case 12: constant = new ConstantNameAndType(); break; case 1: constant = new ConstantUtf8(); break; case 15: constant = new ConstantMethodHandle(); break; case 16: constant = new ConstantMethodType(); break; case 18: constant = new ConstantInvokeDynamic(); break; default: ERROR("tag is %d, this should not happened!", tag); break; } if(constant != NULL) { constant->tag_ = tag; if(constant->marshal(stream) == false) { ERROR("constant %d marshal failed! this constant object will be removed.", tag); delete constant; return NULL; } } return constant; }
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)); SanCovTracePCIndir = checkSanitizerInterfaceFunction(M.getOrInsertFunction( kSanCovTracePCIndir, VoidTy, IntptrTy, 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); SanCovTracePC = checkSanitizerInterfaceFunction( M.getOrInsertFunction(kSanCovTracePC, VoidTy, nullptr)); 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, alignTo(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; }
virtual bool runOnFunction(Function & F) { Module * M = F.getParent(); Function * func = &F; string dataStr; Value * globalStringPtr; for(Function::iterator i = func->begin(), e = func->end(); i != e; ++i){ BasicBlock * BB = &*i; for(auto & I : *BB){ Instruction * inst = &I; if(CallInst * callInst = dyn_cast<CallInst>(&*inst)){ string name = callInst->getCalledFunction()->getName().str(); if(name == "substring"){ if(debugPrint) errs()<<"substring = "<<*callInst<<"\n"; Value * startIndex = callInst->getOperand(1); Value * endIndex = callInst->getOperand(2); int startIdx; int endIdx; if(ConstantInt * constValue = dyn_cast<ConstantInt>(&*startIndex)){ if(debugPrint) errs()<<"constant1 = "<< constValue->getZExtValue() <<"\n"; startIdx = constValue->getZExtValue(); } else{ continue; } if(ConstantInt * constValue = dyn_cast<ConstantInt>(&*endIndex)){ if(debugPrint) errs()<<"constant2 = "<< constValue->getZExtValue() <<"\n"; endIdx = constValue->getZExtValue(); } else{ continue; } globalStringPtr = callInst->getOperand(0); // get pointer to constant string StringRef dataString; if(!getConstantStringInfo(globalStringPtr, dataString)) // if argument not a constant string continue; dataStr = dataString.str(); char * sourceString = substring(dataStr.c_str(), startIdx, endIdx); if(debugPrint) errs()<<"sourceString = "<<sourceString<<"\n"; Constant * stringConstant = ConstantDataArray::getString(M->getContext(), StringRef(sourceString), true); GlobalVariable * globalString = new GlobalVariable(*M, stringConstant->getType(), true, GlobalValue::ExternalLinkage, stringConstant, ""); if(debugPrint) errs()<<"globalString = "<<*globalString<<"\n"; IntegerType * intTy = IntegerType::get(M->getContext(), 64); ConstantInt * index1 = ConstantInt::get(intTy, 0); vector<Value *> indxList; indxList.push_back(index1); indxList.push_back(index1); GetElementPtrInst * stringPtr = GetElementPtrInst::Create(NULL, globalString, indxList, Twine(""), callInst); replaceValues[callInst] = stringPtr; } } } } replaceUses(); 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)); }
/// 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 (auto *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI)) { DEBUG(dbgs() << "Folding constant ptr expression: " << *Ptr); Ptr = FoldedPtr; 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 (auto *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI)) Ptr = FoldedPtr; // 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 (auto *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI)) { Ptr = FoldedPtr; 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->isMinusOne() && 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->isInterposable()) { 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(CS, 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 (auto *FoldedInstResult = ConstantFoldConstant(InstResult, DL, TLI)) InstResult = FoldedInstResult; 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; } }
/// getFeasibleSuccessors - Return a vector of booleans to indicate which /// successors are reachable from a given terminator instruction. void SparseSolver::getFeasibleSuccessors(TerminatorInst &TI, SmallVectorImpl<bool> &Succs, bool AggressiveUndef) { Succs.resize(TI.getNumSuccessors()); if (TI.getNumSuccessors() == 0) return; if (BranchInst *BI = dyn_cast<BranchInst>(&TI)) { if (BI->isUnconditional()) { Succs[0] = true; return; } LatticeVal BCValue; if (AggressiveUndef) BCValue = getOrInitValueState(BI->getCondition()); else BCValue = getLatticeState(BI->getCondition()); if (BCValue == LatticeFunc->getOverdefinedVal() || BCValue == LatticeFunc->getUntrackedVal()) { // Overdefined condition variables can branch either way. Succs[0] = Succs[1] = true; return; } // If undefined, neither is feasible yet. if (BCValue == LatticeFunc->getUndefVal()) return; Constant *C = LatticeFunc->GetConstant(BCValue, BI->getCondition(), *this); if (C == 0 || !isa<ConstantInt>(C)) { // Non-constant values can go either way. Succs[0] = Succs[1] = true; return; } // Constant condition variables mean the branch can only go a single way Succs[C->isNullValue()] = true; return; } if (isa<InvokeInst>(TI)) { // Invoke instructions successors are always executable. // TODO: Could ask the lattice function if the value can throw. Succs[0] = Succs[1] = true; return; } if (isa<IndirectBrInst>(TI)) { Succs.assign(Succs.size(), true); return; } SwitchInst &SI = cast<SwitchInst>(TI); LatticeVal SCValue; if (AggressiveUndef) SCValue = getOrInitValueState(SI.getCondition()); else SCValue = getLatticeState(SI.getCondition()); if (SCValue == LatticeFunc->getOverdefinedVal() || SCValue == LatticeFunc->getUntrackedVal()) { // All destinations are executable! Succs.assign(TI.getNumSuccessors(), true); return; } // If undefined, neither is feasible yet. if (SCValue == LatticeFunc->getUndefVal()) return; Constant *C = LatticeFunc->GetConstant(SCValue, SI.getCondition(), *this); if (C == 0 || !isa<ConstantInt>(C)) { // All destinations are executable! Succs.assign(TI.getNumSuccessors(), true); return; } SwitchInst::CaseIt Case = SI.findCaseValue(cast<ConstantInt>(C)); Succs[Case.getSuccessorIndex()] = true; }
void IA64AsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { const TargetData *TD = TM.getTargetData(); if (!GVar->hasInitializer()) return; // External global require no code // Check to see if this is a special global used by LLVM, if so, emit it. if (EmitSpecialLLVMGlobal(GVar)) return; O << "\n\n"; std::string name = Mang->getValueName(GVar); Constant *C = GVar->getInitializer(); unsigned Size = TD->getTypePaddedSize(C->getType()); unsigned Align = TD->getPreferredAlignmentLog(GVar); printVisibility(name, GVar->getVisibility()); SwitchToSection(TAI->SectionForGlobal(GVar)); if (C->isNullValue() && !GVar->hasSection()) { if (!GVar->isThreadLocal() && (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) { if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. if (GVar->hasLocalLinkage()) { O << "\t.lcomm " << name << "#," << Size << ',' << (1 << Align); O << '\n'; } else { O << "\t.common " << name << "#," << Size << ',' << (1 << Align); O << '\n'; } return; } } switch (GVar->getLinkage()) { case GlobalValue::LinkOnceAnyLinkage: case GlobalValue::LinkOnceODRLinkage: case GlobalValue::CommonLinkage: case GlobalValue::WeakAnyLinkage: case GlobalValue::WeakODRLinkage: // Nonnull linkonce -> weak O << "\t.weak " << name << '\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 << TAI->getGlobalDirective() << name << '\n'; // FALL THROUGH case GlobalValue::InternalLinkage: case GlobalValue::PrivateLinkage: break; case GlobalValue::GhostLinkage: cerr << "GhostLinkage cannot appear in IA64AsmPrinter!\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!"); } EmitAlignment(Align, GVar); if (TAI->hasDotTypeDotSizeDirective()) { O << "\t.type " << name << ",@object\n"; O << "\t.size " << name << ',' << Size << '\n'; } O << name << ":\n"; EmitGlobalConstant(C); }
bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals, Module &M, bool isConst, unsigned AddrSpace) const { // FIXME: Find better heuristics std::stable_sort(Globals.begin(), Globals.end(), [this](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; StructType *MergedTy = StructType::get(M.getContext(), Tys); Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); // 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. GlobalVariable *MergedGV = new GlobalVariable( M, MergedTy, isConst, Linkage, MergedInit, HasExternal ? "_MergedGlobals_" + TheFirstExternal->getName() : "_MergedGlobals", 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; }
int VectorField::ReadXML(string xmlfilename) { FILE *xmlfile; mxml_node_t *tree; mxml_node_t *node; bool bad_attr; xmlfile = fopen(xmlfilename.c_str(),"r"); if (xmlfile == NULL) { // Failed to open the file. cerr << "Error: Unable to open " << xmlfilename << "\n"; exit(-1); } tree = mxmlLoadFile(NULL,xmlfile,MXML_NO_CALLBACK); fclose(xmlfile); if (tree == NULL) { cerr << "Error: Unable to load the vector field from the file " << xmlfilename << ".\n"; cerr << "There may be an error in the XML definition of the vector field.\n"; mxmlDelete(tree); exit(-1); } node = mxmlFindElement(tree,tree,"VectorField",NULL,NULL,MXML_DESCEND); if (node == NULL) { cerr << "Error: No VectorField element found in XML defintion.\n"; mxmlDelete(tree); exit(-1); } else { bad_attr = false; for (int i = 0; i < node->value.element.num_attrs; ++i) { string attr = node->value.element.attrs[i].name; if (attr != "Name" && attr != "IndependentVariable" && attr != "Description") { cerr << "Error: The VectorField element has an unknown attribute: " << attr << endl; bad_attr = true; } } if (bad_attr) exit(-1); const char *attr; attr = mxmlElementGetAttr(node,"Name"); if (attr == NULL) { cerr << "Error: The VectorField element has no Name attribute.\n"; mxmlDelete(tree); exit(-1); } else { if (!isValidName(attr)) { cerr << "Error: The VectorField Name \"" << attr << "\" is not valid.\n"; mxmlDelete(tree); exit(-1); } string s(attr); Name(s); } attr = mxmlElementGetAttr(node,"Description"); if (attr != NULL) { string s(attr); Description(s); } attr = mxmlElementGetAttr(node,"IndependentVariable"); if (attr == NULL) IndependentVariable = "t"; else { if (!isValidName(attr)) { cerr << "Error: The VectorField IndependentVariable \"" << attr << "\" is not valid.\n"; mxmlDelete(tree); exit(-1); } string s(attr); IndependentVariable = s; } } // // Get the constants // for (node = mxmlFindElement(tree,tree,"Constant",NULL,NULL,MXML_DESCEND); node != NULL; node = mxmlFindElement(node,tree,"Constant",NULL,NULL,MXML_DESCEND)) { bad_attr = false; for (int i = 0; i < node->value.element.num_attrs; ++i) { string attr = node->value.element.attrs[i].name; if (attr != "Name" && attr != "Value" && attr != "Description" && attr != "Latex") { cerr << "Error: A Constant element has an unknown attribute: " << attr << endl; bad_attr = true; } } if (bad_attr) { cerr << "Valid Constant attributes are: Name, Value, Description, Latex.\n"; exit(-1); } const char *attr; attr = mxmlElementGetAttr(node,"Name"); if (attr == NULL) { cerr << "Error: A Constant element has no Name attribute.\n"; mxmlDelete(tree); exit(-1); } else { if (!isValidName(attr)) { cerr << "Error: The Constant Name \"" << attr << "\" is not valid.\n"; mxmlDelete(tree); exit(-1); } string name(attr); Constant *c = new Constant(name); AddConstant(c); attr = mxmlElementGetAttr(node,"Description"); if (attr != NULL) { string descr(attr); c->Description(descr); } attr = mxmlElementGetAttr(node,"Value"); if (attr == NULL) { cerr << "Error: The Constant element with Name=\"" << c->Name() << "\" has no Value attribute.\n"; mxmlDelete(tree); exit(-1); } else { string val(attr); c->Value(val); } attr = mxmlElementGetAttr(node,"Latex"); if (attr != NULL) { string latex(attr); c->Latex(latex); } } } // // Get the parameters // for (node = mxmlFindElement(tree,tree,"Parameter",NULL,NULL,MXML_DESCEND); node != NULL; node = mxmlFindElement(node,tree,"Parameter",NULL,NULL,MXML_DESCEND)) { bad_attr = false; for (int i = 0; i < node->value.element.num_attrs; ++i) { string attr = node->value.element.attrs[i].name; if (attr != "Name" && attr != "DefaultValue" && attr != "Description" && attr != "Latex") { cerr << "Error: A Parameter element has an unknown attribute: " << attr << endl; bad_attr = true; } } if (bad_attr) { cerr << "Valid Parameter attributes are: Name, DefaultValue, Description, Latex.\n"; exit(-1); } const char *attr; attr = mxmlElementGetAttr(node,"Name"); if (attr == NULL) { cerr << "Error: A Parameter element has no Name attribute.\n"; mxmlDelete(tree); exit(-1); } else { if (!isValidName(attr)) { cerr << "Error: The Parameter Name \"" << attr << "\" is not valid.\n"; mxmlDelete(tree); exit(-1); } string name(attr); Parameter *p = new Parameter(name); AddParameter(p); attr = mxmlElementGetAttr(node,"Description"); if (attr != NULL) { string descr(attr); p->Description(descr); } attr = mxmlElementGetAttr(node,"DefaultValue"); if (attr != NULL) { string defval(attr); p->DefaultValue(defval); } attr = mxmlElementGetAttr(node,"Latex"); if (attr != NULL) { string latex(attr); p->Latex(latex); } } } // // Get the auxiliary expressions // for (node = mxmlFindElement(tree,tree,"Expression",NULL,NULL,MXML_DESCEND); node != NULL; node = mxmlFindElement(node,tree,"Expression",NULL,NULL,MXML_DESCEND)) { bad_attr = false; for (int i = 0; i < node->value.element.num_attrs; ++i) { string attr = node->value.element.attrs[i].name; if (attr != "Name" && attr != "Formula" && attr != "Description" && attr != "Latex") { cerr << "Error: An Expression element has an unknown attribute: " << attr << endl; bad_attr = true; } } if (bad_attr) { cerr << "Valid Expression attributes are: Name, Formula, Description, Latex.\n"; exit(-1); } const char *attr; attr = mxmlElementGetAttr(node,"Name"); if (attr == NULL) { cerr << "Error: An Expression element has no Name attribute.\n"; mxmlDelete(tree); exit(-1); } else { if (!isValidName(attr)) { cerr << "Error: The Expression Name \"" << attr << "\" is not valid.\n"; mxmlDelete(tree); exit(-1); } string name(attr); Expression *e = new Expression(name); AddExpression(e); attr = mxmlElementGetAttr(node,"Description"); if (attr != NULL) { string descr(attr); e->Description(descr); } attr = mxmlElementGetAttr(node,"Formula"); if (attr == NULL) { cerr << "Error: The Expression with Name=\"" << e->Name() << "\" has no Formula attribute.\n"; mxmlDelete(tree); exit(-1); } else { string f(attr); e->Formula(f); } attr = mxmlElementGetAttr(node,"Latex"); if (attr != NULL) { string latex(attr); e->Latex(latex); } } } // // Get the state variables // for (node = mxmlFindElement(tree,tree,"StateVariable",NULL,NULL,MXML_DESCEND); node != NULL; node = mxmlFindElement(node,tree,"StateVariable",NULL,NULL,MXML_DESCEND)) { bad_attr = false; for (int i = 0; i < node->value.element.num_attrs; ++i) { string attr = node->value.element.attrs[i].name; if (attr != "Name" && attr != "DefaultInitialCondition" && attr != "Description" && attr != "Formula" && attr != "PeriodFrom" && attr != "PeriodTo" && attr != "DefaultHistory" && attr != "Latex") { cerr << "Error: A StateVariable element has an unknown attribute: " << attr << endl; bad_attr = true; } } if (bad_attr) { cerr << "Valid StateVariable attributes are: Name, Formula, Description, DefaultInitialCondition, DefaultHistory, PeriodFrom, PeriodTo, Latex.\n"; exit(-1); } const char *attr; attr = mxmlElementGetAttr(node,"Name"); if (attr == NULL) { cerr << "Error: A StateVariable element has no Name attribute.\n"; mxmlDelete(tree); exit(-1); } else { if (!isValidName(attr)) { cerr << "Error: The StateVariable Name \"" << attr << "\" is not valid.\n"; mxmlDelete(tree); exit(-1); } string name(attr); StateVariable *sv = new StateVariable(name); AddStateVariable(sv); attr = mxmlElementGetAttr(node,"Description"); if (attr != NULL) { string descr(attr); sv->Description(descr); } attr = mxmlElementGetAttr(node,"Formula"); if (attr == NULL) { cerr << "Error: The StateVariable with Name=\"" << sv->Name() << "\" has no Formula attribute.\n"; mxmlDelete(tree); exit(-1); } else { string f(attr); sv->Formula(f); } attr = mxmlElementGetAttr(node,"PeriodFrom"); if (attr != NULL) { string pfrom(attr); sv->PeriodicFrom(pfrom); } attr = mxmlElementGetAttr(node,"PeriodTo"); if (attr != NULL) { string pto(attr); sv->PeriodicTo(pto); } if (sv->PeriodicFrom() != "" & sv->PeriodicTo() == "") { cerr << "Error: The StateVariable with Name=\"" << sv->Name() << "\" has a PeriodicFrom attribute but no PeriodicTo attribute.\n"; mxmlDelete(tree); exit(-1); } if (sv->PeriodicFrom() == "" & sv->PeriodicTo() != "") { cerr << "Error: The StateVariable with Name=\"" << sv->Name() << "\" has a PeriodTo attribute but no PeriodicFrom attribute.\n"; mxmlDelete(tree); exit(-1); } attr = mxmlElementGetAttr(node,"DefaultInitialCondition"); if (attr != NULL) { string ic(attr); sv->DefaultInitialCondition(ic); } attr = mxmlElementGetAttr(node,"DefaultHistory"); if (attr != NULL) { string hist(attr); sv->DefaultHistory(hist); } attr = mxmlElementGetAttr(node,"Latex"); if (attr != NULL) { string latex(attr); sv->Latex(latex); } } } // // Get the functions // for (node = mxmlFindElement(tree,tree,"Function",NULL,NULL,MXML_DESCEND); node != NULL; node = mxmlFindElement(node,tree,"Function",NULL,NULL,MXML_DESCEND)) { bad_attr = false; for (int i = 0; i < node->value.element.num_attrs; ++i) { string attr = node->value.element.attrs[i].name; if (attr != "Name" && attr != "Formula" && attr != "Description") { cerr << "Error: A Function element has an unknown attribute: " << attr << endl; bad_attr = true; } } if (bad_attr) { cerr << "Valid Function attributes are: Name, Formula, Description.\n"; exit(-1); } const char *attr; attr = mxmlElementGetAttr(node,"Name"); if (attr == NULL) { cerr << "Error: A Function element has no Name attribute.\n"; mxmlDelete(tree); exit(-1); } else { if (!isValidName(attr)) { cerr << "Error: The Function Name \"" << attr << "\" is not valid.\n"; mxmlDelete(tree); exit(-1); } string name(attr); Function *func = new Function(name); AddFunction(func); attr = mxmlElementGetAttr(node,"Description"); if (attr != NULL) { string descr(attr); func->Description(descr); } attr = mxmlElementGetAttr(node,"Formula"); if (attr == NULL) { cerr << "Error: The Function element with Name=\"" << func->Name() << "\" has no Formula attibute.\n"; mxmlDelete(tree); exit(-1); } else { string f(attr); func->Formula(f); } } } mxmlDelete(tree); return 0; }
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 (); } }
void ControlFlowIntegrity::ParseAnnotations(void) { GlobalVariable *global_ctors = _M.getNamedGlobal("llvm.global.annotations"); // check for ctor section if (!global_ctors || !global_ctors->getOperand(0)) { return; } Constant *c = global_ctors->getInitializer(); if (!c) report_fatal_error("llvm.global.annotations without initializer!", false); ConstantArray *CA = dyn_cast<ConstantArray>(c); if (!CA) report_fatal_error("Cast to ConstantArray failed", true); for (Value *Op : ValueOpRange(*CA)) { ConstantStruct *CS = dyn_cast<ConstantStruct>(Op); if (!CS) report_fatal_error("Cast to ConstantStruct failed", true); Constant *FP = CS->getOperand(0); if (FP->isNullValue()) break; // found a NULL termintator, stop here ConstantExpr *CE; Function *F = dyn_cast_or_null<Function>(FP); if (F == NULL) { // Strip off constant expression cast CE = dyn_cast<ConstantExpr>(FP); if (!CE) report_fatal_error("Cast to ConstantExpr failed", true); if (CE->isCast()) { FP = CE->getOperand(0); F = dyn_cast_or_null<Function>(FP); } } if (!F) report_fatal_error("Cast to Function failed", true); Constant *SP = CS->getOperand(1); if (SP->isNullValue()) break; // found a NULL termintator, stop here // Strip off constant expression cast CE = dyn_cast<ConstantExpr>(SP); if (!CE) report_fatal_error("Cast to ConstantExpr failed", true); if (CE->isCast()) { SP = CE->getOperand(0); } Value *V = SP->getOperand(0); GlobalVariable *GV = dyn_cast_or_null<GlobalVariable>(V); if (!GV) report_fatal_error("Cast to GlobalVariable failed", false); assert(GV && "cast to GlobalVariable failed"); Constant *cval = GV->getInitializer(); const StringRef s = (cast<ConstantDataArray>(cval))->getAsCString(); if (s == ANNOTATION_IGNORE_BLOCK) { _IgnoredBlocksFunctions.insert(F->getName()); } } if (global_ctors->getNumUses() > 0) report_fatal_error("llvm.global.annotations uses count is > 0", false); }