From: Chris Lattner Date: Tue, 21 Aug 2007 04:59:27 +0000 (+0000) Subject: reimplement addition of complex numbers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ee755f9118c4061b21e0a787d4a20484df36f603;p=clang reimplement addition of complex numbers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41215 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CodeGen/CGAggExpr.cpp b/CodeGen/CGAggExpr.cpp index 869e35dac5..4382fec6a4 100644 --- a/CodeGen/CGAggExpr.cpp +++ b/CodeGen/CGAggExpr.cpp @@ -20,40 +20,6 @@ using namespace clang; using namespace CodeGen; -// FIXME: Handle volatility! -void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, - llvm::Value *SrcPtr, QualType Ty) { - // Don't use memcpy for complex numbers. - if (Ty->isComplexType()) { - llvm::Value *Real, *Imag; - EmitLoadOfComplex(RValue::getAggregate(SrcPtr), Real, Imag); - EmitStoreOfComplex(Real, Imag, DestPtr); - return; - } - - // Aggregate assignment turns into llvm.memcpy. - const llvm::Type *BP = llvm::PointerType::get(llvm::Type::Int8Ty); - if (DestPtr->getType() != BP) - DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); - if (SrcPtr->getType() != BP) - SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); - - // Get size and alignment info for this aggregate. - std::pair TypeInfo = - getContext().getTypeInfo(Ty, SourceLocation()); - - // FIXME: Handle variable sized types. - const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth); - - llvm::Value *MemCpyOps[4] = { - DestPtr, SrcPtr, - llvm::ConstantInt::get(IntPtr, TypeInfo.first), - llvm::ConstantInt::get(llvm::Type::Int32Ty, TypeInfo.second) - }; - - Builder.CreateCall(CGM.getMemCpyFn(), MemCpyOps, MemCpyOps+4); -} - //===----------------------------------------------------------------------===// // Aggregate Expression Emitter //===----------------------------------------------------------------------===// @@ -68,11 +34,26 @@ public: : CGF(cgf), DestPtr(destPtr), VolatileDest(volatileDest) { } + typedef std::pair ComplexPairTy; + + //===--------------------------------------------------------------------===// + // Utilities + //===--------------------------------------------------------------------===// + /// EmitAggLoadOfLValue - Given an expression with aggregate type that /// represents a value lvalue, this method emits the address of the lvalue, /// then loads the result into DestPtr. void EmitAggLoadOfLValue(const Expr *E); + /// EmitComplexExpr - Emit the specified complex expression, returning the + /// real and imaginary values. + ComplexPairTy EmitComplexExpr(const Expr *E); + + + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// + void VisitStmt(Stmt *S) { fprintf(stderr, "Unimplemented agg expr!\n"); S->dump(); @@ -89,6 +70,7 @@ public: // case Expr::CastExprClass: // case Expr::CallExprClass: void VisitBinaryOperator(const BinaryOperator *BO); + void VisitBinAdd(const BinaryOperator *E); void VisitBinAssign(const BinaryOperator *E); @@ -97,20 +79,26 @@ public: }; } // end anonymous namespace. +//===----------------------------------------------------------------------===// +// Utilities +//===----------------------------------------------------------------------===// +/// EmitComplexExpr - Emit the specified complex expression, returning the +/// real and imaginary values. +AggExprEmitter::ComplexPairTy AggExprEmitter::EmitComplexExpr(const Expr *E) { + // Create a temporary alloca to hold this result. + llvm::Value *TmpPtr = CGF.CreateTempAlloca(CGF.ConvertType(E->getType())); + // Emit the expression into TmpPtr. + AggExprEmitter(CGF, TmpPtr, false).Visit(const_cast(E)); -/// 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. -void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr, - bool VolatileDest) { - assert(E && hasAggregateLLVMType(E->getType()) && - "Invalid aggregate expression to emit"); - - AggExprEmitter(*this, DestPtr, VolatileDest).Visit(const_cast(E)); + // Return the real/imag values by reloading them from the stack. + llvm::Value *Real, *Imag; + CGF.EmitLoadOfComplex(TmpPtr, Real, Imag); + return std::make_pair(Real, Imag); } + /// EmitAggLoadOfLValue - Given an expression with aggregate type that /// represents a value lvalue, this method emits the address of the lvalue, /// then loads the result into DestPtr. @@ -127,6 +115,10 @@ void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) { CGF.EmitAggregateCopy(DestPtr, SrcPtr, E->getType()); } +//===----------------------------------------------------------------------===// +// Visitor Methods +//===----------------------------------------------------------------------===// + void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) { fprintf(stderr, "Unimplemented aggregate binary expr!\n"); E->dump(); @@ -258,6 +250,17 @@ void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) { #endif } +void AggExprEmitter::VisitBinAdd(const BinaryOperator *E) { + // This must be a complex number. + ComplexPairTy LHS = EmitComplexExpr(E->getLHS()); + ComplexPairTy RHS = EmitComplexExpr(E->getRHS()); + + llvm::Value *ResR = CGF.Builder.CreateAdd(LHS.first, RHS.first, "add.r"); + llvm::Value *ResI = CGF.Builder.CreateAdd(LHS.second, RHS.second, "add.i"); + + CGF.EmitStoreOfComplex(ResR, ResI, DestPtr /*FIXME: Volatile!*/); +} + void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { assert(E->getLHS()->getType().getCanonicalType() == E->getRHS()->getType().getCanonicalType() && "Invalid assignment"); @@ -298,3 +301,53 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) { CGF.EmitBlock(ContBlock); } + +//===----------------------------------------------------------------------===// +// Entry Points into this File +//===----------------------------------------------------------------------===// + +/// 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. +void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr, + bool VolatileDest) { + assert(E && hasAggregateLLVMType(E->getType()) && + "Invalid aggregate expression to emit"); + + AggExprEmitter(*this, DestPtr, VolatileDest).Visit(const_cast(E)); +} + + +// FIXME: Handle volatility! +void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, + llvm::Value *SrcPtr, QualType Ty) { + // Don't use memcpy for complex numbers. + if (Ty->isComplexType()) { + llvm::Value *Real, *Imag; + EmitLoadOfComplex(SrcPtr, Real, Imag); + EmitStoreOfComplex(Real, Imag, DestPtr); + return; + } + + // Aggregate assignment turns into llvm.memcpy. + const llvm::Type *BP = llvm::PointerType::get(llvm::Type::Int8Ty); + if (DestPtr->getType() != BP) + DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); + if (SrcPtr->getType() != BP) + SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); + + // Get size and alignment info for this aggregate. + std::pair TypeInfo = + getContext().getTypeInfo(Ty, SourceLocation()); + + // FIXME: Handle variable sized types. + const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth); + + llvm::Value *MemCpyOps[4] = { + DestPtr, SrcPtr, + llvm::ConstantInt::get(IntPtr, TypeInfo.first), + llvm::ConstantInt::get(llvm::Type::Int32Ty, TypeInfo.second) + }; + + Builder.CreateCall(CGM.getMemCpyFn(), MemCpyOps, MemCpyOps+4); +} diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp index 9713cf8e1a..2b6fd727da 100644 --- a/CodeGen/CGExpr.cpp +++ b/CodeGen/CGExpr.cpp @@ -42,15 +42,13 @@ llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) { /// EmitLoadOfComplex - Given an RValue reference for a complex, emit code to /// load the real and imaginary pieces, returning them as Real/Imag. -void CodeGenFunction::EmitLoadOfComplex(RValue V, +void CodeGenFunction::EmitLoadOfComplex(llvm::Value *SrcPtr, llvm::Value *&Real, llvm::Value *&Imag){ - llvm::Value *Ptr = V.getAggregateAddr(); - llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); llvm::Constant *One = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1); // FIXME: It would be nice to make this "Ptr->getName()+realp" - llvm::Value *RealPtr = Builder.CreateGEP(Ptr, Zero, Zero, "realp"); - llvm::Value *ImagPtr = Builder.CreateGEP(Ptr, Zero, One, "imagp"); + llvm::Value *RealPtr = Builder.CreateGEP(SrcPtr, Zero, Zero, "realp"); + llvm::Value *ImagPtr = Builder.CreateGEP(SrcPtr, Zero, One, "imagp"); // FIXME: Handle volatility. // FIXME: It would be nice to make this "Ptr->getName()+real" @@ -1106,12 +1104,12 @@ RValue CodeGenFunction::EmitBinaryOperator(const BinaryOperator *E) { } RValue CodeGenFunction::EmitMul(RValue LHS, RValue RHS, QualType ResTy) { - if (LHS.isScalar()) - return RValue::get(Builder.CreateMul(LHS.getVal(), RHS.getVal(), "mul")); + return RValue::get(Builder.CreateMul(LHS.getVal(), RHS.getVal(), "mul")); +#if 0 // Otherwise, this must be a complex number. llvm::Value *LHSR, *LHSI, *RHSR, *RHSI; - + EmitLoadOfComplex(LHS, LHSR, LHSI); EmitLoadOfComplex(RHS, RHSR, RHSI); @@ -1126,6 +1124,7 @@ RValue CodeGenFunction::EmitMul(RValue LHS, RValue RHS, QualType ResTy) { llvm::Value *Res = CreateTempAlloca(ConvertType(ResTy)); EmitStoreOfComplex(ResR, ResI, Res); return RValue::getAggregate(Res); +#endif } RValue CodeGenFunction::EmitDiv(RValue LHS, RValue RHS, QualType ResTy) { @@ -1157,21 +1156,7 @@ RValue CodeGenFunction::EmitRem(RValue LHS, RValue RHS, QualType ResTy) { } RValue CodeGenFunction::EmitAdd(RValue LHS, RValue RHS, QualType ResTy) { - if (LHS.isScalar()) - return RValue::get(Builder.CreateAdd(LHS.getVal(), RHS.getVal(), "add")); - - // Otherwise, this must be a complex number. - llvm::Value *LHSR, *LHSI, *RHSR, *RHSI; - - EmitLoadOfComplex(LHS, LHSR, LHSI); - EmitLoadOfComplex(RHS, RHSR, RHSI); - - llvm::Value *ResR = Builder.CreateAdd(LHSR, RHSR, "add.r"); - llvm::Value *ResI = Builder.CreateAdd(LHSI, RHSI, "add.i"); - - llvm::Value *Res = CreateTempAlloca(ConvertType(ResTy)); - EmitStoreOfComplex(ResR, ResI, Res); - return RValue::getAggregate(Res); + return RValue::get(Builder.CreateAdd(LHS.getVal(), RHS.getVal(), "add")); } RValue CodeGenFunction::EmitPointerAdd(RValue LHS, QualType LHSTy, @@ -1285,6 +1270,7 @@ RValue CodeGenFunction::EmitBinaryCompare(const BinaryOperator *E, LHS.getVal(), RHS.getVal(), "cmp"); } } else { +#if 0 // Struct/union/complex llvm::Value *LHSR, *LHSI, *RHSR, *RHSI, *ResultR, *ResultI; EmitLoadOfComplex(LHS, LHSR, LHSI); @@ -1303,6 +1289,7 @@ RValue CodeGenFunction::EmitBinaryCompare(const BinaryOperator *E, } else { assert(0 && "Complex comparison other than == or != ?"); } +#endif } // ZExt result to int. diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h index eaf2b1ded2..ca391b01ad 100644 --- a/CodeGen/CodeGenFunction.h +++ b/CodeGen/CodeGenFunction.h @@ -249,7 +249,8 @@ public: /// EmitLoadOfComplex - Given an RValue reference for a complex, emit code to /// load the real and imaginary pieces, returning them as Real/Imag. - void EmitLoadOfComplex(RValue V, llvm::Value *&Real, llvm::Value *&Imag); + void EmitLoadOfComplex(llvm::Value *SrcPtr, llvm::Value *&Real, + llvm::Value *&Imag); /// EmitStoreOfComplex - Store the specified real/imag parts into the /// specified value pointer.