/// \brief Emit materialization code for all rebased constants and update their /// users. void ConstantHoisting::EmitBaseConstants(Function &F, User *U, Instruction *Base, Constant *Offset, ConstantInt *OriginalConstant) { if (Instruction *I = dyn_cast<Instruction>(U)) { Instruction *Mat = Base; if (!Offset->isNullValue()) { Mat = BinaryOperator::Create(Instruction::Add, Base, Offset, "const_mat", getMatInsertPt(I, DT)); // Use the same debug location as the instruction we are about to update. Mat->setDebugLoc(I->getDebugLoc()); DEBUG(dbgs() << "Materialize constant (" << *Base->getOperand(0) << " + " << *Offset << ") in BB " << I->getParent()->getName() << '\n' << *Mat << '\n'); } DEBUG(dbgs() << "Update: " << *I << '\n'); I->replaceUsesOfWith(OriginalConstant, Mat); DEBUG(dbgs() << "To: " << *I << '\n'); return; } assert(isa<ConstantExpr>(U) && "Expected a ConstantExpr."); ConstantExpr *CE = cast<ConstantExpr>(U); for (Value::use_iterator UU = CE->use_begin(), E = CE->use_end(); UU != E; ++UU) { // We only handel instructions here and won't walk down a ConstantExpr chain // to replace all ConstExpr with instructions. if (Instruction *I = dyn_cast<Instruction>(*UU)) { // Only update constant expressions in the current function. if (I->getParent()->getParent() != &F) continue; Instruction *Mat = Base; Instruction *InsertBefore = getMatInsertPt(I, DT); if (!Offset->isNullValue()) { Mat = BinaryOperator::Create(Instruction::Add, Base, Offset, "const_mat", InsertBefore); // Use the same debug location as the instruction we are about to // update. Mat->setDebugLoc(I->getDebugLoc()); DEBUG(dbgs() << "Materialize constant (" << *Base->getOperand(0) << " + " << *Offset << ") in BB " << I->getParent()->getName() << '\n' << *Mat << '\n'); } Instruction *ICE = CE->getAsInstruction(); ICE->replaceUsesOfWith(OriginalConstant, Mat); ICE->insertBefore(InsertBefore); // Use the same debug location as the instruction we are about to update. ICE->setDebugLoc(I->getDebugLoc()); DEBUG(dbgs() << "Create instruction: " << *ICE << '\n'); DEBUG(dbgs() << "Update: " << *I << '\n'); I->replaceUsesOfWith(CE, ICE); DEBUG(dbgs() << "To: " << *I << '\n'); } } }
// Breaks down a constraint into all of it's individual pieces, returning a // list of IndependentElementSets or the independent factors. // // Caller takes ownership of returned std::list. static std::list<IndependentElementSet>* getAllIndependentConstraintsSets(const Query &query) { std::list<IndependentElementSet> *factors = new std::list<IndependentElementSet>(); ConstantExpr *CE = dyn_cast<ConstantExpr>(query.expr); if (CE) { assert(CE && CE->isFalse() && "the expr should always be false and " "therefore not included in factors"); } else { ref<Expr> neg = Expr::createIsZero(query.expr); factors->push_back(IndependentElementSet(neg)); } for (ConstraintManager::const_iterator it = query.constraints.begin(), ie = query.constraints.end(); it != ie; ++it) { // iterate through all the previously separated constraints. Until we // actually return, factors is treated as a queue of expressions to be // evaluated. If the queue property isn't maintained, then the exprs // could be returned in an order different from how they came it, negatively // affecting later stages. factors->push_back(IndependentElementSet(*it)); } bool doneLoop = false; do { doneLoop = true; std::list<IndependentElementSet> *done = new std::list<IndependentElementSet>; while (factors->size() > 0) { IndependentElementSet current = factors->front(); factors->pop_front(); // This list represents the set of factors that are separate from current. // Those that are not inserted into this list (queue) intersect with // current. std::list<IndependentElementSet> *keep = new std::list<IndependentElementSet>; while (factors->size() > 0) { IndependentElementSet compare = factors->front(); factors->pop_front(); if (current.intersects(compare)) { if (current.add(compare)) { // Means that we have added (z=y)added to (x=y) // Now need to see if there are any (z=?)'s doneLoop = false; } } else { keep->push_back(compare); } } done->push_back(current); delete factors; factors = keep; } delete factors; factors = done; } while (!doneLoop); return factors; }
void ControlFlowIntegrity::PatchDtorFunctions(void) { GlobalVariable *global_dtors = _M.getNamedGlobal("llvm.global_dtors"); // check for dtor section if (!global_dtors || !global_dtors->getOperand(0)) { return; } Constant *c = global_dtors->getInitializer(); if (!c) report_fatal_error("llvm.global_dtors 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(1); if (FP->isNullValue()) break; // found a NULL termintator, stop here Function *F = dyn_cast_or_null<Function>(FP); if (F == NULL) { // Strip off constant expression cast ConstantExpr *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); // set visibility to hidden (do not export), unless it is already // local (for ex. static), in which case we have to make it non-static if (F->hasLocalLinkage()) { F->setLinkage(llvm::GlobalValue::ExternalLinkage); } F->setVisibility(GlobalValue::HiddenVisibility); _FiniFunctions.insert(F->getName()); } if (global_dtors->getNumUses() > 0) report_fatal_error("llvm.global_dtors uses count is > 0!", false); global_dtors->removeFromParent(); }
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)); }
/// AddCatchInfo - Extract the personality and type infos from an eh.selector /// call, and add them to the specified machine basic block. void llvm::AddCatchInfo(CallInst &I, MachineModuleInfo *MMI, MachineBasicBlock *MBB) { // Inform the MachineModuleInfo of the personality for this landing pad. ConstantExpr *CE = cast<ConstantExpr>(I.getOperand(2)); assert(CE->getOpcode() == Instruction::BitCast && isa<Function>(CE->getOperand(0)) && "Personality should be a function"); MMI->addPersonality(MBB, cast<Function>(CE->getOperand(0))); // Gather all the type infos for this landing pad and pass them along to // MachineModuleInfo. std::vector<GlobalVariable *> TyInfo; unsigned N = I.getNumOperands(); for (unsigned i = N - 1; i > 2; --i) { if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(i))) { unsigned FilterLength = CI->getZExtValue(); unsigned FirstCatch = i + FilterLength + !FilterLength; assert (FirstCatch <= N && "Invalid filter length"); if (FirstCatch < N) { TyInfo.reserve(N - FirstCatch); for (unsigned j = FirstCatch; j < N; ++j) TyInfo.push_back(ExtractTypeInfo(I.getOperand(j))); MMI->addCatchTypeInfo(MBB, TyInfo); TyInfo.clear(); } if (!FilterLength) { // Cleanup. MMI->addCleanup(MBB); } else { // Filter. TyInfo.reserve(FilterLength - 1); for (unsigned j = i + 1; j < FirstCatch; ++j) TyInfo.push_back(ExtractTypeInfo(I.getOperand(j))); MMI->addFilterTypeInfo(MBB, TyInfo); TyInfo.clear(); } N = i; } } if (N > 3) { TyInfo.reserve(N - 3); for (unsigned j = 3; j < N; ++j) TyInfo.push_back(ExtractTypeInfo(I.getOperand(j))); MMI->addCatchTypeInfo(MBB, TyInfo); } }
GlobalValue *GlobalAlias::getAliasedGlobal() { Constant *C = getAliasee(); if (C == 0) return 0; if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) return GV; ConstantExpr *CE = cast<ConstantExpr>(C); assert((CE->getOpcode() == Instruction::BitCast || CE->getOpcode() == Instruction::AddrSpaceCast || CE->getOpcode() == Instruction::GetElementPtr) && "Unsupported aliasee"); return cast<GlobalValue>(CE->getOperand(0)); }
static GlobalValue *getAliaseeGV(GlobalAlias *GA) { Constant *C = GA->getAliasee(); assert(C && "Must alias something"); if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) return GV; ConstantExpr *CE = cast<ConstantExpr>(C); assert((CE->getOpcode() == Instruction::BitCast || CE->getOpcode() == Instruction::AddrSpaceCast || CE->getOpcode() == Instruction::GetElementPtr) && "Unsupported aliasee"); return cast<GlobalValue>(CE->getOperand(0)); }
void DebugDatabase::getGEPBaseAndOffset(ConstantExpr *GEP, Value **getBase, int *getOffset) { int offset = 0; Value *base = NULL; User *baseAddress = GEP->getOperand(0); ConstantExpr *CE = dyn_cast<ConstantExpr>(baseAddress); if (CE && CE->getOpcode() == Instruction::GetElementPtr) { // Nested GEP getGEPBaseAndOffset(CE, &base, &offset); } else if (isa<GlobalVariable>(baseAddress) || isa<AllocaInst>(baseAddress)) { base = baseAddress; } else { assert(false); } assert(base); gep_type_iterator GTI = gep_type_begin(GEP); for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e; ++i, ++GTI) { Value *Op = *i; // Build a mask for high order bits. const DataLayout *TD = dbgInfo->getAlloc()->getDataLayout(); unsigned IntPtrWidth = TD->getPointerSizeInBits(); uint64_t PtrSizeMask = ~0ULL >> (64 - IntPtrWidth); // apply mask uint64_t Size = TD->getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask; assert(isa<ConstantInt>(Op)); if (ConstantInt *OpC = dyn_cast<ConstantInt>(Op)) { // Handle a struct index, which adds its field offset. if (StructType *STy = dyn_cast<StructType>(*GTI)) { offset += TD->getStructLayout(STy) ->getElementOffset(OpC->getZExtValue()); } else { offset += Size * OpC->getValue().getSExtValue(); } } } *getBase = base; *getOffset = offset; }
static Constant* sd_getDestructorFunction(Constant* vtblElement) { ConstantExpr* bcExpr = NULL; // if this a constant bitcast expression, this might be a vthunk if ((bcExpr = dyn_cast<ConstantExpr>(vtblElement)) && bcExpr->getOpcode() == BITCAST_OPCODE) { Constant* operand = bcExpr->getOperand(0); // this is a vthunk if (sd_isDestructorName(operand->getName())) { return operand; } } return NULL; }
ref<Expr> BitfieldSimplifier::replaceWithConstant(ref<Expr> e, uint64_t value) { ConstantExpr *ce = dyn_cast<ConstantExpr>(e); if(ce && ce->getZExtValue() == value) return e; // Remove kids from cache unsigned numKids = e->getNumKids(); for(unsigned i = 0; i < numKids; ++i) m_bitsInfoCache.erase(e->getKid(i)); // Remove e from cache m_bitsInfoCache.erase(e); return ConstantExpr::create(value & ~zeroMask(e->getWidth()), e->getWidth()); }
static Constant* sd_isRTTI(Constant* vtblElement) { ConstantExpr* bcExpr = NULL; // if this a constant bitcast expression, this might be a vthunk if ((bcExpr = dyn_cast<ConstantExpr>(vtblElement)) && bcExpr->getOpcode() == Instruction::BitCast) { Constant* operand = bcExpr->getOperand(0); // this is a vthunk if (operand->getName().startswith("_ZTI")) { return operand; } } return NULL; }
std::string readAnnotate(Function *f) { std::string annotation = ""; // Get annotation variable GlobalVariable *glob = f->getParent()->getGlobalVariable("llvm.global.annotations"); if (glob != NULL) { // Get the array if (ConstantArray *ca = dyn_cast<ConstantArray>(glob->getInitializer())) { for (unsigned i = 0; i < ca->getNumOperands(); ++i) { // Get the struct if (ConstantStruct *structAn = dyn_cast<ConstantStruct>(ca->getOperand(i))) { if (ConstantExpr *expr = dyn_cast<ConstantExpr>(structAn->getOperand(0))) { // If it's a bitcast we can check if the annotation is concerning // the current function if (expr->getOpcode() == Instruction::BitCast && expr->getOperand(0) == f) { ConstantExpr *note = cast<ConstantExpr>(structAn->getOperand(1)); // If it's a GetElementPtr, that means we found the variable // containing the annotations if (note->getOpcode() == Instruction::GetElementPtr) { if (GlobalVariable *annoteStr = dyn_cast<GlobalVariable>(note->getOperand(0))) { if (ConstantDataSequential *data = dyn_cast<ConstantDataSequential>( annoteStr->getInitializer())) { if (data->isString()) { annotation += data->getAsString().lower() + " "; } } } } } } } } } } return annotation; }
/// IsConstantOffsetFromGlobal - If this constant is actually a constant offset /// from a global, return the global and the constant. Because of /// constantexprs, this function is recursive. static bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, int64_t &Offset, const TargetData &TD) { // Trivial case, constant is the global. if ((GV = dyn_cast<GlobalValue>(C))) { Offset = 0; return true; } // Otherwise, if this isn't a constant expr, bail out. ConstantExpr *CE = dyn_cast<ConstantExpr>(C); if (!CE) return false; // Look through ptr->int and ptr->ptr casts. if (CE->getOpcode() == Instruction::PtrToInt || CE->getOpcode() == Instruction::BitCast) return IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD); // i32* getelementptr ([5 x i32]* @a, i32 0, i32 5) if (CE->getOpcode() == Instruction::GetElementPtr) { // Cannot compute this if the element type of the pointer is missing size // info. if (!cast<PointerType>(CE->getOperand(0)->getType())->getElementType()->isSized()) return false; // If the base isn't a global+constant, we aren't either. if (!IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD)) return false; // Otherwise, add any offset that our operands provide. gep_type_iterator GTI = gep_type_begin(CE); for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i, ++GTI) { ConstantInt *CI = dyn_cast<ConstantInt>(CE->getOperand(i)); if (!CI) return false; // Index isn't a simple constant? if (CI->getZExtValue() == 0) continue; // Not adding anything. if (const StructType *ST = dyn_cast<StructType>(*GTI)) { // N = N + Offset Offset += TD.getStructLayout(ST)->getElementOffset(CI->getZExtValue()); } else { const SequentialType *SQT = cast<SequentialType>(*GTI); Offset += TD.getTypeSize(SQT->getElementType())*CI->getSExtValue(); } } return true; } return false; }
/** * 将ConstantExpr转换为对应的Constant类型 */ Constant* Transfer::expr2Constant(Expr* expr, Type* type) { Constant* param = NULL; if (type->isIntegerTy()) { ConstantExpr* constantExpr = dyn_cast<ConstantExpr>(expr); param = ConstantInt::get(type, constantExpr->getAPValue()); } else if (type->isFloatTy()) { ConstantExpr* constantExpr = dyn_cast<ConstantExpr>(expr); APFloat apValue(APFloat::IEEEsingle, constantExpr->getAPValue()); param = ConstantFP::get(type->getContext(), apValue); } else if (type->isDoubleTy()) { ConstantExpr* constantExpr = dyn_cast<ConstantExpr>(expr); APFloat apValue(APFloat::IEEEdouble, constantExpr->getAPValue()); param = ConstantFP::get(type->getContext(), apValue); } else if (type->isPointerTy()) { ConstantExpr* constantExpr = dyn_cast<ConstantExpr>(expr); param = ConstantInt::get( Type::getIntNTy(type->getContext(), Context::get().getPointerWidth()), constantExpr->getAPValue()); } else { assert(0 && "not support type"); } return param; }
z3::expr KQuery2Z3::eachExprToZ3(ref<Expr> &ele) { z3::expr res = z3_ctx.bool_val(true); switch (ele->getKind()) { case Expr::Constant: { ConstantExpr *ce = cast<ConstantExpr>(ele); Expr::Width width = ce->getWidth(); if (ele.get()->isFloat) { //float point number //in z3 there is no difference between float and double //they are all real value. double temp = 1.0; if (width == 32) { llvm::APFloat resValue(llvm::APFloat::IEEEsingle, ce->getAPValue()); temp = resValue.convertToFloat(); //the real float number,how to establish expr of z3 } else if (width == 64) { llvm::APFloat resValue(llvm::APFloat::IEEEdouble, ce->getAPValue()); temp = resValue.convertToDouble(); // the real double number. } Fraction frac; getFraction(temp, frac); // std::stringstream ss; // ss << temp; // std::cerr << "frac.num = " << frac.num << " " // << "frac.den = " << frac.den << std::endl; // res = z3_ctx.real_val(ss.str().c_str()); res = z3_ctx.real_val(frac.num, frac.den); // std::cerr << "float point value = " << res << std::endl; } else { if (width == Expr::Bool) { if (ce->isTrue()) { //that is true res = z3_ctx.bool_val(true); } else { //that is false res = z3_ctx.bool_val(false); } } else if (width != Expr::Fl80) { int temp = ce->getZExtValue(); // std::cerr << "temp = " << temp << std::endl; #if INT_ARITHMETIC res = z3_ctx.int_val(temp); #else res = z3_ctx.bv_val(temp, BIT_WIDTH); #endif // std::cerr << res; } else { assert(0 && "The Fl80 out, value bit number extends 64"); } } return res; } case Expr::NotOptimized: { assert(0 && "don't handle NotOptimized expression"); return res; } case Expr::Read: { //type char ReadExpr *re = cast<ReadExpr>(ele); assert(re && re->updates.root); const std::string varName = re->updates.root->name; if (re->getWidth() == Expr::Bool) { res = z3_ctx.bool_const(varName.c_str()); } else { #if INT_ARITHMETIC res = z3_ctx.constant(varName.c_str(), z3_ctx.int_sort()); #else res = z3_ctx.constant(varName.c_str(), z3_ctx.bv_sort(BIT_WIDTH)); #endif } return res; } case Expr::Select: { SelectExpr *se = cast<SelectExpr>(ele); z3::expr cond = eachExprToZ3(se->cond); z3::expr tExpr = eachExprToZ3(se->trueExpr); z3::expr fExpr = eachExprToZ3(se->falseExpr); res = z3::ite(cond, tExpr, fExpr); return res; } case Expr::Concat: { ConcatExpr *ce = cast<ConcatExpr>(ele); ReadExpr *re = NULL; if (ce->getKid(0)->getKind() == Expr::Read) re = cast<ReadExpr>(ce->getKid(0)); else if (ce->getKid(1)->getKind() == Expr::Read) re = cast<ReadExpr>(ce->getKid(1)); else if (ce->getKid(1)->getKind() == Expr::Concat){ while (ce->getKid(1)->getKind() == Expr::Concat) { ce = cast<ConcatExpr>(ce->getKid(1)); } re = cast<ReadExpr>(ce->getKid(1)); } else { assert("file: kQuery2z3, Expr::Concat" && false); } const std::string varName = re->updates.root->name; if (re->updates.root->isFloat) { //float point symbolics // std::cerr << "build float " << varName << std::endl; res = z3_ctx.constant(varName.c_str(), z3_ctx.real_sort()); } else { // std::cerr << "build bitvector" << varName << std::endl; if (ele.get()->isFloat) res = z3_ctx.constant(varName.c_str(), z3_ctx.real_sort()); else #if INT_ARITHMETIC res = z3_ctx.constant(varName.c_str(), z3_ctx.int_sort()); #else res = z3_ctx.constant(varName.c_str(), z3_ctx.bv_sort(BIT_WIDTH)); #endif } // else { // assert("real concat operation happened in Expr::Concat\n" // "need to be handle in minutes"); // } return res; } //Trunc and FPTrunc and FPtoSI and FPtoUI case Expr::Extract: { ExtractExpr * ee = cast<ExtractExpr>(ele); z3::expr src = eachExprToZ3(ee->expr); // std::cerr << "print in the Extract in kquery2z3\n"; // ele->dump(); // ee->expr.get()->dump(); //convert to boolean value, that means the result //depends on the ExtractExpr's least significant //bytes. if (ee->expr.get()->isFloat && !ee->isFloat) { //handle fptosi and fptoui // std::cerr << "handle fptosi \n"; // ele.get()->dump(); try { #if INT_ARITHMETIC z3::expr temp = z3::to_expr(z3_ctx, Z3_mk_real2int(z3_ctx, src)); #else z3::expr temp = z3::to_expr(z3_ctx, Z3_mk_real2int(z3_ctx, src)); z3::expr vecTemp = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, temp)); #endif if (ee->width == Expr::Bool) { //handle double->bool the special #if INT_ARITHMETIC res = z3::ite(temp, z3_ctx.bool_val(1), z3_ctx.bool_val(0)); #else res = z3::ite( z3::to_expr(z3_ctx, Z3_mk_extract(z3_ctx, 0, 0, vecTemp)), z3_ctx.bv_val(1, BIT_WIDTH), z3_ctx.bv_val(0, BIT_WIDTH)); #endif } else { #if INT_ARITHMETIC res = temp; #else res = vecTemp; #endif } } catch (z3::exception &ex) { std::cerr << "exception = " << ex << std::endl; } } else if (!ee->expr.get()->isFloat && !ee->isFloat) { //handle trunc and fptrunc, both these instructions //have same type before or after convert. if (ee->width == Expr::Bool) { //handle int->bool the special #if INT_ARITHMETIC res = z3::ite(src, z3_ctx.int_val(1), z3_ctx.int_val(0)); #else res = z3::ite( z3::to_expr(z3_ctx, Z3_mk_extract(z3_ctx, 0, 0, src)), z3_ctx.bv_val(1, BIT_WIDTH), z3_ctx.bv_val(0, BIT_WIDTH)); #endif } else { res = src; } } else { //float->float; res = src; } return res; } //ZExt SExt handle methods from encode.cpp case Expr::ZExt: { CastExpr * ce = cast<CastExpr>(ele); z3::expr src = eachExprToZ3(ce->src); if (ce->src.get()->getWidth() == Expr::Bool) { #if INT_ARITHMETIC res = z3::ite(src, z3_ctx.int_val(1), z3_ctx.int_val(0)); #else res = z3::ite(src, z3_ctx.bv_val(1, BIT_WIDTH), z3_ctx.bv_val(0, BIT_WIDTH)); // res = z3::ite( // z3::to_expr(z3_ctx, Z3_mk_extract(z3_ctx, 0, 0, src)), // z3_ctx.bool_val(true), z3_ctx.bool_val(false)); #endif // if (Z3_TRUE == Z3_algebraic_is_zero(z3_ctx, src)) { // res = z3_ctx.bool_val(false); // } else { // res = z3_ctx.bool_val(true); // } } else { res = src; } return res; } case Expr::SExt: { CastExpr * ce = cast<CastExpr>(ele); //convert int or unsigned int to float point //need to handle alone. // if (ce->isFloat) { // res = eachExprToZ3(ce->src, true); // } else { z3::expr src = eachExprToZ3(ce->src); if (ce->isFloat && !ce->src.get()->isFloat) { try { #if INT_ARITHMETIC z3::expr realTemp = to_expr(z3_ctx, Z3_mk_int2real(z3_ctx, src)); #else z3::expr temp = to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, src, true)); z3::expr realTemp = to_expr(z3_ctx, Z3_mk_int2real(z3_ctx, temp)); #endif res = realTemp; } catch (z3::exception &ex) { std::cerr << "exception = " << ex << std::endl; } } else if (!ce->isFloat && !ce->src.get()->isFloat) { if (ce->src.get()->getWidth() == Expr::Bool && ce->width != Expr::Bool) { #if INT_ARITHMETIC res = z3::ite(src, z3_ctx.int_val(1), z3_ctx.int_val(0)); #else res = z3::ite(src, z3_ctx.bv_val(1, BIT_WIDTH), z3_ctx.bv_val(0, BIT_WIDTH)); #endif // res = z3::ite(src, z3_ctx.bool_val(true), z3_ctx.bool_val(false)); // res = z3::ite( // z3::to_expr(z3_ctx, Z3_mk_extract(z3_ctx, 0, 0, src)), // z3_ctx.bool_val(true), z3_ctx.bool_val(false)); } else { res = src; } } else { res = src; } // } return res; } case Expr::Add: { AddExpr *ae = cast<AddExpr>(ele); // std::cerr << "Is this wrong?\n"; // ae->left.get()->dump(); // ae->right.get()->dump(); // std::cerr << "Add expr show\n"; // ele.get()->dump(); // if one of the operand is a float point number // then the left and right are all float point number. if (ae->left.get()->isFloat || ae->right.get()->isFloat) { ae->left.get()->isFloat = true; ae->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(ae->left); z3::expr right = eachExprToZ3(ae->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::Add\n"); res = left + right; return res; } case Expr::Sub: { SubExpr *se = cast<SubExpr>(ele); if (se->left.get()->isFloat || se->right.get()->isFloat) { se->left.get()->isFloat = true; se->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(se->left); z3::expr right = eachExprToZ3(se->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::Sub\n"); res = left - right; return res; } case Expr::Mul: { MulExpr *me = cast<MulExpr>(ele); if (me->left.get()->isFloat || me->right.get()->isFloat) { me->left.get()->isFloat = true; me->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(me->left); z3::expr right = eachExprToZ3(me->right); // std::cerr << left << "\n"; // std::cerr << right << "\n"; // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::Mul\n"); res = left * right; return res; } case Expr::UDiv: { //could handled with SDiv, but for test just do in here. UDivExpr *ue = cast<UDivExpr>(ele); if (ue->left.get()->isFloat || ue->right.get()->isFloat) { ue->left.get()->isFloat = true; ue->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(ue->left); z3::expr right = eachExprToZ3(ue->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::UDiv\n"); try { if (left.is_bv()) { res = z3::to_expr(z3_ctx, Z3_mk_bvudiv(z3_ctx, left, right)); } else { res = z3::to_expr(z3_ctx, Z3_mk_div(z3_ctx, left, right)); } } catch (z3::exception &ex) { std::cerr << "UDiv exception = " << ex << std::endl; } return res; } case Expr::SDiv: { SDivExpr *se = cast<SDivExpr>(ele); if (se->left.get()->isFloat || se->right.get()->isFloat) { se->left.get()->isFloat = true; se->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(se->left); z3::expr right = eachExprToZ3(se->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::SDiv\n"); try { if (left.is_bv()) { res = z3::to_expr(z3_ctx, Z3_mk_bvsdiv(z3_ctx, left, right)); } else { res = z3::to_expr(z3_ctx, Z3_mk_div(z3_ctx, left, right)); } } catch (z3::exception &ex) { std::cerr << "SDiv exception = " << ex << std::endl; } return res; } case Expr::URem: { URemExpr *ur = cast<URemExpr>(ele); if (ur->left.get()->isFloat || ur->right.get()->isFloat) { ur->left.get()->isFloat = true; ur->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(ur->left); z3::expr right = eachExprToZ3(ur->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::URem\n"); try { if (left.is_bv()) { //bitvecotor, all int are bitvector; res = z3::to_expr(z3_ctx, Z3_mk_bvurem(z3_ctx, left, right)); } else { //float res = z3::to_expr(z3_ctx, Z3_mk_rem(z3_ctx, left, right)); } } catch (z3::exception &ex) { std::cerr << "URem exception = " << ex << std::endl; } return res; } case Expr::SRem: { SRemExpr *sr = cast<SRemExpr>(ele); if (sr->left.get()->isFloat || sr->right.get()->isFloat) { sr->left.get()->isFloat = true; sr->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(sr->left); z3::expr right = eachExprToZ3(sr->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::SRem\n"); try { if (left.is_bv()) { //bitvecotor, all int are bitvector; res = z3::to_expr(z3_ctx, Z3_mk_bvsrem(z3_ctx, left, right)); } else { //float res = z3::to_expr(z3_ctx, Z3_mk_rem(z3_ctx, left, right)); } } catch (z3::exception &ex) { std::cerr << "SRem exception = " << ex << std::endl; } return res; } case Expr::Not: { NotExpr *ne = cast<NotExpr>(ele); res = eachExprToZ3(ne->expr); try { if (res.is_bv()) { res = z3::to_expr(z3_ctx, Z3_mk_bvnot(z3_ctx, res)); } else { res = z3::to_expr(z3_ctx, Z3_mk_not(z3_ctx, res)); } } catch (z3::exception &ex) { std::cerr << "Not exception = " << ex << std::endl; } return res; } case Expr::And: { AndExpr *ae = cast<AndExpr>(ele); if (ae->left.get()->isFloat || ae->right.get()->isFloat) { ae->left.get()->isFloat = true; ae->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(ae->left); z3::expr right = eachExprToZ3(ae->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::And\n"); // std::cerr << "And left = " << left << std::endl; // std::cerr << "And right = " << right << std::endl; if (left.is_bv()) { res = z3::to_expr(z3_ctx, Z3_mk_bvand(z3_ctx, left, right)); } else { // std::cerr << "left = " << left << ", left sort = " << left.get_sort() << std::endl; // std::cerr << "right = " << right << ", right sort = " << right.get_sort() << std::endl; #if INT_ARITHMETIC try { if (left.is_int()) { z3::expr tempLeft = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, left)); // std::cerr << "tempLeft = " << tempLeft << std::endl; z3::expr tempRight = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, right)); // std::cerr << "tempRight = " << tempRight << std::endl; z3::expr tempRes = z3::to_expr(z3_ctx, Z3_mk_bvand(z3_ctx, tempLeft, tempRight)); // std::cerr << "tempRes = " << tempRes << std::endl; res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true)); // std::cerr << "res = " << res << std::endl; } else { res = left && right; } } catch (z3::exception &ex) { std::cerr << "And exception = " << ex << std::endl; } #else res = left && right; #endif } return res; } case Expr::Or: { OrExpr *oe = cast<OrExpr>(ele); if (oe->left.get()->isFloat || oe->right.get()->isFloat) { oe->left.get()->isFloat = true; oe->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(oe->left); z3::expr right = eachExprToZ3(oe->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::Or\n"); if (left.is_bv()) { res = z3::to_expr(z3_ctx, Z3_mk_bvor(z3_ctx, left, right)); } else { #if INT_ARITHMETIC try { if (left.is_int()) { z3::expr tempLeft = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, left)); z3::expr tempRight = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, right)); z3::expr tempRes = z3::to_expr(z3_ctx, Z3_mk_bvor(z3_ctx, tempLeft, tempRight)); res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true)); } else { res = left || right; } } catch(z3::exception &ex) { std::cerr << "Or exception : " << ex << std::endl; } #else res = left || right; #endif } return res; } case Expr::Xor: { XorExpr *xe = cast<XorExpr>(ele); if (xe->left.get()->isFloat || xe->right.get()->isFloat) { xe->left.get()->isFloat = true; xe->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(xe->left); z3::expr right = eachExprToZ3(xe->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::Xor\n"); try { if (left.is_bv()) { res = z3::to_expr(z3_ctx, Z3_mk_bvxor(z3_ctx, left, right)); } else { res = z3::to_expr(z3_ctx, Z3_mk_xor(z3_ctx, left, right)); } } catch(z3::exception &ex) { std::cerr << "Xor exception : " << ex << std::endl; } return res; } //following shift operation must be bitvector operand. case Expr::Shl: { ShlExpr * se = cast<ShlExpr>(ele); z3::expr left = eachExprToZ3(se->left); z3::expr right = eachExprToZ3(se->right); //convert bit vector to int in order to binary operation. // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::Shl\n"); #if INT_ARITHMETIC try { z3::expr tempLeft = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, left)); z3::expr tempRight = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, right)); z3::expr tempRes = z3::to_expr(z3_ctx, Z3_mk_bvshl(z3_ctx, tempLeft, tempRight)); res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true)); } catch(z3::exception &ex) { std::cerr << "Shl exception : " << ex << std::endl; } #else res = z3::to_expr(z3_ctx, Z3_mk_bvshl(z3_ctx, left, right)); // res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true)); #endif return res; } case Expr::LShr: { LShrExpr * lse = cast<LShrExpr>(ele); z3::expr left = eachExprToZ3(lse->left); z3::expr right = eachExprToZ3(lse->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::LShr\n"); #if INT_ARITHMETIC try { z3::expr tempLeft = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, left)); z3::expr tempRight = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, right)); z3::expr tempRes = z3::to_expr(z3_ctx, Z3_mk_bvlshr(z3_ctx, tempLeft, tempRight)); res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true)); } catch(z3::exception &ex) { std::cerr << "LShr exception : " << ex << std::endl; } #else res = z3::to_expr(z3_ctx, Z3_mk_bvlshr(z3_ctx, left, right)); // res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true)); #endif return res; } case Expr::AShr: { AShrExpr * ase = cast<AShrExpr>(ele); z3::expr left = eachExprToZ3(ase->left); z3::expr right = eachExprToZ3(ase->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::AShr\n"); #if INT_ARITHMETIC try { z3::expr tempLeft = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, left)); z3::expr tempRight = z3::to_expr(z3_ctx, Z3_mk_int2bv(z3_ctx, BIT_WIDTH, right)); z3::expr tempRes = z3::to_expr(z3_ctx, Z3_mk_bvashr(z3_ctx, tempLeft, tempRight)); res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true)); } catch(z3::exception &ex) { std::cerr << "AShr exception : " << ex << std::endl; } #else res = z3::to_expr(z3_ctx, Z3_mk_bvashr(z3_ctx, left, right)); // res = z3::to_expr(z3_ctx, Z3_mk_bv2int(z3_ctx, tempRes, true)); #endif return res; } case Expr::Eq: { EqExpr *ee = cast<EqExpr>(ele); if (ee->left.get()->isFloat || ee->right.get()->isFloat) { ee->left.get()->isFloat = true; ee->right.get()->isFloat = true; } // std::cerr << "ele = " << ele << std::endl; z3::expr left = eachExprToZ3(ee->left); // std::cerr << "left = " << left << std::endl; z3::expr right = eachExprToZ3(ee->right); // assert( // Z3_get_sort_kind(z3_ctx, left) // && "sort between left and right are different in Expr::Eq\n"); // std::cerr << "right = " << right << std::endl; // std::cerr << "ee left = " << ee->left << std::endl; // std::cerr << "ee right = " << ee->right << std::endl; // std::cerr << "left = " << left << ", left sort = " << left.get_sort() << std::endl; // std::cerr << "right = " << right << ", right sort = " << right.get_sort() << std::endl; res = (left == right); return res; } case Expr::Ult: { //probably can float point value's comparison. UltExpr *ue = cast<UltExpr>(ele); if (ue->left.get()->isFloat || ue->right.get()->isFloat) { ue->left.get()->isFloat = true; ue->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(ue->left); z3::expr right = eachExprToZ3(ue->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::Ult\n"); try { if (left.is_bv()) { res = z3::to_expr(z3_ctx, Z3_mk_bvult(z3_ctx, left, right)); } else { res = z3::to_expr(z3_ctx, Z3_mk_lt(z3_ctx, left, right)); } } catch(z3::exception &ex) { std::cerr << "Ult exception : " << ex << std::endl; } return res; } case Expr::Ule: { UleExpr *ue = cast<UleExpr>(ele); if (ue->left.get()->isFloat || ue->right.get()->isFloat) { ue->left.get()->isFloat = true; ue->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(ue->left); z3::expr right = eachExprToZ3(ue->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::Ule\n"); try { if (left.is_bv()) { res = z3::to_expr(z3_ctx, Z3_mk_bvule(z3_ctx, left, right)); } else { res = z3::to_expr(z3_ctx, Z3_mk_le(z3_ctx, left, right)); } } catch(z3::exception &ex) { std::cerr << "Ule exception : " << ex << std::endl; } return res; } case Expr::Slt: { SltExpr *se = cast<SltExpr>(ele); if (se->left.get()->isFloat || se->right.get()->isFloat) { se->left.get()->isFloat = true; se->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(se->left); z3::expr right = eachExprToZ3(se->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::Slt\n"); try { if (left.is_bv()) { res = z3::to_expr(z3_ctx, Z3_mk_bvslt(z3_ctx, left, right)); } else { res = z3::to_expr(z3_ctx, Z3_mk_lt(z3_ctx, left, right)); } } catch(z3::exception &ex) { std::cerr << "Slt exception : " << ex << std::endl; } return res; } case Expr::Sle: { SleExpr *se = cast<SleExpr>(ele); if (se->left.get()->isFloat || se->right.get()->isFloat) { se->left.get()->isFloat = true; se->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(se->left); z3::expr right = eachExprToZ3(se->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::Sle\n"); try { if (left.is_bv()) { res = z3::to_expr(z3_ctx, Z3_mk_bvsle(z3_ctx, left, right)); } else { res = z3::to_expr(z3_ctx, Z3_mk_le(z3_ctx, left, right)); } } catch (z3::exception &ex) { std::cerr << "Sle exception : " << ex << std::endl; } return res; } case Expr::Ne: { NeExpr *ne = cast<NeExpr>(ele); if (ne->left.get()->isFloat || ne->right.get()->isFloat) { ne->left.get()->isFloat = true; ne->right.get()->isFloat = true; } z3::expr left = eachExprToZ3(ne->left); z3::expr right = eachExprToZ3(ne->right); // assert( // left.get_sort() == right.get_sort() // && "sort between left and right are different in Expr::Ne\n"); res = (left != right); return res; } //stp unhandled type /* case Expr::Ne: case Expr::Ugt: case Expr::Uge: case Expr::Sgt: case Expr::Sge: */ default: assert(0 && "unhandled Expr type in kueryExpr to Z3Expr"); return res; } std::cerr << "end of switch\n"; return res; }
/** if *width_out!=1 then result is a bitvector, otherwise it is a bool */ ExprHandle STPBuilder::constructActual(ref<Expr> e, int *width_out) { int width; if (!width_out) width_out = &width; ++stats::queryConstructs; switch (e->getKind()) { case Expr::Constant: { ConstantExpr *CE = cast<ConstantExpr>(e); *width_out = CE->getWidth(); // Coerce to bool if necessary. if (*width_out == 1) return CE->isTrue() ? getTrue() : getFalse(); // Fast path. if (*width_out <= 32) return bvConst32(*width_out, CE->getZExtValue(32)); if (*width_out <= 64) return bvConst64(*width_out, CE->getZExtValue()); ref<ConstantExpr> Tmp = CE; ExprHandle Res = bvConst64(64, Tmp->Extract(0, 64)->getZExtValue()); while (Tmp->getWidth() > 64) { Tmp = Tmp->Extract(64, Tmp->getWidth()-64); unsigned Width = std::min(64U, Tmp->getWidth()); Res = vc_bvConcatExpr(vc, bvConst64(Width, Tmp->Extract(0, Width)->getZExtValue()), Res); } return Res; } // Special case Expr::NotOptimized: { NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e); return construct(noe->src, width_out); } case Expr::Read: { ReadExpr *re = cast<ReadExpr>(e); assert(re && re->updates.root); *width_out = re->updates.root->getRange(); return vc_readExpr(vc, getArrayForUpdate(re->updates.root, re->updates.head), construct(re->index, 0)); } case Expr::Select: { SelectExpr *se = cast<SelectExpr>(e); ExprHandle cond = construct(se->cond, 0); ExprHandle tExpr = construct(se->trueExpr, width_out); ExprHandle fExpr = construct(se->falseExpr, width_out); return vc_iteExpr(vc, cond, tExpr, fExpr); } case Expr::Concat: { ConcatExpr *ce = cast<ConcatExpr>(e); unsigned numKids = ce->getNumKids(); ExprHandle res = construct(ce->getKid(numKids-1), 0); for (int i=numKids-2; i>=0; i--) { res = vc_bvConcatExpr(vc, construct(ce->getKid(i), 0), res); } *width_out = ce->getWidth(); return res; } case Expr::Extract: { ExtractExpr *ee = cast<ExtractExpr>(e); ExprHandle src = construct(ee->expr, width_out); *width_out = ee->getWidth(); if (*width_out==1) { return bvBoolExtract(src, ee->offset); } else { return vc_bvExtract(vc, src, ee->offset + *width_out - 1, ee->offset); } } // Casting case Expr::ZExt: { int srcWidth; CastExpr *ce = cast<CastExpr>(e); ExprHandle src = construct(ce->src, &srcWidth); *width_out = ce->getWidth(); if (srcWidth==1) { return vc_iteExpr(vc, src, bvOne(*width_out), bvZero(*width_out)); } else { return vc_bvConcatExpr(vc, bvZero(*width_out-srcWidth), src); } } case Expr::SExt: { int srcWidth; CastExpr *ce = cast<CastExpr>(e); ExprHandle src = construct(ce->src, &srcWidth); *width_out = ce->getWidth(); if (srcWidth==1) { return vc_iteExpr(vc, src, bvMinusOne(*width_out), bvZero(*width_out)); } else { return vc_bvSignExtend(vc, src, *width_out); } } // Arithmetic case Expr::Add: { AddExpr *ae = cast<AddExpr>(e); ExprHandle left = construct(ae->left, width_out); ExprHandle right = construct(ae->right, width_out); assert(*width_out!=1 && "uncanonicalized add"); return vc_bvPlusExpr(vc, *width_out, left, right); } case Expr::Sub: { SubExpr *se = cast<SubExpr>(e); ExprHandle left = construct(se->left, width_out); ExprHandle right = construct(se->right, width_out); assert(*width_out!=1 && "uncanonicalized sub"); return vc_bvMinusExpr(vc, *width_out, left, right); } case Expr::Mul: { MulExpr *me = cast<MulExpr>(e); ExprHandle right = construct(me->right, width_out); assert(*width_out!=1 && "uncanonicalized mul"); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(me->left)) if (CE->getWidth() <= 64) return constructMulByConstant(right, *width_out, CE->getZExtValue()); ExprHandle left = construct(me->left, width_out); return vc_bvMultExpr(vc, *width_out, left, right); } case Expr::UDiv: { UDivExpr *de = cast<UDivExpr>(e); ExprHandle left = construct(de->left, width_out); assert(*width_out!=1 && "uncanonicalized udiv"); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) { if (CE->getWidth() <= 64) { uint64_t divisor = CE->getZExtValue(); if (bits64::isPowerOfTwo(divisor)) { return bvRightShift(left, bits64::indexOfSingleBit(divisor)); } else if (optimizeDivides) { if (*width_out == 32) //only works for 32-bit division return constructUDivByConstant( left, *width_out, (uint32_t) divisor); } } } ExprHandle right = construct(de->right, width_out); return vc_bvDivExpr(vc, *width_out, left, right); } case Expr::SDiv: { SDivExpr *de = cast<SDivExpr>(e); ExprHandle left = construct(de->left, width_out); assert(*width_out!=1 && "uncanonicalized sdiv"); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) if (optimizeDivides) if (*width_out == 32) //only works for 32-bit division return constructSDivByConstant( left, *width_out, CE->getZExtValue(32)); // XXX need to test for proper handling of sign, not sure I // trust STP ExprHandle right = construct(de->right, width_out); return vc_sbvDivExpr(vc, *width_out, left, right); } case Expr::URem: { URemExpr *de = cast<URemExpr>(e); ExprHandle left = construct(de->left, width_out); assert(*width_out!=1 && "uncanonicalized urem"); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) { if (CE->getWidth() <= 64) { uint64_t divisor = CE->getZExtValue(); if (bits64::isPowerOfTwo(divisor)) { unsigned bits = bits64::indexOfSingleBit(divisor); // special case for modding by 1 or else we bvExtract -1:0 if (bits == 0) { return bvZero(*width_out); } else { return vc_bvConcatExpr(vc, bvZero(*width_out - bits), bvExtract(left, bits - 1, 0)); } } // Use fast division to compute modulo without explicit division for // constant divisor. if (optimizeDivides) { if (*width_out == 32) { //only works for 32-bit division ExprHandle quotient = constructUDivByConstant( left, *width_out, (uint32_t)divisor ); ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor ); ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor ); return rem; } } } } ExprHandle right = construct(de->right, width_out); return vc_bvModExpr(vc, *width_out, left, right); } case Expr::SRem: { SRemExpr *de = cast<SRemExpr>(e); ExprHandle left = construct(de->left, width_out); ExprHandle right = construct(de->right, width_out); assert(*width_out!=1 && "uncanonicalized srem"); #if 0 //not faster per first benchmark if (optimizeDivides) { if (ConstantExpr *cre = de->right->asConstant()) { uint64_t divisor = cre->asUInt64; //use fast division to compute modulo without explicit division for constant divisor if( *width_out == 32 ) { //only works for 32-bit division ExprHandle quotient = constructSDivByConstant( left, *width_out, divisor ); ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor ); ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor ); return rem; } } } #endif // XXX implement my fast path and test for proper handling of sign return vc_sbvModExpr(vc, *width_out, left, right); } // Bitwise case Expr::Not: { NotExpr *ne = cast<NotExpr>(e); ExprHandle expr = construct(ne->expr, width_out); if (*width_out==1) { return vc_notExpr(vc, expr); } else { return vc_bvNotExpr(vc, expr); } } case Expr::And: { AndExpr *ae = cast<AndExpr>(e); ExprHandle left = construct(ae->left, width_out); ExprHandle right = construct(ae->right, width_out); if (*width_out==1) { return vc_andExpr(vc, left, right); } else { return vc_bvAndExpr(vc, left, right); } } case Expr::Or: { OrExpr *oe = cast<OrExpr>(e); ExprHandle left = construct(oe->left, width_out); ExprHandle right = construct(oe->right, width_out); if (*width_out==1) { return vc_orExpr(vc, left, right); } else { return vc_bvOrExpr(vc, left, right); } } case Expr::Xor: { XorExpr *xe = cast<XorExpr>(e); ExprHandle left = construct(xe->left, width_out); ExprHandle right = construct(xe->right, width_out); if (*width_out==1) { // XXX check for most efficient? return vc_iteExpr(vc, left, ExprHandle(vc_notExpr(vc, right)), right); } else { return vc_bvXorExpr(vc, left, right); } } case Expr::Shl: { ShlExpr *se = cast<ShlExpr>(e); ExprHandle left = construct(se->left, width_out); assert(*width_out!=1 && "uncanonicalized shl"); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(se->right)) { return bvLeftShift(left, (unsigned) CE->getLimitedValue()); } else { int shiftWidth; ExprHandle amount = construct(se->right, &shiftWidth); return bvVarLeftShift( left, amount); } } case Expr::LShr: { LShrExpr *lse = cast<LShrExpr>(e); ExprHandle left = construct(lse->left, width_out); assert(*width_out!=1 && "uncanonicalized lshr"); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(lse->right)) { return bvRightShift(left, (unsigned) CE->getLimitedValue()); } else { int shiftWidth; ExprHandle amount = construct(lse->right, &shiftWidth); return bvVarRightShift( left, amount); } } case Expr::AShr: { AShrExpr *ase = cast<AShrExpr>(e); ExprHandle left = construct(ase->left, width_out); assert(*width_out!=1 && "uncanonicalized ashr"); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ase->right)) { unsigned shift = (unsigned) CE->getLimitedValue(); ExprHandle signedBool = bvBoolExtract(left, *width_out-1); return constructAShrByConstant(left, shift, signedBool); } else { int shiftWidth; ExprHandle amount = construct(ase->right, &shiftWidth); return bvVarArithRightShift( left, amount); } } // Comparison case Expr::Eq: { EqExpr *ee = cast<EqExpr>(e); ExprHandle left = construct(ee->left, width_out); ExprHandle right = construct(ee->right, width_out); if (*width_out==1) { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left)) { if (CE->isTrue()) return right; return vc_notExpr(vc, right); } else { return vc_iffExpr(vc, left, right); } } else { *width_out = 1; return vc_eqExpr(vc, left, right); } } case Expr::Ult: { UltExpr *ue = cast<UltExpr>(e); ExprHandle left = construct(ue->left, width_out); ExprHandle right = construct(ue->right, width_out); assert(*width_out!=1 && "uncanonicalized ult"); *width_out = 1; return vc_bvLtExpr(vc, left, right); } case Expr::Ule: { UleExpr *ue = cast<UleExpr>(e); ExprHandle left = construct(ue->left, width_out); ExprHandle right = construct(ue->right, width_out); assert(*width_out!=1 && "uncanonicalized ule"); *width_out = 1; return vc_bvLeExpr(vc, left, right); } case Expr::Slt: { SltExpr *se = cast<SltExpr>(e); ExprHandle left = construct(se->left, width_out); ExprHandle right = construct(se->right, width_out); assert(*width_out!=1 && "uncanonicalized slt"); *width_out = 1; return vc_sbvLtExpr(vc, left, right); } case Expr::Sle: { SleExpr *se = cast<SleExpr>(e); ExprHandle left = construct(se->left, width_out); ExprHandle right = construct(se->right, width_out); assert(*width_out!=1 && "uncanonicalized sle"); *width_out = 1; return vc_sbvLeExpr(vc, left, right); } // unused due to canonicalization #if 0 case Expr::Ne: case Expr::Ugt: case Expr::Uge: case Expr::Sgt: case Expr::Sge: #endif default: assert(0 && "unhandled Expr type"); return vc_trueExpr(vc); } }
/// Return true if the specified constant can be handled by the code generator. /// We don't want to generate something like: /// void *X = &X/42; /// because the code generator doesn't have a relocation that can handle that. /// /// This function should be called if C was not found (but just got inserted) /// in SimpleConstants to avoid having to rescan the same constants all the /// time. static bool isSimpleEnoughValueToCommitHelper(Constant *C, SmallPtrSetImpl<Constant *> &SimpleConstants, const DataLayout &DL) { // Simple global addresses are supported, do not allow dllimport or // thread-local globals. if (auto *GV = dyn_cast<GlobalValue>(C)) return !GV->hasDLLImportStorageClass() && !GV->isThreadLocal(); // Simple integer, undef, constant aggregate zero, etc are all supported. if (C->getNumOperands() == 0 || isa<BlockAddress>(C)) return true; // Aggregate values are safe if all their elements are. if (isa<ConstantAggregate>(C)) { for (Value *Op : C->operands()) if (!isSimpleEnoughValueToCommit(cast<Constant>(Op), SimpleConstants, DL)) return false; return true; } // We don't know exactly what relocations are allowed in constant expressions, // so we allow &global+constantoffset, which is safe and uniformly supported // across targets. ConstantExpr *CE = cast<ConstantExpr>(C); switch (CE->getOpcode()) { case Instruction::BitCast: // Bitcast is fine if the casted value is fine. return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL); case Instruction::IntToPtr: case Instruction::PtrToInt: // int <=> ptr is fine if the int type is the same size as the // pointer type. if (DL.getTypeSizeInBits(CE->getType()) != DL.getTypeSizeInBits(CE->getOperand(0)->getType())) return false; return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL); // GEP is fine if it is simple + constant offset. case Instruction::GetElementPtr: for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i) if (!isa<ConstantInt>(CE->getOperand(i))) return false; return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL); case Instruction::Add: // We allow simple+cst. if (!isa<ConstantInt>(CE->getOperand(1))) return false; return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL); } return false; }
uint64_t ExprFrame::SerializeExpr(const ref<Expr> e) { data::ExprNode *ser_expr_node = expr_data_->add_expr(); ser_expr_node->set_id(s_.next_id_++); ser_expr_node->set_kind((data::ExprKind)e->getKind()); switch (e->getKind()) { case Expr::Constant: { ConstantExpr *ce = cast<ConstantExpr>(e); assert(ce->getWidth() <= 64 && "FIXME"); ser_expr_node->set_value(ce->getZExtValue()); ser_expr_node->set_width(ce->getWidth()); break; } case Expr::NotOptimized: { NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(noe->src)); break; } case Expr::Read: { ReadExpr *re = cast<ReadExpr>(e); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(re->index)); if (re->updates.head) { ExprSerializer::UpdateNodePosition un_pos = GetOrSerializeUpdateList(re->updates); ser_expr_node->set_update_list_id(un_pos.first); ser_expr_node->set_update_list_offset(un_pos.second); } ser_expr_node->set_array_id(GetOrSerializeArray(re->updates.root)); break; } case Expr::Select: { SelectExpr *se = cast<SelectExpr>(e); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(se->cond)); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(se->trueExpr)); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(se->falseExpr)); break; } case Expr::Concat: { ConcatExpr *ce = cast<ConcatExpr>(e); for (unsigned i = 0; i < ce->getNumKids(); ++i) { ser_expr_node->add_child_expr_id(GetOrSerializeExpr(ce->getKid(i))); } break; } case Expr::Extract: { ExtractExpr *ee = cast<ExtractExpr>(e); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(ee->expr)); ser_expr_node->set_offset(ee->offset); ser_expr_node->set_width(ee->getWidth()); break; } // Casting, case Expr::ZExt: case Expr::SExt: { CastExpr *ce = cast<CastExpr>(e); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(ce->src)); ser_expr_node->set_width(ce->getWidth()); break; } // All subsequent kinds are binary. // Arithmetic case Expr::Add: case Expr::Sub: case Expr::Mul: case Expr::UDiv: case Expr::SDiv: case Expr::URem: case Expr::SRem: { BinaryExpr *be = cast<BinaryExpr>(e); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->left)); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->right)); break; } // Bit case Expr::Not: { NotExpr *ne = cast<NotExpr>(e); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(ne->expr)); break; } case Expr::And: case Expr::Or: case Expr::Xor: case Expr::Shl: case Expr::LShr: case Expr::AShr: { BinaryExpr *be = cast<BinaryExpr>(e); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->left)); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->right)); break; } // Compare case Expr::Eq: case Expr::Ne: ///< Not used in canonical form case Expr::Ult: case Expr::Ule: case Expr::Ugt: ///< Not used in canonical form case Expr::Uge: ///< Not used in canonical form case Expr::Slt: case Expr::Sle: case Expr::Sgt: ///< Not used in canonical form case Expr::Sge: { ///< Not used in canonical form BinaryExpr *be = cast<BinaryExpr>(e); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->left)); ser_expr_node->add_child_expr_id(GetOrSerializeExpr(be->right)); break; } default: assert(0 && "Unhandled Expr type"); } return ser_expr_node->id(); }
z3::expr Z3Builder::makeExpr(ref<Expr> e) { ++stats::queryConstructs; switch (e->getKind()) { case Expr::Constant: { ConstantExpr *CE = cast<ConstantExpr>(e); unsigned width = CE->getWidth(); if (width == 1) return context_.bool_val(CE->isTrue()); if (width <= 64) return context_.bv_val((__uint64)CE->getZExtValue(), width); // This is slower than concatenating 64-bit extractions, like STPBuilder // does, but the assumption is that it's quite infrequent. // TODO: Log these transformations. llvm::SmallString<32> const_repr; CE->getAPValue().toStringUnsigned(const_repr, 10); return context_.bv_val(const_repr.c_str(), width); } case Expr::NotOptimized: { NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e); return getOrMakeExpr(noe->src); } case Expr::Read: { return makeReadExpr(cast<ReadExpr>(e)); } case Expr::Select: { SelectExpr *se = cast<SelectExpr>(e); // XXX: A bug in Clang prevents us from using z3::ite return z3::to_expr(context_, Z3_mk_ite(context_, getOrMakeExpr(se->cond), getOrMakeExpr(se->trueExpr), getOrMakeExpr(se->falseExpr))); } case Expr::Concat: { ConcatExpr *ce = cast<ConcatExpr>(e); unsigned numKids = ce->getNumKids(); z3::expr res = getOrMakeExpr(ce->getKid(numKids-1)); for (int i = numKids - 2; i >= 0; --i) { res = z3::to_expr(context_, Z3_mk_concat(context_, getOrMakeExpr(ce->getKid(i)), res)); } return res; } case Expr::Extract: { ExtractExpr *ee = cast<ExtractExpr>(e); z3::expr src = getOrMakeExpr(ee->expr); if (ee->getWidth() == 1) { return z3::to_expr(context_, Z3_mk_extract(context_, ee->offset, ee->offset, src)) == context_.bv_val(1, 1); } else { return z3::to_expr(context_, Z3_mk_extract(context_, ee->offset + ee->getWidth() - 1, ee->offset, src)); } } // Casting case Expr::ZExt: { CastExpr *ce = cast<CastExpr>(e); z3::expr src = getOrMakeExpr(ce->src); if (src.is_bool()) { // XXX: A bug in Clang prevents us from using z3::ite return z3::to_expr(context_, Z3_mk_ite(context_, src, context_.bv_val(1, ce->getWidth()), context_.bv_val(0, ce->getWidth()))); } else { return z3::to_expr(context_, Z3_mk_zero_ext(context_, ce->getWidth() - src.get_sort().bv_size(), src)); } } case Expr::SExt: { CastExpr *ce = cast<CastExpr>(e); z3::expr src = getOrMakeExpr(ce->src); if (src.is_bool()) { return z3::to_expr(context_, Z3_mk_ite(context_, src, context_.bv_val(1, ce->getWidth()), context_.bv_val(0, ce->getWidth()))); } else { return z3::to_expr(context_, Z3_mk_sign_ext(context_, ce->getWidth() - src.get_sort().bv_size(), src)); } } // Arithmetic case Expr::Add: { AddExpr *ae = cast<AddExpr>(e); return getOrMakeExpr(ae->left) + getOrMakeExpr(ae->right); } case Expr::Sub: { SubExpr *se = cast<SubExpr>(e); // STP here takes an extra width parameter, wondering why... return getOrMakeExpr(se->left) - getOrMakeExpr(se->right); } case Expr::Mul: { MulExpr *me = cast<MulExpr>(e); // Again, we skip some optimizations from STPBuilder; just let the solver // do its own set of simplifications. return getOrMakeExpr(me->left) * getOrMakeExpr(me->right); } case Expr::UDiv: { UDivExpr *de = cast<UDivExpr>(e); return z3::udiv(getOrMakeExpr(de->left), getOrMakeExpr(de->right)); } case Expr::SDiv: { SDivExpr *de = cast<SDivExpr>(e); return getOrMakeExpr(de->left) / getOrMakeExpr(de->right); } case Expr::URem: { URemExpr *de = cast<URemExpr>(e); return z3::to_expr(context_, Z3_mk_bvurem(context_, getOrMakeExpr(de->left), getOrMakeExpr(de->right))); } case Expr::SRem: { SRemExpr *de = cast<SRemExpr>(e); // Assuming the sign follows dividend (otherwise we should have used // the Z3_mk_bvsmod() call) return z3::to_expr(context_, Z3_mk_bvsrem(context_, getOrMakeExpr(de->left), getOrMakeExpr(de->right))); } // Bitwise case Expr::Not: { NotExpr *ne = cast<NotExpr>(e); z3::expr expr = getOrMakeExpr(ne->expr); if (expr.is_bool()) { return !expr; } else { return ~expr; } } case Expr::And: { AndExpr *ae = cast<AndExpr>(e); z3::expr left = getOrMakeExpr(ae->left); z3::expr right = getOrMakeExpr(ae->right); if (left.is_bool()) { return left && right; } else { return left & right; } } case Expr::Or: { OrExpr *oe = cast<OrExpr>(e); z3::expr left = getOrMakeExpr(oe->left); z3::expr right = getOrMakeExpr(oe->right); if (left.is_bool()) { return left || right; } else { return left | right; } } case Expr::Xor: { XorExpr *xe = cast<XorExpr>(e); z3::expr left = getOrMakeExpr(xe->left); z3::expr right = getOrMakeExpr(xe->right); if (left.is_bool()) { return z3::to_expr(context_, Z3_mk_xor(context_, left, right)); } else { return left ^ right; } } case Expr::Shl: { ShlExpr *se = cast<ShlExpr>(e); return z3::to_expr(context_, Z3_mk_bvshl(context_, getOrMakeExpr(se->left), getOrMakeExpr(se->right))); } case Expr::LShr: { LShrExpr *lse = cast<LShrExpr>(e); return z3::to_expr(context_, Z3_mk_bvlshr(context_, getOrMakeExpr(lse->left), getOrMakeExpr(lse->right))); } case Expr::AShr: { AShrExpr *ase = cast<AShrExpr>(e); return z3::to_expr(context_, Z3_mk_bvashr(context_, getOrMakeExpr(ase->left), getOrMakeExpr(ase->right))); } // Comparison case Expr::Eq: { EqExpr *ee = cast<EqExpr>(e); return getOrMakeExpr(ee->left) == getOrMakeExpr(ee->right); } case Expr::Ult: { UltExpr *ue = cast<UltExpr>(e); return z3::ult(getOrMakeExpr(ue->left), getOrMakeExpr(ue->right)); } case Expr::Ule: { UleExpr *ue = cast<UleExpr>(e); return z3::ule(getOrMakeExpr(ue->left), getOrMakeExpr(ue->right)); } case Expr::Slt: { SltExpr *se = cast<SltExpr>(e); return getOrMakeExpr(se->left) < getOrMakeExpr(se->right); } case Expr::Sle: { SleExpr *se = cast<SleExpr>(e); return getOrMakeExpr(se->left) <= getOrMakeExpr(se->right); } // unused due to canonicalization #if 0 case Expr::Ne: case Expr::Ugt: case Expr::Uge: case Expr::Sgt: case Expr::Sge: #endif default: assert(0 && "unhandled Expr type"); } }
// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. // Search for all call sites to casted functions. // Check if they only differ in an argument type // Cast the argument, and call the original function // // 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 ArgCast::runOnModule(Module& M) { std::vector<CallInst*> worklist; for (Module::iterator I = M.begin(); I != M.end(); ++I) { if (I->mayBeOverridden()) continue; // Find all uses of this function for(Value::user_iterator ui = I->user_begin(), ue = I->user_end(); ui != ue; ) { // check if is ever casted to a different function type ConstantExpr *CE = dyn_cast<ConstantExpr>(*ui++); if(!CE) continue; if (CE->getOpcode() != Instruction::BitCast) continue; if(CE->getOperand(0) != I) continue; const PointerType *PTy = dyn_cast<PointerType>(CE->getType()); if (!PTy) continue; const Type *ETy = PTy->getElementType(); const FunctionType *FTy = dyn_cast<FunctionType>(ETy); if(!FTy) continue; // casting to a varargs funtion // or function with same number of arguments // possibly varying types of arguments if(FTy->getNumParams() != I->arg_size() && !FTy->isVarArg()) continue; for(Value::user_iterator uii = CE->user_begin(), uee = CE->user_end(); uii != uee; ++uii) { // Find all uses of the casted value, and check if it is // used in a Call Instruction if (CallInst* CI = dyn_cast<CallInst>(*uii)) { // Check that it is the called value, and not an argument if(CI->getCalledValue() != CE) continue; // Check that the number of arguments passed, and expected // by the function are the same. if(!I->isVarArg()) { if(CI->getNumOperands() != I->arg_size() + 1) continue; } else { if(CI->getNumOperands() < I->arg_size() + 1) continue; } // If so, add to worklist worklist.push_back(CI); } } } } // Proces the worklist of potential call sites to transform while(!worklist.empty()) { CallInst *CI = worklist.back(); worklist.pop_back(); // Get the called Function Function *F = cast<Function>(CI->getCalledValue()->stripPointerCasts()); const FunctionType *FTy = F->getFunctionType(); SmallVector<Value*, 8> Args; unsigned i =0; for(i =0; i< FTy->getNumParams(); ++i) { Type *ArgType = CI->getOperand(i+1)->getType(); Type *FormalType = FTy->getParamType(i); // If the types for this argument match, just add it to the // parameter list. No cast needs to be inserted. if(ArgType == FormalType) { Args.push_back(CI->getOperand(i+1)); } else if(ArgType->isPointerTy() && FormalType->isPointerTy()) { CastInst *CastI = CastInst::CreatePointerCast(CI->getOperand(i+1), FormalType, "", CI); Args.push_back(CastI); } else if (ArgType->isIntegerTy() && FormalType->isIntegerTy()) { unsigned SrcBits = ArgType->getScalarSizeInBits(); unsigned DstBits = FormalType->getScalarSizeInBits(); if(SrcBits > DstBits) { CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), FormalType, true, "", CI); Args.push_back(CastI); } else { if (F->getAttributes().hasAttribute(i+1, Attribute::SExt)) { CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), FormalType, true, "", CI); Args.push_back(CastI); } else if (F->getAttributes().hasAttribute(i+1, Attribute::ZExt)) { CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), FormalType, false, "", CI); Args.push_back(CastI); } else { // Use ZExt in default case. // Derived from InstCombine. Also, the only reason this should happen // is mismatched prototypes. // Seen in case of integer constants which get interpreted as i32, // even if being used as i64. // TODO: is this correct? CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1), FormalType, false, "", CI); Args.push_back(CastI); } } } else { DEBUG(ArgType->dump()); DEBUG(FormalType->dump()); break; } } // If we found an argument we could not cast, try the next instruction if(i != FTy->getNumParams()) { continue; } if(FTy->isVarArg()) { for(; i< CI->getNumOperands() - 1 ;i++) { Args.push_back(CI->getOperand(i+1)); } } // else replace the call instruction CallInst *CINew = CallInst::Create(F, Args, "", CI); CINew->setCallingConv(CI->getCallingConv()); CINew->setAttributes(CI->getAttributes()); if(!CI->use_empty()) { CastInst *RetCast; if(CI->getType() != CINew->getType()) { if(CI->getType()->isPointerTy() && CINew->getType()->isPointerTy()) RetCast = CastInst::CreatePointerCast(CINew, CI->getType(), "", CI); else if(CI->getType()->isIntOrIntVectorTy() && CINew->getType()->isIntOrIntVectorTy()) RetCast = CastInst::CreateIntegerCast(CINew, CI->getType(), false, "", CI); else if(CI->getType()->isIntOrIntVectorTy() && CINew->getType()->isPointerTy()) RetCast = CastInst::CreatePointerCast(CINew, CI->getType(), "", CI); else if(CI->getType()->isPointerTy() && CINew->getType()->isIntOrIntVectorTy()) RetCast = new IntToPtrInst(CINew, CI->getType(), "", CI); else { // TODO: I'm not sure what right behavior is here, but this case should be handled. llvm_unreachable("Unexpected type conversion in call!"); abort(); } CI->replaceAllUsesWith(RetCast); } else { CI->replaceAllUsesWith(CINew); } } // Debug printing DEBUG(errs() << "ARGCAST:"); DEBUG(errs() << "ERASE:"); DEBUG(CI->dump()); DEBUG(errs() << "ARGCAST:"); DEBUG(errs() << "ADDED:"); DEBUG(CINew->dump()); CI->eraseFromParent(); numChanged++; } return true; }
/** if *et_out==etBV then result is a bitvector, otherwise it is a bool */ ExprHandle STPBuilder::constructActual(ref<Expr> e, int *width_out, STPExprType *et_out) { int width; if (!width_out) width_out = &width; ++stats::queryConstructs; switch (e->getKind()) { case Expr::Constant: { ConstantExpr *CE = cast<ConstantExpr>(e); *width_out = CE->getWidth(); // Coerce to bool if necessary. if (*width_out == 1 && (*et_out == etBOOL || *et_out == etDontCare)) { *et_out = etBOOL; return CE->isTrue() ? getTrue() : getFalse(); } *et_out = etBV; // Fast path. if (*width_out <= 32) return bvConst32(*width_out, CE->getZExtValue(32)); if (*width_out <= 64) return bvConst64(*width_out, CE->getZExtValue()); ref<ConstantExpr> Tmp = CE; ExprHandle Res = bvConst64(64, Tmp->Extract(0, 64)->getZExtValue()); while (Tmp->getWidth() > 64) { Tmp = Tmp->Extract(64, Tmp->getWidth()-64); unsigned Width = std::min(64U, Tmp->getWidth()); Res = vc_bvConcatExpr(vc, bvConst64(Width, Tmp->Extract(0, Width)->getZExtValue()), Res); } return Res; } // Special case Expr::NotOptimized: { NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e); return construct(noe->src, width_out, et_out); } case Expr::Read: { ReadExpr *re = cast<ReadExpr>(e); *width_out = 8; *et_out = etBV; return vc_readExpr(vc, getArrayForUpdate(re->updates.root, re->updates.head), construct(re->index, 0, etBV)); } case Expr::Select: { SelectExpr *se = cast<SelectExpr>(e); ExprHandle cond = construct(se->cond, 0, etBOOL); ExprHandle tExpr = construct(se->trueExpr, width_out, etBV); ExprHandle fExpr = construct(se->falseExpr, width_out, etBV); *et_out = etBV; return vc_iteExpr(vc, cond, tExpr, fExpr); } case Expr::Concat: { ConcatExpr *ce = cast<ConcatExpr>(e); unsigned numKids = ce->getNumKids(); ExprHandle res = construct(ce->getKid(numKids-1), 0, etBV); for (int i=numKids-2; i>=0; i--) { res = vc_bvConcatExpr(vc, construct(ce->getKid(i), 0, etBV), res); } *width_out = ce->getWidth(); *et_out = etBV; return res; } case Expr::Extract: { ExtractExpr *ee = cast<ExtractExpr>(e); ExprHandle src = construct(ee->expr, width_out, etBV); *width_out = ee->getWidth(); *et_out = etBV; return vc_bvExtract(vc, src, ee->offset + *width_out - 1, ee->offset); } // Casting case Expr::ZExt: { int srcWidth; CastExpr *ce = cast<CastExpr>(e); STPExprType src_rt = etDontCare; ExprHandle src = construct(ce->src, &srcWidth, &src_rt); *width_out = ce->getWidth(); *et_out = etBV; if (src_rt==etBOOL) { return vc_iteExpr(vc, src, bvOne(*width_out), bvZero(*width_out)); } else { return vc_bvConcatExpr(vc, bvZero(*width_out-srcWidth), src); } } case Expr::SExt: { int srcWidth; CastExpr *ce = cast<CastExpr>(e); STPExprType src_rt = etDontCare; ExprHandle src = construct(ce->src, &srcWidth, &src_rt); *width_out = ce->getWidth(); *et_out = etBV; if (src_rt==etBOOL) { return vc_iteExpr(vc, src, bvMinusOne(*width_out), bvZero(*width_out)); } else { return vc_bvSignExtend(vc, src, *width_out); } } // Arithmetic case Expr::Add: { AddExpr *ae = cast<AddExpr>(e); ExprHandle left = construct(ae->left, width_out, etBV); ExprHandle right = construct(ae->right, width_out, etBV); assert(*width_out!=1 && "uncanonicalized add"); *et_out = etBV; return vc_bvPlusExpr(vc, *width_out, left, right); } case Expr::Sub: { SubExpr *se = cast<SubExpr>(e); ExprHandle left = construct(se->left, width_out, etBV); ExprHandle right = construct(se->right, width_out, etBV); assert(*width_out!=1 && "uncanonicalized sub"); *et_out = etBV; return vc_bvMinusExpr(vc, *width_out, left, right); } case Expr::Mul: { MulExpr *me = cast<MulExpr>(e); ExprHandle right = construct(me->right, width_out, etBV); assert(*width_out!=1 && "uncanonicalized mul"); *et_out = etBV; if (ConstantExpr *CE = dyn_cast<ConstantExpr>(me->left)) if (CE->getWidth() <= 64) return constructMulByConstant(right, *width_out, CE->getZExtValue()); ExprHandle left = construct(me->left, width_out, etBV); return vc_bvMultExpr(vc, *width_out, left, right); } case Expr::UDiv: { UDivExpr *de = cast<UDivExpr>(e); ExprHandle left = construct(de->left, width_out, etBV); assert(*width_out!=1 && "uncanonicalized udiv"); *et_out = etBV; if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) { if (CE->getWidth() <= 64) { uint64_t divisor = CE->getZExtValue(); if (bits64::isPowerOfTwo(divisor)) { return bvRightShift(left, bits64::indexOfSingleBit(divisor), getShiftBits(*width_out)); } else if (optimizeDivides) { if (*width_out == 32) //only works for 32-bit division return constructUDivByConstant( left, *width_out, (uint32_t) divisor); } } } ExprHandle right = construct(de->right, width_out, etBV); return vc_bvDivExpr(vc, *width_out, left, right); } case Expr::SDiv: { SDivExpr *de = cast<SDivExpr>(e); ExprHandle left = construct(de->left, width_out, etBV); assert(*width_out!=1 && "uncanonicalized sdiv"); *et_out = etBV; if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) if (optimizeDivides) if (*width_out == 32) //only works for 32-bit division return constructSDivByConstant( left, *width_out, CE->getZExtValue(32)); // XXX need to test for proper handling of sign, not sure I // trust STP ExprHandle right = construct(de->right, width_out, etBV); return vc_sbvDivExpr(vc, *width_out, left, right); } case Expr::URem: { URemExpr *de = cast<URemExpr>(e); ExprHandle left = construct(de->left, width_out, etBV); assert(*width_out!=1 && "uncanonicalized urem"); *et_out = etBV; if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) { if (CE->getWidth() <= 64) { uint64_t divisor = CE->getZExtValue(); if (bits64::isPowerOfTwo(divisor)) { unsigned bits = bits64::indexOfSingleBit(divisor); // special case for modding by 1 or else we bvExtract -1:0 if (bits == 0) { return bvZero(*width_out); } else { return vc_bvConcatExpr(vc, bvZero(*width_out - bits), bvExtract(left, bits - 1, 0)); } } // Use fast division to compute modulo without explicit division for // constant divisor. if (optimizeDivides) { if (*width_out == 32) { //only works for 32-bit division ExprHandle quotient = constructUDivByConstant( left, *width_out, (uint32_t)divisor ); ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor ); ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor ); return rem; } } } } ExprHandle right = construct(de->right, width_out, etBV); return vc_bvModExpr(vc, *width_out, left, right); } case Expr::SRem: { SRemExpr *de = cast<SRemExpr>(e); ExprHandle left = construct(de->left, width_out, etBV); ExprHandle right = construct(de->right, width_out, etBV); assert(*width_out!=1 && "uncanonicalized srem"); *et_out = etBV; #if 0 //not faster per first benchmark if (optimizeDivides) { if (ConstantExpr *cre = de->right->asConstant()) { uint64_t divisor = cre->asUInt64; //use fast division to compute modulo without explicit division for constant divisor if( *width_out == 32 ) { //only works for 32-bit division ExprHandle quotient = constructSDivByConstant( left, *width_out, divisor ); ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor ); ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor ); return rem; } } } #endif // XXX implement my fast path and test for proper handling of sign return vc_sbvModExpr(vc, *width_out, left, right); } // Bitwise case Expr::Not: { NotExpr *ne = cast<NotExpr>(e); ExprHandle expr = construct(ne->expr, width_out, et_out); if (*et_out == etBOOL) { return vc_notExpr(vc, expr); } else { return vc_bvNotExpr(vc, expr); } } case Expr::And: { AndExpr *ae = cast<AndExpr>(e); ExprHandle left = construct(ae->left, width_out, et_out); ExprHandle right = construct(ae->right, width_out, *et_out); if (*et_out == etBOOL) { return vc_andExpr(vc, left, right); } else { return vc_bvAndExpr(vc, left, right); } } case Expr::Or: { OrExpr *oe = cast<OrExpr>(e); ExprHandle left = construct(oe->left, width_out, et_out); ExprHandle right = construct(oe->right, width_out, *et_out); if (*et_out == etBOOL) { return vc_orExpr(vc, left, right); } else { return vc_bvOrExpr(vc, left, right); } } case Expr::Xor: { XorExpr *xe = cast<XorExpr>(e); ExprHandle left = construct(xe->left, width_out, et_out); ExprHandle right = construct(xe->right, width_out, *et_out); if (*et_out == etBOOL) { // XXX check for most efficient? return vc_iteExpr(vc, left, ExprHandle(vc_notExpr(vc, right)), right); } else { return vc_bvXorExpr(vc, left, right); } } case Expr::Shl: { ShlExpr *se = cast<ShlExpr>(e); ExprHandle left = construct(se->left, width_out, etBV); assert(*width_out!=1 && "uncanonicalized shl"); *et_out = etBV; if (ConstantExpr *CE = dyn_cast<ConstantExpr>(se->right)) { return bvLeftShift(left, (unsigned) CE->getLimitedValue(), getShiftBits(*width_out)); } else { int shiftWidth; ExprHandle amount = construct(se->right, &shiftWidth, etBV); return bvVarLeftShift( left, amount, *width_out ); } } case Expr::LShr: { LShrExpr *lse = cast<LShrExpr>(e); ExprHandle left = construct(lse->left, width_out, etBV); unsigned shiftBits = getShiftBits(*width_out); assert(*width_out!=1 && "uncanonicalized lshr"); *et_out = etBV; if (ConstantExpr *CE = dyn_cast<ConstantExpr>(lse->right)) { return bvRightShift(left, (unsigned) CE->getLimitedValue(), shiftBits); } else { int shiftWidth; ExprHandle amount = construct(lse->right, &shiftWidth, etBV); return bvVarRightShift( left, amount, *width_out ); } } case Expr::AShr: { AShrExpr *ase = cast<AShrExpr>(e); ExprHandle left = construct(ase->left, width_out, etBV); assert(*width_out!=1 && "uncanonicalized ashr"); *et_out = etBV; if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ase->right)) { unsigned shift = (unsigned) CE->getLimitedValue(); ExprHandle signedBool = bvBoolExtract(left, *width_out-1); return constructAShrByConstant(left, shift, signedBool, getShiftBits(*width_out)); } else { int shiftWidth; ExprHandle amount = construct(ase->right, &shiftWidth, etBV); return bvVarArithRightShift( left, amount, *width_out ); } } // Comparison case Expr::Eq: { EqExpr *ee = cast<EqExpr>(e); STPExprType src_rt = etDontCare; ExprHandle left = construct(ee->left, width_out, &src_rt); ExprHandle right = construct(ee->right, width_out, src_rt); *et_out = etBOOL; *width_out = 1; if (src_rt == etBOOL) { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left)) { if (CE->isTrue()) return right; return vc_notExpr(vc, right); } else { return vc_iffExpr(vc, left, right); } } else { return vc_eqExpr(vc, left, right); } } case Expr::Ult: { UltExpr *ue = cast<UltExpr>(e); ExprHandle left = construct(ue->left, width_out, etBV); ExprHandle right = construct(ue->right, width_out, etBV); assert(*width_out!=1 && "uncanonicalized ult"); *width_out = 1; *et_out = etBOOL; return vc_bvLtExpr(vc, left, right); } case Expr::Ule: { UleExpr *ue = cast<UleExpr>(e); ExprHandle left = construct(ue->left, width_out, etBV); ExprHandle right = construct(ue->right, width_out, etBV); assert(*width_out!=1 && "uncanonicalized ule"); *width_out = 1; *et_out = etBOOL; return vc_bvLeExpr(vc, left, right); } case Expr::Slt: { SltExpr *se = cast<SltExpr>(e); ExprHandle left = construct(se->left, width_out, etBV); ExprHandle right = construct(se->right, width_out, etBV); assert(*width_out!=1 && "uncanonicalized slt"); *width_out = 1; *et_out = etBOOL; return vc_sbvLtExpr(vc, left, right); } case Expr::Sle: { SleExpr *se = cast<SleExpr>(e); ExprHandle left = construct(se->left, width_out, etBV); ExprHandle right = construct(se->right, width_out, etBV); assert(*width_out!=1 && "uncanonicalized sle"); *width_out = 1; *et_out = etBOOL; return vc_sbvLeExpr(vc, left, right); } // unused due to canonicalization #if 0 case Expr::Ne: case Expr::Ugt: case Expr::Uge: case Expr::Sgt: case Expr::Sge: #endif case Expr::FPToSI: case Expr::FPToUI: { if (UseFPToIAbstraction) { std::ostringstream ss; ss << "FPtoI" << fpCount++; *width_out = e->getWidth(); *et_out = etBV; return buildVar(ss.str().c_str(), e->getWidth()); } else { F2IConvertExpr *ce = cast<F2IConvertExpr>(e); ref<Expr> res = floatUtils(ce->src, ce->roundNearest() ? ieee_floatt::ROUND_TO_EVEN : ieee_floatt::ROUND_TO_ZERO).to_integer(ce->src, ce->getWidth(), e->getKind() == Expr::FPToSI); return constructActual(res, width_out, et_out); } } case Expr::UIToFP: { UIToFPExpr *ue = cast<UIToFPExpr>(e); ref<Expr> res = floatUtils(e).from_unsigned_integer(ue->src); return constructActual(res, width_out, et_out); } case Expr::SIToFP: { SIToFPExpr *se = cast<SIToFPExpr>(e); ref<Expr> res = floatUtils(e).from_signed_integer(se->src); return constructActual(res, width_out, et_out); } case Expr::FCmp: { FCmpExpr *ce = cast<FCmpExpr>(e); float_utilst &u = floatUtils(ce->left); ref<Expr> res; switch (ce->getPredicate()) { case FCmpExpr::OEQ: res = u.relation(ce->left, float_utilst::EQ, ce->right); break; case FCmpExpr::OGT: res = u.relation(ce->left, float_utilst::GT, ce->right); break; case FCmpExpr::OGE: res = u.relation(ce->left, float_utilst::GE, ce->right); break; case FCmpExpr::OLT: res = u.relation(ce->left, float_utilst::LT, ce->right); break; case FCmpExpr::OLE: res = u.relation(ce->left, float_utilst::LE, ce->right); break; case FCmpExpr::ONE: res = OrExpr::create(u.relation(ce->left, float_utilst::LT, ce->right), u.relation(ce->left, float_utilst::GT, ce->right)); break; case FCmpExpr::ORD: res = Expr::createIsZero(OrExpr::create(u.is_NaN(ce->left), u.is_NaN(ce->right))); break; case FCmpExpr::UNO: res = OrExpr::create(u.is_NaN(ce->left), u.is_NaN(ce->right)); break; case FCmpExpr::UEQ: res = Expr::createIsZero( OrExpr::create(u.relation(ce->left, float_utilst::LT, ce->right), u.relation(ce->left, float_utilst::GT, ce->right))); break; case FCmpExpr::UGT: res = Expr::createIsZero( u.relation(ce->left, float_utilst::LE, ce->right)); break; case FCmpExpr::UGE: res = Expr::createIsZero( u.relation(ce->left, float_utilst::LT, ce->right)); break; case FCmpExpr::ULT: res = Expr::createIsZero( u.relation(ce->left, float_utilst::GE, ce->right)); break; case FCmpExpr::ULE: res = Expr::createIsZero( u.relation(ce->left, float_utilst::GT, ce->right)); break; case FCmpExpr::UNE: res = Expr::createIsZero( u.relation(ce->left, float_utilst::EQ, ce->right)); break; default: assert(0 && "fp cmp not implemented yet"); } return constructActual(res, width_out, et_out); } case Expr::FPExt: case Expr::FPTrunc: { F2FConvertExpr *ce = cast<F2FConvertExpr>(e); float_utilst &fromu = floatUtils(ce->src), &tou = floatUtils(ce); ref<Expr> res = fromu.conversion(ce->src, tou.spec); return constructActual(res, width_out, et_out); } case Expr::FAdd: { FAddExpr *ae = cast<FAddExpr>(e); ref<Expr> res = floatUtils(e).add(ae->left, ae->right); return constructActual(res, width_out, et_out); } case Expr::FSub: { FSubExpr *se = cast<FSubExpr>(e); ref<Expr> res = floatUtils(e).sub(se->left, se->right); return constructActual(res, width_out, et_out); } case Expr::FMul: { FMulExpr *me = cast<FMulExpr>(e); ref<Expr> res = floatUtils(e).mul(me->left, me->right); return constructActual(res, width_out, et_out); } case Expr::FDiv: { FDivExpr *de = cast<FDivExpr>(e); ref<Expr> res = floatUtils(e).div(de->left, de->right); return constructActual(res, width_out, et_out); } default: assert(0 && "unhandled Expr type"); *et_out = etBOOL; return vc_trueExpr(vc); } }
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); }
virtual bool runOnFunction(Function &F) { //F.dump(); bool changed = false; for (inst_iterator inst_it = inst_begin(F), _inst_end = inst_end(F); inst_it != _inst_end; ++inst_it) { LoadInst *li = dyn_cast<LoadInst>(&*inst_it); if (!li) continue; ConstantExpr *ce = dyn_cast<ConstantExpr>(li->getOperand(0)); // Not 100% sure what the isGEPWithNoNotionalOverIndexing() means, but // at least it checks if it's a gep: if (ce && ce->isGEPWithNoNotionalOverIndexing() && ce->getOperand(0)->getType() == g.llvm_flavor_type_ptr) { changed = handleFlavor(li, ce); } GlobalVariable *gv = dyn_cast<GlobalVariable>(li->getOperand(0)); if (!gv) continue; llvm::Type* gv_t = gv->getType(); if (gv_t == g.llvm_bool_type_ptr->getPointerTo()) { changed = handleBool(li, gv) || changed; continue; } if (gv_t == g.llvm_class_type_ptr->getPointerTo()) { changed = handleCls(li, gv) || changed; continue; } } return changed; }