Constant *LLVMFormula::getGlobalVariableFor (double *ptr) { // Thanks to the unladen-swallow project for this snippet, which was almost // impossible to figure out from the LLVM docs! // See if the JIT already knows about this global GlobalVariable *result = const_cast<GlobalVariable *>( cast_or_null<GlobalVariable>( engine->getGlobalValueAtAddress (ptr))); if (result && result->hasInitializer ()) return result; Constant *initializer = ConstantFP::get (Type::getDoubleTy (getGlobalContext ()), *ptr); if (result == NULL) { // Make a global variable result = new GlobalVariable (*module, initializer->getType (), false, GlobalVariable::InternalLinkage, NULL, ""); // Link the global variable to the right address engine->addGlobalMapping (result, ptr); } assert (!result->hasInitializer ()); // Add the initial value result->setInitializer (initializer); return result; }
void ClassHierarchyUtils::findClassHierarchy(Module& M) { // Extract class hierarchy using std::type_info structures rather than debug // info. The former works even for when there are anonymous namespaces. // (for more info, see http://mentorembedded.github.io/cxx-abi/abi.html) // // Class names are usually global, except in the case of anonymous namespaces, in which case // they may be renamed during linking. This renaming is not consistent across type_info and // vtables. For example, the following are for the same class: // _ZTIN7content12_GLOBAL__N_115HeaderFlattenerE60908 and // _ZTVN7content12_GLOBAL__N_115HeaderFlattenerE60906. // // (renamed from // _ZTVN7content12_GLOBAL__N_115HeaderFlattenerE and // _ZTIN7content12_GLOBAL__N_115HeaderFlattenerE). // // VTables give us the corresponding type_info, so we process them first and store // the VT <-> TI mappings, as this will be useful later. for (Module::global_iterator I=M.global_begin(), E=M.global_end(); I != E; I++) { GlobalVariable* VT = &*I; if (VT->getName().startswith("_ZTV")) { SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found vtable: " << VT->getName() << "\n"); if (VT->hasInitializer()) { ConstantStruct* VTinit = cast<ConstantStruct>(VT->getInitializer()); // all occurrences of a type_info object refer to this class's type_info, so we // can pick the first array ConstantArray* VTinitElem = cast<ConstantArray>(VTinit->getOperand(0)); for (int i=0; i<VTinitElem->getNumOperands(); i++) { // type_info will be the first global variable in the array. // It's not always at a fixed index so we have to search for it... // The first one corresponds to the primary vtable, all others // correspond to secondary vtables. All type_info occurrences will // be the same. if (GlobalVariable* TI = dyn_cast<GlobalVariable>(VTinitElem->getOperand(i)->stripPointerCasts())) { if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) { report_fatal_error(TI->getName() + " <-> " + VT->getName() + " mapping already exists!"); } // Record TI <-> VT mappings, as they will be useful later typeInfoToVTable[TI] = VT; vTableToTypeInfo[VT] = TI; break; // we only need to process the first one } } } else { SDEBUG("soaap.util.classhierarchy", 1, dbgs() << "WARNING: VTable " << VT->getName() << " does not have initializer\n"); } } } // Process type_info structures, recording class-hierarchy information and base offsets for (Module::global_iterator I=M.global_begin(), E=M.global_end(); I != E; I++) { GlobalVariable* G = &*I; if (G->getName().startswith("_ZTI")) { SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found type_info: " << G->getName() << "\n"); processTypeInfo(G, M); } } SDEBUG("soaap.util.classhierarchy", 3, ppClassHierarchy(classToSubclasses)); }
Value *DbgStopPointInst::getDirectory() const { // Once the operand indices are verified, update this assert assert(LLVMDebugVersion == (7 << 16) && "Verify operand indices"); GlobalVariable *GV = cast<GlobalVariable>(getContext()); if (!GV->hasInitializer()) return NULL; ConstantStruct *CS = cast<ConstantStruct>(GV->getInitializer()); return CS->getOperand(4); }
void ClassHierarchyUtils::findClassHierarchy(Module& M) { // extract call hierarchy using std::type_info structures rather // than debug info. The former works even for when there are anonymous // namespaces. type_info structs can be obtained from vtable globals. // (for more info, see http://mentorembedded.github.io/cxx-abi/abi.html) for (Module::global_iterator I=M.global_begin(), E=M.global_end(); I != E; I++) { GlobalVariable* G = &*I; if (G->getName().startswith("_ZTV")) { if (G->hasInitializer()) { SDEBUG("soaap.util.classhierarchy", 3, G->dump()); ConstantArray* Ginit = cast<ConstantArray>(G->getInitializer()); // Ginit[1] is the type_info global for this vtable's type bool typeInfoFound = false; bool primaryVTable = true; for (int i=0; i<Ginit->getNumOperands(); i++) { // typeinfo will be the first global variable in the array. // It's not always at a fixed index so we have to search for it... if (GlobalVariable* TI = dyn_cast<GlobalVariable>(Ginit->getOperand(i)->stripPointerCasts())) { //TI->dump(); typeInfoToVTable[TI] = G; vTableToTypeInfo[G] = TI; processTypeInfo(TI); // process TI recursively (it contains refs to super-class TIs) typeInfoFound = true; if (primaryVTable) { primaryVTable = false; vTableToSecondaryVTableMaps[G][0] = i+1; // i+1 is also the size of the vtable header } else { // offset_to_top is at the previous index ConstantExpr* offsetValCast = cast<ConstantExpr>(Ginit->getOperand(i-1)->stripPointerCasts()); ConstantInt* offsetVal = cast<ConstantInt>(offsetValCast->getOperand(0)); int offsetToTop = offsetVal->getSExtValue(); if (offsetToTop > 0) { dbgs() << "ERROR: offsetToTop is positive!\n"; G->dump(); } else { offsetToTop *= -1; } SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "offsetToTop: " << offsetToTop << "\n"); vTableToSecondaryVTableMaps[G][offsetToTop] = i+1; } } } if (!typeInfoFound) { dbgs() << "ERROR: vtable initializer is not a global variable...\n"; dbgs() << *G << " = " << *Ginit << "\n"; } } } } SDEBUG("soaap.util.classhierarchy", 3, ppClassHierarchy(classToSubclasses)); }
GlobalVariable *llvm::collectUsedGlobalVariables( const Module &M, SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed) { const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used"; GlobalVariable *GV = M.getGlobalVariable(Name); if (!GV || !GV->hasInitializer()) return GV; const ConstantArray *Init = cast<ConstantArray>(GV->getInitializer()); for (Value *Op : Init->operands()) { GlobalValue *G = cast<GlobalValue>(Op->stripPointerCastsNoFollowAliases()); Set.insert(G); } return GV; }
/// AnalyzeModule - Scan the module for global debug information. /// void MachineModuleInfo::AnalyzeModule(Module &M) { // Insert functions in the llvm.used array (but not llvm.compiler.used) into // UsedFunctions. GlobalVariable *GV = M.getGlobalVariable("llvm.used"); if (!GV || !GV->hasInitializer()) return; // Should be an array of 'i8*'. ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); if (InitList == 0) return; for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) if (Function *F = dyn_cast<Function>(InitList->getOperand(i)->stripPointerCasts())) UsedFunctions.insert(F); }
/// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. GlobalVariable *llvm::ExtractTypeInfo(Value *V) { V = V->stripPointerCasts(); GlobalVariable *GV = dyn_cast<GlobalVariable>(V); if (GV && GV->getName() == "llvm.eh.catch.all.value") { assert(GV->hasInitializer() && "The EH catch-all value must have an initializer"); Value *Init = GV->getInitializer(); GV = dyn_cast<GlobalVariable>(Init); if (!GV) V = cast<ConstantPointerNull>(Init); } assert((GV || isa<ConstantPointerNull>(V)) && "TypeInfo must be a global variable or NULL"); return GV; }
void moveGlobalVariableInitializer(GlobalVariable &OrigGV, ValueToValueMapTy &VMap, ValueMaterializer *Materializer, GlobalVariable *NewGV) { assert(OrigGV.hasInitializer() && "Nothing to move"); if (!NewGV) NewGV = cast<GlobalVariable>(VMap[&OrigGV]); else assert(VMap[&OrigGV] == NewGV && "Incorrect global variable mapping in VMap."); assert(NewGV->getParent() != OrigGV.getParent() && "moveGlobalVariableInitializer should only be used to move " "initializers between modules"); NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None, nullptr, Materializer)); }
static void setGlobalVariableValue(Module &M, const char *Name, Constant *Value) { GlobalVariable *Var = M.getNamedGlobal(Name); if (!Var) { // This warning can happen in a program that does not use a libc // and does not initialize TLS variables. Such a program might be // linked with "-nostdlib". errs() << "Warning: Variable " << Name << " not referenced\n"; } else { if (Var->hasInitializer()) { report_fatal_error(std::string("Variable ") + Name + " already has an initializer"); } Var->replaceAllUsesWith(ConstantExpr::getBitCast(Value, Var->getType())); Var->eraseFromParent(); } }
/// GetConstantStringInfo - This function computes the length of a /// null-terminated C string pointed to by V. If successful, it returns true /// and returns the string in Str. If unsuccessful, it returns false. bool llvm::GetConstantStringInfo(Value *V, std::string &Str, uint64_t Offset, bool StopAtNul) { // If V is NULL then return false; if (V == NULL) return false; // Look through bitcast instructions. if (BitCastInst *BCI = dyn_cast<BitCastInst>(V)) return GetConstantStringInfo(BCI->getOperand(0), Str, Offset, StopAtNul); // If the value is not a GEP instruction nor a constant expression with a // GEP instruction, then return false because ConstantArray can't occur // any other way User *GEP = 0; if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(V)) { GEP = GEPI; } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { if (CE->getOpcode() == Instruction::BitCast) return GetConstantStringInfo(CE->getOperand(0), Str, Offset, StopAtNul); if (CE->getOpcode() != Instruction::GetElementPtr) return false; GEP = CE; } if (GEP) { // Make sure the GEP has exactly three arguments. if (GEP->getNumOperands() != 3) return false; // Make sure the index-ee is a pointer to array of i8. const PointerType *PT = cast<PointerType>(GEP->getOperand(0)->getType()); const ArrayType *AT = dyn_cast<ArrayType>(PT->getElementType()); if (AT == 0 || AT->getElementType() != Type::Int8Ty) return false; // Check to make sure that the first operand of the GEP is an integer and // has value 0 so that we are sure we're indexing into the initializer. ConstantInt *FirstIdx = dyn_cast<ConstantInt>(GEP->getOperand(1)); if (FirstIdx == 0 || !FirstIdx->isZero()) return false; // If the second index isn't a ConstantInt, then this is a variable index // into the array. If this occurs, we can't say anything meaningful about // the string. uint64_t StartIdx = 0; if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(2))) StartIdx = CI->getZExtValue(); else return false; return GetConstantStringInfo(GEP->getOperand(0), Str, StartIdx+Offset, StopAtNul); } // The GEP instruction, constant or instruction, must reference a global // variable that is a constant and is initialized. The referenced constant // initializer is the array that we'll use for optimization. GlobalVariable* GV = dyn_cast<GlobalVariable>(V); if (!GV || !GV->isConstant() || !GV->hasInitializer()) return false; Constant *GlobalInit = GV->getInitializer(); // Handle the ConstantAggregateZero case if (isa<ConstantAggregateZero>(GlobalInit)) { // This is a degenerate case. The initializer is constant zero so the // length of the string must be zero. Str.clear(); return true; } // Must be a Constant Array ConstantArray *Array = dyn_cast<ConstantArray>(GlobalInit); if (Array == 0 || Array->getType()->getElementType() != Type::Int8Ty) return false; // Get the number of elements in the array uint64_t NumElts = Array->getType()->getNumElements(); if (Offset > NumElts) return false; // Traverse the constant array from 'Offset' which is the place the GEP refers // to in the array. Str.reserve(NumElts-Offset); for (unsigned i = Offset; i != NumElts; ++i) { Constant *Elt = Array->getOperand(i); ConstantInt *CI = dyn_cast<ConstantInt>(Elt); if (!CI) // This array isn't suitable, non-int initializer. return false; if (StopAtNul && CI->isZero()) return true; // we found end of string, success! Str += (char)CI->getZExtValue(); } // The array isn't null terminated, but maybe this is a memcpy, not a strcpy. return true; }
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->getValueType(), 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; }
void llvm::copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig, ValueToValueMapTy &VMap) { if (Orig.hasInitializer()) New.setInitializer(MapValue(Orig.getInitializer(), VMap)); }
bool SpDefUseInstrumenter::runOnModule(Module &M) { cerr << "instrument: --- Def-Use pair Spectrum ---\n"; Function *Main = M.getFunction("main"); LLVMContext &C = M.getContext(); if (Main == 0) { cerr << "WARNING: cannot insert def-use instrumentation into a module" << " with no main function!\n"; return false; // No main, no instrumentation! } // Add library function prototype Constant *SpFn = M.getOrInsertFunction("_updateSpectrum", Type::getVoidTy(C), Type::getInt32Ty(C), // spectrum index Type::getInt32Ty(C), // component index NULL); unsigned spectrumIndex = IndexManager::getSpectrumIndex(); unsigned nDefs = 0; unsigned nUses = 0; // Loop through all functions within module for (Module::iterator F = M.begin(), ME = M.end(); F != ME; ++F) { // skip function declarations if(F->isDeclaration()) continue; // skip the _registerAll function if(F->getName()=="_registerAll") continue; // Loop through all basic blocks within function for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) { //skip dead blocks //is this really safe?? BasicBlock *bb = B; if (B!=F->begin() && (pred_begin(bb)==pred_end(bb))) continue; //skip dead blocks // Loop through all instructions within basic block for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE; I++) { if(isa<DbgDeclareInst>(*I)) { // extract source file information from debug intrinsic DbgDeclareInst &DDI = cast<DbgDeclareInst>(*I); std::string file, dir; std::string name; GlobalVariable *gv = cast<GlobalVariable>(DDI.getVariable()); if(!gv->hasInitializer()) continue; ConstantStruct *cs = cast<ConstantStruct>(gv->getInitializer()); llvm::GetConstantStringInfo(cs->getOperand(2), name); unsigned int line = unsigned(cast<ConstantInt>(cs->getOperand(4))->getZExtValue()); Value *V = cast<Value>(cs->getOperand(3)); GlobalVariable *gv2 = cast<GlobalVariable>(cast<ConstantExpr>(V)->getOperand(0)); if(!gv2->hasInitializer()) continue; ConstantStruct *cs2 = cast<ConstantStruct>(gv2->getInitializer()); llvm::GetConstantStringInfo(cs2->getOperand(3), file); llvm::GetConstantStringInfo(cs2->getOperand(4), dir); // get the allocation instruction of the variable definition AllocaInst *AI; if(isa<AllocaInst>(DDI.getAddress())) { AI = cast<AllocaInst>(DDI.getAddress()); } else if (isa<BitCastInst>(DDI.getAddress())) { AI = cast<AllocaInst>(cast<BitCastInst>(DDI.getAddress())->getOperand(0)); } else { continue; } nDefs++; // add calls to lib function for each use of the variable int currUses = 0; for(AllocaInst::use_iterator U = AI->use_begin(), UE = AI->use_end(); U != UE; ++U) { if(isa<Instruction>(*U)) { User *user = *U; Instruction *insertInst = (Instruction*)user; // find most likely context location of use int useline = line; std::string usefile = file, usedir = dir; BasicBlock *parent = insertInst->getParent(); BasicBlock::iterator inst = parent->begin(); while(((Instruction *)inst) != insertInst && inst != parent->end()) { /*TODO: solve DbgStopPointInst problem*/ /*if(isa<DbgStopPointInst>(*inst)) { DbgStopPointInst &DSPI = cast<DbgStopPointInst>(*inst); llvm::GetConstantStringInfo(DSPI.getDirectory(), usedir); llvm::GetConstantStringInfo(DSPI.getFileName(), usefile); useline = DSPI.getLine(); }*/ inst++; } std::stringstream usename; usename << name << "(use_" << currUses << ")"; // add source context of this invariant to context file ContextManager::addSpectrumContext( spectrumIndex, // spectrumIndex nUses, // componentIndex usedir, // path usefile, // file useline, // line usename.str()); // name currUses++; std::vector<Value*> Args(2); Args[0] = ConstantInt::get(Type::getInt32Ty(C), spectrumIndex); Args[1] = ConstantInt::get(Type::getInt32Ty(C), nUses++); CallInst::Create(SpFn, Args.begin(), Args.end(), "", insertInst); } } } } } } // add the registration of the instrumented spectrum points in the _registerAll() function addSpectrumRegistration(M, spectrumIndex, nUses, "Def-Use_Pairs"); std::cerr << "instrument: " << nDefs << " defines with a total number of " << nUses << " uses instrumented\n"; // notify change of program return true; }
DyckVertex* AAAnalyzer::wrapValue(Value * v) { // if the vertex of v exists, return it, otherwise create one pair < DyckVertex*, bool> retpair = dgraph->retrieveDyckVertex(v); if (retpair.second) { return retpair.first; } DyckVertex* vdv = retpair.first; // constantTy are handled as below. if (isa<ConstantExpr>(v)) { // constant expr should be handled like a assignment instruction if (isa<GEPOperator>(v)) { DyckVertex * got = handle_gep((GEPOperator*) v); makeAlias(vdv, got); } else if (((ConstantExpr*) v)->isCast()) { // errs() << *v << "\n"; DyckVertex * got = wrapValue(((ConstantExpr*) v)->getOperand(0)); makeAlias(vdv, got); } else { unsigned opcode = ((ConstantExpr*) v)->getOpcode(); switch (opcode) { case 23: // BinaryConstantExpr "and" case 24: // BinaryConstantExpr "or" { // do nothing } break; default: { errs() << "ERROR when handle the following constant expression\n"; errs() << *v << "\n"; errs() << ((ConstantExpr*) v)->getOpcode() << "\n"; errs() << ((ConstantExpr*) v)->getOpcodeName() << "\n"; errs().flush(); exit(-1); } break; } } } else if (isa<ConstantArray>(v)) { #ifndef ARRAY_SIMPLIFIED DyckVertex* ptr = addPtrTo(NULL, vdv, dgraph); DyckVertex* current = ptr; Constant * vAgg = (Constant*) v; int numElmt = vAgg->getNumOperands(); for (int i = 0; i < numElmt; i++) { Value * vi = vAgg->getOperand(i); DyckVertex* viptr = addPtrOffset(current, i * dl.getTypeAllocSize(vi->getType()), dgraph); addPtrTo(viptr, wrapValue(vi, dgraph, dl), dgraph); } #else Constant * vAgg = (Constant*) v; int numElmt = vAgg->getNumOperands(); for (int i = 0; i < numElmt; i++) { Value * vi = vAgg->getOperand(i); makeAlias(vdv, wrapValue(vi)); } #endif } else if (isa<ConstantStruct>(v)) { //DyckVertex* ptr = addPtrTo(NULL, vdv); //DyckVertex* current = ptr; Constant * vAgg = (Constant*) v; int numElmt = vAgg->getNumOperands(); for (int i = 0; i < numElmt; i++) { Value * vi = vAgg->getOperand(i); addField(vdv, -2 - i, wrapValue(vi)); } } else if (isa<GlobalValue>(v)) { if (isa<GlobalVariable>(v)) { GlobalVariable * global = (GlobalVariable *) v; if (global->hasInitializer()) { Value * initializer = global->getInitializer(); if (!isa<UndefValue>(initializer)) { DyckVertex * initVer = wrapValue(initializer); addPtrTo(vdv, initVer); } } } else if (isa<GlobalAlias>(v)) { GlobalAlias * global = (GlobalAlias *) v; Value * aliasee = global->getAliasee(); makeAlias(vdv, wrapValue(aliasee)); } else if (isa<Function>(v)) { // do nothing } // no else } else if (isa<ConstantInt>(v) || isa<ConstantFP>(v) || isa<ConstantPointerNull>(v) || isa<UndefValue>(v)) { // do nothing } else if (isa<ConstantDataArray>(v) || isa<ConstantAggregateZero>(v)) { // do nothing } else if (isa<BlockAddress>(v)) { // do nothing } else if (isa<ConstantDataVector>(v)) { errs() << "ERROR when handle the following ConstantDataSequential, ConstantDataVector\n"; errs() << *v << "\n"; errs().flush(); exit(-1); } else if (isa<ConstantVector>(v)) { errs() << "ERROR when handle the following ConstantVector\n"; errs() << *v << "\n"; errs().flush(); exit(-1); } else if (isa<Constant>(v)) { errs() << "ERROR when handle the following constant value\n"; errs() << *v << "\n"; errs().flush(); exit(-1); } return vdv; }
void SDBuildCHA::buildClouds(Module &M) { // this set is used for checking if a parent class is defined or not std::set<vtbl_t> build_undefinedVtables; for(auto itr = M.getNamedMDList().begin(); itr != M.getNamedMDList().end(); itr++) { NamedMDNode* md = itr; // check if this is a metadata that we've added if(! md->getName().startswith(SD_MD_CLASSINFO)) continue; //sd_print("GOT METADATA: %s\n", md->getName().data()); std::vector<nmd_t> infoVec = extractMetadata(md); for (const nmd_t& info : infoVec) { // record the old vtable array GlobalVariable* oldVtable = M.getGlobalVariable(info.className, true); //sd_print("class %s with %d subtables\n", info.className.c_str(), info.subVTables.size()); /* sd_print("oldvtables: %p, %d, class %s\n", oldVtable, oldVtable ? oldVtable->hasInitializer() : -1, info.className.c_str()); */ if (oldVtable && oldVtable->hasInitializer()) { ConstantArray* vtable = dyn_cast<ConstantArray>(oldVtable->getInitializer()); assert(vtable); oldVTables[info.className] = vtable; } else { undefinedVTables.insert(info.className); } for(unsigned ind = 0; ind < info.subVTables.size(); ind++) { const nmd_sub_t* subInfo = & info.subVTables[ind]; vtbl_t name(info.className, ind); /* sd_print("SubVtable[%d] Order: %d Parents[%d]: %s [%d-%d] AddrPt: %d\n", ind, subInfo->order, subInfo->parents.size(), "NYI", subInfo->start, subInfo->end, subInfo->addressPoint); */ if (build_undefinedVtables.find(name) != build_undefinedVtables.end()) { //sd_print("Removing %s,%d from build_udnefinedVtables\n", name.first.c_str(), name.second); build_undefinedVtables.erase(name); } if (cloudMap.find(name) == cloudMap.end()){ //sd_print("Inserting %s, %d in cloudMap\n", name.first.c_str(), name.second); cloudMap[name] = std::set<vtbl_t>(); } vtbl_set_t parents; for (auto it : subInfo->parents) { if (it.first != "") { vtbl_t &parent = it; parents.insert(parent); // if the parent class is not defined yet, add it to the // undefined vtable set if (cloudMap.find(parent) == cloudMap.end()) { //sd_print("Inserting %s, %d in cloudMap - undefined parent\n", parent.first.c_str(), parent.second); cloudMap[parent] = std::set<vtbl_t>(); build_undefinedVtables.insert(parent); } // add the current class to the parent's children set cloudMap[parent].insert(name); } else { assert(ind == 0); // make sure secondary vtables have a direct parent // add the class to the root set roots.insert(info.className); } } parentMap[info.className].push_back(parents); // record the original address points addrPtMap[info.className].push_back(subInfo->addressPoint); // record the sub-vtable ends rangeMap[info.className].push_back(range_t(subInfo->start, subInfo->end)); } } } if (build_undefinedVtables.size() != 0) { sd_print("Build Undefined vtables:\n"); for (auto n : build_undefinedVtables) { sd_print("%s,%d\n", n.first.c_str(), n.second); } } assert(build_undefinedVtables.size() == 0); for (auto rootName : roots) { vtbl_t root(rootName, 0); for (auto child : preorder(root)) { if (ancestorMap.find(child) == ancestorMap.end()) { ancestorMap[child] = rootName; } } } for (auto it : parentMap) { const vtbl_name_t &className = it.first; const std::vector<vtbl_set_t> &parentSetV = it.second; for (int ind = 0; ind < parentSetV.size(); ind++) { vtbl_name_t layoutClass = "none"; // Check that all possible parents are in the same layout cloud for (auto ptIt : parentSetV[ind]) { if (layoutClass != "none") assert(layoutClass == ancestorMap[ptIt] && "All parents of a primitive vtable should have the same root layout."); else layoutClass = ancestorMap[ptIt]; } // No parents - then our "layout class" is ourselves. if (layoutClass == "none") layoutClass = className; // record the class name of the sub-object subObjNameMap[className].push_back(layoutClass); } } }