/// ConvertToSInt - Convert APF to an integer, if possible. static bool ConvertToSInt(const APFloat &APF, int64_t &IntVal) { bool isExact = false; if (&APF.getSemantics() == &APFloat::PPCDoubleDouble) return false; // See if we can convert this to an int64_t uint64_t UIntVal; if (APF.convertToInteger(&UIntVal, 64, true, APFloat::rmTowardZero, &isExact) != APFloat::opOK || !isExact) return false; IntVal = UIntVal; return true; }
/// convertToInt - Convert APF to an integer, if possible. static bool convertToInt(const APFloat &APF, uint64_t *intVal) { bool isExact = false; if (&APF.getSemantics() == &APFloat::PPCDoubleDouble) return false; if (APF.convertToInteger(intVal, 32, APF.isNegative(), APFloat::rmTowardZero, &isExact) != APFloat::opOK) return false; if (!isExact) return false; return true; }
/// This function converts a Constant* into a GenericValue. The interesting /// part is if C is a ConstantExpr. /// @brief Get a GenericValue for a Constant* GenericValue ExecutionEngine::getConstantValue(const Constant *C) { // If its undefined, return the garbage. if (isa<UndefValue>(C)) return GenericValue(); // If the value is a ConstantExpr if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { Constant *Op0 = CE->getOperand(0); switch (CE->getOpcode()) { case Instruction::GetElementPtr: { // Compute the index GenericValue Result = getConstantValue(Op0); SmallVector<Value*, 8> Indices(CE->op_begin()+1, CE->op_end()); uint64_t Offset = TD->getIndexedOffset(Op0->getType(), &Indices[0], Indices.size()); char* tmp = (char*) Result.PointerVal; Result = PTOGV(tmp + Offset); return Result; } case Instruction::Trunc: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); GV.IntVal = GV.IntVal.trunc(BitWidth); return GV; } case Instruction::ZExt: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); GV.IntVal = GV.IntVal.zext(BitWidth); return GV; } case Instruction::SExt: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); GV.IntVal = GV.IntVal.sext(BitWidth); return GV; } case Instruction::FPTrunc: { // FIXME long double GenericValue GV = getConstantValue(Op0); GV.FloatVal = float(GV.DoubleVal); return GV; } case Instruction::FPExt:{ // FIXME long double GenericValue GV = getConstantValue(Op0); GV.DoubleVal = double(GV.FloatVal); return GV; } case Instruction::UIToFP: { GenericValue GV = getConstantValue(Op0); if (CE->getType() == Type::FloatTy) GV.FloatVal = float(GV.IntVal.roundToDouble()); else if (CE->getType() == Type::DoubleTy) GV.DoubleVal = GV.IntVal.roundToDouble(); else if (CE->getType() == Type::X86_FP80Ty) { const uint64_t zero[] = {0, 0}; APFloat apf = APFloat(APInt(80, 2, zero)); (void)apf.convertFromAPInt(GV.IntVal, false, APFloat::rmNearestTiesToEven); GV.IntVal = apf.bitcastToAPInt(); } return GV; } case Instruction::SIToFP: { GenericValue GV = getConstantValue(Op0); if (CE->getType() == Type::FloatTy) GV.FloatVal = float(GV.IntVal.signedRoundToDouble()); else if (CE->getType() == Type::DoubleTy) GV.DoubleVal = GV.IntVal.signedRoundToDouble(); else if (CE->getType() == Type::X86_FP80Ty) { const uint64_t zero[] = { 0, 0}; APFloat apf = APFloat(APInt(80, 2, zero)); (void)apf.convertFromAPInt(GV.IntVal, true, APFloat::rmNearestTiesToEven); GV.IntVal = apf.bitcastToAPInt(); } return GV; } case Instruction::FPToUI: // double->APInt conversion handles sign case Instruction::FPToSI: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); if (Op0->getType() == Type::FloatTy) GV.IntVal = APIntOps::RoundFloatToAPInt(GV.FloatVal, BitWidth); else if (Op0->getType() == Type::DoubleTy) GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth); else if (Op0->getType() == Type::X86_FP80Ty) { APFloat apf = APFloat(GV.IntVal); uint64_t v; bool ignored; (void)apf.convertToInteger(&v, BitWidth, CE->getOpcode()==Instruction::FPToSI, APFloat::rmTowardZero, &ignored); GV.IntVal = v; // endian? } return GV; } case Instruction::PtrToInt: { GenericValue GV = getConstantValue(Op0); uint32_t PtrWidth = TD->getPointerSizeInBits(); GV.IntVal = APInt(PtrWidth, uintptr_t(GV.PointerVal)); return GV; } case Instruction::IntToPtr: { GenericValue GV = getConstantValue(Op0); uint32_t PtrWidth = TD->getPointerSizeInBits(); if (PtrWidth != GV.IntVal.getBitWidth()) GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth); assert(GV.IntVal.getBitWidth() <= 64 && "Bad pointer width"); GV.PointerVal = PointerTy(uintptr_t(GV.IntVal.getZExtValue())); return GV; } case Instruction::BitCast: { GenericValue GV = getConstantValue(Op0); const Type* DestTy = CE->getType(); switch (Op0->getType()->getTypeID()) { default: assert(0 && "Invalid bitcast operand"); case Type::IntegerTyID: assert(DestTy->isFloatingPoint() && "invalid bitcast"); if (DestTy == Type::FloatTy) GV.FloatVal = GV.IntVal.bitsToFloat(); else if (DestTy == Type::DoubleTy) GV.DoubleVal = GV.IntVal.bitsToDouble(); break; case Type::FloatTyID: assert(DestTy == Type::Int32Ty && "Invalid bitcast"); GV.IntVal.floatToBits(GV.FloatVal); break; case Type::DoubleTyID: assert(DestTy == Type::Int64Ty && "Invalid bitcast"); GV.IntVal.doubleToBits(GV.DoubleVal); break; case Type::PointerTyID: assert(isa<PointerType>(DestTy) && "Invalid bitcast"); break; // getConstantValue(Op0) above already converted it } return GV; } case Instruction::Add: case Instruction::Sub: case Instruction::Mul: case Instruction::UDiv: case Instruction::SDiv: case Instruction::URem: case Instruction::SRem: case Instruction::And: case Instruction::Or: case Instruction::Xor: { GenericValue LHS = getConstantValue(Op0); GenericValue RHS = getConstantValue(CE->getOperand(1)); GenericValue GV; switch (CE->getOperand(0)->getType()->getTypeID()) { default: assert(0 && "Bad add type!"); abort(); case Type::IntegerTyID: switch (CE->getOpcode()) { default: assert(0 && "Invalid integer opcode"); case Instruction::Add: GV.IntVal = LHS.IntVal + RHS.IntVal; break; case Instruction::Sub: GV.IntVal = LHS.IntVal - RHS.IntVal; break; case Instruction::Mul: GV.IntVal = LHS.IntVal * RHS.IntVal; break; case Instruction::UDiv:GV.IntVal = LHS.IntVal.udiv(RHS.IntVal); break; case Instruction::SDiv:GV.IntVal = LHS.IntVal.sdiv(RHS.IntVal); break; case Instruction::URem:GV.IntVal = LHS.IntVal.urem(RHS.IntVal); break; case Instruction::SRem:GV.IntVal = LHS.IntVal.srem(RHS.IntVal); break; case Instruction::And: GV.IntVal = LHS.IntVal & RHS.IntVal; break; case Instruction::Or: GV.IntVal = LHS.IntVal | RHS.IntVal; break; case Instruction::Xor: GV.IntVal = LHS.IntVal ^ RHS.IntVal; break; } break; case Type::FloatTyID: switch (CE->getOpcode()) { default: assert(0 && "Invalid float opcode"); abort(); case Instruction::Add: GV.FloatVal = LHS.FloatVal + RHS.FloatVal; break; case Instruction::Sub: GV.FloatVal = LHS.FloatVal - RHS.FloatVal; break; case Instruction::Mul: GV.FloatVal = LHS.FloatVal * RHS.FloatVal; break; case Instruction::FDiv: GV.FloatVal = LHS.FloatVal / RHS.FloatVal; break; case Instruction::FRem: GV.FloatVal = ::fmodf(LHS.FloatVal,RHS.FloatVal); break; } break; case Type::DoubleTyID: switch (CE->getOpcode()) { default: assert(0 && "Invalid double opcode"); abort(); case Instruction::Add: GV.DoubleVal = LHS.DoubleVal + RHS.DoubleVal; break; case Instruction::Sub: GV.DoubleVal = LHS.DoubleVal - RHS.DoubleVal; break; case Instruction::Mul: GV.DoubleVal = LHS.DoubleVal * RHS.DoubleVal; break; case Instruction::FDiv: GV.DoubleVal = LHS.DoubleVal / RHS.DoubleVal; break; case Instruction::FRem: GV.DoubleVal = ::fmod(LHS.DoubleVal,RHS.DoubleVal); break; } break; case Type::X86_FP80TyID: case Type::PPC_FP128TyID: case Type::FP128TyID: { APFloat apfLHS = APFloat(LHS.IntVal); switch (CE->getOpcode()) { default: assert(0 && "Invalid long double opcode"); abort(); case Instruction::Add: apfLHS.add(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::Sub: apfLHS.subtract(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::Mul: apfLHS.multiply(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::FDiv: apfLHS.divide(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::FRem: apfLHS.mod(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; } } break; } return GV; } default: break; } cerr << "ConstantExpr not handled: " << *CE << "\n"; abort(); } GenericValue Result; switch (C->getType()->getTypeID()) { case Type::FloatTyID: Result.FloatVal = cast<ConstantFP>(C)->getValueAPF().convertToFloat(); break; case Type::DoubleTyID: Result.DoubleVal = cast<ConstantFP>(C)->getValueAPF().convertToDouble(); break; case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: Result.IntVal = cast <ConstantFP>(C)->getValueAPF().bitcastToAPInt(); break; case Type::IntegerTyID: Result.IntVal = cast<ConstantInt>(C)->getValue(); break; case Type::PointerTyID: if (isa<ConstantPointerNull>(C)) Result.PointerVal = 0; else if (const Function *F = dyn_cast<Function>(C)) Result = PTOGV(getPointerToFunctionOrStub(const_cast<Function*>(F))); else if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(C)) Result = PTOGV(getOrEmitGlobalVariable(const_cast<GlobalVariable*>(GV))); else assert(0 && "Unknown constant pointer type!"); break; default: cerr << "ERROR: Constant unimplemented for type: " << *C->getType() << "\n"; abort(); } return Result; }