diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/CodeGen/CGDecl.cpp | 2 | ||||
-rw-r--r-- | clang/CodeGen/CGExpr.cpp | 58 | ||||
-rw-r--r-- | clang/CodeGen/CodeGenFunction.h | 20 |
3 files changed, 76 insertions, 4 deletions
diff --git a/clang/CodeGen/CGDecl.cpp b/clang/CodeGen/CGDecl.cpp index 15f8610ed0c..822aca3f557 100644 --- a/clang/CodeGen/CGDecl.cpp +++ b/clang/CodeGen/CGDecl.cpp @@ -74,7 +74,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const BlockVarDecl &D) { // A normal fixed sized variable becomes an alloca in the entry block. const llvm::Type *LTy = ConvertType(Ty); // TODO: Alignment - DeclPtr = new llvm::AllocaInst(LTy, 0, D.getName(), AllocaInsertPt); + DeclPtr = CreateTempAlloca(LTy, D.getName()); } else { // TODO: Create a dynamic alloca. assert(0 && "FIXME: Local VLAs not implemented yet"); diff --git a/clang/CodeGen/CGExpr.cpp b/clang/CodeGen/CGExpr.cpp index f0a0f6ee189..8c3c2d4898c 100644 --- a/clang/CodeGen/CGExpr.cpp +++ b/clang/CodeGen/CGExpr.cpp @@ -25,6 +25,12 @@ using namespace CodeGen; // Miscellaneous Helper Methods //===--------------------------------------------------------------------===// +/// CreateTempAlloca - This creates a alloca and inserts it into the entry +/// block. +llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(const llvm::Type *Ty, + const char *Name) { + return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt); +} /// EvaluateExprAsBool - Perform the usual unary conversions on the specified /// expression and compare the result against zero, returning an Int1Ty value. @@ -34,6 +40,36 @@ llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) { return ConvertScalarValueToBool(Val, Ty); } +/// 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, + 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); + llvm::Value *RealPtr = Builder.CreateGEP(Ptr, Zero, Zero, "realp"); + llvm::Value *ImagPtr = Builder.CreateGEP(Ptr, Zero, One, "imagp"); + + // FIXME: Handle volatility. + Real = Builder.CreateLoad(RealPtr, "real"); + Imag = Builder.CreateLoad(ImagPtr, "imag"); +} + +/// EmitStoreOfComplex - Store the specified real/imag parts into the +/// specified value pointer. +void CodeGenFunction::EmitStoreOfComplex(llvm::Value *Real, llvm::Value *Imag, + llvm::Value *ResPtr) { + llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *One = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1); + llvm::Value *RealPtr = Builder.CreateGEP(ResPtr, Zero, Zero, "real"); + llvm::Value *ImagPtr = Builder.CreateGEP(ResPtr, Zero, One, "imag"); + + // FIXME: Handle volatility. + Builder.CreateStore(Real, RealPtr); + Builder.CreateStore(Imag, ImagPtr); +} + //===--------------------------------------------------------------------===// // Conversions //===--------------------------------------------------------------------===// @@ -260,6 +296,14 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, return; } + // Don't use memcpy for complex numbers. + if (Ty->isComplexType()) { + llvm::Value *Real, *Imag; + EmitLoadOfComplex(Src, Real, Imag); + EmitStoreOfComplex(Real, Imag, Dst.getAddress()); + return; + } + // Aggregate assignment turns into llvm.memcpy. const llvm::Type *SBP = llvm::PointerType::get(llvm::Type::Int8Ty); llvm::Value *SrcAddr = Src.getAggregateAddr(); @@ -759,9 +803,19 @@ RValue CodeGenFunction::EmitBinaryAdd(const BinaryOperator *E) { if (LHS.isScalar()) return RValue::get(Builder.CreateAdd(LHS.getVal(), RHS.getVal(), "add")); - - assert(0 && "FIXME: This doesn't handle complex operands yet"); + // 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(E->getType())); + EmitStoreOfComplex(ResR, ResI, Res); + return RValue::getAggregate(Res); } RValue CodeGenFunction::EmitBinarySub(const BinaryOperator *E) { diff --git a/clang/CodeGen/CodeGenFunction.h b/clang/CodeGen/CodeGenFunction.h index ad7deea46a1..a1d009f4f0d 100644 --- a/clang/CodeGen/CodeGenFunction.h +++ b/clang/CodeGen/CodeGenFunction.h @@ -160,11 +160,29 @@ public: void EmitBlock(llvm::BasicBlock *BB); - + //===--------------------------------------------------------------------===// + // Helpers + //===--------------------------------------------------------------------===// + + /// CreateTempAlloca - This creates a alloca and inserts it into the entry + /// block. + llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty, + const char *Name = "tmp"); + /// EvaluateExprAsBool - Perform the usual unary conversions on the specified /// expression and compare the result against zero, returning an Int1Ty value. llvm::Value *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 EmitLoadOfComplex(RValue V, llvm::Value *&Real, llvm::Value *&Imag); + + /// EmitStoreOfComplex - Store the specified real/imag parts into the + /// specified value pointer. + void EmitStoreOfComplex(llvm::Value *Real, llvm::Value *Imag, + llvm::Value *ResPtr); + //===--------------------------------------------------------------------===// // Conversions //===--------------------------------------------------------------------===// |