예제 #1
0
/// 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;

}
예제 #3
0
/// 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;
}