refactor scalar conversions out into CGExprScalar.cpp
llvm-svn: 41433
This commit is contained in:
parent
e026ebd6fe
commit
3474c202ab
|
@ -57,65 +57,9 @@ RValue CodeGenFunction::EmitConversion(RValue Val, QualType ValTy,
|
|||
if (DestBT->getKind() == BuiltinType::Bool)
|
||||
return RValue::get(ConvertScalarValueToBool(Val, ValTy));
|
||||
|
||||
// Handle pointer conversions next: pointers can only be converted to/from
|
||||
// other pointers and integers.
|
||||
if (isa<PointerType>(DstTy)) {
|
||||
const llvm::Type *DestTy = ConvertType(DstTy);
|
||||
|
||||
if (Val.getVal()->getType() == DestTy)
|
||||
return Val;
|
||||
|
||||
// The source value may be an integer, or a pointer.
|
||||
assert(Val.isScalar() && "Can only convert from integer or pointer");
|
||||
if (isa<llvm::PointerType>(Val.getVal()->getType()))
|
||||
return RValue::get(Builder.CreateBitCast(Val.getVal(), DestTy, "conv"));
|
||||
assert(ValTy->isIntegerType() && "Not ptr->ptr or int->ptr conversion?");
|
||||
return RValue::get(Builder.CreateIntToPtr(Val.getVal(), DestTy, "conv"));
|
||||
}
|
||||
if (Val.isScalar() && !hasAggregateLLVMType(DstTy))
|
||||
return RValue::get(EmitScalarConversion(Val.getVal(), ValTy, DstTy));
|
||||
|
||||
if (isa<PointerType>(ValTy)) {
|
||||
// Must be an ptr to int cast.
|
||||
const llvm::Type *DestTy = ConvertType(DstTy);
|
||||
assert(isa<llvm::IntegerType>(DestTy) && "not ptr->int?");
|
||||
return RValue::get(Builder.CreateIntToPtr(Val.getVal(), DestTy, "conv"));
|
||||
}
|
||||
|
||||
// Finally, we have the arithmetic types: real int/float and complex
|
||||
// int/float. Handle real->real conversions first, they are the most
|
||||
// common.
|
||||
if (Val.isScalar() && DstTy->isRealType()) {
|
||||
// We know that these are representable as scalars in LLVM, convert to LLVM
|
||||
// types since they are easier to reason about.
|
||||
llvm::Value *SrcVal = Val.getVal();
|
||||
const llvm::Type *DestTy = ConvertType(DstTy);
|
||||
if (SrcVal->getType() == DestTy) return Val;
|
||||
|
||||
llvm::Value *Result;
|
||||
if (isa<llvm::IntegerType>(SrcVal->getType())) {
|
||||
bool InputSigned = ValTy->isSignedIntegerType();
|
||||
if (isa<llvm::IntegerType>(DestTy))
|
||||
Result = Builder.CreateIntCast(SrcVal, DestTy, InputSigned, "conv");
|
||||
else if (InputSigned)
|
||||
Result = Builder.CreateSIToFP(SrcVal, DestTy, "conv");
|
||||
else
|
||||
Result = Builder.CreateUIToFP(SrcVal, DestTy, "conv");
|
||||
} else {
|
||||
assert(SrcVal->getType()->isFloatingPoint() && "Unknown real conversion");
|
||||
if (isa<llvm::IntegerType>(DestTy)) {
|
||||
if (DstTy->isSignedIntegerType())
|
||||
Result = Builder.CreateFPToSI(SrcVal, DestTy, "conv");
|
||||
else
|
||||
Result = Builder.CreateFPToUI(SrcVal, DestTy, "conv");
|
||||
} else {
|
||||
assert(DestTy->isFloatingPoint() && "Unknown real conversion");
|
||||
if (DestTy->getTypeID() < SrcVal->getType()->getTypeID())
|
||||
Result = Builder.CreateFPTrunc(SrcVal, DestTy, "conv");
|
||||
else
|
||||
Result = Builder.CreateFPExt(SrcVal, DestTy, "conv");
|
||||
}
|
||||
}
|
||||
return RValue::get(Result);
|
||||
}
|
||||
|
||||
assert(0 && "FIXME: We don't support complex conversions yet!");
|
||||
}
|
||||
|
|
|
@ -203,10 +203,8 @@ ComplexPairTy ComplexExprEmitter::EmitCast(Expr *Op, QualType DestTy) {
|
|||
// rules for the corresponding real types.
|
||||
ComplexPairTy Res = Visit(Op);
|
||||
QualType SrcEltTy = CT->getElementType();
|
||||
Res.first = CGF.EmitConversion(RValue::get(Res.first), SrcEltTy,
|
||||
DestTy).getVal();
|
||||
Res.second = CGF.EmitConversion(RValue::get(Res.second), SrcEltTy,
|
||||
DestTy).getVal();
|
||||
Res.first = CGF.EmitScalarConversion(Res.first, SrcEltTy, DestTy);
|
||||
Res.second = CGF.EmitScalarConversion(Res.second, SrcEltTy, DestTy);
|
||||
return Res;
|
||||
}
|
||||
// C99 6.3.1.7: When a value of real type is converted to a complex type, the
|
||||
|
@ -216,7 +214,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(Expr *Op, QualType DestTy) {
|
|||
llvm::Value *Elt = CGF.EmitScalarExpr(Op);
|
||||
|
||||
// Convert the input element to the element type of the complex.
|
||||
Elt = CGF.EmitConversion(RValue::get(Elt), Op->getType(), DestTy).getVal();
|
||||
Elt = CGF.EmitScalarConversion(Elt, Op->getType(), DestTy);
|
||||
|
||||
// Return (realval, 0).
|
||||
return ComplexPairTy(Elt, llvm::Constant::getNullValue(Elt->getType()));
|
||||
|
|
|
@ -62,6 +62,12 @@ public:
|
|||
return EmitLoadOfLValue(EmitLValue(E), E->getType());
|
||||
}
|
||||
|
||||
/// EmitScalarConversion - Emit a conversion from the specified type to the
|
||||
/// specified destination type, both of which are LLVM scalar types.
|
||||
llvm::Value *EmitScalarConversion(llvm::Value *Src, QualType SrcTy,
|
||||
QualType DstTy);
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Visitor Methods
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -237,6 +243,68 @@ public:
|
|||
// Utilities
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// EmitScalarConversion - Emit a conversion from the specified type to the
|
||||
/// specified destination type, both of which are LLVM scalar types.
|
||||
llvm::Value *ScalarExprEmitter::EmitScalarConversion(llvm::Value *Src,
|
||||
QualType SrcType,
|
||||
QualType DstType) {
|
||||
SrcType = SrcType.getCanonicalType();
|
||||
DstType = DstType.getCanonicalType();
|
||||
if (SrcType == DstType) return Src;
|
||||
|
||||
// Handle conversions to bool first, they are special: comparisons against 0.
|
||||
if (const BuiltinType *DestBT = dyn_cast<BuiltinType>(DstType))
|
||||
if (DestBT->getKind() == BuiltinType::Bool)
|
||||
return CGF.ConvertScalarValueToBool(RValue::get(Src), SrcType);
|
||||
|
||||
const llvm::Type *DstTy = ConvertType(DstType);
|
||||
|
||||
// Ignore conversions like int -> uint.
|
||||
if (Src->getType() == DstTy)
|
||||
return Src;
|
||||
|
||||
// Handle pointer conversions next: pointers can only be converted to/from
|
||||
// other pointers and integers.
|
||||
if (isa<PointerType>(DstType)) {
|
||||
// The source value may be an integer, or a pointer.
|
||||
if (isa<llvm::PointerType>(Src->getType()))
|
||||
return Builder.CreateBitCast(Src, DstTy, "conv");
|
||||
assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?");
|
||||
return Builder.CreateIntToPtr(Src, DstTy, "conv");
|
||||
}
|
||||
|
||||
if (isa<PointerType>(SrcType)) {
|
||||
// Must be an ptr to int cast.
|
||||
assert(isa<llvm::IntegerType>(DstTy) && "not ptr->int?");
|
||||
return Builder.CreateIntToPtr(Src, DstTy, "conv");
|
||||
}
|
||||
|
||||
// Finally, we have the arithmetic types: real int/float.
|
||||
if (isa<llvm::IntegerType>(Src->getType())) {
|
||||
bool InputSigned = SrcType->isSignedIntegerType();
|
||||
if (isa<llvm::IntegerType>(DstTy))
|
||||
return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
|
||||
else if (InputSigned)
|
||||
return Builder.CreateSIToFP(Src, DstTy, "conv");
|
||||
else
|
||||
return Builder.CreateUIToFP(Src, DstTy, "conv");
|
||||
}
|
||||
|
||||
assert(Src->getType()->isFloatingPoint() && "Unknown real conversion");
|
||||
if (isa<llvm::IntegerType>(DstTy)) {
|
||||
if (DstType->isSignedIntegerType())
|
||||
return Builder.CreateFPToSI(Src, DstTy, "conv");
|
||||
else
|
||||
return Builder.CreateFPToUI(Src, DstTy, "conv");
|
||||
}
|
||||
|
||||
assert(DstTy->isFloatingPoint() && "Unknown real conversion");
|
||||
if (DstTy->getTypeID() < Src->getType()->getTypeID())
|
||||
return Builder.CreateFPTrunc(Src, DstTy, "conv");
|
||||
else
|
||||
return Builder.CreateFPExt(Src, DstTy, "conv");
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Visitor Methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -295,11 +363,21 @@ Value *ScalarExprEmitter::VisitImplicitCastExpr(const ImplicitCastExpr *E) {
|
|||
// have to handle a more broad range of conversions than explicit casts, as they
|
||||
// handle things like function to ptr-to-function decay etc.
|
||||
Value *ScalarExprEmitter::EmitCastExpr(const Expr *E, QualType DestTy) {
|
||||
// Handle cases where the source is an LLVM Scalar type.
|
||||
if (!CGF.hasAggregateLLVMType(E->getType())) {
|
||||
Value *Src = Visit(const_cast<Expr*>(E));
|
||||
|
||||
// If the destination is void, just evaluate the source.
|
||||
if (DestTy->isVoidType()) return 0;
|
||||
|
||||
// Use EmitScalarConversion to perform the conversion.
|
||||
return EmitScalarConversion(Src, E->getType(), DestTy);
|
||||
}
|
||||
|
||||
RValue Src = CGF.EmitAnyExpr(E);
|
||||
|
||||
// If the destination is void, just evaluate the source.
|
||||
if (DestTy->isVoidType())
|
||||
return 0;
|
||||
if (DestTy->isVoidType()) return 0;
|
||||
|
||||
// FIXME: Refactor EmitConversion to not return an RValue. Sink it into this
|
||||
// method.
|
||||
|
@ -742,3 +820,13 @@ Value *CodeGenFunction::EmitScalarExpr(const Expr *E) {
|
|||
|
||||
return ScalarExprEmitter(*this).Visit(const_cast<Expr*>(E));
|
||||
}
|
||||
|
||||
/// EmitScalarConversion - Emit a conversion from the specified type to the
|
||||
/// specified destination type, both of which are LLVM scalar types.
|
||||
llvm::Value *CodeGenFunction::EmitScalarConversion(llvm::Value *Src,
|
||||
QualType SrcTy,
|
||||
QualType DstTy) {
|
||||
assert(!hasAggregateLLVMType(SrcTy) && !hasAggregateLLVMType(DstTy) &&
|
||||
"Invalid scalar expression to emit");
|
||||
return ScalarExprEmitter(*this).EmitScalarConversion(Src, SrcTy, DstTy);
|
||||
}
|
||||
|
|
|
@ -361,6 +361,12 @@ public:
|
|||
/// LLVM scalar type, returning the result.
|
||||
llvm::Value *EmitScalarExpr(const Expr *E);
|
||||
|
||||
/// EmitScalarConversion - Emit a conversion from the specified type to the
|
||||
/// specified destination type, both of which are LLVM scalar types.
|
||||
llvm::Value *EmitScalarConversion(llvm::Value *Src, QualType SrcTy,
|
||||
QualType DstTy);
|
||||
|
||||
|
||||
/// EmitAggExpr - Emit the computation of the specified expression of
|
||||
/// aggregate type. The result is computed into DestPtr. Note that if
|
||||
/// DestPtr is null, the value of the aggregate expression is not needed.
|
||||
|
|
Loading…
Reference in New Issue