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:
Reid Spencer 2007-03-06 22:23:15 +00:00
parent 5ed781b0db
commit 4fd528f213
1 changed files with 151 additions and 42 deletions

View File

@ -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;