From: Chris Lattner Date: Sun, 26 Aug 2007 06:48:56 +0000 (+0000) Subject: refactor scalar conversions out into CGExprScalar.cpp X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3707b255f8993fb362904c9cff87b0e9bc6ca317;p=clang refactor scalar conversions out into CGExprScalar.cpp git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41433 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp index 9256a5d773..3a4e406c76 100644 --- a/CodeGen/CGExpr.cpp +++ b/CodeGen/CGExpr.cpp @@ -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(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(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 (isa(ValTy)) { - // Must be an ptr to int cast. - const llvm::Type *DestTy = ConvertType(DstTy); - assert(isa(DestTy) && "not ptr->int?"); - return RValue::get(Builder.CreateIntToPtr(Val.getVal(), DestTy, "conv")); - } + if (Val.isScalar() && !hasAggregateLLVMType(DstTy)) + return RValue::get(EmitScalarConversion(Val.getVal(), ValTy, DstTy)); - // 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(SrcVal->getType())) { - bool InputSigned = ValTy->isSignedIntegerType(); - if (isa(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(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!"); } diff --git a/CodeGen/CGExprComplex.cpp b/CodeGen/CGExprComplex.cpp index a54bd2cc16..49b5859f8b 100644 --- a/CodeGen/CGExprComplex.cpp +++ b/CodeGen/CGExprComplex.cpp @@ -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())); diff --git a/CodeGen/CGExprScalar.cpp b/CodeGen/CGExprScalar.cpp index 9bd5b3f1cc..f1989893e7 100644 --- a/CodeGen/CGExprScalar.cpp +++ b/CodeGen/CGExprScalar.cpp @@ -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(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(DstType)) { + // The source value may be an integer, or a pointer. + if (isa(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(SrcType)) { + // Must be an ptr to int cast. + assert(isa(DstTy) && "not ptr->int?"); + return Builder.CreateIntToPtr(Src, DstTy, "conv"); + } + + // Finally, we have the arithmetic types: real int/float. + if (isa(Src->getType())) { + bool InputSigned = SrcType->isSignedIntegerType(); + if (isa(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(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(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(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); +} diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h index 85b6c6318f..71573df679 100644 --- a/CodeGen/CodeGenFunction.h +++ b/CodeGen/CodeGenFunction.h @@ -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.