SizeOffsetType ObjectSizeOffsetVisitor::visitGEPOperator(GEPOperator &GEP) { SizeOffsetType PtrData = compute(GEP.getPointerOperand()); APInt Offset(IntTyBits, 0); if (!bothKnown(PtrData) || !GEP.accumulateConstantOffset(*TD, Offset)) return unknown(); return std::make_pair(PtrData.first, PtrData.second + Offset); }
SizeOffsetType ObjectSizeOffsetVisitor::visitGEPOperator(GEPOperator &GEP) { SizeOffsetType PtrData = compute(GEP.getPointerOperand()); if (!bothKnown(PtrData) || !GEP.hasAllConstantIndices()) return unknown(); SmallVector<Value*, 8> Ops(GEP.idx_begin(), GEP.idx_end()); APInt Offset(IntTyBits,TD->getIndexedOffset(GEP.getPointerOperandType(),Ops)); return std::make_pair(PtrData.first, PtrData.second + Offset); }
/// \brief Accumulate a constant GEP offset into an APInt if possible. /// /// Returns false if unable to compute the offset for any reason. Respects any /// simplified values known during the analysis of this callsite. bool CallAnalyzer::accumulateGEPOffset(GEPOperator &GEP, APInt &Offset) { if (!TD) return false; unsigned AS = GEP.getPointerAddressSpace(); unsigned IntPtrWidth = TD->getPointerSizeInBits(AS); assert(IntPtrWidth == Offset.getBitWidth()); for (gep_type_iterator GTI = gep_type_begin(GEP), GTE = gep_type_end(GEP); GTI != GTE; ++GTI) { ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); if (!OpC) if (Constant *SimpleOp = SimplifiedValues.lookup(GTI.getOperand())) OpC = dyn_cast<ConstantInt>(SimpleOp); if (!OpC) return false; if (OpC->isZero()) continue; // Handle a struct index, which adds its field offset to the pointer. if (StructType *STy = dyn_cast<StructType>(*GTI)) { unsigned ElementIdx = OpC->getZExtValue(); const StructLayout *SL = TD->getStructLayout(STy); Offset += APInt(IntPtrWidth, SL->getElementOffset(ElementIdx)); continue; } APInt TypeSize(IntPtrWidth, TD->getTypeAllocSize(GTI.getIndexedType())); Offset += OpC->getValue().sextOrTrunc(IntPtrWidth) * TypeSize; } return true; }
SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitGEPOperator(GEPOperator &GEP) { SizeOffsetEvalType PtrData = compute_(GEP.getPointerOperand()); if (!bothKnown(PtrData)) return unknown(); Value *Offset = EmitGEPOffset(&Builder, *TD, &GEP, /*NoAssumptions=*/true); Offset = Builder.CreateAdd(PtrData.second, Offset); return std::make_pair(PtrData.first, Offset); }
string esp::parseName(Value *value){ // has existed if(names.find(value) != names.end()) return names[value]; string name = ""; Value *current = value; /* bool continueFlag = true; do{ if(isa<Instruction > (current)){ Instruction* inst = dyn_cast<Instruction>(current); unsigned op = inst->getOpcode(); switch(op){ case Instruction::Ret :{ break; } case Instruction::Br :{ break; } case Instruction::Switch :{ break; } case Instruction::Call :{ CallInst *callinst = (CallInst*) current; if (((CallInst*) current)->getCalledFunction() != NULL) { name += string("@")+((CallInst*) current)->getCalledFunction()->getNameStr() + "("; } else { name += string("@[funcPTR]("); name += ((CallInst*) current)->getCalledValue()->getNameStr(); } for (unsigned i = 1; i < callinst->getNumOperands(); i++) { name += esp::parseName(callinst->getOperand(i)); } name += string(")"); continueFlag = false; break; } case Instruction::PHI :{ name += string("PHI["); name += current->getNameStr(); PHINode *phi = (PHINode*) current; for (unsigned i = 0; i < phi->getNumIncomingValues(); i++) { Value *incoming = phi->getIncomingValue(i); if (i != 0) name += ","; if (!hasLoop(incoming)) { if (!incoming->hasName()) { name += esp::parseName(incoming); } else { name += incoming->getNameStr(); } } } name += std::string("]"); continueFlag = false; break; } case Instruction::Select :{ break; } case Instruction::Add :{ name += "+"; name += parseBinaryOpName(inst); break; } case Instruction::Sub :{ name += "-"; name += parseBinaryOpName(inst); break; } case Instruction::Mul :{ name += "*"; name += parseBinaryOpName(inst); break; } case Instruction::UDiv :{ name += "/"; name += parseBinaryOpName(inst); break; } case Instruction::SDiv :{ name += "//"; name += parseBinaryOpName(inst); break; } case Instruction::And :{ name += "&"; name += parseBinaryOpName(inst); break; } case Instruction::Or :{ name += "|"; name += parseBinaryOpName(inst); break; } case Instruction::Xor :{ name += "^"; name += parseBinaryOpName(inst); break; } case Instruction::Shl :{ name += "<<"; name += parseBinaryOpName(inst); break; } case Instruction::LShr :{ name += ">>"; name += parseBinaryOpName(inst); break; } case Instruction::AShr :{ name += ">>>"; name += parseBinaryOpName(inst); break; } case Instruction::ICmp :{ ICmpInst * icmp = dyn_cast<ICmpInst>(current); if (isa<Constant>(icmp->getOperand(0))) { name += esp::parseName(icmp->getOperand(1)); continueFlag = false; } else { name += esp::parseName(icmp->getOperand(0)); continueFlag = false; } break; } case Instruction::Alloca :{ name += current->getNameStr(); break; } case Instruction::Load :{ if (((LoadInst*) inst)->isVolatile()) name += std::string("@VolatileLoad"); name += "*"; name += esp::parseName(inst->getOperand(0)); continueFlag = false; break; } case Instruction::Store :{ // need to handle continueFlag = false; break; } case Instruction::GetElementPtr :{ GetElementPtrInst * gep = dyn_cast<GetElementPtrInst>(current); unsigned ops = gep->getNumOperands(); name += "["; for (unsigned i = 1; i < ops; i++) { Value *v = gep->getOperand(i); if (ConstantInt * ci = dyn_cast<ConstantInt>(v)) { if (i == 1 && ci->equalsInt(0)) continue; name += "."; name += ci->getValue().toString(10, false); } else { name += "."; name += esp::parseName(v); } } name += "]"; name += esp::parseName(gep->getOperand(0)); continueFlag = false; break; } case Instruction::BitCast:{ name += esp::parseName(inst->getOperand(0)); continueFlag = false; break; } default :{ // Illegal or unsupported instruction name += current->getNameStr(); break; } } }else if(isa<Argument>(current)){ if (arguments.find(current) != arguments.end()) name += std::string("$") + current->getNameStr(); }else if(isa<GlobalValue>(current)){ name += std::string("@") + current->getNameStr(); }else if(isa<ConstantInt>(current)){ ConstantInt * cint = dyn_cast<ConstantInt > (current); name += cint->getValue().toString(10, true); }else if (isa<Constant > (current)) { Constant *c = dyn_cast<Constant > (current); if (c->isNullValue()) { name += "null"; } }else{ // Illegal format } if(!continueFlag) break; current = parents[current]; }while(current); */ //Refactor do { if (isa<LoadInst > (current)) { name += "*"; if (parents[current] == NULL) name += (((LoadInst*) current)->getOperand(0))->getNameStr(); if (((LoadInst*) current)->isVolatile()) name += std::string("@VolatileLoad"); } else if (dyn_cast<GetElementPtrInst > (current)) { GetElementPtrInst * gep = dyn_cast<GetElementPtrInst > (current); unsigned ops = gep->getNumOperands(); name += "["; for (unsigned i = 1; i < ops; i++) { Value *v = gep->getOperand(i); if (dyn_cast<ConstantInt > (current)) { ConstantInt * ci = dyn_cast<ConstantInt > (current); if (i == 1 && ci->equalsInt(0)) continue; name += "."; name += ci->getValue().toString(10, false); } else { name += "."; name += parseName(v); } } name += "]"; name += parseName(gep->getOperand(0)); break; } else if (isa<AllocaInst > (current)) { name += current->getNameStr(); } else if (isa<Argument > (current)) { if (arguments.find(current) != arguments.end()) name += std::string("$") + current->getNameStr(); } else if (isa<GlobalValue > (current)) { name += std::string("@") + current->getNameStr(); } else if (isa<CallInst > (current)) { CallInst *callinst = (CallInst*) current; if (((CallInst*) current)->getCalledFunction() != NULL) { name += std::string("@")+((CallInst*) current)->getCalledFunction()->getNameStr() + "("; } else { name += std::string("@[funcPTR]("); name += ((CallInst*) current)->getCalledValue()->getNameStr(); } for (unsigned i = 1; i < callinst->getNumOperands(); i++) { name += parseName(callinst->getOperand(i)); } name += std::string(")"); break; } else if (isa<CastInst > (current)) { } else if (isa<PHINode > (current)) { /* name += std::string("PHI["); s += parent->getNameStr(); PHINode *phi = (PHINode*) parent; for (unsigned i = 0; i < phi->getNumIncomingValues(); i++) { //s+=phi->getIncomingBlock(i)->getNameStr(); Value *incoming = phi->getIncomingValue(i); if (i != 0) s += ","; if (!hasLoop(incoming)) { DEBUG(errs() << "incoming#" << i << " no loop(i rather doubt it)\n"); if (!incoming->hasName()) { s += parseName(incoming); } else { s += incoming->getNameStr(); } } } // PHI nodes...ugh s += std::string("]"); break; */ } else if (isa<BinaryOperator > (current)) { BinaryOperator *bo = dyn_cast<BinaryOperator > (current); Instruction::BinaryOps opcode = bo->getOpcode(); if (opcode == Instruction::Add) { name.append("+"); } else if (opcode == Instruction::Sub) { name.append("-"); } else if (opcode == Instruction::Or) { name.append("||"); } else if (opcode == Instruction::Mul) { name.append("*"); } else if (opcode == Instruction::Xor) { name.append("^"); } else if (opcode == Instruction::And) { name.append("&&"); } else if (opcode == Instruction::Shl) { name.append("<<"); } else if (opcode == Instruction::AShr) { name.append(">>"); } else if (opcode == Instruction::LShr) { name.append(">>>"); } Value *v0 = bo->getOperand(0); Value *v1 = bo->getOperand(1); if (isa<ConstantInt > (v0)) { name += ((ConstantInt*) v0)->getValue().toString(10, false); } else if (isa<ConstantInt > (v1)) { name += ((ConstantInt*) v1)->getValue().toString(10, false); } else { printDebugMsg("Binary Operation between non-constants\n"); } } else if (dyn_cast<GEPOperator > (current)) { GEPOperator * gep = dyn_cast<GEPOperator > (current); unsigned ops = gep->getNumOperands(); name += "["; for (unsigned i = 1; i < ops; i++) { Value *v = gep->getOperand(i); if (dyn_cast<ConstantInt > (v)) { ConstantInt * ci = dyn_cast<ConstantInt > (v); if (i == 1 && ci->equalsInt(0)) continue; name += "."; name += ci->getValue().toString(10, false); } } name += "]"; name += parseName(gep->getOperand(0)); break; } else if (dyn_cast<ICmpInst > (current)) { ICmpInst * icmp = dyn_cast<ICmpInst > (current); if (isa<Constant > (icmp->getOperand(0))) { name += parseName(icmp->getOperand(1)); break; } else { name += parseName(icmp->getOperand(0)); break; } } else if (dyn_cast<ConstantInt > (current)) { ConstantInt * cint = dyn_cast<ConstantInt > (current); name += cint->getValue().toString(10, true); } else { name += current->getNameStr(); // might not work } } while ((current = parents[current])); names[value] = name; return name; }
// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. // Clone functions that take GEPs as arguments // // Inputs: // M - A reference to the LLVM module to transform // // Outputs: // M - The transformed LLVM module. // // Return value: // true - The module was modified. // false - The module was not modified. // bool GEPExprArgs::runOnModule(Module& M) { bool changed; do { changed = false; for (Module::iterator F = M.begin(); F != M.end(); ++F){ for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) { for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) { CallInst *CI = dyn_cast<CallInst>(I++); if(!CI) continue; if(CI->hasByValArgument()) continue; // if the GEP calls a function, that is externally defined, // or might be changed, ignore this call site. Function *F = CI->getCalledFunction(); if (!F || (F->isDeclaration() || F->mayBeOverridden())) continue; if(F->hasStructRetAttr()) continue; if(F->isVarArg()) continue; // find the argument we must replace Function::arg_iterator ai = F->arg_begin(), ae = F->arg_end(); unsigned argNum = 1; for(; argNum < CI->getNumOperands();argNum++, ++ai) { if(ai->use_empty()) continue; if (isa<GEPOperator>(CI->getOperand(argNum))) break; } // if no argument was a GEP operator to be changed if(ai == ae) continue; GEPOperator *GEP = dyn_cast<GEPOperator>(CI->getOperand(argNum)); if(!GEP->hasAllConstantIndices()) continue; // Construct the new Type // Appends the struct Type at the beginning std::vector<Type*>TP; TP.push_back(GEP->getPointerOperand()->getType()); for(unsigned c = 1; c < CI->getNumOperands();c++) { TP.push_back(CI->getOperand(c)->getType()); } //return type is same as that of original instruction FunctionType *NewFTy = FunctionType::get(CI->getType(), TP, false); Function *NewF; numSimplified++; if(numSimplified > 800) return true; NewF = Function::Create(NewFTy, GlobalValue::InternalLinkage, F->getName().str() + ".TEST", &M); Function::arg_iterator NI = NewF->arg_begin(); NI->setName("GEParg"); ++NI; ValueToValueMapTy ValueMap; for (Function::arg_iterator II = F->arg_begin(); NI != NewF->arg_end(); ++II, ++NI) { ValueMap[II] = NI; NI->setName(II->getName()); NI->addAttr(F->getAttributes().getParamAttributes(II->getArgNo() + 1)); } NewF->setAttributes(NewF->getAttributes().addAttr( 0, F->getAttributes().getRetAttributes())); // Perform the cloning. SmallVector<ReturnInst*,100> Returns; CloneFunctionInto(NewF, F, ValueMap, false, Returns); std::vector<Value*> fargs; for(Function::arg_iterator ai = NewF->arg_begin(), ae= NewF->arg_end(); ai != ae; ++ai) { fargs.push_back(ai); } NewF->setAttributes(NewF->getAttributes().addAttr( ~0, F->getAttributes().getFnAttributes())); //Get the point to insert the GEP instr. SmallVector<Value*, 8> Ops(CI->op_begin()+1, CI->op_end()); Instruction *InsertPoint; for (BasicBlock::iterator insrt = NewF->front().begin(); isa<AllocaInst>(InsertPoint = insrt); ++insrt) {;} NI = NewF->arg_begin(); SmallVector<Value*, 8> Indices; Indices.append(GEP->op_begin()+1, GEP->op_end()); GetElementPtrInst *GEP_new = GetElementPtrInst::Create(cast<Value>(NI), Indices, "", InsertPoint); fargs.at(argNum)->replaceAllUsesWith(GEP_new); unsigned j = argNum + 1; for(; j < CI->getNumOperands();j++) { if(CI->getOperand(j) == GEP) fargs.at(j)->replaceAllUsesWith(GEP_new); } SmallVector<AttributeWithIndex, 8> AttributesVec; // Get the initial attributes of the call AttrListPtr CallPAL = CI->getAttributes(); Attributes RAttrs = CallPAL.getRetAttributes(); Attributes FnAttrs = CallPAL.getFnAttributes(); if (RAttrs) AttributesVec.push_back(AttributeWithIndex::get(0, RAttrs)); SmallVector<Value*, 8> Args; Args.push_back(GEP->getPointerOperand()); for(unsigned j =1;j<CI->getNumOperands();j++) { Args.push_back(CI->getOperand(j)); // position in the AttributesVec if (Attributes Attrs = CallPAL.getParamAttributes(j)) AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); } // Create the new attributes vec. if (FnAttrs != Attribute::None) AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()); CallInst *CallI = CallInst::Create(NewF,Args,"", CI); CallI->setCallingConv(CI->getCallingConv()); CallI->setAttributes(NewCallPAL); CI->replaceAllUsesWith(CallI); CI->eraseFromParent(); changed = true; } } } } while(changed); return true; }