From: Chris Lattner Date: Sat, 11 Aug 2007 00:04:45 +0000 (+0000) Subject: start splitting out aggregate value computation from EmitExpr into EmitAggExpr. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=883f6a7cc7dccb1d675e27121a82614d63492a8d;p=clang start splitting out aggregate value computation from EmitExpr into EmitAggExpr. aggregate value and scalar expression computation are very different, this gets them away from each other. This causes a temporary regression on some complex number examples. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41014 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CodeGen/CGAggExpr.cpp b/CodeGen/CGAggExpr.cpp index 42b45a9327..c584b0b750 100644 --- a/CodeGen/CGAggExpr.cpp +++ b/CodeGen/CGAggExpr.cpp @@ -12,6 +12,286 @@ //===----------------------------------------------------------------------===// #include "CodeGenFunction.h" - +#include "CodeGenModule.h" +#include "clang/AST/AST.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" 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); +} + + +/// 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"); + + switch (E->getStmtClass()) { + default: + fprintf(stderr, "Unimplemented agg expr!\n"); + E->dump(); + return; + + // l-values. + case Expr::DeclRefExprClass: + return EmitAggLoadOfLValue(E, DestPtr, VolatileDest); +// case Expr::ArraySubscriptExprClass: +// return EmitArraySubscriptExprRV(cast(E)); + + // Operators. + case Expr::ParenExprClass: + return EmitAggExpr(cast(E)->getSubExpr(), DestPtr, VolatileDest); +// case Expr::UnaryOperatorClass: +// return EmitUnaryOperator(cast(E)); +// case Expr::ImplicitCastExprClass: +// return EmitCastExpr(cast(E)->getSubExpr(),E->getType()); +// case Expr::CastExprClass: +// return EmitCastExpr(cast(E)->getSubExpr(), E->getType()); +// case Expr::CallExprClass: +// return EmitCallExpr(cast(E)); + case Expr::BinaryOperatorClass: + return EmitAggBinaryOperator(cast(E), DestPtr,VolatileDest); + + case Expr::ConditionalOperatorClass: + return EmitAggConditionalOperator(cast(E), + DestPtr, VolatileDest); +// case Expr::ChooseExprClass: +// return EmitChooseExpr(cast(E)); + } +} + +/// 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 CodeGenFunction::EmitAggLoadOfLValue(const Expr *E, llvm::Value *DestPtr, + bool VolatileDest) { + LValue LV = EmitLValue(E); + assert(LV.isSimple() && "Can't have aggregate bitfield, vector, etc"); + llvm::Value *SrcPtr = LV.getAddress(); + + // If the result is ignored, don't copy from the value. + if (DestPtr == 0) + // FIXME: If the source is volatile, we must read from it. + return; + + EmitAggregateCopy(DestPtr, SrcPtr, E->getType()); +} + +void CodeGenFunction::EmitAggBinaryOperator(const BinaryOperator *E, + llvm::Value *DestPtr, + bool VolatileDest) { + switch (E->getOpcode()) { + default: + fprintf(stderr, "Unimplemented aggregate binary expr!\n"); + E->dump(); + return; +#if 0 + case BinaryOperator::Mul: + LHS = EmitExpr(E->getLHS()); + RHS = EmitExpr(E->getRHS()); + return EmitMul(LHS, RHS, E->getType()); + case BinaryOperator::Div: + LHS = EmitExpr(E->getLHS()); + RHS = EmitExpr(E->getRHS()); + return EmitDiv(LHS, RHS, E->getType()); + case BinaryOperator::Rem: + LHS = EmitExpr(E->getLHS()); + RHS = EmitExpr(E->getRHS()); + return EmitRem(LHS, RHS, E->getType()); + case BinaryOperator::Add: + LHS = EmitExpr(E->getLHS()); + RHS = EmitExpr(E->getRHS()); + if (!E->getType()->isPointerType()) + return EmitAdd(LHS, RHS, E->getType()); + + return EmitPointerAdd(LHS, E->getLHS()->getType(), + RHS, E->getRHS()->getType(), E->getType()); + case BinaryOperator::Sub: + LHS = EmitExpr(E->getLHS()); + RHS = EmitExpr(E->getRHS()); + + if (!E->getLHS()->getType()->isPointerType()) + return EmitSub(LHS, RHS, E->getType()); + + return EmitPointerSub(LHS, E->getLHS()->getType(), + RHS, E->getRHS()->getType(), E->getType()); + case BinaryOperator::Shl: + LHS = EmitExpr(E->getLHS()); + RHS = EmitExpr(E->getRHS()); + return EmitShl(LHS, RHS, E->getType()); + case BinaryOperator::Shr: + LHS = EmitExpr(E->getLHS()); + RHS = EmitExpr(E->getRHS()); + return EmitShr(LHS, RHS, E->getType()); + case BinaryOperator::And: + LHS = EmitExpr(E->getLHS()); + RHS = EmitExpr(E->getRHS()); + return EmitAnd(LHS, RHS, E->getType()); + case BinaryOperator::Xor: + LHS = EmitExpr(E->getLHS()); + RHS = EmitExpr(E->getRHS()); + return EmitXor(LHS, RHS, E->getType()); + case BinaryOperator::Or : + LHS = EmitExpr(E->getLHS()); + RHS = EmitExpr(E->getRHS()); + return EmitOr(LHS, RHS, E->getType()); +#endif + case BinaryOperator::Assign: + return EmitAggBinaryAssign(E, DestPtr, VolatileDest); + +#if 0 + case BinaryOperator::MulAssign: { + const CompoundAssignOperator *CAO = cast(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitMul(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::DivAssign: { + const CompoundAssignOperator *CAO = cast(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitDiv(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::RemAssign: { + const CompoundAssignOperator *CAO = cast(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitRem(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::AddAssign: { + const CompoundAssignOperator *CAO = cast(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitAdd(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::SubAssign: { + const CompoundAssignOperator *CAO = cast(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitSub(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::ShlAssign: { + const CompoundAssignOperator *CAO = cast(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitShl(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::ShrAssign: { + const CompoundAssignOperator *CAO = cast(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitShr(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::AndAssign: { + const CompoundAssignOperator *CAO = cast(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitAnd(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::OrAssign: { + const CompoundAssignOperator *CAO = cast(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitOr(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::XorAssign: { + const CompoundAssignOperator *CAO = cast(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitXor(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::Comma: return EmitBinaryComma(E); +#endif + } +} + +void CodeGenFunction::EmitAggBinaryAssign(const BinaryOperator *E, + llvm::Value *DestPtr, + bool VolatileDest) { + assert(E->getLHS()->getType().getCanonicalType() == + E->getRHS()->getType().getCanonicalType() && "Invalid assignment"); + LValue LHS = EmitLValue(E->getLHS()); + + // Codegen the RHS so that it stores directly into the LHS. + EmitAggExpr(E->getRHS(), LHS.getAddress(), false /*FIXME: VOLATILE LHS*/); + + // If the result of the assignment is used, copy the RHS there also. + if (DestPtr) { + assert(0 && "FIXME: Chained agg assignment not implemented yet"); + } +} + + +void CodeGenFunction::EmitAggConditionalOperator(const ConditionalOperator *E, + llvm::Value *DestPtr, + bool VolatileDest) { + llvm::BasicBlock *LHSBlock = new llvm::BasicBlock("cond.?"); + llvm::BasicBlock *RHSBlock = new llvm::BasicBlock("cond.:"); + llvm::BasicBlock *ContBlock = new llvm::BasicBlock("cond.cont"); + + llvm::Value *Cond = EvaluateExprAsBool(E->getCond()); + Builder.CreateCondBr(Cond, LHSBlock, RHSBlock); + + EmitBlock(LHSBlock); + + // Handle the GNU extension for missing LHS. + assert(E->getLHS() && "Must have LHS for aggregate value"); + + EmitAggExpr(E->getLHS(), DestPtr, VolatileDest); + Builder.CreateBr(ContBlock); + LHSBlock = Builder.GetInsertBlock(); + + EmitBlock(RHSBlock); + + EmitAggExpr(E->getRHS(), DestPtr, VolatileDest); + Builder.CreateBr(ContBlock); + RHSBlock = Builder.GetInsertBlock(); + + EmitBlock(ContBlock); +} diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp index 8937eaffba..896db31a1b 100644 --- a/CodeGen/CGExpr.cpp +++ b/CodeGen/CGExpr.cpp @@ -47,10 +47,12 @@ void CodeGenFunction::EmitLoadOfComplex(RValue V, 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"); // FIXME: Handle volatility. + // FIXME: It would be nice to make this "Ptr->getName()+real" Real = Builder.CreateLoad(RealPtr, "real"); Imag = Builder.CreateLoad(ImagPtr, "imag"); } @@ -272,11 +274,8 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) { if (EltTy->isFirstClassType()) return RValue::get(Builder.CreateLoad(Ptr, "tmp")); - if (ExprType->isFunctionType()) - return RValue::get(Ptr); - - // Otherwise, we have an aggregate lvalue. - return RValue::getAggregate(Ptr); + assert(ExprType->isFunctionType() && "Unknown scalar value"); + return RValue::get(Ptr); } if (LV.isVectorElt()) { @@ -376,48 +375,16 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, } llvm::Value *DstAddr = Dst.getAddress(); - if (Src.isScalar()) { - // FIXME: Handle volatility etc. - const llvm::Type *SrcTy = Src.getVal()->getType(); - const llvm::Type *AddrTy = - cast(DstAddr->getType())->getElementType(); - - if (AddrTy != SrcTy) - DstAddr = Builder.CreateBitCast(DstAddr, llvm::PointerType::get(SrcTy), - "storetmp"); - Builder.CreateStore(Src.getVal(), DstAddr); - 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(); - - if (DstAddr->getType() != SBP) - DstAddr = Builder.CreateBitCast(DstAddr, SBP, "tmp"); - if (SrcAddr->getType() != SBP) - SrcAddr = Builder.CreateBitCast(SrcAddr, SBP, "tmp"); - - unsigned Align = 1; // FIXME: Compute type alignments. - unsigned Size = 1234; // FIXME: Compute type sizes. - - // FIXME: Handle variable sized types. - const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth); - llvm::Value *SizeVal = llvm::ConstantInt::get(IntPtr, Size); - - llvm::Value *MemCpyOps[4] = { - DstAddr, SrcAddr, SizeVal,llvm::ConstantInt::get(llvm::Type::Int32Ty, Align) - }; - - Builder.CreateCall(CGM.getMemCpyFn(), MemCpyOps, MemCpyOps+4); + assert(Src.isScalar() && "Can't emit an agg store with this method"); + // FIXME: Handle volatility etc. + const llvm::Type *SrcTy = Src.getVal()->getType(); + const llvm::Type *AddrTy = + cast(DstAddr->getType())->getElementType(); + + if (AddrTy != SrcTy) + DstAddr = Builder.CreateBitCast(DstAddr, llvm::PointerType::get(SrcTy), + "storetmp"); + Builder.CreateStore(Src.getVal(), DstAddr); } void CodeGenFunction::EmitStoreThroughOCUComponentLValue(RValue Src, LValue Dst, @@ -585,7 +552,8 @@ EmitOCUVectorElementExpr(const OCUVectorElementExpr *E) { //===--------------------------------------------------------------------===// RValue CodeGenFunction::EmitExpr(const Expr *E) { - assert(E && "Null expression?"); + assert(E && !hasAggregateLLVMType(E->getType()) && + "Invalid scalar expression to emit"); switch (E->getStmtClass()) { default: @@ -641,7 +609,6 @@ RValue CodeGenFunction::EmitExpr(const Expr *E) { case Expr::ChooseExprClass: return EmitChooseExpr(cast(E)); } - } RValue CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) { @@ -1401,8 +1368,8 @@ RValue CodeGenFunction::EmitBinaryAssign(const BinaryOperator *E) { // Store the value into the LHS. EmitStoreThroughLValue(RHS, LHS, E->getType()); - - // Return the converted RHS. + + // Return the RHS. return RHS; } @@ -1420,8 +1387,6 @@ RValue CodeGenFunction::EmitConditionalOperator(const ConditionalOperator *E) { llvm::Value *Cond = EvaluateExprAsBool(E->getCond()); Builder.CreateCondBr(Cond, LHSBlock, RHSBlock); - // FIXME: Implement this for aggregate values. - EmitBlock(LHSBlock); // Handle the GNU extension for missing LHS. llvm::Value *LHSValue = E->getLHS() ? EmitExpr(E->getLHS()).getVal() : Cond; diff --git a/CodeGen/CGStmt.cpp b/CodeGen/CGStmt.cpp index 1e72c9df47..131e2b553c 100644 --- a/CodeGen/CGStmt.cpp +++ b/CodeGen/CGStmt.cpp @@ -31,7 +31,10 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { // Must be an expression in a stmt context. Emit the value and ignore the // result. if (const Expr *E = dyn_cast(S)) { - EmitExpr(E); + if (hasAggregateLLVMType(E->getType())) + EmitAggExpr(E, 0, false); // Emit an aggregate, ignoring the result. + else + EmitExpr(E); } else { printf("Unimplemented stmt!\n"); S->dump(); @@ -257,7 +260,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) { // If there is an increment, emit it next. if (S.getInc()) - EmitExpr(S.getInc()); + EmitStmt(S.getInc()); // Finally, branch back up to the condition for the next iteration. Builder.CreateBr(CondBlock); @@ -274,6 +277,7 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { // Emit the result value, even if unused, to evalute the side effects. const Expr *RV = S.getRetValue(); + // FIXME: Handle return of an aggregate! if (RV) RetVal = EmitExpr(RV); else // Silence a bogus GCC warning. diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h index 5cebb53074..314896a874 100644 --- a/CodeGen/CodeGenFunction.h +++ b/CodeGen/CodeGenFunction.h @@ -336,7 +336,7 @@ public: LValue EmitOCUVectorElementExpr(const OCUVectorElementExpr *E); //===--------------------------------------------------------------------===// - // Expression Emission + // Scalar Expression Emission //===--------------------------------------------------------------------===// void EmitCompoundAssignmentOperands(const CompoundAssignOperator *CAO, @@ -344,7 +344,6 @@ public: RValue EmitCompoundAssignmentResult(const CompoundAssignOperator *E, LValue LHSLV, RValue ResV); - RValue EmitExpr(const Expr *E); RValue EmitIntegerLiteral(const IntegerLiteral *E); RValue EmitFloatingLiteral(const FloatingLiteral *E); @@ -396,6 +395,36 @@ public: // Conditional Operator. RValue EmitConditionalOperator(const ConditionalOperator *E); RValue EmitChooseExpr(const ChooseExpr *E); + + //===--------------------------------------------------------------------===// + // Aggregate Expression Emission + //===--------------------------------------------------------------------===// + + void EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr, + QualType EltTy); + + /// 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 EmitAggExpr(const Expr *E, llvm::Value *DestPtr, bool VolatileDest); + + /// 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, llvm::Value *DestPtr, bool VolDest); + + + + // Binary Operators. + void EmitAggBinaryOperator(const BinaryOperator *E, + llvm::Value *DestPtr, bool VolatileDest); + + + void EmitAggBinaryAssign(const BinaryOperator *E, llvm::Value *DestPtr, + bool VolatileDest); + + void EmitAggConditionalOperator(const ConditionalOperator *E, + llvm::Value *DestPtr, bool VolatileDest); }; } // end namespace CodeGen } // end namespace clang