Fix all of last night's JIT failures in Prolangs-C++ by finishing the
implementation of getConstantValue(). llvm-svn: 34988
This commit is contained in:
parent
5ed781b0db
commit
4fd528f213
|
@ -302,82 +302,191 @@ void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) {
|
||||||
/// part is if C is a ConstantExpr.
|
/// part is if C is a ConstantExpr.
|
||||||
/// @brief Get a GenericValue for a Constnat*
|
/// @brief Get a GenericValue for a Constnat*
|
||||||
GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
|
GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
|
||||||
// Declare the result as garbage.
|
|
||||||
GenericValue Result;
|
|
||||||
|
|
||||||
// If its undefined, return the garbage.
|
// If its undefined, return the garbage.
|
||||||
if (isa<UndefValue>(C)) return Result;
|
if (isa<UndefValue>(C))
|
||||||
|
return GenericValue();
|
||||||
|
|
||||||
// If the value is a ConstantExpr
|
// If the value is a ConstantExpr
|
||||||
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
|
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
|
||||||
|
Constant *Op0 = CE->getOperand(0);
|
||||||
switch (CE->getOpcode()) {
|
switch (CE->getOpcode()) {
|
||||||
case Instruction::GetElementPtr: {
|
case Instruction::GetElementPtr: {
|
||||||
// Compute the index
|
// Compute the index
|
||||||
Result = getConstantValue(CE->getOperand(0));
|
GenericValue Result = getConstantValue(Op0);
|
||||||
SmallVector<Value*, 8> Indices(CE->op_begin()+1, CE->op_end());
|
SmallVector<Value*, 8> Indices(CE->op_begin()+1, CE->op_end());
|
||||||
uint64_t Offset =
|
uint64_t Offset =
|
||||||
TD->getIndexedOffset(CE->getOperand(0)->getType(),
|
TD->getIndexedOffset(Op0->getType(), &Indices[0], Indices.size());
|
||||||
&Indices[0], Indices.size());
|
|
||||||
|
|
||||||
char* tmp = (char*) Result.PointerVal;
|
char* tmp = (char*) Result.PointerVal;
|
||||||
Result = PTOGV(tmp + Offset);
|
Result = PTOGV(tmp + Offset);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
case Instruction::Trunc:
|
case Instruction::Trunc: {
|
||||||
case Instruction::ZExt:
|
GenericValue GV = getConstantValue(Op0);
|
||||||
case Instruction::SExt:
|
uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth();
|
||||||
case Instruction::FPTrunc:
|
GV.IntVal = GV.IntVal.trunc(BitWidth);
|
||||||
case Instruction::FPExt:
|
return GV;
|
||||||
case Instruction::UIToFP:
|
}
|
||||||
case Instruction::SIToFP:
|
case Instruction::ZExt: {
|
||||||
case Instruction::FPToUI:
|
GenericValue GV = getConstantValue(Op0);
|
||||||
case Instruction::FPToSI:
|
uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth();
|
||||||
break;
|
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: {
|
||||||
|
GenericValue GV = getConstantValue(Op0);
|
||||||
|
GV.FloatVal = float(GV.DoubleVal);
|
||||||
|
return GV;
|
||||||
|
}
|
||||||
|
case Instruction::FPExt:{
|
||||||
|
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
|
||||||
|
GV.DoubleVal = GV.IntVal.roundToDouble();
|
||||||
|
return GV;
|
||||||
|
}
|
||||||
|
case Instruction::SIToFP: {
|
||||||
|
GenericValue GV = getConstantValue(Op0);
|
||||||
|
if (CE->getType() == Type::FloatTy)
|
||||||
|
GV.FloatVal = float(GV.IntVal.signedRoundToDouble());
|
||||||
|
else
|
||||||
|
GV.DoubleVal = GV.IntVal.signedRoundToDouble();
|
||||||
|
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
|
||||||
|
GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth);
|
||||||
|
return GV;
|
||||||
|
}
|
||||||
case Instruction::PtrToInt: {
|
case Instruction::PtrToInt: {
|
||||||
Constant *Op = CE->getOperand(0);
|
GenericValue GV = getConstantValue(Op0);
|
||||||
GenericValue GV = getConstantValue(Op);
|
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;
|
return GV;
|
||||||
}
|
}
|
||||||
case Instruction::BitCast: {
|
case Instruction::BitCast: {
|
||||||
// Bit casts are no-ops but we can only return the GV of the operand if
|
GenericValue GV = getConstantValue(Op0);
|
||||||
// they are the same basic type (pointer->pointer, packed->packed, etc.)
|
const Type* DestTy = CE->getType();
|
||||||
Constant *Op = CE->getOperand(0);
|
switch (Op0->getType()->getTypeID()) {
|
||||||
GenericValue GV = getConstantValue(Op);
|
default: assert(0 && "Invalid bitcast operand");
|
||||||
if (Op->getType()->getTypeID() == C->getType()->getTypeID())
|
case Type::IntegerTyID:
|
||||||
return GV;
|
assert(DestTy->isFloatingPoint() && "invalid bitcast");
|
||||||
break;
|
if (DestTy == Type::FloatTy)
|
||||||
}
|
GV.FloatVal = GV.IntVal.bitsToFloat();
|
||||||
case Instruction::IntToPtr: {
|
else if (DestTy == Type::DoubleTy)
|
||||||
// IntToPtr casts are just so special. Cast to intptr_t first.
|
GV.DoubleVal = GV.IntVal.bitsToDouble();
|
||||||
Constant *Op = CE->getOperand(0);
|
break;
|
||||||
GenericValue GV = getConstantValue(Op);
|
case Type::FloatTyID:
|
||||||
return PTOGV((void*)(uintptr_t)GV.IntVal.getZExtValue());
|
assert(DestTy == Type::Int32Ty && "Invalid bitcast");
|
||||||
break;
|
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::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()) {
|
switch (CE->getOperand(0)->getType()->getTypeID()) {
|
||||||
default: assert(0 && "Bad add type!"); abort();
|
default: assert(0 && "Bad add type!"); abort();
|
||||||
case Type::IntegerTyID:
|
case Type::IntegerTyID:
|
||||||
Result.IntVal = getConstantValue(CE->getOperand(0)).IntVal + \
|
switch (CE->getOpcode()) {
|
||||||
getConstantValue(CE->getOperand(1)).IntVal;
|
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;
|
break;
|
||||||
case Type::FloatTyID:
|
case Type::FloatTyID:
|
||||||
Result.FloatVal = getConstantValue(CE->getOperand(0)).FloatVal +
|
switch (CE->getOpcode()) {
|
||||||
getConstantValue(CE->getOperand(1)).FloatVal;
|
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;
|
break;
|
||||||
case Type::DoubleTyID:
|
case Type::DoubleTyID:
|
||||||
Result.DoubleVal = getConstantValue(CE->getOperand(0)).DoubleVal +
|
switch (CE->getOpcode()) {
|
||||||
getConstantValue(CE->getOperand(1)).DoubleVal;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
return Result;
|
return GV;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cerr << "ConstantExpr not handled as global var init: " << *CE << "\n";
|
cerr << "ConstantExpr not handled: " << *CE << "\n";
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GenericValue Result;
|
||||||
switch (C->getType()->getTypeID()) {
|
switch (C->getType()->getTypeID()) {
|
||||||
case Type::FloatTyID:
|
case Type::FloatTyID:
|
||||||
Result.FloatVal = (float)cast<ConstantFP>(C)->getValue();
|
Result.FloatVal = (float)cast<ConstantFP>(C)->getValue();
|
||||||
|
@ -399,7 +508,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
|
||||||
assert(0 && "Unknown constant pointer type!");
|
assert(0 && "Unknown constant pointer type!");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cerr << "ERROR: Constant unimp for type: " << *C->getType() << "\n";
|
cerr << "ERROR: Constant unimplemented for type: " << *C->getType() << "\n";
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
|
|
Loading…
Reference in New Issue