123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839 |
- //===--- CGExprComplex.cpp - Emit LLVM Code for Complex Exprs -------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This contains code to emit Expr nodes with complex types as LLVM code.
- //
- //===----------------------------------------------------------------------===//
- #include "CodeGenFunction.h"
- #include "CodeGenModule.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/StmtVisitor.h"
- #include "llvm/Constants.h"
- #include "llvm/Function.h"
- #include "llvm/ADT/SmallString.h"
- using namespace clang;
- using namespace CodeGen;
- //===----------------------------------------------------------------------===//
- // Complex Expression Emitter
- //===----------------------------------------------------------------------===//
- typedef CodeGenFunction::ComplexPairTy ComplexPairTy;
- namespace {
- class ComplexExprEmitter
- : public StmtVisitor<ComplexExprEmitter, ComplexPairTy> {
- CodeGenFunction &CGF;
- CGBuilderTy &Builder;
- // True is we should ignore the value of a
- bool IgnoreReal;
- bool IgnoreImag;
- public:
- ComplexExprEmitter(CodeGenFunction &cgf, bool ir=false, bool ii=false)
- : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii) {
- }
- //===--------------------------------------------------------------------===//
- // Utilities
- //===--------------------------------------------------------------------===//
- bool TestAndClearIgnoreReal() {
- bool I = IgnoreReal;
- IgnoreReal = false;
- return I;
- }
- bool TestAndClearIgnoreImag() {
- bool I = IgnoreImag;
- IgnoreImag = false;
- return I;
- }
- /// EmitLoadOfLValue - Given an expression with complex type that represents a
- /// value l-value, this method emits the address of the l-value, then loads
- /// and returns the result.
- ComplexPairTy EmitLoadOfLValue(const Expr *E) {
- return EmitLoadOfLValue(CGF.EmitLValue(E));
- }
- ComplexPairTy EmitLoadOfLValue(LValue LV) {
- assert(LV.isSimple() && "complex l-value must be simple");
- return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
- }
- /// EmitLoadOfComplex - Given a pointer to a complex value, emit code to load
- /// the real and imaginary pieces.
- ComplexPairTy EmitLoadOfComplex(llvm::Value *SrcPtr, bool isVolatile);
- /// EmitStoreThroughLValue - Given an l-value of complex type, store
- /// a complex number into it.
- void EmitStoreThroughLValue(ComplexPairTy Val, LValue LV) {
- assert(LV.isSimple() && "complex l-value must be simple");
- return EmitStoreOfComplex(Val, LV.getAddress(), LV.isVolatileQualified());
- }
- /// EmitStoreOfComplex - Store the specified real/imag parts into the
- /// specified value pointer.
- void EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *ResPtr, bool isVol);
- /// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
- ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType,
- QualType DestType);
- //===--------------------------------------------------------------------===//
- // Visitor Methods
- //===--------------------------------------------------------------------===//
- ComplexPairTy Visit(Expr *E) {
- return StmtVisitor<ComplexExprEmitter, ComplexPairTy>::Visit(E);
- }
-
- ComplexPairTy VisitStmt(Stmt *S) {
- S->dump(CGF.getContext().getSourceManager());
- llvm_unreachable("Stmt can't have complex result type!");
- }
- ComplexPairTy VisitExpr(Expr *S);
- ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());}
- ComplexPairTy VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
- return Visit(GE->getResultExpr());
- }
- ComplexPairTy VisitImaginaryLiteral(const ImaginaryLiteral *IL);
- ComplexPairTy
- VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE) {
- return Visit(PE->getReplacement());
- }
- // l-values.
- ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) {
- if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) {
- if (result.isReference())
- return EmitLoadOfLValue(result.getReferenceLValue(CGF, E));
- llvm::ConstantStruct *pair =
- cast<llvm::ConstantStruct>(result.getValue());
- return ComplexPairTy(pair->getOperand(0), pair->getOperand(1));
- }
- return EmitLoadOfLValue(E);
- }
- ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
- return EmitLoadOfLValue(E);
- }
- ComplexPairTy VisitObjCMessageExpr(ObjCMessageExpr *E) {
- return CGF.EmitObjCMessageExpr(E).getComplexVal();
- }
- ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
- ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); }
- ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
- if (E->isGLValue())
- return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E));
- return CGF.getOpaqueRValueMapping(E).getComplexVal();
- }
- ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) {
- return CGF.EmitPseudoObjectRValue(E).getComplexVal();
- }
- // FIXME: CompoundLiteralExpr
- ComplexPairTy EmitCast(CastExpr::CastKind CK, Expr *Op, QualType DestTy);
- ComplexPairTy VisitImplicitCastExpr(ImplicitCastExpr *E) {
- // Unlike for scalars, we don't have to worry about function->ptr demotion
- // here.
- return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
- }
- ComplexPairTy VisitCastExpr(CastExpr *E) {
- return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
- }
- ComplexPairTy VisitCallExpr(const CallExpr *E);
- ComplexPairTy VisitStmtExpr(const StmtExpr *E);
- // Operators.
- ComplexPairTy VisitPrePostIncDec(const UnaryOperator *E,
- bool isInc, bool isPre) {
- LValue LV = CGF.EmitLValue(E->getSubExpr());
- return CGF.EmitComplexPrePostIncDec(E, LV, isInc, isPre);
- }
- ComplexPairTy VisitUnaryPostDec(const UnaryOperator *E) {
- return VisitPrePostIncDec(E, false, false);
- }
- ComplexPairTy VisitUnaryPostInc(const UnaryOperator *E) {
- return VisitPrePostIncDec(E, true, false);
- }
- ComplexPairTy VisitUnaryPreDec(const UnaryOperator *E) {
- return VisitPrePostIncDec(E, false, true);
- }
- ComplexPairTy VisitUnaryPreInc(const UnaryOperator *E) {
- return VisitPrePostIncDec(E, true, true);
- }
- ComplexPairTy VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); }
- ComplexPairTy VisitUnaryPlus (const UnaryOperator *E) {
- TestAndClearIgnoreReal();
- TestAndClearIgnoreImag();
- return Visit(E->getSubExpr());
- }
- ComplexPairTy VisitUnaryMinus (const UnaryOperator *E);
- ComplexPairTy VisitUnaryNot (const UnaryOperator *E);
- // LNot,Real,Imag never return complex.
- ComplexPairTy VisitUnaryExtension(const UnaryOperator *E) {
- return Visit(E->getSubExpr());
- }
- ComplexPairTy VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
- return Visit(DAE->getExpr());
- }
- ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) {
- CGF.enterFullExpression(E);
- CodeGenFunction::RunCleanupsScope Scope(CGF);
- return Visit(E->getSubExpr());
- }
- ComplexPairTy VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
- assert(E->getType()->isAnyComplexType() && "Expected complex type!");
- QualType Elem = E->getType()->getAs<ComplexType>()->getElementType();
- llvm::Constant *Null = llvm::Constant::getNullValue(CGF.ConvertType(Elem));
- return ComplexPairTy(Null, Null);
- }
- ComplexPairTy VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
- assert(E->getType()->isAnyComplexType() && "Expected complex type!");
- QualType Elem = E->getType()->getAs<ComplexType>()->getElementType();
- llvm::Constant *Null =
- llvm::Constant::getNullValue(CGF.ConvertType(Elem));
- return ComplexPairTy(Null, Null);
- }
- struct BinOpInfo {
- ComplexPairTy LHS;
- ComplexPairTy RHS;
- QualType Ty; // Computation Type.
- };
- BinOpInfo EmitBinOps(const BinaryOperator *E);
- LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E,
- ComplexPairTy (ComplexExprEmitter::*Func)
- (const BinOpInfo &),
- ComplexPairTy &Val);
- ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E,
- ComplexPairTy (ComplexExprEmitter::*Func)
- (const BinOpInfo &));
- ComplexPairTy EmitBinAdd(const BinOpInfo &Op);
- ComplexPairTy EmitBinSub(const BinOpInfo &Op);
- ComplexPairTy EmitBinMul(const BinOpInfo &Op);
- ComplexPairTy EmitBinDiv(const BinOpInfo &Op);
- ComplexPairTy VisitBinAdd(const BinaryOperator *E) {
- return EmitBinAdd(EmitBinOps(E));
- }
- ComplexPairTy VisitBinSub(const BinaryOperator *E) {
- return EmitBinSub(EmitBinOps(E));
- }
- ComplexPairTy VisitBinMul(const BinaryOperator *E) {
- return EmitBinMul(EmitBinOps(E));
- }
- ComplexPairTy VisitBinDiv(const BinaryOperator *E) {
- return EmitBinDiv(EmitBinOps(E));
- }
- // Compound assignments.
- ComplexPairTy VisitBinAddAssign(const CompoundAssignOperator *E) {
- return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinAdd);
- }
- ComplexPairTy VisitBinSubAssign(const CompoundAssignOperator *E) {
- return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinSub);
- }
- ComplexPairTy VisitBinMulAssign(const CompoundAssignOperator *E) {
- return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinMul);
- }
- ComplexPairTy VisitBinDivAssign(const CompoundAssignOperator *E) {
- return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinDiv);
- }
- // GCC rejects rem/and/or/xor for integer complex.
- // Logical and/or always return int, never complex.
- // No comparisons produce a complex result.
- LValue EmitBinAssignLValue(const BinaryOperator *E,
- ComplexPairTy &Val);
- ComplexPairTy VisitBinAssign (const BinaryOperator *E);
- ComplexPairTy VisitBinComma (const BinaryOperator *E);
- ComplexPairTy
- VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
- ComplexPairTy VisitChooseExpr(ChooseExpr *CE);
- ComplexPairTy VisitInitListExpr(InitListExpr *E);
- ComplexPairTy VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
- return EmitLoadOfLValue(E);
- }
- ComplexPairTy VisitVAArgExpr(VAArgExpr *E);
- ComplexPairTy VisitAtomicExpr(AtomicExpr *E) {
- return CGF.EmitAtomicExpr(E).getComplexVal();
- }
- };
- } // end anonymous namespace.
- //===----------------------------------------------------------------------===//
- // Utilities
- //===----------------------------------------------------------------------===//
- /// EmitLoadOfComplex - Given an RValue reference for a complex, emit code to
- /// load the real and imaginary pieces, returning them as Real/Imag.
- ComplexPairTy ComplexExprEmitter::EmitLoadOfComplex(llvm::Value *SrcPtr,
- bool isVolatile) {
- llvm::Value *Real=0, *Imag=0;
- if (!IgnoreReal || isVolatile) {
- llvm::Value *RealP = Builder.CreateStructGEP(SrcPtr, 0,
- SrcPtr->getName() + ".realp");
- Real = Builder.CreateLoad(RealP, isVolatile, SrcPtr->getName() + ".real");
- }
- if (!IgnoreImag || isVolatile) {
- llvm::Value *ImagP = Builder.CreateStructGEP(SrcPtr, 1,
- SrcPtr->getName() + ".imagp");
- Imag = Builder.CreateLoad(ImagP, isVolatile, SrcPtr->getName() + ".imag");
- }
- return ComplexPairTy(Real, Imag);
- }
- /// EmitStoreOfComplex - Store the specified real/imag parts into the
- /// specified value pointer.
- void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *Ptr,
- bool isVolatile) {
- llvm::Value *RealPtr = Builder.CreateStructGEP(Ptr, 0, "real");
- llvm::Value *ImagPtr = Builder.CreateStructGEP(Ptr, 1, "imag");
- Builder.CreateStore(Val.first, RealPtr, isVolatile);
- Builder.CreateStore(Val.second, ImagPtr, isVolatile);
- }
- //===----------------------------------------------------------------------===//
- // Visitor Methods
- //===----------------------------------------------------------------------===//
- ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) {
- CGF.ErrorUnsupported(E, "complex expression");
- llvm::Type *EltTy =
- CGF.ConvertType(E->getType()->getAs<ComplexType>()->getElementType());
- llvm::Value *U = llvm::UndefValue::get(EltTy);
- return ComplexPairTy(U, U);
- }
- ComplexPairTy ComplexExprEmitter::
- VisitImaginaryLiteral(const ImaginaryLiteral *IL) {
- llvm::Value *Imag = CGF.EmitScalarExpr(IL->getSubExpr());
- return ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag);
- }
- ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) {
- if (E->getCallReturnType()->isReferenceType())
- return EmitLoadOfLValue(E);
- return CGF.EmitCallExpr(E).getComplexVal();
- }
- ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) {
- CodeGenFunction::StmtExprEvaluation eval(CGF);
- return CGF.EmitCompoundStmt(*E->getSubStmt(), true).getComplexVal();
- }
- /// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
- ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val,
- QualType SrcType,
- QualType DestType) {
- // Get the src/dest element type.
- SrcType = SrcType->getAs<ComplexType>()->getElementType();
- DestType = DestType->getAs<ComplexType>()->getElementType();
- // C99 6.3.1.6: When a value of complex type is converted to another
- // complex type, both the real and imaginary parts follow the conversion
- // rules for the corresponding real types.
- Val.first = CGF.EmitScalarConversion(Val.first, SrcType, DestType);
- Val.second = CGF.EmitScalarConversion(Val.second, SrcType, DestType);
- return Val;
- }
- ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op,
- QualType DestTy) {
- switch (CK) {
- case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!");
- // Atomic to non-atomic casts may be more than a no-op for some platforms and
- // for some types.
- case CK_AtomicToNonAtomic:
- case CK_NonAtomicToAtomic:
- case CK_NoOp:
- case CK_LValueToRValue:
- case CK_UserDefinedConversion:
- return Visit(Op);
- case CK_LValueBitCast: {
- llvm::Value *V = CGF.EmitLValue(Op).getAddress();
- V = Builder.CreateBitCast(V,
- CGF.ConvertType(CGF.getContext().getPointerType(DestTy)));
- // FIXME: Are the qualifiers correct here?
- return EmitLoadOfComplex(V, DestTy.isVolatileQualified());
- }
- case CK_BitCast:
- case CK_BaseToDerived:
- case CK_DerivedToBase:
- case CK_UncheckedDerivedToBase:
- case CK_Dynamic:
- case CK_ToUnion:
- case CK_ArrayToPointerDecay:
- case CK_FunctionToPointerDecay:
- case CK_NullToPointer:
- case CK_NullToMemberPointer:
- case CK_BaseToDerivedMemberPointer:
- case CK_DerivedToBaseMemberPointer:
- case CK_MemberPointerToBoolean:
- case CK_ReinterpretMemberPointer:
- case CK_ConstructorConversion:
- case CK_IntegralToPointer:
- case CK_PointerToIntegral:
- case CK_PointerToBoolean:
- case CK_ToVoid:
- case CK_VectorSplat:
- case CK_IntegralCast:
- case CK_IntegralToBoolean:
- case CK_IntegralToFloating:
- case CK_FloatingToIntegral:
- case CK_FloatingToBoolean:
- case CK_FloatingCast:
- case CK_CPointerToObjCPointerCast:
- case CK_BlockPointerToObjCPointerCast:
- case CK_AnyPointerToBlockPointerCast:
- case CK_ObjCObjectLValueCast:
- case CK_FloatingComplexToReal:
- case CK_FloatingComplexToBoolean:
- case CK_IntegralComplexToReal:
- case CK_IntegralComplexToBoolean:
- case CK_ARCProduceObject:
- case CK_ARCConsumeObject:
- case CK_ARCReclaimReturnedObject:
- case CK_ARCExtendBlockObject:
- case CK_CopyAndAutoreleaseBlockObject:
- llvm_unreachable("invalid cast kind for complex value");
- case CK_FloatingRealToComplex:
- case CK_IntegralRealToComplex: {
- llvm::Value *Elt = CGF.EmitScalarExpr(Op);
- // Convert the input element to the element type of the complex.
- DestTy = DestTy->getAs<ComplexType>()->getElementType();
- Elt = CGF.EmitScalarConversion(Elt, Op->getType(), DestTy);
- // Return (realval, 0).
- return ComplexPairTy(Elt, llvm::Constant::getNullValue(Elt->getType()));
- }
- case CK_FloatingComplexCast:
- case CK_FloatingComplexToIntegralComplex:
- case CK_IntegralComplexCast:
- case CK_IntegralComplexToFloatingComplex:
- return EmitComplexToComplexCast(Visit(Op), Op->getType(), DestTy);
- }
- llvm_unreachable("unknown cast resulting in complex value");
- }
- ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
- TestAndClearIgnoreReal();
- TestAndClearIgnoreImag();
- ComplexPairTy Op = Visit(E->getSubExpr());
- llvm::Value *ResR, *ResI;
- if (Op.first->getType()->isFloatingPointTy()) {
- ResR = Builder.CreateFNeg(Op.first, "neg.r");
- ResI = Builder.CreateFNeg(Op.second, "neg.i");
- } else {
- ResR = Builder.CreateNeg(Op.first, "neg.r");
- ResI = Builder.CreateNeg(Op.second, "neg.i");
- }
- return ComplexPairTy(ResR, ResI);
- }
- ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
- TestAndClearIgnoreReal();
- TestAndClearIgnoreImag();
- // ~(a+ib) = a + i*-b
- ComplexPairTy Op = Visit(E->getSubExpr());
- llvm::Value *ResI;
- if (Op.second->getType()->isFloatingPointTy())
- ResI = Builder.CreateFNeg(Op.second, "conj.i");
- else
- ResI = Builder.CreateNeg(Op.second, "conj.i");
- return ComplexPairTy(Op.first, ResI);
- }
- ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) {
- llvm::Value *ResR, *ResI;
- if (Op.LHS.first->getType()->isFloatingPointTy()) {
- ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first, "add.r");
- ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second, "add.i");
- } else {
- ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r");
- ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i");
- }
- return ComplexPairTy(ResR, ResI);
- }
- ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) {
- llvm::Value *ResR, *ResI;
- if (Op.LHS.first->getType()->isFloatingPointTy()) {
- ResR = Builder.CreateFSub(Op.LHS.first, Op.RHS.first, "sub.r");
- ResI = Builder.CreateFSub(Op.LHS.second, Op.RHS.second, "sub.i");
- } else {
- ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r");
- ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i");
- }
- return ComplexPairTy(ResR, ResI);
- }
- ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
- using llvm::Value;
- Value *ResR, *ResI;
- if (Op.LHS.first->getType()->isFloatingPointTy()) {
- Value *ResRl = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul.rl");
- Value *ResRr = Builder.CreateFMul(Op.LHS.second, Op.RHS.second,"mul.rr");
- ResR = Builder.CreateFSub(ResRl, ResRr, "mul.r");
- Value *ResIl = Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul.il");
- Value *ResIr = Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul.ir");
- ResI = Builder.CreateFAdd(ResIl, ResIr, "mul.i");
- } else {
- Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl");
- Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second,"mul.rr");
- ResR = Builder.CreateSub(ResRl, ResRr, "mul.r");
- Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il");
- Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir");
- ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i");
- }
- return ComplexPairTy(ResR, ResI);
- }
- ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
- llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second;
- llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second;
- llvm::Value *DSTr, *DSTi;
- if (Op.LHS.first->getType()->isFloatingPointTy()) {
- // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
- llvm::Value *Tmp1 = Builder.CreateFMul(LHSr, RHSr); // a*c
- llvm::Value *Tmp2 = Builder.CreateFMul(LHSi, RHSi); // b*d
- llvm::Value *Tmp3 = Builder.CreateFAdd(Tmp1, Tmp2); // ac+bd
- llvm::Value *Tmp4 = Builder.CreateFMul(RHSr, RHSr); // c*c
- llvm::Value *Tmp5 = Builder.CreateFMul(RHSi, RHSi); // d*d
- llvm::Value *Tmp6 = Builder.CreateFAdd(Tmp4, Tmp5); // cc+dd
- llvm::Value *Tmp7 = Builder.CreateFMul(LHSi, RHSr); // b*c
- llvm::Value *Tmp8 = Builder.CreateFMul(LHSr, RHSi); // a*d
- llvm::Value *Tmp9 = Builder.CreateFSub(Tmp7, Tmp8); // bc-ad
- DSTr = Builder.CreateFDiv(Tmp3, Tmp6);
- DSTi = Builder.CreateFDiv(Tmp9, Tmp6);
- } else {
- // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
- llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr); // a*c
- llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi); // b*d
- llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2); // ac+bd
- llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr); // c*c
- llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi); // d*d
- llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5); // cc+dd
- llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr); // b*c
- llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi); // a*d
- llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8); // bc-ad
- if (Op.Ty->getAs<ComplexType>()->getElementType()->isUnsignedIntegerType()) {
- DSTr = Builder.CreateUDiv(Tmp3, Tmp6);
- DSTi = Builder.CreateUDiv(Tmp9, Tmp6);
- } else {
- DSTr = Builder.CreateSDiv(Tmp3, Tmp6);
- DSTi = Builder.CreateSDiv(Tmp9, Tmp6);
- }
- }
- return ComplexPairTy(DSTr, DSTi);
- }
- ComplexExprEmitter::BinOpInfo
- ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) {
- TestAndClearIgnoreReal();
- TestAndClearIgnoreImag();
- BinOpInfo Ops;
- Ops.LHS = Visit(E->getLHS());
- Ops.RHS = Visit(E->getRHS());
- Ops.Ty = E->getType();
- return Ops;
- }
- LValue ComplexExprEmitter::
- EmitCompoundAssignLValue(const CompoundAssignOperator *E,
- ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
- ComplexPairTy &Val) {
- TestAndClearIgnoreReal();
- TestAndClearIgnoreImag();
- QualType LHSTy = E->getLHS()->getType();
- BinOpInfo OpInfo;
- // Load the RHS and LHS operands.
- // __block variables need to have the rhs evaluated first, plus this should
- // improve codegen a little.
- OpInfo.Ty = E->getComputationResultType();
- // The RHS should have been converted to the computation type.
- assert(OpInfo.Ty->isAnyComplexType());
- assert(CGF.getContext().hasSameUnqualifiedType(OpInfo.Ty,
- E->getRHS()->getType()));
- OpInfo.RHS = Visit(E->getRHS());
-
- LValue LHS = CGF.EmitLValue(E->getLHS());
- // Load from the l-value.
- ComplexPairTy LHSComplexPair = EmitLoadOfLValue(LHS);
-
- OpInfo.LHS = EmitComplexToComplexCast(LHSComplexPair, LHSTy, OpInfo.Ty);
- // Expand the binary operator.
- ComplexPairTy Result = (this->*Func)(OpInfo);
- // Truncate the result back to the LHS type.
- Result = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy);
- Val = Result;
- // Store the result value into the LHS lvalue.
- EmitStoreThroughLValue(Result, LHS);
- return LHS;
- }
- // Compound assignments.
- ComplexPairTy ComplexExprEmitter::
- EmitCompoundAssign(const CompoundAssignOperator *E,
- ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){
- ComplexPairTy Val;
- LValue LV = EmitCompoundAssignLValue(E, Func, Val);
- // The result of an assignment in C is the assigned r-value.
- if (!CGF.getContext().getLangOpts().CPlusPlus)
- return Val;
- // If the lvalue is non-volatile, return the computed value of the assignment.
- if (!LV.isVolatileQualified())
- return Val;
- return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
- }
- LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E,
- ComplexPairTy &Val) {
- assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(),
- E->getRHS()->getType()) &&
- "Invalid assignment");
- TestAndClearIgnoreReal();
- TestAndClearIgnoreImag();
- // Emit the RHS. __block variables need the RHS evaluated first.
- Val = Visit(E->getRHS());
- // Compute the address to store into.
- LValue LHS = CGF.EmitLValue(E->getLHS());
- // Store the result value into the LHS lvalue.
- EmitStoreThroughLValue(Val, LHS);
- return LHS;
- }
- ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
- ComplexPairTy Val;
- LValue LV = EmitBinAssignLValue(E, Val);
- // The result of an assignment in C is the assigned r-value.
- if (!CGF.getContext().getLangOpts().CPlusPlus)
- return Val;
- // If the lvalue is non-volatile, return the computed value of the assignment.
- if (!LV.isVolatileQualified())
- return Val;
- return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
- }
- ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
- CGF.EmitIgnoredExpr(E->getLHS());
- return Visit(E->getRHS());
- }
- ComplexPairTy ComplexExprEmitter::
- VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
- TestAndClearIgnoreReal();
- TestAndClearIgnoreImag();
- llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
- llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
- llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
- // Bind the common expression if necessary.
- CodeGenFunction::OpaqueValueMapping binding(CGF, E);
- CodeGenFunction::ConditionalEvaluation eval(CGF);
- CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
- eval.begin(CGF);
- CGF.EmitBlock(LHSBlock);
- ComplexPairTy LHS = Visit(E->getTrueExpr());
- LHSBlock = Builder.GetInsertBlock();
- CGF.EmitBranch(ContBlock);
- eval.end(CGF);
- eval.begin(CGF);
- CGF.EmitBlock(RHSBlock);
- ComplexPairTy RHS = Visit(E->getFalseExpr());
- RHSBlock = Builder.GetInsertBlock();
- CGF.EmitBlock(ContBlock);
- eval.end(CGF);
- // Create a PHI node for the real part.
- llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), 2, "cond.r");
- RealPN->addIncoming(LHS.first, LHSBlock);
- RealPN->addIncoming(RHS.first, RHSBlock);
- // Create a PHI node for the imaginary part.
- llvm::PHINode *ImagPN = Builder.CreatePHI(LHS.first->getType(), 2, "cond.i");
- ImagPN->addIncoming(LHS.second, LHSBlock);
- ImagPN->addIncoming(RHS.second, RHSBlock);
- return ComplexPairTy(RealPN, ImagPN);
- }
- ComplexPairTy ComplexExprEmitter::VisitChooseExpr(ChooseExpr *E) {
- return Visit(E->getChosenSubExpr(CGF.getContext()));
- }
- ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
- bool Ignore = TestAndClearIgnoreReal();
- (void)Ignore;
- assert (Ignore == false && "init list ignored");
- Ignore = TestAndClearIgnoreImag();
- (void)Ignore;
- assert (Ignore == false && "init list ignored");
- if (E->getNumInits() == 2) {
- llvm::Value *Real = CGF.EmitScalarExpr(E->getInit(0));
- llvm::Value *Imag = CGF.EmitScalarExpr(E->getInit(1));
- return ComplexPairTy(Real, Imag);
- } else if (E->getNumInits() == 1) {
- return Visit(E->getInit(0));
- }
- // Empty init list intializes to null
- assert(E->getNumInits() == 0 && "Unexpected number of inits");
- QualType Ty = E->getType()->getAs<ComplexType>()->getElementType();
- llvm::Type* LTy = CGF.ConvertType(Ty);
- llvm::Value* zeroConstant = llvm::Constant::getNullValue(LTy);
- return ComplexPairTy(zeroConstant, zeroConstant);
- }
- ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
- llvm::Value *ArgValue = CGF.EmitVAListRef(E->getSubExpr());
- llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, E->getType());
- if (!ArgPtr) {
- CGF.ErrorUnsupported(E, "complex va_arg expression");
- llvm::Type *EltTy =
- CGF.ConvertType(E->getType()->getAs<ComplexType>()->getElementType());
- llvm::Value *U = llvm::UndefValue::get(EltTy);
- return ComplexPairTy(U, U);
- }
- // FIXME Volatility.
- return EmitLoadOfComplex(ArgPtr, false);
- }
- //===----------------------------------------------------------------------===//
- // Entry Point into this File
- //===----------------------------------------------------------------------===//
- /// EmitComplexExpr - Emit the computation of the specified expression of
- /// complex type, ignoring the result.
- ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal,
- bool IgnoreImag) {
- assert(E && E->getType()->isAnyComplexType() &&
- "Invalid complex expression to emit");
- return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag)
- .Visit(const_cast<Expr*>(E));
- }
- /// EmitComplexExprIntoAddr - Emit the computation of the specified expression
- /// of complex type, storing into the specified Value*.
- void CodeGenFunction::EmitComplexExprIntoAddr(const Expr *E,
- llvm::Value *DestAddr,
- bool DestIsVolatile) {
- assert(E && E->getType()->isAnyComplexType() &&
- "Invalid complex expression to emit");
- ComplexExprEmitter Emitter(*this);
- ComplexPairTy Val = Emitter.Visit(const_cast<Expr*>(E));
- Emitter.EmitStoreOfComplex(Val, DestAddr, DestIsVolatile);
- }
- /// StoreComplexToAddr - Store a complex number into the specified address.
- void CodeGenFunction::StoreComplexToAddr(ComplexPairTy V,
- llvm::Value *DestAddr,
- bool DestIsVolatile) {
- ComplexExprEmitter(*this).EmitStoreOfComplex(V, DestAddr, DestIsVolatile);
- }
- /// LoadComplexFromAddr - Load a complex number from the specified address.
- ComplexPairTy CodeGenFunction::LoadComplexFromAddr(llvm::Value *SrcAddr,
- bool SrcIsVolatile) {
- return ComplexExprEmitter(*this).EmitLoadOfComplex(SrcAddr, SrcIsVolatile);
- }
- LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) {
- assert(E->getOpcode() == BO_Assign);
- ComplexPairTy Val; // ignored
- return ComplexExprEmitter(*this).EmitBinAssignLValue(E, Val);
- }
- LValue CodeGenFunction::
- EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) {
- ComplexPairTy(ComplexExprEmitter::*Op)(const ComplexExprEmitter::BinOpInfo &);
- switch (E->getOpcode()) {
- case BO_MulAssign: Op = &ComplexExprEmitter::EmitBinMul; break;
- case BO_DivAssign: Op = &ComplexExprEmitter::EmitBinDiv; break;
- case BO_SubAssign: Op = &ComplexExprEmitter::EmitBinSub; break;
- case BO_AddAssign: Op = &ComplexExprEmitter::EmitBinAdd; break;
- default:
- llvm_unreachable("unexpected complex compound assignment");
- }
- ComplexPairTy Val; // ignored
- return ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
- }
|