1ec2b103cSEd Schouten //===--- CGExprComplex.cpp - Emit LLVM Code for Complex Exprs -------------===//
2ec2b103cSEd Schouten //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ec2b103cSEd Schouten //
7ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
8ec2b103cSEd Schouten //
9ec2b103cSEd Schouten // This contains code to emit Expr nodes with complex types as LLVM code.
10ec2b103cSEd Schouten //
11ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
12ec2b103cSEd Schouten
13706b4fc4SDimitry Andric #include "CGOpenMPRuntime.h"
14ec2b103cSEd Schouten #include "CodeGenFunction.h"
15ec2b103cSEd Schouten #include "CodeGenModule.h"
16cfca06d7SDimitry Andric #include "ConstantEmitter.h"
17ec2b103cSEd Schouten #include "clang/AST/StmtVisitor.h"
1806d4ba38SDimitry Andric #include "llvm/ADT/STLExtras.h"
19809500fcSDimitry Andric #include "llvm/IR/Constants.h"
2006d4ba38SDimitry Andric #include "llvm/IR/Instructions.h"
2106d4ba38SDimitry Andric #include "llvm/IR/MDBuilder.h"
2206d4ba38SDimitry Andric #include "llvm/IR/Metadata.h"
23bfef3995SDimitry Andric #include <algorithm>
24ec2b103cSEd Schouten using namespace clang;
25ec2b103cSEd Schouten using namespace CodeGen;
26ec2b103cSEd Schouten
27ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
28ec2b103cSEd Schouten // Complex Expression Emitter
29ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
30ec2b103cSEd Schouten
31ac9a064cSDimitry Andric namespace llvm {
32ac9a064cSDimitry Andric extern cl::opt<bool> EnableSingleByteCoverage;
33ac9a064cSDimitry Andric } // namespace llvm
34ac9a064cSDimitry Andric
35ec2b103cSEd Schouten typedef CodeGenFunction::ComplexPairTy ComplexPairTy;
36ec2b103cSEd Schouten
37809500fcSDimitry Andric /// Return the complex type that we are meant to emit.
getComplexType(QualType type)38809500fcSDimitry Andric static const ComplexType *getComplexType(QualType type) {
39809500fcSDimitry Andric type = type.getCanonicalType();
40809500fcSDimitry Andric if (const ComplexType *comp = dyn_cast<ComplexType>(type)) {
41809500fcSDimitry Andric return comp;
42809500fcSDimitry Andric } else {
43809500fcSDimitry Andric return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
44809500fcSDimitry Andric }
45809500fcSDimitry Andric }
46809500fcSDimitry Andric
47ec2b103cSEd Schouten namespace {
481569ce68SRoman Divacky class ComplexExprEmitter
49ec2b103cSEd Schouten : public StmtVisitor<ComplexExprEmitter, ComplexPairTy> {
50ec2b103cSEd Schouten CodeGenFunction &CGF;
51ec2b103cSEd Schouten CGBuilderTy &Builder;
52ec2b103cSEd Schouten bool IgnoreReal;
53ec2b103cSEd Schouten bool IgnoreImag;
54ac9a064cSDimitry Andric bool FPHasBeenPromoted;
55ac9a064cSDimitry Andric
56ec2b103cSEd Schouten public:
ComplexExprEmitter(CodeGenFunction & cgf,bool ir=false,bool ii=false)57bca07a45SDimitry Andric ComplexExprEmitter(CodeGenFunction &cgf, bool ir = false, bool ii = false)
58ac9a064cSDimitry Andric : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii),
59ac9a064cSDimitry Andric FPHasBeenPromoted(false) {}
60ec2b103cSEd Schouten
61ec2b103cSEd Schouten //===--------------------------------------------------------------------===//
62ec2b103cSEd Schouten // Utilities
63ec2b103cSEd Schouten //===--------------------------------------------------------------------===//
64ec2b103cSEd Schouten
TestAndClearIgnoreReal()65ec2b103cSEd Schouten bool TestAndClearIgnoreReal() {
66ec2b103cSEd Schouten bool I = IgnoreReal;
67ec2b103cSEd Schouten IgnoreReal = false;
68ec2b103cSEd Schouten return I;
69ec2b103cSEd Schouten }
TestAndClearIgnoreImag()70ec2b103cSEd Schouten bool TestAndClearIgnoreImag() {
71ec2b103cSEd Schouten bool I = IgnoreImag;
72ec2b103cSEd Schouten IgnoreImag = false;
73ec2b103cSEd Schouten return I;
74ec2b103cSEd Schouten }
75ec2b103cSEd Schouten
76ec2b103cSEd Schouten /// EmitLoadOfLValue - Given an expression with complex type that represents a
77ec2b103cSEd Schouten /// value l-value, this method emits the address of the l-value, then loads
78ec2b103cSEd Schouten /// and returns the result.
EmitLoadOfLValue(const Expr * E)79ec2b103cSEd Schouten ComplexPairTy EmitLoadOfLValue(const Expr *E) {
80bfef3995SDimitry Andric return EmitLoadOfLValue(CGF.EmitLValue(E), E->getExprLoc());
81bca07a45SDimitry Andric }
82bca07a45SDimitry Andric
83bfef3995SDimitry Andric ComplexPairTy EmitLoadOfLValue(LValue LV, SourceLocation Loc);
84bca07a45SDimitry Andric
85ec2b103cSEd Schouten /// EmitStoreOfComplex - Store the specified real/imag parts into the
86ec2b103cSEd Schouten /// specified value pointer.
87809500fcSDimitry Andric void EmitStoreOfComplex(ComplexPairTy Val, LValue LV, bool isInit);
88ec2b103cSEd Schouten
8945b53394SDimitry Andric /// Emit a cast from complex value Val to DestType.
90ec2b103cSEd Schouten ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType,
9145b53394SDimitry Andric QualType DestType, SourceLocation Loc);
9245b53394SDimitry Andric /// Emit a cast from scalar value Val to DestType.
93bfef3995SDimitry Andric ComplexPairTy EmitScalarToComplexCast(llvm::Value *Val, QualType SrcType,
9445b53394SDimitry Andric QualType DestType, SourceLocation Loc);
95ec2b103cSEd Schouten
96ec2b103cSEd Schouten //===--------------------------------------------------------------------===//
97ec2b103cSEd Schouten // Visitor Methods
98ec2b103cSEd Schouten //===--------------------------------------------------------------------===//
99ec2b103cSEd Schouten
Visit(Expr * E)100bca07a45SDimitry Andric ComplexPairTy Visit(Expr *E) {
1015e20cdd8SDimitry Andric ApplyDebugLocation DL(CGF, E);
102bca07a45SDimitry Andric return StmtVisitor<ComplexExprEmitter, ComplexPairTy>::Visit(E);
103bca07a45SDimitry Andric }
104bca07a45SDimitry Andric
VisitStmt(Stmt * S)105ec2b103cSEd Schouten ComplexPairTy VisitStmt(Stmt *S) {
106cfca06d7SDimitry Andric S->dump(llvm::errs(), CGF.getContext());
10736981b17SDimitry Andric llvm_unreachable("Stmt can't have complex result type!");
108ec2b103cSEd Schouten }
109ec2b103cSEd Schouten ComplexPairTy VisitExpr(Expr *S);
VisitConstantExpr(ConstantExpr * E)110676fbe81SDimitry Andric ComplexPairTy VisitConstantExpr(ConstantExpr *E) {
111cfca06d7SDimitry Andric if (llvm::Constant *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E))
112cfca06d7SDimitry Andric return ComplexPairTy(Result->getAggregateElement(0U),
113cfca06d7SDimitry Andric Result->getAggregateElement(1U));
114676fbe81SDimitry Andric return Visit(E->getSubExpr());
115676fbe81SDimitry Andric }
VisitParenExpr(ParenExpr * PE)116ec2b103cSEd Schouten ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());}
VisitGenericSelectionExpr(GenericSelectionExpr * GE)11701af97d3SDimitry Andric ComplexPairTy VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
11801af97d3SDimitry Andric return Visit(GE->getResultExpr());
11901af97d3SDimitry Andric }
120ec2b103cSEd Schouten ComplexPairTy VisitImaginaryLiteral(const ImaginaryLiteral *IL);
121180abc3dSDimitry Andric ComplexPairTy
VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr * PE)122180abc3dSDimitry Andric VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE) {
123180abc3dSDimitry Andric return Visit(PE->getReplacement());
124180abc3dSDimitry Andric }
VisitCoawaitExpr(CoawaitExpr * S)1257442d6faSDimitry Andric ComplexPairTy VisitCoawaitExpr(CoawaitExpr *S) {
1267442d6faSDimitry Andric return CGF.EmitCoawaitExpr(*S).getComplexVal();
1277442d6faSDimitry Andric }
VisitCoyieldExpr(CoyieldExpr * S)1287442d6faSDimitry Andric ComplexPairTy VisitCoyieldExpr(CoyieldExpr *S) {
1297442d6faSDimitry Andric return CGF.EmitCoyieldExpr(*S).getComplexVal();
1307442d6faSDimitry Andric }
VisitUnaryCoawait(const UnaryOperator * E)1317442d6faSDimitry Andric ComplexPairTy VisitUnaryCoawait(const UnaryOperator *E) {
1327442d6faSDimitry Andric return Visit(E->getSubExpr());
1337442d6faSDimitry Andric }
1347442d6faSDimitry Andric
emitConstant(const CodeGenFunction::ConstantEmission & Constant,Expr * E)135461a67faSDimitry Andric ComplexPairTy emitConstant(const CodeGenFunction::ConstantEmission &Constant,
136461a67faSDimitry Andric Expr *E) {
137461a67faSDimitry Andric assert(Constant && "not a constant");
138461a67faSDimitry Andric if (Constant.isReference())
139461a67faSDimitry Andric return EmitLoadOfLValue(Constant.getReferenceLValue(CGF, E),
140bfef3995SDimitry Andric E->getExprLoc());
141dbe13110SDimitry Andric
142461a67faSDimitry Andric llvm::Constant *pair = Constant.getValue();
143bfef3995SDimitry Andric return ComplexPairTy(pair->getAggregateElement(0U),
144bfef3995SDimitry Andric pair->getAggregateElement(1U));
145dbe13110SDimitry Andric }
146461a67faSDimitry Andric
147461a67faSDimitry Andric // l-values.
VisitDeclRefExpr(DeclRefExpr * E)148461a67faSDimitry Andric ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) {
149461a67faSDimitry Andric if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E))
150461a67faSDimitry Andric return emitConstant(Constant, E);
1517ef7bab7SEd Schouten return EmitLoadOfLValue(E);
1527ef7bab7SEd Schouten }
VisitObjCIvarRefExpr(ObjCIvarRefExpr * E)153dbe13110SDimitry Andric ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
1547ef7bab7SEd Schouten return EmitLoadOfLValue(E);
1557ef7bab7SEd Schouten }
VisitObjCMessageExpr(ObjCMessageExpr * E)1567ef7bab7SEd Schouten ComplexPairTy VisitObjCMessageExpr(ObjCMessageExpr *E) {
1577ef7bab7SEd Schouten return CGF.EmitObjCMessageExpr(E).getComplexVal();
1587ef7bab7SEd Schouten }
VisitArraySubscriptExpr(Expr * E)159ec2b103cSEd Schouten ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
VisitMemberExpr(MemberExpr * ME)160461a67faSDimitry Andric ComplexPairTy VisitMemberExpr(MemberExpr *ME) {
161461a67faSDimitry Andric if (CodeGenFunction::ConstantEmission Constant =
162461a67faSDimitry Andric CGF.tryEmitAsConstant(ME)) {
163461a67faSDimitry Andric CGF.EmitIgnoredExpr(ME->getBase());
164461a67faSDimitry Andric return emitConstant(Constant, ME);
165461a67faSDimitry Andric }
166461a67faSDimitry Andric return EmitLoadOfLValue(ME);
167461a67faSDimitry Andric }
VisitOpaqueValueExpr(OpaqueValueExpr * E)168bca07a45SDimitry Andric ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
169bca07a45SDimitry Andric if (E->isGLValue())
17048675466SDimitry Andric return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E),
17148675466SDimitry Andric E->getExprLoc());
17248675466SDimitry Andric return CGF.getOrCreateOpaqueRValueMapping(E).getComplexVal();
173bca07a45SDimitry Andric }
174ec2b103cSEd Schouten
VisitPseudoObjectExpr(PseudoObjectExpr * E)175dbe13110SDimitry Andric ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) {
176dbe13110SDimitry Andric return CGF.EmitPseudoObjectRValue(E).getComplexVal();
177dbe13110SDimitry Andric }
178dbe13110SDimitry Andric
179ec2b103cSEd Schouten // FIXME: CompoundLiteralExpr
180ec2b103cSEd Schouten
18106d4ba38SDimitry Andric ComplexPairTy EmitCast(CastKind CK, Expr *Op, QualType DestTy);
VisitImplicitCastExpr(ImplicitCastExpr * E)182ec2b103cSEd Schouten ComplexPairTy VisitImplicitCastExpr(ImplicitCastExpr *E) {
183ec2b103cSEd Schouten // Unlike for scalars, we don't have to worry about function->ptr demotion
184ec2b103cSEd Schouten // here.
185b1c73532SDimitry Andric if (E->changesVolatileQualification())
186b1c73532SDimitry Andric return EmitLoadOfLValue(E);
1874e58654bSRoman Divacky return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
188ec2b103cSEd Schouten }
VisitCastExpr(CastExpr * E)189ec2b103cSEd Schouten ComplexPairTy VisitCastExpr(CastExpr *E) {
19045b53394SDimitry Andric if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E))
19145b53394SDimitry Andric CGF.CGM.EmitExplicitCastExprType(ECE, &CGF);
192b1c73532SDimitry Andric if (E->changesVolatileQualification())
193b1c73532SDimitry Andric return EmitLoadOfLValue(E);
1944e58654bSRoman Divacky return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
195ec2b103cSEd Schouten }
196ec2b103cSEd Schouten ComplexPairTy VisitCallExpr(const CallExpr *E);
197ec2b103cSEd Schouten ComplexPairTy VisitStmtExpr(const StmtExpr *E);
198ec2b103cSEd Schouten
199ec2b103cSEd Schouten // Operators.
VisitPrePostIncDec(const UnaryOperator * E,bool isInc,bool isPre)200ec2b103cSEd Schouten ComplexPairTy VisitPrePostIncDec(const UnaryOperator *E,
201ee791ddeSRoman Divacky bool isInc, bool isPre) {
202ee791ddeSRoman Divacky LValue LV = CGF.EmitLValue(E->getSubExpr());
203ee791ddeSRoman Divacky return CGF.EmitComplexPrePostIncDec(E, LV, isInc, isPre);
204ee791ddeSRoman Divacky }
VisitUnaryPostDec(const UnaryOperator * E)205ec2b103cSEd Schouten ComplexPairTy VisitUnaryPostDec(const UnaryOperator *E) {
206ec2b103cSEd Schouten return VisitPrePostIncDec(E, false, false);
207ec2b103cSEd Schouten }
VisitUnaryPostInc(const UnaryOperator * E)208ec2b103cSEd Schouten ComplexPairTy VisitUnaryPostInc(const UnaryOperator *E) {
209ec2b103cSEd Schouten return VisitPrePostIncDec(E, true, false);
210ec2b103cSEd Schouten }
VisitUnaryPreDec(const UnaryOperator * E)211ec2b103cSEd Schouten ComplexPairTy VisitUnaryPreDec(const UnaryOperator *E) {
212ec2b103cSEd Schouten return VisitPrePostIncDec(E, false, true);
213ec2b103cSEd Schouten }
VisitUnaryPreInc(const UnaryOperator * E)214ec2b103cSEd Schouten ComplexPairTy VisitUnaryPreInc(const UnaryOperator *E) {
215ec2b103cSEd Schouten return VisitPrePostIncDec(E, true, true);
216ec2b103cSEd Schouten }
VisitUnaryDeref(const Expr * E)217ec2b103cSEd Schouten ComplexPairTy VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); }
218e3b55780SDimitry Andric
219e3b55780SDimitry Andric ComplexPairTy VisitUnaryPlus(const UnaryOperator *E,
220e3b55780SDimitry Andric QualType PromotionType = QualType());
221e3b55780SDimitry Andric ComplexPairTy VisitPlus(const UnaryOperator *E, QualType PromotionType);
222e3b55780SDimitry Andric ComplexPairTy VisitUnaryMinus(const UnaryOperator *E,
223e3b55780SDimitry Andric QualType PromotionType = QualType());
224e3b55780SDimitry Andric ComplexPairTy VisitMinus(const UnaryOperator *E, QualType PromotionType);
225ec2b103cSEd Schouten ComplexPairTy VisitUnaryNot (const UnaryOperator *E);
226ec2b103cSEd Schouten // LNot,Real,Imag never return complex.
VisitUnaryExtension(const UnaryOperator * E)227ec2b103cSEd Schouten ComplexPairTy VisitUnaryExtension(const UnaryOperator *E) {
228ec2b103cSEd Schouten return Visit(E->getSubExpr());
229ec2b103cSEd Schouten }
VisitCXXDefaultArgExpr(CXXDefaultArgExpr * DAE)230ec2b103cSEd Schouten ComplexPairTy VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
23122989816SDimitry Andric CodeGenFunction::CXXDefaultArgExprScope Scope(CGF, DAE);
232ec2b103cSEd Schouten return Visit(DAE->getExpr());
233ec2b103cSEd Schouten }
VisitCXXDefaultInitExpr(CXXDefaultInitExpr * DIE)2346a037251SDimitry Andric ComplexPairTy VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
23522989816SDimitry Andric CodeGenFunction::CXXDefaultInitExprScope Scope(CGF, DIE);
2366a037251SDimitry Andric return Visit(DIE->getExpr());
2376a037251SDimitry Andric }
VisitExprWithCleanups(ExprWithCleanups * E)238bca07a45SDimitry Andric ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) {
239dbe13110SDimitry Andric CodeGenFunction::RunCleanupsScope Scope(CGF);
2407442d6faSDimitry Andric ComplexPairTy Vals = Visit(E->getSubExpr());
2417442d6faSDimitry Andric // Defend against dominance problems caused by jumps out of expression
2427442d6faSDimitry Andric // evaluation through the shared cleanup block.
2437442d6faSDimitry Andric Scope.ForceCleanup({&Vals.first, &Vals.second});
2447442d6faSDimitry Andric return Vals;
245ec2b103cSEd Schouten }
VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr * E)2464ba67500SRoman Divacky ComplexPairTy VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
247ec2b103cSEd Schouten assert(E->getType()->isAnyComplexType() && "Expected complex type!");
248809500fcSDimitry Andric QualType Elem = E->getType()->castAs<ComplexType>()->getElementType();
249ec2b103cSEd Schouten llvm::Constant *Null = llvm::Constant::getNullValue(CGF.ConvertType(Elem));
250ec2b103cSEd Schouten return ComplexPairTy(Null, Null);
251ec2b103cSEd Schouten }
VisitImplicitValueInitExpr(ImplicitValueInitExpr * E)252ec2b103cSEd Schouten ComplexPairTy VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
253ec2b103cSEd Schouten assert(E->getType()->isAnyComplexType() && "Expected complex type!");
254809500fcSDimitry Andric QualType Elem = E->getType()->castAs<ComplexType>()->getElementType();
2554c8b2481SRoman Divacky llvm::Constant *Null =
2564c8b2481SRoman Divacky llvm::Constant::getNullValue(CGF.ConvertType(Elem));
257ec2b103cSEd Schouten return ComplexPairTy(Null, Null);
258ec2b103cSEd Schouten }
259ec2b103cSEd Schouten
260ec2b103cSEd Schouten struct BinOpInfo {
261ec2b103cSEd Schouten ComplexPairTy LHS;
262ec2b103cSEd Schouten ComplexPairTy RHS;
263ec2b103cSEd Schouten QualType Ty; // Computation Type.
264e3b55780SDimitry Andric FPOptions FPFeatures;
265ec2b103cSEd Schouten };
266ec2b103cSEd Schouten
267e3b55780SDimitry Andric BinOpInfo EmitBinOps(const BinaryOperator *E,
268e3b55780SDimitry Andric QualType PromotionTy = QualType());
269e3b55780SDimitry Andric ComplexPairTy EmitPromoted(const Expr *E, QualType PromotionTy);
270e3b55780SDimitry Andric ComplexPairTy EmitPromotedComplexOperand(const Expr *E, QualType PromotionTy);
271bca07a45SDimitry Andric LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E,
272bca07a45SDimitry Andric ComplexPairTy (ComplexExprEmitter::*Func)
273bca07a45SDimitry Andric (const BinOpInfo &),
274bfef3995SDimitry Andric RValue &Val);
275ec2b103cSEd Schouten ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E,
276ec2b103cSEd Schouten ComplexPairTy (ComplexExprEmitter::*Func)
277ec2b103cSEd Schouten (const BinOpInfo &));
278ec2b103cSEd Schouten
279ec2b103cSEd Schouten ComplexPairTy EmitBinAdd(const BinOpInfo &Op);
280ec2b103cSEd Schouten ComplexPairTy EmitBinSub(const BinOpInfo &Op);
281ec2b103cSEd Schouten ComplexPairTy EmitBinMul(const BinOpInfo &Op);
282ec2b103cSEd Schouten ComplexPairTy EmitBinDiv(const BinOpInfo &Op);
283312c0ed1SDimitry Andric ComplexPairTy EmitAlgebraicDiv(llvm::Value *A, llvm::Value *B, llvm::Value *C,
284312c0ed1SDimitry Andric llvm::Value *D);
285312c0ed1SDimitry Andric ComplexPairTy EmitRangeReductionDiv(llvm::Value *A, llvm::Value *B,
286312c0ed1SDimitry Andric llvm::Value *C, llvm::Value *D);
287ec2b103cSEd Schouten
28806d4ba38SDimitry Andric ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName,
28906d4ba38SDimitry Andric const BinOpInfo &Op);
29006d4ba38SDimitry Andric
GetHigherPrecisionFPType(QualType ElementType)291ac9a064cSDimitry Andric QualType GetHigherPrecisionFPType(QualType ElementType) {
292ac9a064cSDimitry Andric const auto *CurrentBT = cast<BuiltinType>(ElementType);
293ac9a064cSDimitry Andric switch (CurrentBT->getKind()) {
294ac9a064cSDimitry Andric case BuiltinType::Kind::Float16:
295ac9a064cSDimitry Andric return CGF.getContext().FloatTy;
296ac9a064cSDimitry Andric case BuiltinType::Kind::Float:
297ac9a064cSDimitry Andric case BuiltinType::Kind::BFloat16:
298ac9a064cSDimitry Andric return CGF.getContext().DoubleTy;
299ac9a064cSDimitry Andric case BuiltinType::Kind::Double:
300ac9a064cSDimitry Andric return CGF.getContext().LongDoubleTy;
301ac9a064cSDimitry Andric default:
302ac9a064cSDimitry Andric return ElementType;
303ac9a064cSDimitry Andric }
304ac9a064cSDimitry Andric }
305ac9a064cSDimitry Andric
HigherPrecisionTypeForComplexArithmetic(QualType ElementType,bool IsDivOpCode)306ac9a064cSDimitry Andric QualType HigherPrecisionTypeForComplexArithmetic(QualType ElementType,
307ac9a064cSDimitry Andric bool IsDivOpCode) {
308ac9a064cSDimitry Andric QualType HigherElementType = GetHigherPrecisionFPType(ElementType);
309ac9a064cSDimitry Andric const llvm::fltSemantics &ElementTypeSemantics =
310ac9a064cSDimitry Andric CGF.getContext().getFloatTypeSemantics(ElementType);
311ac9a064cSDimitry Andric const llvm::fltSemantics &HigherElementTypeSemantics =
312ac9a064cSDimitry Andric CGF.getContext().getFloatTypeSemantics(HigherElementType);
313ac9a064cSDimitry Andric // Check that the promoted type can handle the intermediate values without
314ac9a064cSDimitry Andric // overflowing. This can be interpreted as:
315ac9a064cSDimitry Andric // (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal) * 2 <=
316ac9a064cSDimitry Andric // LargerType.LargestFiniteVal.
317ac9a064cSDimitry Andric // In terms of exponent it gives this formula:
318ac9a064cSDimitry Andric // (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal
319ac9a064cSDimitry Andric // doubles the exponent of SmallerType.LargestFiniteVal)
320ac9a064cSDimitry Andric if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <=
321ac9a064cSDimitry Andric llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
322ac9a064cSDimitry Andric FPHasBeenPromoted = true;
323ac9a064cSDimitry Andric return CGF.getContext().getComplexType(HigherElementType);
324ac9a064cSDimitry Andric } else {
325ac9a064cSDimitry Andric DiagnosticsEngine &Diags = CGF.CGM.getDiags();
326ac9a064cSDimitry Andric Diags.Report(diag::warn_next_larger_fp_type_same_size_than_fp);
327ac9a064cSDimitry Andric return QualType();
328ac9a064cSDimitry Andric }
329ac9a064cSDimitry Andric }
330ac9a064cSDimitry Andric
getPromotionType(FPOptionsOverride Features,QualType Ty,bool IsDivOpCode=false)331ac9a064cSDimitry Andric QualType getPromotionType(FPOptionsOverride Features, QualType Ty,
332ac9a064cSDimitry Andric bool IsDivOpCode = false) {
333e3b55780SDimitry Andric if (auto *CT = Ty->getAs<ComplexType>()) {
334e3b55780SDimitry Andric QualType ElementType = CT->getElementType();
335ac9a064cSDimitry Andric bool IsFloatingType = ElementType->isFloatingType();
336ac9a064cSDimitry Andric bool IsComplexRangePromoted = CGF.getLangOpts().getComplexRange() ==
337ac9a064cSDimitry Andric LangOptions::ComplexRangeKind::CX_Promoted;
338ac9a064cSDimitry Andric bool HasNoComplexRangeOverride = !Features.hasComplexRangeOverride();
339ac9a064cSDimitry Andric bool HasMatchingComplexRange = Features.hasComplexRangeOverride() &&
340ac9a064cSDimitry Andric Features.getComplexRangeOverride() ==
341ac9a064cSDimitry Andric CGF.getLangOpts().getComplexRange();
342ac9a064cSDimitry Andric
343ac9a064cSDimitry Andric if (IsDivOpCode && IsFloatingType && IsComplexRangePromoted &&
344ac9a064cSDimitry Andric (HasNoComplexRangeOverride || HasMatchingComplexRange))
345ac9a064cSDimitry Andric return HigherPrecisionTypeForComplexArithmetic(ElementType,
346ac9a064cSDimitry Andric IsDivOpCode);
347e3b55780SDimitry Andric if (ElementType.UseExcessPrecision(CGF.getContext()))
348e3b55780SDimitry Andric return CGF.getContext().getComplexType(CGF.getContext().FloatTy);
349ec2b103cSEd Schouten }
350e3b55780SDimitry Andric if (Ty.UseExcessPrecision(CGF.getContext()))
351e3b55780SDimitry Andric return CGF.getContext().FloatTy;
352e3b55780SDimitry Andric return QualType();
353ec2b103cSEd Schouten }
354e3b55780SDimitry Andric
355e3b55780SDimitry Andric #define HANDLEBINOP(OP) \
356e3b55780SDimitry Andric ComplexPairTy VisitBin##OP(const BinaryOperator *E) { \
357ac9a064cSDimitry Andric QualType promotionTy = getPromotionType( \
358ac9a064cSDimitry Andric E->getStoredFPFeaturesOrDefault(), E->getType(), \
359ac9a064cSDimitry Andric (E->getOpcode() == BinaryOperatorKind::BO_Div) ? true : false); \
360e3b55780SDimitry Andric ComplexPairTy result = EmitBin##OP(EmitBinOps(E, promotionTy)); \
361e3b55780SDimitry Andric if (!promotionTy.isNull()) \
362ac9a064cSDimitry Andric result = CGF.EmitUnPromotedValue(result, E->getType()); \
363e3b55780SDimitry Andric return result; \
364bca07a45SDimitry Andric }
365e3b55780SDimitry Andric
366e3b55780SDimitry Andric HANDLEBINOP(Mul)
HANDLEBINOP(Div)367e3b55780SDimitry Andric HANDLEBINOP(Div)
368e3b55780SDimitry Andric HANDLEBINOP(Add)
369e3b55780SDimitry Andric HANDLEBINOP(Sub)
370e3b55780SDimitry Andric #undef HANDLEBINOP
371ec2b103cSEd Schouten
372519fc96cSDimitry Andric ComplexPairTy VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *E) {
373519fc96cSDimitry Andric return Visit(E->getSemanticForm());
374519fc96cSDimitry Andric }
375519fc96cSDimitry Andric
376ec2b103cSEd Schouten // Compound assignments.
VisitBinAddAssign(const CompoundAssignOperator * E)377ec2b103cSEd Schouten ComplexPairTy VisitBinAddAssign(const CompoundAssignOperator *E) {
378ec2b103cSEd Schouten return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinAdd);
379ec2b103cSEd Schouten }
VisitBinSubAssign(const CompoundAssignOperator * E)380ec2b103cSEd Schouten ComplexPairTy VisitBinSubAssign(const CompoundAssignOperator *E) {
381ec2b103cSEd Schouten return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinSub);
382ec2b103cSEd Schouten }
VisitBinMulAssign(const CompoundAssignOperator * E)383ec2b103cSEd Schouten ComplexPairTy VisitBinMulAssign(const CompoundAssignOperator *E) {
384ec2b103cSEd Schouten return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinMul);
385ec2b103cSEd Schouten }
VisitBinDivAssign(const CompoundAssignOperator * E)386ec2b103cSEd Schouten ComplexPairTy VisitBinDivAssign(const CompoundAssignOperator *E) {
387ec2b103cSEd Schouten return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinDiv);
388ec2b103cSEd Schouten }
389ec2b103cSEd Schouten
390ec2b103cSEd Schouten // GCC rejects rem/and/or/xor for integer complex.
391ec2b103cSEd Schouten // Logical and/or always return int, never complex.
392ec2b103cSEd Schouten
393ec2b103cSEd Schouten // No comparisons produce a complex result.
394bca07a45SDimitry Andric
395bca07a45SDimitry Andric LValue EmitBinAssignLValue(const BinaryOperator *E,
396bca07a45SDimitry Andric ComplexPairTy &Val);
397ec2b103cSEd Schouten ComplexPairTy VisitBinAssign (const BinaryOperator *E);
398ec2b103cSEd Schouten ComplexPairTy VisitBinComma (const BinaryOperator *E);
399ec2b103cSEd Schouten
400ec2b103cSEd Schouten
401bca07a45SDimitry Andric ComplexPairTy
402bca07a45SDimitry Andric VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
403ec2b103cSEd Schouten ComplexPairTy VisitChooseExpr(ChooseExpr *CE);
404ec2b103cSEd Schouten
405ec2b103cSEd Schouten ComplexPairTy VisitInitListExpr(InitListExpr *E);
406ec2b103cSEd Schouten
VisitCompoundLiteralExpr(CompoundLiteralExpr * E)407dbe13110SDimitry Andric ComplexPairTy VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
408dbe13110SDimitry Andric return EmitLoadOfLValue(E);
409dbe13110SDimitry Andric }
410dbe13110SDimitry Andric
411ec2b103cSEd Schouten ComplexPairTy VisitVAArgExpr(VAArgExpr *E);
41236981b17SDimitry Andric
VisitAtomicExpr(AtomicExpr * E)41336981b17SDimitry Andric ComplexPairTy VisitAtomicExpr(AtomicExpr *E) {
41436981b17SDimitry Andric return CGF.EmitAtomicExpr(E).getComplexVal();
41536981b17SDimitry Andric }
416ac9a064cSDimitry Andric
VisitPackIndexingExpr(PackIndexingExpr * E)417ac9a064cSDimitry Andric ComplexPairTy VisitPackIndexingExpr(PackIndexingExpr *E) {
418ac9a064cSDimitry Andric return Visit(E->getSelectedExpr());
419ac9a064cSDimitry Andric }
420ec2b103cSEd Schouten };
421ec2b103cSEd Schouten } // end anonymous namespace.
422ec2b103cSEd Schouten
423ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
424ec2b103cSEd Schouten // Utilities
425ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
426ec2b103cSEd Schouten
emitAddrOfRealComponent(Address addr,QualType complexType)42745b53394SDimitry Andric Address CodeGenFunction::emitAddrOfRealComponent(Address addr,
42845b53394SDimitry Andric QualType complexType) {
42922989816SDimitry Andric return Builder.CreateStructGEP(addr, 0, addr.getName() + ".realp");
43045b53394SDimitry Andric }
43145b53394SDimitry Andric
emitAddrOfImagComponent(Address addr,QualType complexType)43245b53394SDimitry Andric Address CodeGenFunction::emitAddrOfImagComponent(Address addr,
43345b53394SDimitry Andric QualType complexType) {
43422989816SDimitry Andric return Builder.CreateStructGEP(addr, 1, addr.getName() + ".imagp");
43545b53394SDimitry Andric }
43645b53394SDimitry Andric
437809500fcSDimitry Andric /// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to
438ec2b103cSEd Schouten /// load the real and imaginary pieces, returning them as Real/Imag.
EmitLoadOfLValue(LValue lvalue,SourceLocation loc)439bfef3995SDimitry Andric ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue,
440bfef3995SDimitry Andric SourceLocation loc) {
441809500fcSDimitry Andric assert(lvalue.isSimple() && "non-simple complex l-value?");
442809500fcSDimitry Andric if (lvalue.getType()->isAtomicType())
443bfef3995SDimitry Andric return CGF.EmitAtomicLoad(lvalue, loc).getComplexVal();
444809500fcSDimitry Andric
445ac9a064cSDimitry Andric Address SrcPtr = lvalue.getAddress();
446809500fcSDimitry Andric bool isVolatile = lvalue.isVolatileQualified();
447809500fcSDimitry Andric
4489f4dbff6SDimitry Andric llvm::Value *Real = nullptr, *Imag = nullptr;
449ec2b103cSEd Schouten
450bca07a45SDimitry Andric if (!IgnoreReal || isVolatile) {
45145b53394SDimitry Andric Address RealP = CGF.emitAddrOfRealComponent(SrcPtr, lvalue.getType());
45245b53394SDimitry Andric Real = Builder.CreateLoad(RealP, isVolatile, SrcPtr.getName() + ".real");
453ec2b103cSEd Schouten }
454ec2b103cSEd Schouten
455bca07a45SDimitry Andric if (!IgnoreImag || isVolatile) {
45645b53394SDimitry Andric Address ImagP = CGF.emitAddrOfImagComponent(SrcPtr, lvalue.getType());
45745b53394SDimitry Andric Imag = Builder.CreateLoad(ImagP, isVolatile, SrcPtr.getName() + ".imag");
458ec2b103cSEd Schouten }
45945b53394SDimitry Andric
460ec2b103cSEd Schouten return ComplexPairTy(Real, Imag);
461ec2b103cSEd Schouten }
462ec2b103cSEd Schouten
463ec2b103cSEd Schouten /// EmitStoreOfComplex - Store the specified real/imag parts into the
464ec2b103cSEd Schouten /// specified value pointer.
EmitStoreOfComplex(ComplexPairTy Val,LValue lvalue,bool isInit)46506d4ba38SDimitry Andric void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue,
466809500fcSDimitry Andric bool isInit) {
4675e20cdd8SDimitry Andric if (lvalue.getType()->isAtomicType() ||
4685e20cdd8SDimitry Andric (!isInit && CGF.LValueIsSuitableForInlineAtomic(lvalue)))
469809500fcSDimitry Andric return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit);
470809500fcSDimitry Andric
471ac9a064cSDimitry Andric Address Ptr = lvalue.getAddress();
47245b53394SDimitry Andric Address RealPtr = CGF.emitAddrOfRealComponent(Ptr, lvalue.getType());
47345b53394SDimitry Andric Address ImagPtr = CGF.emitAddrOfImagComponent(Ptr, lvalue.getType());
474ec2b103cSEd Schouten
47545b53394SDimitry Andric Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
47645b53394SDimitry Andric Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
477ec2b103cSEd Schouten }
478ec2b103cSEd Schouten
479ec2b103cSEd Schouten
480ec2b103cSEd Schouten
481ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
482ec2b103cSEd Schouten // Visitor Methods
483ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
484ec2b103cSEd Schouten
VisitExpr(Expr * E)485ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) {
486ec2b103cSEd Schouten CGF.ErrorUnsupported(E, "complex expression");
48736981b17SDimitry Andric llvm::Type *EltTy =
488809500fcSDimitry Andric CGF.ConvertType(getComplexType(E->getType())->getElementType());
489ec2b103cSEd Schouten llvm::Value *U = llvm::UndefValue::get(EltTy);
490ec2b103cSEd Schouten return ComplexPairTy(U, U);
491ec2b103cSEd Schouten }
492ec2b103cSEd Schouten
493ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::
VisitImaginaryLiteral(const ImaginaryLiteral * IL)494ec2b103cSEd Schouten VisitImaginaryLiteral(const ImaginaryLiteral *IL) {
495ec2b103cSEd Schouten llvm::Value *Imag = CGF.EmitScalarExpr(IL->getSubExpr());
496bca07a45SDimitry Andric return ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag);
497ec2b103cSEd Schouten }
498ec2b103cSEd Schouten
499ec2b103cSEd Schouten
VisitCallExpr(const CallExpr * E)500ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) {
5015e20cdd8SDimitry Andric if (E->getCallReturnType(CGF.getContext())->isReferenceType())
502ec2b103cSEd Schouten return EmitLoadOfLValue(E);
503ec2b103cSEd Schouten
504ec2b103cSEd Schouten return CGF.EmitCallExpr(E).getComplexVal();
505ec2b103cSEd Schouten }
506ec2b103cSEd Schouten
VisitStmtExpr(const StmtExpr * E)507ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) {
508bca07a45SDimitry Andric CodeGenFunction::StmtExprEvaluation eval(CGF);
50945b53394SDimitry Andric Address RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(), true);
51045b53394SDimitry Andric assert(RetAlloca.isValid() && "Expected complex return value");
511bfef3995SDimitry Andric return EmitLoadOfLValue(CGF.MakeAddrLValue(RetAlloca, E->getType()),
512bfef3995SDimitry Andric E->getExprLoc());
513ec2b103cSEd Schouten }
514ec2b103cSEd Schouten
51545b53394SDimitry Andric /// Emit a cast from complex value Val to DestType.
EmitComplexToComplexCast(ComplexPairTy Val,QualType SrcType,QualType DestType,SourceLocation Loc)516ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val,
517ec2b103cSEd Schouten QualType SrcType,
51845b53394SDimitry Andric QualType DestType,
51945b53394SDimitry Andric SourceLocation Loc) {
520ec2b103cSEd Schouten // Get the src/dest element type.
521809500fcSDimitry Andric SrcType = SrcType->castAs<ComplexType>()->getElementType();
522809500fcSDimitry Andric DestType = DestType->castAs<ComplexType>()->getElementType();
523ec2b103cSEd Schouten
524ec2b103cSEd Schouten // C99 6.3.1.6: When a value of complex type is converted to another
525ec2b103cSEd Schouten // complex type, both the real and imaginary parts follow the conversion
526ec2b103cSEd Schouten // rules for the corresponding real types.
527cfca06d7SDimitry Andric if (Val.first)
52845b53394SDimitry Andric Val.first = CGF.EmitScalarConversion(Val.first, SrcType, DestType, Loc);
529cfca06d7SDimitry Andric if (Val.second)
53045b53394SDimitry Andric Val.second = CGF.EmitScalarConversion(Val.second, SrcType, DestType, Loc);
531ec2b103cSEd Schouten return Val;
532ec2b103cSEd Schouten }
533ec2b103cSEd Schouten
EmitScalarToComplexCast(llvm::Value * Val,QualType SrcType,QualType DestType,SourceLocation Loc)534bfef3995SDimitry Andric ComplexPairTy ComplexExprEmitter::EmitScalarToComplexCast(llvm::Value *Val,
535bfef3995SDimitry Andric QualType SrcType,
53645b53394SDimitry Andric QualType DestType,
53745b53394SDimitry Andric SourceLocation Loc) {
538bfef3995SDimitry Andric // Convert the input element to the element type of the complex.
539bfef3995SDimitry Andric DestType = DestType->castAs<ComplexType>()->getElementType();
54045b53394SDimitry Andric Val = CGF.EmitScalarConversion(Val, SrcType, DestType, Loc);
541bfef3995SDimitry Andric
542bfef3995SDimitry Andric // Return (realval, 0).
543bfef3995SDimitry Andric return ComplexPairTy(Val, llvm::Constant::getNullValue(Val->getType()));
544bfef3995SDimitry Andric }
545bfef3995SDimitry Andric
EmitCast(CastKind CK,Expr * Op,QualType DestTy)54606d4ba38SDimitry Andric ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
5474e58654bSRoman Divacky QualType DestTy) {
548bca07a45SDimitry Andric switch (CK) {
549180abc3dSDimitry Andric case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!");
550180abc3dSDimitry Andric
551dbe13110SDimitry Andric // Atomic to non-atomic casts may be more than a no-op for some platforms and
552dbe13110SDimitry Andric // for some types.
553dbe13110SDimitry Andric case CK_AtomicToNonAtomic:
554dbe13110SDimitry Andric case CK_NonAtomicToAtomic:
555bca07a45SDimitry Andric case CK_NoOp:
556bca07a45SDimitry Andric case CK_LValueToRValue:
557180abc3dSDimitry Andric case CK_UserDefinedConversion:
558bca07a45SDimitry Andric return Visit(Op);
559bca07a45SDimitry Andric
560180abc3dSDimitry Andric case CK_LValueBitCast: {
561809500fcSDimitry Andric LValue origLV = CGF.EmitLValue(Op);
562ac9a064cSDimitry Andric Address V = origLV.getAddress().withElementType(CGF.ConvertType(DestTy));
56345b53394SDimitry Andric return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy), Op->getExprLoc());
5644e58654bSRoman Divacky }
5654e58654bSRoman Divacky
56622989816SDimitry Andric case CK_LValueToRValueBitCast: {
56722989816SDimitry Andric LValue SourceLVal = CGF.EmitLValue(Op);
568ac9a064cSDimitry Andric Address Addr =
569ac9a064cSDimitry Andric SourceLVal.getAddress().withElementType(CGF.ConvertTypeForMem(DestTy));
57022989816SDimitry Andric LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy);
57122989816SDimitry Andric DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo());
57222989816SDimitry Andric return EmitLoadOfLValue(DestLV, Op->getExprLoc());
57322989816SDimitry Andric }
57422989816SDimitry Andric
575180abc3dSDimitry Andric case CK_BitCast:
576180abc3dSDimitry Andric case CK_BaseToDerived:
577180abc3dSDimitry Andric case CK_DerivedToBase:
578180abc3dSDimitry Andric case CK_UncheckedDerivedToBase:
579180abc3dSDimitry Andric case CK_Dynamic:
580180abc3dSDimitry Andric case CK_ToUnion:
581180abc3dSDimitry Andric case CK_ArrayToPointerDecay:
582180abc3dSDimitry Andric case CK_FunctionToPointerDecay:
583180abc3dSDimitry Andric case CK_NullToPointer:
584180abc3dSDimitry Andric case CK_NullToMemberPointer:
585180abc3dSDimitry Andric case CK_BaseToDerivedMemberPointer:
586180abc3dSDimitry Andric case CK_DerivedToBaseMemberPointer:
587180abc3dSDimitry Andric case CK_MemberPointerToBoolean:
588dbe13110SDimitry Andric case CK_ReinterpretMemberPointer:
589180abc3dSDimitry Andric case CK_ConstructorConversion:
590180abc3dSDimitry Andric case CK_IntegralToPointer:
591180abc3dSDimitry Andric case CK_PointerToIntegral:
592180abc3dSDimitry Andric case CK_PointerToBoolean:
593180abc3dSDimitry Andric case CK_ToVoid:
594180abc3dSDimitry Andric case CK_VectorSplat:
595180abc3dSDimitry Andric case CK_IntegralCast:
5960414e226SDimitry Andric case CK_BooleanToSignedIntegral:
597180abc3dSDimitry Andric case CK_IntegralToBoolean:
598180abc3dSDimitry Andric case CK_IntegralToFloating:
599180abc3dSDimitry Andric case CK_FloatingToIntegral:
600180abc3dSDimitry Andric case CK_FloatingToBoolean:
601180abc3dSDimitry Andric case CK_FloatingCast:
60236981b17SDimitry Andric case CK_CPointerToObjCPointerCast:
60336981b17SDimitry Andric case CK_BlockPointerToObjCPointerCast:
604180abc3dSDimitry Andric case CK_AnyPointerToBlockPointerCast:
605180abc3dSDimitry Andric case CK_ObjCObjectLValueCast:
606180abc3dSDimitry Andric case CK_FloatingComplexToReal:
607180abc3dSDimitry Andric case CK_FloatingComplexToBoolean:
608180abc3dSDimitry Andric case CK_IntegralComplexToReal:
609180abc3dSDimitry Andric case CK_IntegralComplexToBoolean:
61036981b17SDimitry Andric case CK_ARCProduceObject:
61136981b17SDimitry Andric case CK_ARCConsumeObject:
61236981b17SDimitry Andric case CK_ARCReclaimReturnedObject:
61336981b17SDimitry Andric case CK_ARCExtendBlockObject:
614dbe13110SDimitry Andric case CK_CopyAndAutoreleaseBlockObject:
61513cc256eSDimitry Andric case CK_BuiltinFnToFnPtr:
616676fbe81SDimitry Andric case CK_ZeroToOCLOpaqueType:
6179f4dbff6SDimitry Andric case CK_AddressSpaceConversion:
618bab175ecSDimitry Andric case CK_IntToOCLSampler:
619b60736ecSDimitry Andric case CK_FloatingToFixedPoint:
620b60736ecSDimitry Andric case CK_FixedPointToFloating:
621676fbe81SDimitry Andric case CK_FixedPointCast:
622676fbe81SDimitry Andric case CK_FixedPointToBoolean:
62322989816SDimitry Andric case CK_FixedPointToIntegral:
62422989816SDimitry Andric case CK_IntegralToFixedPoint:
625344a3780SDimitry Andric case CK_MatrixCast:
626ac9a064cSDimitry Andric case CK_HLSLVectorTruncation:
627ac9a064cSDimitry Andric case CK_HLSLArrayRValue:
628180abc3dSDimitry Andric llvm_unreachable("invalid cast kind for complex value");
629180abc3dSDimitry Andric
630180abc3dSDimitry Andric case CK_FloatingRealToComplex:
631b60736ecSDimitry Andric case CK_IntegralRealToComplex: {
632b60736ecSDimitry Andric CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op);
63345b53394SDimitry Andric return EmitScalarToComplexCast(CGF.EmitScalarExpr(Op), Op->getType(),
63445b53394SDimitry Andric DestTy, Op->getExprLoc());
635b60736ecSDimitry Andric }
636ec2b103cSEd Schouten
637180abc3dSDimitry Andric case CK_FloatingComplexCast:
638180abc3dSDimitry Andric case CK_FloatingComplexToIntegralComplex:
639180abc3dSDimitry Andric case CK_IntegralComplexCast:
640b60736ecSDimitry Andric case CK_IntegralComplexToFloatingComplex: {
641b60736ecSDimitry Andric CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op);
64245b53394SDimitry Andric return EmitComplexToComplexCast(Visit(Op), Op->getType(), DestTy,
64345b53394SDimitry Andric Op->getExprLoc());
644180abc3dSDimitry Andric }
645b60736ecSDimitry Andric }
646180abc3dSDimitry Andric
647180abc3dSDimitry Andric llvm_unreachable("unknown cast resulting in complex value");
648180abc3dSDimitry Andric }
649180abc3dSDimitry Andric
VisitUnaryPlus(const UnaryOperator * E,QualType PromotionType)650e3b55780SDimitry Andric ComplexPairTy ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *E,
651e3b55780SDimitry Andric QualType PromotionType) {
652ac9a064cSDimitry Andric E->hasStoredFPFeatures();
653ac9a064cSDimitry Andric QualType promotionTy =
654ac9a064cSDimitry Andric PromotionType.isNull()
655ac9a064cSDimitry Andric ? getPromotionType(E->getStoredFPFeaturesOrDefault(),
656ac9a064cSDimitry Andric E->getSubExpr()->getType())
657e3b55780SDimitry Andric : PromotionType;
658e3b55780SDimitry Andric ComplexPairTy result = VisitPlus(E, promotionTy);
659e3b55780SDimitry Andric if (!promotionTy.isNull())
660e3b55780SDimitry Andric return CGF.EmitUnPromotedValue(result, E->getSubExpr()->getType());
661e3b55780SDimitry Andric return result;
662e3b55780SDimitry Andric }
663e3b55780SDimitry Andric
VisitPlus(const UnaryOperator * E,QualType PromotionType)664e3b55780SDimitry Andric ComplexPairTy ComplexExprEmitter::VisitPlus(const UnaryOperator *E,
665e3b55780SDimitry Andric QualType PromotionType) {
666ec2b103cSEd Schouten TestAndClearIgnoreReal();
667ec2b103cSEd Schouten TestAndClearIgnoreImag();
668e3b55780SDimitry Andric if (!PromotionType.isNull())
669e3b55780SDimitry Andric return CGF.EmitPromotedComplexExpr(E->getSubExpr(), PromotionType);
670e3b55780SDimitry Andric return Visit(E->getSubExpr());
671e3b55780SDimitry Andric }
672e3b55780SDimitry Andric
VisitUnaryMinus(const UnaryOperator * E,QualType PromotionType)673e3b55780SDimitry Andric ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E,
674e3b55780SDimitry Andric QualType PromotionType) {
675ac9a064cSDimitry Andric QualType promotionTy =
676ac9a064cSDimitry Andric PromotionType.isNull()
677ac9a064cSDimitry Andric ? getPromotionType(E->getStoredFPFeaturesOrDefault(),
678ac9a064cSDimitry Andric E->getSubExpr()->getType())
679e3b55780SDimitry Andric : PromotionType;
680e3b55780SDimitry Andric ComplexPairTy result = VisitMinus(E, promotionTy);
681e3b55780SDimitry Andric if (!promotionTy.isNull())
682e3b55780SDimitry Andric return CGF.EmitUnPromotedValue(result, E->getSubExpr()->getType());
683e3b55780SDimitry Andric return result;
684e3b55780SDimitry Andric }
VisitMinus(const UnaryOperator * E,QualType PromotionType)685e3b55780SDimitry Andric ComplexPairTy ComplexExprEmitter::VisitMinus(const UnaryOperator *E,
686e3b55780SDimitry Andric QualType PromotionType) {
687e3b55780SDimitry Andric TestAndClearIgnoreReal();
688e3b55780SDimitry Andric TestAndClearIgnoreImag();
689e3b55780SDimitry Andric ComplexPairTy Op;
690e3b55780SDimitry Andric if (!PromotionType.isNull())
691e3b55780SDimitry Andric Op = CGF.EmitPromotedComplexExpr(E->getSubExpr(), PromotionType);
692e3b55780SDimitry Andric else
693e3b55780SDimitry Andric Op = Visit(E->getSubExpr());
694b897c866SEd Schouten
695b897c866SEd Schouten llvm::Value *ResR, *ResI;
696ecb7e5c8SRoman Divacky if (Op.first->getType()->isFloatingPointTy()) {
697b897c866SEd Schouten ResR = Builder.CreateFNeg(Op.first, "neg.r");
698b897c866SEd Schouten ResI = Builder.CreateFNeg(Op.second, "neg.i");
699b897c866SEd Schouten } else {
700b897c866SEd Schouten ResR = Builder.CreateNeg(Op.first, "neg.r");
701b897c866SEd Schouten ResI = Builder.CreateNeg(Op.second, "neg.i");
702b897c866SEd Schouten }
703ec2b103cSEd Schouten return ComplexPairTy(ResR, ResI);
704ec2b103cSEd Schouten }
705ec2b103cSEd Schouten
VisitUnaryNot(const UnaryOperator * E)706ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
707ec2b103cSEd Schouten TestAndClearIgnoreReal();
708ec2b103cSEd Schouten TestAndClearIgnoreImag();
709ec2b103cSEd Schouten // ~(a+ib) = a + i*-b
710ec2b103cSEd Schouten ComplexPairTy Op = Visit(E->getSubExpr());
711b897c866SEd Schouten llvm::Value *ResI;
712ecb7e5c8SRoman Divacky if (Op.second->getType()->isFloatingPointTy())
713b897c866SEd Schouten ResI = Builder.CreateFNeg(Op.second, "conj.i");
714b897c866SEd Schouten else
715b897c866SEd Schouten ResI = Builder.CreateNeg(Op.second, "conj.i");
716b897c866SEd Schouten
717ec2b103cSEd Schouten return ComplexPairTy(Op.first, ResI);
718ec2b103cSEd Schouten }
719ec2b103cSEd Schouten
EmitBinAdd(const BinOpInfo & Op)720ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) {
721b897c866SEd Schouten llvm::Value *ResR, *ResI;
722b897c866SEd Schouten
723ecb7e5c8SRoman Divacky if (Op.LHS.first->getType()->isFloatingPointTy()) {
724e3b55780SDimitry Andric CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures);
725b897c866SEd Schouten ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first, "add.r");
72606d4ba38SDimitry Andric if (Op.LHS.second && Op.RHS.second)
727b897c866SEd Schouten ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second, "add.i");
72806d4ba38SDimitry Andric else
72906d4ba38SDimitry Andric ResI = Op.LHS.second ? Op.LHS.second : Op.RHS.second;
73006d4ba38SDimitry Andric assert(ResI && "Only one operand may be real!");
731b897c866SEd Schouten } else {
732b897c866SEd Schouten ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r");
73306d4ba38SDimitry Andric assert(Op.LHS.second && Op.RHS.second &&
73406d4ba38SDimitry Andric "Both operands of integer complex operators must be complex!");
735b897c866SEd Schouten ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i");
736b897c866SEd Schouten }
737ec2b103cSEd Schouten return ComplexPairTy(ResR, ResI);
738ec2b103cSEd Schouten }
739ec2b103cSEd Schouten
EmitBinSub(const BinOpInfo & Op)740ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) {
741b897c866SEd Schouten llvm::Value *ResR, *ResI;
742ecb7e5c8SRoman Divacky if (Op.LHS.first->getType()->isFloatingPointTy()) {
743e3b55780SDimitry Andric CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures);
744b897c866SEd Schouten ResR = Builder.CreateFSub(Op.LHS.first, Op.RHS.first, "sub.r");
74506d4ba38SDimitry Andric if (Op.LHS.second && Op.RHS.second)
746b897c866SEd Schouten ResI = Builder.CreateFSub(Op.LHS.second, Op.RHS.second, "sub.i");
74706d4ba38SDimitry Andric else
74806d4ba38SDimitry Andric ResI = Op.LHS.second ? Op.LHS.second
74906d4ba38SDimitry Andric : Builder.CreateFNeg(Op.RHS.second, "sub.i");
75006d4ba38SDimitry Andric assert(ResI && "Only one operand may be real!");
751b897c866SEd Schouten } else {
752b897c866SEd Schouten ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r");
75306d4ba38SDimitry Andric assert(Op.LHS.second && Op.RHS.second &&
75406d4ba38SDimitry Andric "Both operands of integer complex operators must be complex!");
755b897c866SEd Schouten ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i");
756b897c866SEd Schouten }
757ec2b103cSEd Schouten return ComplexPairTy(ResR, ResI);
758ec2b103cSEd Schouten }
759ec2b103cSEd Schouten
76048675466SDimitry Andric /// Emit a libcall for a binary operation on complex types.
EmitComplexBinOpLibCall(StringRef LibCallName,const BinOpInfo & Op)76106d4ba38SDimitry Andric ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName,
76206d4ba38SDimitry Andric const BinOpInfo &Op) {
76306d4ba38SDimitry Andric CallArgList Args;
76406d4ba38SDimitry Andric Args.add(RValue::get(Op.LHS.first),
76506d4ba38SDimitry Andric Op.Ty->castAs<ComplexType>()->getElementType());
76606d4ba38SDimitry Andric Args.add(RValue::get(Op.LHS.second),
76706d4ba38SDimitry Andric Op.Ty->castAs<ComplexType>()->getElementType());
76806d4ba38SDimitry Andric Args.add(RValue::get(Op.RHS.first),
76906d4ba38SDimitry Andric Op.Ty->castAs<ComplexType>()->getElementType());
77006d4ba38SDimitry Andric Args.add(RValue::get(Op.RHS.second),
77106d4ba38SDimitry Andric Op.Ty->castAs<ComplexType>()->getElementType());
772ec2b103cSEd Schouten
77306d4ba38SDimitry Andric // We *must* use the full CG function call building logic here because the
77406d4ba38SDimitry Andric // complex type has special ABI handling. We also should not forget about
77506d4ba38SDimitry Andric // special calling convention which may be used for compiler builtins.
77645b53394SDimitry Andric
77745b53394SDimitry Andric // We create a function qualified type to state that this call does not have
77845b53394SDimitry Andric // any exceptions.
77945b53394SDimitry Andric FunctionProtoType::ExtProtoInfo EPI;
78045b53394SDimitry Andric EPI = EPI.withExceptionSpec(
78145b53394SDimitry Andric FunctionProtoType::ExceptionSpecInfo(EST_BasicNoexcept));
78245b53394SDimitry Andric SmallVector<QualType, 4> ArgsQTys(
78345b53394SDimitry Andric 4, Op.Ty->castAs<ComplexType>()->getElementType());
78445b53394SDimitry Andric QualType FQTy = CGF.getContext().getFunctionType(Op.Ty, ArgsQTys, EPI);
78545b53394SDimitry Andric const CGFunctionInfo &FuncInfo = CGF.CGM.getTypes().arrangeFreeFunctionCall(
78645b53394SDimitry Andric Args, cast<FunctionType>(FQTy.getTypePtr()), false);
78745b53394SDimitry Andric
78806d4ba38SDimitry Andric llvm::FunctionType *FTy = CGF.CGM.getTypes().GetFunctionType(FuncInfo);
78922989816SDimitry Andric llvm::FunctionCallee Func = CGF.CGM.CreateRuntimeFunction(
79022989816SDimitry Andric FTy, LibCallName, llvm::AttributeList(), true);
791bab175ecSDimitry Andric CGCallee Callee = CGCallee::forDirect(Func, FQTy->getAs<FunctionProtoType>());
79206d4ba38SDimitry Andric
79322989816SDimitry Andric llvm::CallBase *Call;
794bab175ecSDimitry Andric RValue Res = CGF.EmitCall(FuncInfo, Callee, ReturnValueSlot(), Args, &Call);
79522989816SDimitry Andric Call->setCallingConv(CGF.CGM.getRuntimeCC());
79606d4ba38SDimitry Andric return Res.getComplexVal();
79706d4ba38SDimitry Andric }
79806d4ba38SDimitry Andric
79948675466SDimitry Andric /// Lookup the libcall name for a given floating point type complex
80006d4ba38SDimitry Andric /// multiply.
getComplexMultiplyLibCallName(llvm::Type * Ty)80106d4ba38SDimitry Andric static StringRef getComplexMultiplyLibCallName(llvm::Type *Ty) {
80206d4ba38SDimitry Andric switch (Ty->getTypeID()) {
80306d4ba38SDimitry Andric default:
80406d4ba38SDimitry Andric llvm_unreachable("Unsupported floating point type!");
80506d4ba38SDimitry Andric case llvm::Type::HalfTyID:
80606d4ba38SDimitry Andric return "__mulhc3";
80706d4ba38SDimitry Andric case llvm::Type::FloatTyID:
80806d4ba38SDimitry Andric return "__mulsc3";
80906d4ba38SDimitry Andric case llvm::Type::DoubleTyID:
81006d4ba38SDimitry Andric return "__muldc3";
81106d4ba38SDimitry Andric case llvm::Type::PPC_FP128TyID:
81206d4ba38SDimitry Andric return "__multc3";
81306d4ba38SDimitry Andric case llvm::Type::X86_FP80TyID:
81406d4ba38SDimitry Andric return "__mulxc3";
81506d4ba38SDimitry Andric case llvm::Type::FP128TyID:
81606d4ba38SDimitry Andric return "__multc3";
81706d4ba38SDimitry Andric }
81806d4ba38SDimitry Andric }
81906d4ba38SDimitry Andric
82006d4ba38SDimitry Andric // See C11 Annex G.5.1 for the semantics of multiplicative operators on complex
82106d4ba38SDimitry Andric // typed values.
EmitBinMul(const BinOpInfo & Op)822ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
823b897c866SEd Schouten using llvm::Value;
824b897c866SEd Schouten Value *ResR, *ResI;
82506d4ba38SDimitry Andric llvm::MDBuilder MDHelper(CGF.getLLVMContext());
826ec2b103cSEd Schouten
827ecb7e5c8SRoman Divacky if (Op.LHS.first->getType()->isFloatingPointTy()) {
82806d4ba38SDimitry Andric // The general formulation is:
82906d4ba38SDimitry Andric // (a + ib) * (c + id) = (a * c - b * d) + i(a * d + b * c)
83006d4ba38SDimitry Andric //
83106d4ba38SDimitry Andric // But we can fold away components which would be zero due to a real
83206d4ba38SDimitry Andric // operand according to C11 Annex G.5.1p2.
833b897c866SEd Schouten
834e3b55780SDimitry Andric CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures);
83506d4ba38SDimitry Andric if (Op.LHS.second && Op.RHS.second) {
83606d4ba38SDimitry Andric // If both operands are complex, emit the core math directly, and then
83706d4ba38SDimitry Andric // test for NaNs. If we find NaNs in the result, we delegate to a libcall
83806d4ba38SDimitry Andric // to carefully re-compute the correct infinity representation if
83906d4ba38SDimitry Andric // possible. The expectation is that the presence of NaNs here is
84006d4ba38SDimitry Andric // *extremely* rare, and so the cost of the libcall is almost irrelevant.
84106d4ba38SDimitry Andric // This is good, because the libcall re-computes the core multiplication
84206d4ba38SDimitry Andric // exactly the same as we do here and re-tests for NaNs in order to be
84306d4ba38SDimitry Andric // a generic complex*complex libcall.
84406d4ba38SDimitry Andric
84506d4ba38SDimitry Andric // First compute the four products.
84606d4ba38SDimitry Andric Value *AC = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul_ac");
84706d4ba38SDimitry Andric Value *BD = Builder.CreateFMul(Op.LHS.second, Op.RHS.second, "mul_bd");
84806d4ba38SDimitry Andric Value *AD = Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul_ad");
84906d4ba38SDimitry Andric Value *BC = Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul_bc");
85006d4ba38SDimitry Andric
85106d4ba38SDimitry Andric // The real part is the difference of the first two, the imaginary part is
85206d4ba38SDimitry Andric // the sum of the second.
85306d4ba38SDimitry Andric ResR = Builder.CreateFSub(AC, BD, "mul_r");
85406d4ba38SDimitry Andric ResI = Builder.CreateFAdd(AD, BC, "mul_i");
85506d4ba38SDimitry Andric
856ac9a064cSDimitry Andric if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic ||
857ac9a064cSDimitry Andric Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved ||
858ac9a064cSDimitry Andric Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted)
859312c0ed1SDimitry Andric return ComplexPairTy(ResR, ResI);
860312c0ed1SDimitry Andric
86106d4ba38SDimitry Andric // Emit the test for the real part becoming NaN and create a branch to
86206d4ba38SDimitry Andric // handle it. We test for NaN by comparing the number to itself.
86306d4ba38SDimitry Andric Value *IsRNaN = Builder.CreateFCmpUNO(ResR, ResR, "isnan_cmp");
86406d4ba38SDimitry Andric llvm::BasicBlock *ContBB = CGF.createBasicBlock("complex_mul_cont");
86506d4ba38SDimitry Andric llvm::BasicBlock *INaNBB = CGF.createBasicBlock("complex_mul_imag_nan");
86606d4ba38SDimitry Andric llvm::Instruction *Branch = Builder.CreateCondBr(IsRNaN, INaNBB, ContBB);
86706d4ba38SDimitry Andric llvm::BasicBlock *OrigBB = Branch->getParent();
86806d4ba38SDimitry Andric
86906d4ba38SDimitry Andric // Give hint that we very much don't expect to see NaNs.
870ac9a064cSDimitry Andric llvm::MDNode *BrWeight = MDHelper.createUnlikelyBranchWeights();
87106d4ba38SDimitry Andric Branch->setMetadata(llvm::LLVMContext::MD_prof, BrWeight);
87206d4ba38SDimitry Andric
87306d4ba38SDimitry Andric // Now test the imaginary part and create its branch.
87406d4ba38SDimitry Andric CGF.EmitBlock(INaNBB);
87506d4ba38SDimitry Andric Value *IsINaN = Builder.CreateFCmpUNO(ResI, ResI, "isnan_cmp");
87606d4ba38SDimitry Andric llvm::BasicBlock *LibCallBB = CGF.createBasicBlock("complex_mul_libcall");
87706d4ba38SDimitry Andric Branch = Builder.CreateCondBr(IsINaN, LibCallBB, ContBB);
87806d4ba38SDimitry Andric Branch->setMetadata(llvm::LLVMContext::MD_prof, BrWeight);
87906d4ba38SDimitry Andric
88006d4ba38SDimitry Andric // Now emit the libcall on this slowest of the slow paths.
88106d4ba38SDimitry Andric CGF.EmitBlock(LibCallBB);
88206d4ba38SDimitry Andric Value *LibCallR, *LibCallI;
88306d4ba38SDimitry Andric std::tie(LibCallR, LibCallI) = EmitComplexBinOpLibCall(
88406d4ba38SDimitry Andric getComplexMultiplyLibCallName(Op.LHS.first->getType()), Op);
88506d4ba38SDimitry Andric Builder.CreateBr(ContBB);
88606d4ba38SDimitry Andric
88706d4ba38SDimitry Andric // Finally continue execution by phi-ing together the different
88806d4ba38SDimitry Andric // computation paths.
88906d4ba38SDimitry Andric CGF.EmitBlock(ContBB);
89006d4ba38SDimitry Andric llvm::PHINode *RealPHI = Builder.CreatePHI(ResR->getType(), 3, "real_mul_phi");
89106d4ba38SDimitry Andric RealPHI->addIncoming(ResR, OrigBB);
89206d4ba38SDimitry Andric RealPHI->addIncoming(ResR, INaNBB);
89306d4ba38SDimitry Andric RealPHI->addIncoming(LibCallR, LibCallBB);
89406d4ba38SDimitry Andric llvm::PHINode *ImagPHI = Builder.CreatePHI(ResI->getType(), 3, "imag_mul_phi");
89506d4ba38SDimitry Andric ImagPHI->addIncoming(ResI, OrigBB);
89606d4ba38SDimitry Andric ImagPHI->addIncoming(ResI, INaNBB);
89706d4ba38SDimitry Andric ImagPHI->addIncoming(LibCallI, LibCallBB);
89806d4ba38SDimitry Andric return ComplexPairTy(RealPHI, ImagPHI);
89906d4ba38SDimitry Andric }
90006d4ba38SDimitry Andric assert((Op.LHS.second || Op.RHS.second) &&
90106d4ba38SDimitry Andric "At least one operand must be complex!");
90206d4ba38SDimitry Andric
90306d4ba38SDimitry Andric // If either of the operands is a real rather than a complex, the
90406d4ba38SDimitry Andric // imaginary component is ignored when computing the real component of the
90506d4ba38SDimitry Andric // result.
90606d4ba38SDimitry Andric ResR = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul.rl");
90706d4ba38SDimitry Andric
90806d4ba38SDimitry Andric ResI = Op.LHS.second
90906d4ba38SDimitry Andric ? Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul.il")
91006d4ba38SDimitry Andric : Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul.ir");
911b897c866SEd Schouten } else {
91206d4ba38SDimitry Andric assert(Op.LHS.second && Op.RHS.second &&
91306d4ba38SDimitry Andric "Both operands of integer complex operators must be complex!");
914b897c866SEd Schouten Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl");
915b897c866SEd Schouten Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second, "mul.rr");
916b897c866SEd Schouten ResR = Builder.CreateSub(ResRl, ResRr, "mul.r");
917b897c866SEd Schouten
918b897c866SEd Schouten Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il");
919b897c866SEd Schouten Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir");
920b897c866SEd Schouten ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i");
921b897c866SEd Schouten }
922ec2b103cSEd Schouten return ComplexPairTy(ResR, ResI);
923ec2b103cSEd Schouten }
924ec2b103cSEd Schouten
EmitAlgebraicDiv(llvm::Value * LHSr,llvm::Value * LHSi,llvm::Value * RHSr,llvm::Value * RHSi)925312c0ed1SDimitry Andric ComplexPairTy ComplexExprEmitter::EmitAlgebraicDiv(llvm::Value *LHSr,
926312c0ed1SDimitry Andric llvm::Value *LHSi,
927312c0ed1SDimitry Andric llvm::Value *RHSr,
928312c0ed1SDimitry Andric llvm::Value *RHSi) {
929312c0ed1SDimitry Andric // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
930312c0ed1SDimitry Andric llvm::Value *DSTr, *DSTi;
931312c0ed1SDimitry Andric
932312c0ed1SDimitry Andric llvm::Value *AC = Builder.CreateFMul(LHSr, RHSr); // a*c
933312c0ed1SDimitry Andric llvm::Value *BD = Builder.CreateFMul(LHSi, RHSi); // b*d
934312c0ed1SDimitry Andric llvm::Value *ACpBD = Builder.CreateFAdd(AC, BD); // ac+bd
935312c0ed1SDimitry Andric
936312c0ed1SDimitry Andric llvm::Value *CC = Builder.CreateFMul(RHSr, RHSr); // c*c
937312c0ed1SDimitry Andric llvm::Value *DD = Builder.CreateFMul(RHSi, RHSi); // d*d
938312c0ed1SDimitry Andric llvm::Value *CCpDD = Builder.CreateFAdd(CC, DD); // cc+dd
939312c0ed1SDimitry Andric
940312c0ed1SDimitry Andric llvm::Value *BC = Builder.CreateFMul(LHSi, RHSr); // b*c
941312c0ed1SDimitry Andric llvm::Value *AD = Builder.CreateFMul(LHSr, RHSi); // a*d
942312c0ed1SDimitry Andric llvm::Value *BCmAD = Builder.CreateFSub(BC, AD); // bc-ad
943312c0ed1SDimitry Andric
944312c0ed1SDimitry Andric DSTr = Builder.CreateFDiv(ACpBD, CCpDD);
945312c0ed1SDimitry Andric DSTi = Builder.CreateFDiv(BCmAD, CCpDD);
946312c0ed1SDimitry Andric return ComplexPairTy(DSTr, DSTi);
947312c0ed1SDimitry Andric }
948312c0ed1SDimitry Andric
949312c0ed1SDimitry Andric // EmitFAbs - Emit a call to @llvm.fabs.
EmitllvmFAbs(CodeGenFunction & CGF,llvm::Value * Value)950312c0ed1SDimitry Andric static llvm::Value *EmitllvmFAbs(CodeGenFunction &CGF, llvm::Value *Value) {
951312c0ed1SDimitry Andric llvm::Function *Func =
952312c0ed1SDimitry Andric CGF.CGM.getIntrinsic(llvm::Intrinsic::fabs, Value->getType());
953312c0ed1SDimitry Andric llvm::Value *Call = CGF.Builder.CreateCall(Func, Value);
954312c0ed1SDimitry Andric return Call;
955312c0ed1SDimitry Andric }
956312c0ed1SDimitry Andric
957312c0ed1SDimitry Andric // EmitRangeReductionDiv - Implements Smith's algorithm for complex division.
958312c0ed1SDimitry Andric // SMITH, R. L. Algorithm 116: Complex division. Commun. ACM 5, 8 (1962).
EmitRangeReductionDiv(llvm::Value * LHSr,llvm::Value * LHSi,llvm::Value * RHSr,llvm::Value * RHSi)959312c0ed1SDimitry Andric ComplexPairTy ComplexExprEmitter::EmitRangeReductionDiv(llvm::Value *LHSr,
960312c0ed1SDimitry Andric llvm::Value *LHSi,
961312c0ed1SDimitry Andric llvm::Value *RHSr,
962312c0ed1SDimitry Andric llvm::Value *RHSi) {
9634df029ccSDimitry Andric // FIXME: This could eventually be replaced by an LLVM intrinsic to
9644df029ccSDimitry Andric // avoid this long IR sequence.
9654df029ccSDimitry Andric
966312c0ed1SDimitry Andric // (a + ib) / (c + id) = (e + if)
967312c0ed1SDimitry Andric llvm::Value *FAbsRHSr = EmitllvmFAbs(CGF, RHSr); // |c|
968312c0ed1SDimitry Andric llvm::Value *FAbsRHSi = EmitllvmFAbs(CGF, RHSi); // |d|
969312c0ed1SDimitry Andric // |c| >= |d|
970312c0ed1SDimitry Andric llvm::Value *IsR = Builder.CreateFCmpUGT(FAbsRHSr, FAbsRHSi, "abs_cmp");
971312c0ed1SDimitry Andric
972312c0ed1SDimitry Andric llvm::BasicBlock *TrueBB =
973312c0ed1SDimitry Andric CGF.createBasicBlock("abs_rhsr_greater_or_equal_abs_rhsi");
974312c0ed1SDimitry Andric llvm::BasicBlock *FalseBB =
975312c0ed1SDimitry Andric CGF.createBasicBlock("abs_rhsr_less_than_abs_rhsi");
976312c0ed1SDimitry Andric llvm::BasicBlock *ContBB = CGF.createBasicBlock("complex_div");
977312c0ed1SDimitry Andric Builder.CreateCondBr(IsR, TrueBB, FalseBB);
978312c0ed1SDimitry Andric
979312c0ed1SDimitry Andric CGF.EmitBlock(TrueBB);
980312c0ed1SDimitry Andric // abs(c) >= abs(d)
981312c0ed1SDimitry Andric // r = d/c
982312c0ed1SDimitry Andric // tmp = c + rd
983312c0ed1SDimitry Andric // e = (a + br)/tmp
984312c0ed1SDimitry Andric // f = (b - ar)/tmp
985312c0ed1SDimitry Andric llvm::Value *DdC = Builder.CreateFDiv(RHSi, RHSr); // r=d/c
986312c0ed1SDimitry Andric
987312c0ed1SDimitry Andric llvm::Value *RD = Builder.CreateFMul(DdC, RHSi); // rd
988312c0ed1SDimitry Andric llvm::Value *CpRD = Builder.CreateFAdd(RHSr, RD); // tmp=c+rd
989312c0ed1SDimitry Andric
990312c0ed1SDimitry Andric llvm::Value *T3 = Builder.CreateFMul(LHSi, DdC); // br
991312c0ed1SDimitry Andric llvm::Value *T4 = Builder.CreateFAdd(LHSr, T3); // a+br
992312c0ed1SDimitry Andric llvm::Value *DSTTr = Builder.CreateFDiv(T4, CpRD); // (a+br)/tmp
993312c0ed1SDimitry Andric
994312c0ed1SDimitry Andric llvm::Value *T5 = Builder.CreateFMul(LHSr, DdC); // ar
995312c0ed1SDimitry Andric llvm::Value *T6 = Builder.CreateFSub(LHSi, T5); // b-ar
996312c0ed1SDimitry Andric llvm::Value *DSTTi = Builder.CreateFDiv(T6, CpRD); // (b-ar)/tmp
997312c0ed1SDimitry Andric Builder.CreateBr(ContBB);
998312c0ed1SDimitry Andric
999312c0ed1SDimitry Andric CGF.EmitBlock(FalseBB);
1000312c0ed1SDimitry Andric // abs(c) < abs(d)
1001312c0ed1SDimitry Andric // r = c/d
1002312c0ed1SDimitry Andric // tmp = d + rc
1003312c0ed1SDimitry Andric // e = (ar + b)/tmp
1004312c0ed1SDimitry Andric // f = (br - a)/tmp
1005312c0ed1SDimitry Andric llvm::Value *CdD = Builder.CreateFDiv(RHSr, RHSi); // r=c/d
1006312c0ed1SDimitry Andric
1007312c0ed1SDimitry Andric llvm::Value *RC = Builder.CreateFMul(CdD, RHSr); // rc
1008312c0ed1SDimitry Andric llvm::Value *DpRC = Builder.CreateFAdd(RHSi, RC); // tmp=d+rc
1009312c0ed1SDimitry Andric
10104df029ccSDimitry Andric llvm::Value *T7 = Builder.CreateFMul(LHSr, CdD); // ar
1011312c0ed1SDimitry Andric llvm::Value *T8 = Builder.CreateFAdd(T7, LHSi); // ar+b
1012312c0ed1SDimitry Andric llvm::Value *DSTFr = Builder.CreateFDiv(T8, DpRC); // (ar+b)/tmp
1013312c0ed1SDimitry Andric
1014312c0ed1SDimitry Andric llvm::Value *T9 = Builder.CreateFMul(LHSi, CdD); // br
1015312c0ed1SDimitry Andric llvm::Value *T10 = Builder.CreateFSub(T9, LHSr); // br-a
1016312c0ed1SDimitry Andric llvm::Value *DSTFi = Builder.CreateFDiv(T10, DpRC); // (br-a)/tmp
1017312c0ed1SDimitry Andric Builder.CreateBr(ContBB);
1018312c0ed1SDimitry Andric
1019312c0ed1SDimitry Andric // Phi together the computation paths.
1020312c0ed1SDimitry Andric CGF.EmitBlock(ContBB);
1021312c0ed1SDimitry Andric llvm::PHINode *VALr = Builder.CreatePHI(DSTTr->getType(), 2);
1022312c0ed1SDimitry Andric VALr->addIncoming(DSTTr, TrueBB);
1023312c0ed1SDimitry Andric VALr->addIncoming(DSTFr, FalseBB);
1024312c0ed1SDimitry Andric llvm::PHINode *VALi = Builder.CreatePHI(DSTTi->getType(), 2);
1025312c0ed1SDimitry Andric VALi->addIncoming(DSTTi, TrueBB);
1026312c0ed1SDimitry Andric VALi->addIncoming(DSTFi, FalseBB);
1027312c0ed1SDimitry Andric return ComplexPairTy(VALr, VALi);
1028312c0ed1SDimitry Andric }
1029312c0ed1SDimitry Andric
103006d4ba38SDimitry Andric // See C11 Annex G.5.1 for the semantics of multiplicative operators on complex
103106d4ba38SDimitry Andric // typed values.
EmitBinDiv(const BinOpInfo & Op)1032ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
1033ec2b103cSEd Schouten llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second;
1034ec2b103cSEd Schouten llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second;
1035b897c866SEd Schouten llvm::Value *DSTr, *DSTi;
103606d4ba38SDimitry Andric if (LHSr->getType()->isFloatingPointTy()) {
1037312c0ed1SDimitry Andric CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures);
1038312c0ed1SDimitry Andric if (!RHSi) {
1039312c0ed1SDimitry Andric assert(LHSi && "Can have at most one non-complex operand!");
1040312c0ed1SDimitry Andric
1041312c0ed1SDimitry Andric DSTr = Builder.CreateFDiv(LHSr, RHSr);
1042312c0ed1SDimitry Andric DSTi = Builder.CreateFDiv(LHSi, RHSr);
1043312c0ed1SDimitry Andric return ComplexPairTy(DSTr, DSTi);
1044312c0ed1SDimitry Andric }
1045312c0ed1SDimitry Andric llvm::Value *OrigLHSi = LHSi;
1046312c0ed1SDimitry Andric if (!LHSi)
1047312c0ed1SDimitry Andric LHSi = llvm::Constant::getNullValue(RHSi->getType());
1048ac9a064cSDimitry Andric if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved ||
1049ac9a064cSDimitry Andric (Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted &&
1050ac9a064cSDimitry Andric !FPHasBeenPromoted))
1051312c0ed1SDimitry Andric return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi);
1052ac9a064cSDimitry Andric else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic ||
1053ac9a064cSDimitry Andric Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted)
1054312c0ed1SDimitry Andric return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi);
10554df029ccSDimitry Andric // '-ffast-math' is used in the command line but followed by an
1056ac9a064cSDimitry Andric // '-fno-cx-limited-range' or '-fcomplex-arithmetic=full'.
1057ac9a064cSDimitry Andric else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Full) {
1058312c0ed1SDimitry Andric LHSi = OrigLHSi;
10596252156dSDimitry Andric // If we have a complex operand on the RHS and FastMath is not allowed, we
10606252156dSDimitry Andric // delegate to a libcall to handle all of the complexities and minimize
10616252156dSDimitry Andric // underflow/overflow cases. When FastMath is allowed we construct the
10626252156dSDimitry Andric // divide inline using the same algorithm as for integer operands.
106306d4ba38SDimitry Andric BinOpInfo LibCallOp = Op;
106406d4ba38SDimitry Andric // If LHS was a real, supply a null imaginary part.
106506d4ba38SDimitry Andric if (!LHSi)
106606d4ba38SDimitry Andric LibCallOp.LHS.second = llvm::Constant::getNullValue(LHSr->getType());
1067b897c866SEd Schouten
106806d4ba38SDimitry Andric switch (LHSr->getType()->getTypeID()) {
106906d4ba38SDimitry Andric default:
107006d4ba38SDimitry Andric llvm_unreachable("Unsupported floating point type!");
107106d4ba38SDimitry Andric case llvm::Type::HalfTyID:
107206d4ba38SDimitry Andric return EmitComplexBinOpLibCall("__divhc3", LibCallOp);
107306d4ba38SDimitry Andric case llvm::Type::FloatTyID:
107406d4ba38SDimitry Andric return EmitComplexBinOpLibCall("__divsc3", LibCallOp);
107506d4ba38SDimitry Andric case llvm::Type::DoubleTyID:
107606d4ba38SDimitry Andric return EmitComplexBinOpLibCall("__divdc3", LibCallOp);
107706d4ba38SDimitry Andric case llvm::Type::PPC_FP128TyID:
107806d4ba38SDimitry Andric return EmitComplexBinOpLibCall("__divtc3", LibCallOp);
107906d4ba38SDimitry Andric case llvm::Type::X86_FP80TyID:
108006d4ba38SDimitry Andric return EmitComplexBinOpLibCall("__divxc3", LibCallOp);
108106d4ba38SDimitry Andric case llvm::Type::FP128TyID:
108206d4ba38SDimitry Andric return EmitComplexBinOpLibCall("__divtc3", LibCallOp);
108306d4ba38SDimitry Andric }
10846252156dSDimitry Andric } else {
1085312c0ed1SDimitry Andric return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi);
10866252156dSDimitry Andric }
1087b897c866SEd Schouten } else {
108806d4ba38SDimitry Andric assert(Op.LHS.second && Op.RHS.second &&
108906d4ba38SDimitry Andric "Both operands of integer complex operators must be complex!");
1090ec2b103cSEd Schouten // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
109136981b17SDimitry Andric llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr); // a*c
109236981b17SDimitry Andric llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi); // b*d
109336981b17SDimitry Andric llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2); // ac+bd
1094ec2b103cSEd Schouten
109536981b17SDimitry Andric llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr); // c*c
109636981b17SDimitry Andric llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi); // d*d
109736981b17SDimitry Andric llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5); // cc+dd
1098ec2b103cSEd Schouten
109936981b17SDimitry Andric llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr); // b*c
110036981b17SDimitry Andric llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi); // a*d
110136981b17SDimitry Andric llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8); // bc-ad
1102ec2b103cSEd Schouten
1103809500fcSDimitry Andric if (Op.Ty->castAs<ComplexType>()->getElementType()->isUnsignedIntegerType()) {
110436981b17SDimitry Andric DSTr = Builder.CreateUDiv(Tmp3, Tmp6);
110536981b17SDimitry Andric DSTi = Builder.CreateUDiv(Tmp9, Tmp6);
1106ec2b103cSEd Schouten } else {
110736981b17SDimitry Andric DSTr = Builder.CreateSDiv(Tmp3, Tmp6);
110836981b17SDimitry Andric DSTi = Builder.CreateSDiv(Tmp9, Tmp6);
1109ec2b103cSEd Schouten }
1110ec2b103cSEd Schouten }
1111ec2b103cSEd Schouten
1112ec2b103cSEd Schouten return ComplexPairTy(DSTr, DSTi);
1113ec2b103cSEd Schouten }
1114ec2b103cSEd Schouten
EmitUnPromotedValue(ComplexPairTy result,QualType UnPromotionType)1115e3b55780SDimitry Andric ComplexPairTy CodeGenFunction::EmitUnPromotedValue(ComplexPairTy result,
1116e3b55780SDimitry Andric QualType UnPromotionType) {
1117e3b55780SDimitry Andric llvm::Type *ComplexElementTy =
1118e3b55780SDimitry Andric ConvertType(UnPromotionType->castAs<ComplexType>()->getElementType());
1119e3b55780SDimitry Andric if (result.first)
1120e3b55780SDimitry Andric result.first =
1121e3b55780SDimitry Andric Builder.CreateFPTrunc(result.first, ComplexElementTy, "unpromotion");
1122e3b55780SDimitry Andric if (result.second)
1123e3b55780SDimitry Andric result.second =
1124e3b55780SDimitry Andric Builder.CreateFPTrunc(result.second, ComplexElementTy, "unpromotion");
1125e3b55780SDimitry Andric return result;
1126e3b55780SDimitry Andric }
1127e3b55780SDimitry Andric
EmitPromotedValue(ComplexPairTy result,QualType PromotionType)1128e3b55780SDimitry Andric ComplexPairTy CodeGenFunction::EmitPromotedValue(ComplexPairTy result,
1129e3b55780SDimitry Andric QualType PromotionType) {
1130e3b55780SDimitry Andric llvm::Type *ComplexElementTy =
1131e3b55780SDimitry Andric ConvertType(PromotionType->castAs<ComplexType>()->getElementType());
1132e3b55780SDimitry Andric if (result.first)
1133e3b55780SDimitry Andric result.first = Builder.CreateFPExt(result.first, ComplexElementTy, "ext");
1134e3b55780SDimitry Andric if (result.second)
1135e3b55780SDimitry Andric result.second = Builder.CreateFPExt(result.second, ComplexElementTy, "ext");
1136e3b55780SDimitry Andric
1137e3b55780SDimitry Andric return result;
1138e3b55780SDimitry Andric }
1139e3b55780SDimitry Andric
EmitPromoted(const Expr * E,QualType PromotionType)1140e3b55780SDimitry Andric ComplexPairTy ComplexExprEmitter::EmitPromoted(const Expr *E,
1141e3b55780SDimitry Andric QualType PromotionType) {
1142e3b55780SDimitry Andric E = E->IgnoreParens();
1143e3b55780SDimitry Andric if (auto BO = dyn_cast<BinaryOperator>(E)) {
1144e3b55780SDimitry Andric switch (BO->getOpcode()) {
1145e3b55780SDimitry Andric #define HANDLE_BINOP(OP) \
1146e3b55780SDimitry Andric case BO_##OP: \
1147e3b55780SDimitry Andric return EmitBin##OP(EmitBinOps(BO, PromotionType));
1148e3b55780SDimitry Andric HANDLE_BINOP(Add)
1149e3b55780SDimitry Andric HANDLE_BINOP(Sub)
1150e3b55780SDimitry Andric HANDLE_BINOP(Mul)
1151e3b55780SDimitry Andric HANDLE_BINOP(Div)
1152e3b55780SDimitry Andric #undef HANDLE_BINOP
1153e3b55780SDimitry Andric default:
1154e3b55780SDimitry Andric break;
1155e3b55780SDimitry Andric }
1156e3b55780SDimitry Andric } else if (auto UO = dyn_cast<UnaryOperator>(E)) {
1157e3b55780SDimitry Andric switch (UO->getOpcode()) {
1158e3b55780SDimitry Andric case UO_Minus:
1159e3b55780SDimitry Andric return VisitMinus(UO, PromotionType);
1160e3b55780SDimitry Andric case UO_Plus:
1161e3b55780SDimitry Andric return VisitPlus(UO, PromotionType);
1162e3b55780SDimitry Andric default:
1163e3b55780SDimitry Andric break;
1164e3b55780SDimitry Andric }
1165e3b55780SDimitry Andric }
1166e3b55780SDimitry Andric auto result = Visit(const_cast<Expr *>(E));
1167e3b55780SDimitry Andric if (!PromotionType.isNull())
1168e3b55780SDimitry Andric return CGF.EmitPromotedValue(result, PromotionType);
1169e3b55780SDimitry Andric else
1170e3b55780SDimitry Andric return result;
1171e3b55780SDimitry Andric }
1172e3b55780SDimitry Andric
EmitPromotedComplexExpr(const Expr * E,QualType DstTy)1173e3b55780SDimitry Andric ComplexPairTy CodeGenFunction::EmitPromotedComplexExpr(const Expr *E,
1174e3b55780SDimitry Andric QualType DstTy) {
1175e3b55780SDimitry Andric return ComplexExprEmitter(*this).EmitPromoted(E, DstTy);
1176e3b55780SDimitry Andric }
1177e3b55780SDimitry Andric
1178e3b55780SDimitry Andric ComplexPairTy
EmitPromotedComplexOperand(const Expr * E,QualType OverallPromotionType)1179e3b55780SDimitry Andric ComplexExprEmitter::EmitPromotedComplexOperand(const Expr *E,
1180e3b55780SDimitry Andric QualType OverallPromotionType) {
1181e3b55780SDimitry Andric if (E->getType()->isAnyComplexType()) {
1182e3b55780SDimitry Andric if (!OverallPromotionType.isNull())
1183e3b55780SDimitry Andric return CGF.EmitPromotedComplexExpr(E, OverallPromotionType);
1184e3b55780SDimitry Andric else
1185e3b55780SDimitry Andric return Visit(const_cast<Expr *>(E));
1186e3b55780SDimitry Andric } else {
1187e3b55780SDimitry Andric if (!OverallPromotionType.isNull()) {
1188e3b55780SDimitry Andric QualType ComplexElementTy =
1189e3b55780SDimitry Andric OverallPromotionType->castAs<ComplexType>()->getElementType();
1190e3b55780SDimitry Andric return ComplexPairTy(CGF.EmitPromotedScalarExpr(E, ComplexElementTy),
1191e3b55780SDimitry Andric nullptr);
1192e3b55780SDimitry Andric } else {
1193e3b55780SDimitry Andric return ComplexPairTy(CGF.EmitScalarExpr(E), nullptr);
1194e3b55780SDimitry Andric }
1195e3b55780SDimitry Andric }
1196e3b55780SDimitry Andric }
1197e3b55780SDimitry Andric
1198ec2b103cSEd Schouten ComplexExprEmitter::BinOpInfo
EmitBinOps(const BinaryOperator * E,QualType PromotionType)1199e3b55780SDimitry Andric ComplexExprEmitter::EmitBinOps(const BinaryOperator *E,
1200e3b55780SDimitry Andric QualType PromotionType) {
1201ec2b103cSEd Schouten TestAndClearIgnoreReal();
1202ec2b103cSEd Schouten TestAndClearIgnoreImag();
1203ec2b103cSEd Schouten BinOpInfo Ops;
120406d4ba38SDimitry Andric
1205e3b55780SDimitry Andric Ops.LHS = EmitPromotedComplexOperand(E->getLHS(), PromotionType);
1206e3b55780SDimitry Andric Ops.RHS = EmitPromotedComplexOperand(E->getRHS(), PromotionType);
1207e3b55780SDimitry Andric if (!PromotionType.isNull())
1208e3b55780SDimitry Andric Ops.Ty = PromotionType;
1209e3b55780SDimitry Andric else
1210ec2b103cSEd Schouten Ops.Ty = E->getType();
1211e3b55780SDimitry Andric Ops.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
1212ec2b103cSEd Schouten return Ops;
1213ec2b103cSEd Schouten }
1214ec2b103cSEd Schouten
1215ec2b103cSEd Schouten
1216bca07a45SDimitry Andric LValue ComplexExprEmitter::
EmitCompoundAssignLValue(const CompoundAssignOperator * E,ComplexPairTy (ComplexExprEmitter::* Func)(const BinOpInfo &),RValue & Val)1217bca07a45SDimitry Andric EmitCompoundAssignLValue(const CompoundAssignOperator *E,
1218bca07a45SDimitry Andric ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
1219bfef3995SDimitry Andric RValue &Val) {
1220ec2b103cSEd Schouten TestAndClearIgnoreReal();
1221ec2b103cSEd Schouten TestAndClearIgnoreImag();
1222bca07a45SDimitry Andric QualType LHSTy = E->getLHS()->getType();
12235e20cdd8SDimitry Andric if (const AtomicType *AT = LHSTy->getAs<AtomicType>())
12245e20cdd8SDimitry Andric LHSTy = AT->getValueType();
1225ec2b103cSEd Schouten
1226ec2b103cSEd Schouten BinOpInfo OpInfo;
1227e3b55780SDimitry Andric OpInfo.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
1228e3b55780SDimitry Andric CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, OpInfo.FPFeatures);
1229ec2b103cSEd Schouten
1230ec2b103cSEd Schouten // Load the RHS and LHS operands.
1231ec2b103cSEd Schouten // __block variables need to have the rhs evaluated first, plus this should
1232bca07a45SDimitry Andric // improve codegen a little.
1233e3b55780SDimitry Andric QualType PromotionTypeCR;
1234ac9a064cSDimitry Andric PromotionTypeCR = getPromotionType(E->getStoredFPFeaturesOrDefault(),
1235ac9a064cSDimitry Andric E->getComputationResultType());
1236e3b55780SDimitry Andric if (PromotionTypeCR.isNull())
1237e3b55780SDimitry Andric PromotionTypeCR = E->getComputationResultType();
1238e3b55780SDimitry Andric OpInfo.Ty = PromotionTypeCR;
1239e3b55780SDimitry Andric QualType ComplexElementTy =
1240e3b55780SDimitry Andric OpInfo.Ty->castAs<ComplexType>()->getElementType();
1241ac9a064cSDimitry Andric QualType PromotionTypeRHS = getPromotionType(
1242ac9a064cSDimitry Andric E->getStoredFPFeaturesOrDefault(), E->getRHS()->getType());
1243bca07a45SDimitry Andric
1244bca07a45SDimitry Andric // The RHS should have been converted to the computation type.
124506d4ba38SDimitry Andric if (E->getRHS()->getType()->isRealFloatingType()) {
1246e3b55780SDimitry Andric if (!PromotionTypeRHS.isNull())
1247e3b55780SDimitry Andric OpInfo.RHS = ComplexPairTy(
1248e3b55780SDimitry Andric CGF.EmitPromotedScalarExpr(E->getRHS(), PromotionTypeRHS), nullptr);
1249e3b55780SDimitry Andric else {
1250e3b55780SDimitry Andric assert(CGF.getContext().hasSameUnqualifiedType(ComplexElementTy,
1251e3b55780SDimitry Andric E->getRHS()->getType()));
1252e3b55780SDimitry Andric
125306d4ba38SDimitry Andric OpInfo.RHS = ComplexPairTy(CGF.EmitScalarExpr(E->getRHS()), nullptr);
1254e3b55780SDimitry Andric }
125506d4ba38SDimitry Andric } else {
1256e3b55780SDimitry Andric if (!PromotionTypeRHS.isNull()) {
1257e3b55780SDimitry Andric OpInfo.RHS = ComplexPairTy(
1258e3b55780SDimitry Andric CGF.EmitPromotedComplexExpr(E->getRHS(), PromotionTypeRHS));
1259e3b55780SDimitry Andric } else {
1260e3b55780SDimitry Andric assert(CGF.getContext().hasSameUnqualifiedType(OpInfo.Ty,
1261e3b55780SDimitry Andric E->getRHS()->getType()));
1262bca07a45SDimitry Andric OpInfo.RHS = Visit(E->getRHS());
126306d4ba38SDimitry Andric }
1264e3b55780SDimitry Andric }
1265ec2b103cSEd Schouten
12664ba67500SRoman Divacky LValue LHS = CGF.EmitLValue(E->getLHS());
1267bca07a45SDimitry Andric
1268bfef3995SDimitry Andric // Load from the l-value and convert it.
126945b53394SDimitry Andric SourceLocation Loc = E->getExprLoc();
1270ac9a064cSDimitry Andric QualType PromotionTypeLHS = getPromotionType(
1271ac9a064cSDimitry Andric E->getStoredFPFeaturesOrDefault(), E->getComputationLHSType());
1272bfef3995SDimitry Andric if (LHSTy->isAnyComplexType()) {
127345b53394SDimitry Andric ComplexPairTy LHSVal = EmitLoadOfLValue(LHS, Loc);
1274e3b55780SDimitry Andric if (!PromotionTypeLHS.isNull())
1275e3b55780SDimitry Andric OpInfo.LHS =
1276e3b55780SDimitry Andric EmitComplexToComplexCast(LHSVal, LHSTy, PromotionTypeLHS, Loc);
1277e3b55780SDimitry Andric else
127845b53394SDimitry Andric OpInfo.LHS = EmitComplexToComplexCast(LHSVal, LHSTy, OpInfo.Ty, Loc);
1279bfef3995SDimitry Andric } else {
128045b53394SDimitry Andric llvm::Value *LHSVal = CGF.EmitLoadOfScalar(LHS, Loc);
128106d4ba38SDimitry Andric // For floating point real operands we can directly pass the scalar form
128206d4ba38SDimitry Andric // to the binary operator emission and potentially get more efficient code.
128306d4ba38SDimitry Andric if (LHSTy->isRealFloatingType()) {
1284e3b55780SDimitry Andric QualType PromotedComplexElementTy;
1285e3b55780SDimitry Andric if (!PromotionTypeLHS.isNull()) {
1286e3b55780SDimitry Andric PromotedComplexElementTy =
1287e3b55780SDimitry Andric cast<ComplexType>(PromotionTypeLHS)->getElementType();
1288e3b55780SDimitry Andric if (!CGF.getContext().hasSameUnqualifiedType(PromotedComplexElementTy,
1289e3b55780SDimitry Andric PromotionTypeLHS))
1290e3b55780SDimitry Andric LHSVal = CGF.EmitScalarConversion(LHSVal, LHSTy,
1291e3b55780SDimitry Andric PromotedComplexElementTy, Loc);
1292e3b55780SDimitry Andric } else {
129306d4ba38SDimitry Andric if (!CGF.getContext().hasSameUnqualifiedType(ComplexElementTy, LHSTy))
1294e3b55780SDimitry Andric LHSVal =
1295e3b55780SDimitry Andric CGF.EmitScalarConversion(LHSVal, LHSTy, ComplexElementTy, Loc);
1296e3b55780SDimitry Andric }
129706d4ba38SDimitry Andric OpInfo.LHS = ComplexPairTy(LHSVal, nullptr);
129806d4ba38SDimitry Andric } else {
129945b53394SDimitry Andric OpInfo.LHS = EmitScalarToComplexCast(LHSVal, LHSTy, OpInfo.Ty, Loc);
1300bfef3995SDimitry Andric }
130106d4ba38SDimitry Andric }
1302ec2b103cSEd Schouten
1303ec2b103cSEd Schouten // Expand the binary operator.
1304ec2b103cSEd Schouten ComplexPairTy Result = (this->*Func)(OpInfo);
1305ec2b103cSEd Schouten
1306bfef3995SDimitry Andric // Truncate the result and store it into the LHS lvalue.
1307bfef3995SDimitry Andric if (LHSTy->isAnyComplexType()) {
130845b53394SDimitry Andric ComplexPairTy ResVal =
130945b53394SDimitry Andric EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy, Loc);
1310bfef3995SDimitry Andric EmitStoreOfComplex(ResVal, LHS, /*isInit*/ false);
1311bfef3995SDimitry Andric Val = RValue::getComplex(ResVal);
1312bfef3995SDimitry Andric } else {
1313bfef3995SDimitry Andric llvm::Value *ResVal =
131445b53394SDimitry Andric CGF.EmitComplexToScalarConversion(Result, OpInfo.Ty, LHSTy, Loc);
1315bfef3995SDimitry Andric CGF.EmitStoreOfScalar(ResVal, LHS, /*isInit*/ false);
1316bfef3995SDimitry Andric Val = RValue::get(ResVal);
1317bfef3995SDimitry Andric }
13184ba67500SRoman Divacky
1319bca07a45SDimitry Andric return LHS;
1320ec2b103cSEd Schouten }
1321ec2b103cSEd Schouten
1322bca07a45SDimitry Andric // Compound assignments.
1323bca07a45SDimitry Andric ComplexPairTy ComplexExprEmitter::
EmitCompoundAssign(const CompoundAssignOperator * E,ComplexPairTy (ComplexExprEmitter::* Func)(const BinOpInfo &))1324bca07a45SDimitry Andric EmitCompoundAssign(const CompoundAssignOperator *E,
1325bca07a45SDimitry Andric ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){
1326bfef3995SDimitry Andric RValue Val;
1327bca07a45SDimitry Andric LValue LV = EmitCompoundAssignLValue(E, Func, Val);
1328bca07a45SDimitry Andric
1329bca07a45SDimitry Andric // The result of an assignment in C is the assigned r-value.
133013cc256eSDimitry Andric if (!CGF.getLangOpts().CPlusPlus)
1331bfef3995SDimitry Andric return Val.getComplexVal();
1332bca07a45SDimitry Andric
1333bca07a45SDimitry Andric // If the lvalue is non-volatile, return the computed value of the assignment.
1334bca07a45SDimitry Andric if (!LV.isVolatileQualified())
1335bfef3995SDimitry Andric return Val.getComplexVal();
1336bca07a45SDimitry Andric
1337bfef3995SDimitry Andric return EmitLoadOfLValue(LV, E->getExprLoc());
1338bca07a45SDimitry Andric }
1339bca07a45SDimitry Andric
EmitBinAssignLValue(const BinaryOperator * E,ComplexPairTy & Val)1340bca07a45SDimitry Andric LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E,
1341bca07a45SDimitry Andric ComplexPairTy &Val) {
13424e58654bSRoman Divacky assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(),
13434e58654bSRoman Divacky E->getRHS()->getType()) &&
1344ec2b103cSEd Schouten "Invalid assignment");
1345bca07a45SDimitry Andric TestAndClearIgnoreReal();
1346bca07a45SDimitry Andric TestAndClearIgnoreImag();
1347bca07a45SDimitry Andric
1348bca07a45SDimitry Andric // Emit the RHS. __block variables need the RHS evaluated first.
1349bca07a45SDimitry Andric Val = Visit(E->getRHS());
1350ec2b103cSEd Schouten
1351ec2b103cSEd Schouten // Compute the address to store into.
1352ec2b103cSEd Schouten LValue LHS = CGF.EmitLValue(E->getLHS());
1353ec2b103cSEd Schouten
13544ba67500SRoman Divacky // Store the result value into the LHS lvalue.
1355809500fcSDimitry Andric EmitStoreOfComplex(Val, LHS, /*isInit*/ false);
13567ef7bab7SEd Schouten
1357bca07a45SDimitry Andric return LHS;
1358bca07a45SDimitry Andric }
13594ba67500SRoman Divacky
VisitBinAssign(const BinaryOperator * E)1360bca07a45SDimitry Andric ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
1361bca07a45SDimitry Andric ComplexPairTy Val;
1362bca07a45SDimitry Andric LValue LV = EmitBinAssignLValue(E, Val);
1363bca07a45SDimitry Andric
1364bca07a45SDimitry Andric // The result of an assignment in C is the assigned r-value.
136513cc256eSDimitry Andric if (!CGF.getLangOpts().CPlusPlus)
1366bca07a45SDimitry Andric return Val;
1367bca07a45SDimitry Andric
1368bca07a45SDimitry Andric // If the lvalue is non-volatile, return the computed value of the assignment.
1369bca07a45SDimitry Andric if (!LV.isVolatileQualified())
1370bca07a45SDimitry Andric return Val;
1371bca07a45SDimitry Andric
1372bfef3995SDimitry Andric return EmitLoadOfLValue(LV, E->getExprLoc());
13737ef7bab7SEd Schouten }
13747ef7bab7SEd Schouten
VisitBinComma(const BinaryOperator * E)1375ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
1376bca07a45SDimitry Andric CGF.EmitIgnoredExpr(E->getLHS());
1377ec2b103cSEd Schouten return Visit(E->getRHS());
1378ec2b103cSEd Schouten }
1379ec2b103cSEd Schouten
1380ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::
VisitAbstractConditionalOperator(const AbstractConditionalOperator * E)1381bca07a45SDimitry Andric VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
1382ec2b103cSEd Schouten TestAndClearIgnoreReal();
1383ec2b103cSEd Schouten TestAndClearIgnoreImag();
1384ec2b103cSEd Schouten llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
1385ec2b103cSEd Schouten llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
1386ec2b103cSEd Schouten llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
1387ec2b103cSEd Schouten
1388bca07a45SDimitry Andric // Bind the common expression if necessary.
1389bca07a45SDimitry Andric CodeGenFunction::OpaqueValueMapping binding(CGF, E);
1390bca07a45SDimitry Andric
13915e20cdd8SDimitry Andric
1392bca07a45SDimitry Andric CodeGenFunction::ConditionalEvaluation eval(CGF);
13935e20cdd8SDimitry Andric CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock,
13945e20cdd8SDimitry Andric CGF.getProfileCount(E));
1395ec2b103cSEd Schouten
1396bca07a45SDimitry Andric eval.begin(CGF);
1397ec2b103cSEd Schouten CGF.EmitBlock(LHSBlock);
1398ac9a064cSDimitry Andric if (llvm::EnableSingleByteCoverage)
1399ac9a064cSDimitry Andric CGF.incrementProfileCounter(E->getTrueExpr());
1400ac9a064cSDimitry Andric else
14015e20cdd8SDimitry Andric CGF.incrementProfileCounter(E);
1402ac9a064cSDimitry Andric
1403bca07a45SDimitry Andric ComplexPairTy LHS = Visit(E->getTrueExpr());
1404ec2b103cSEd Schouten LHSBlock = Builder.GetInsertBlock();
1405ec2b103cSEd Schouten CGF.EmitBranch(ContBlock);
1406bca07a45SDimitry Andric eval.end(CGF);
1407ec2b103cSEd Schouten
1408bca07a45SDimitry Andric eval.begin(CGF);
1409ec2b103cSEd Schouten CGF.EmitBlock(RHSBlock);
1410ac9a064cSDimitry Andric if (llvm::EnableSingleByteCoverage)
1411ac9a064cSDimitry Andric CGF.incrementProfileCounter(E->getFalseExpr());
1412bca07a45SDimitry Andric ComplexPairTy RHS = Visit(E->getFalseExpr());
1413ec2b103cSEd Schouten RHSBlock = Builder.GetInsertBlock();
1414ec2b103cSEd Schouten CGF.EmitBlock(ContBlock);
1415ac9a064cSDimitry Andric if (llvm::EnableSingleByteCoverage)
1416ac9a064cSDimitry Andric CGF.incrementProfileCounter(E);
1417bca07a45SDimitry Andric eval.end(CGF);
1418ec2b103cSEd Schouten
1419ec2b103cSEd Schouten // Create a PHI node for the real part.
142001af97d3SDimitry Andric llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), 2, "cond.r");
1421ec2b103cSEd Schouten RealPN->addIncoming(LHS.first, LHSBlock);
1422ec2b103cSEd Schouten RealPN->addIncoming(RHS.first, RHSBlock);
1423ec2b103cSEd Schouten
1424ec2b103cSEd Schouten // Create a PHI node for the imaginary part.
142501af97d3SDimitry Andric llvm::PHINode *ImagPN = Builder.CreatePHI(LHS.first->getType(), 2, "cond.i");
1426ec2b103cSEd Schouten ImagPN->addIncoming(LHS.second, LHSBlock);
1427ec2b103cSEd Schouten ImagPN->addIncoming(RHS.second, RHSBlock);
1428ec2b103cSEd Schouten
1429ec2b103cSEd Schouten return ComplexPairTy(RealPN, ImagPN);
1430ec2b103cSEd Schouten }
1431ec2b103cSEd Schouten
VisitChooseExpr(ChooseExpr * E)1432ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::VisitChooseExpr(ChooseExpr *E) {
1433bfef3995SDimitry Andric return Visit(E->getChosenSubExpr());
1434ec2b103cSEd Schouten }
1435ec2b103cSEd Schouten
VisitInitListExpr(InitListExpr * E)1436ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
1437ec2b103cSEd Schouten bool Ignore = TestAndClearIgnoreReal();
1438ec2b103cSEd Schouten (void)Ignore;
1439ec2b103cSEd Schouten assert (Ignore == false && "init list ignored");
1440ec2b103cSEd Schouten Ignore = TestAndClearIgnoreImag();
1441ec2b103cSEd Schouten (void)Ignore;
1442ec2b103cSEd Schouten assert (Ignore == false && "init list ignored");
144336981b17SDimitry Andric
144436981b17SDimitry Andric if (E->getNumInits() == 2) {
144536981b17SDimitry Andric llvm::Value *Real = CGF.EmitScalarExpr(E->getInit(0));
144636981b17SDimitry Andric llvm::Value *Imag = CGF.EmitScalarExpr(E->getInit(1));
144736981b17SDimitry Andric return ComplexPairTy(Real, Imag);
144836981b17SDimitry Andric } else if (E->getNumInits() == 1) {
1449ec2b103cSEd Schouten return Visit(E->getInit(0));
145036981b17SDimitry Andric }
1451ec2b103cSEd Schouten
145248675466SDimitry Andric // Empty init list initializes to null
145336981b17SDimitry Andric assert(E->getNumInits() == 0 && "Unexpected number of inits");
1454809500fcSDimitry Andric QualType Ty = E->getType()->castAs<ComplexType>()->getElementType();
145536981b17SDimitry Andric llvm::Type* LTy = CGF.ConvertType(Ty);
1456ec2b103cSEd Schouten llvm::Value* zeroConstant = llvm::Constant::getNullValue(LTy);
1457ec2b103cSEd Schouten return ComplexPairTy(zeroConstant, zeroConstant);
1458ec2b103cSEd Schouten }
1459ec2b103cSEd Schouten
VisitVAArgExpr(VAArgExpr * E)1460ec2b103cSEd Schouten ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
146145b53394SDimitry Andric Address ArgValue = Address::invalid();
1462ac9a064cSDimitry Andric RValue RV = CGF.EmitVAArg(E, ArgValue);
1463ec2b103cSEd Schouten
1464ac9a064cSDimitry Andric if (!ArgValue.isValid()) {
1465ec2b103cSEd Schouten CGF.ErrorUnsupported(E, "complex va_arg expression");
146636981b17SDimitry Andric llvm::Type *EltTy =
1467809500fcSDimitry Andric CGF.ConvertType(E->getType()->castAs<ComplexType>()->getElementType());
1468ec2b103cSEd Schouten llvm::Value *U = llvm::UndefValue::get(EltTy);
1469ec2b103cSEd Schouten return ComplexPairTy(U, U);
1470ec2b103cSEd Schouten }
1471ec2b103cSEd Schouten
1472ac9a064cSDimitry Andric return RV.getComplexVal();
1473ec2b103cSEd Schouten }
1474ec2b103cSEd Schouten
1475ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
1476ec2b103cSEd Schouten // Entry Point into this File
1477ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
1478ec2b103cSEd Schouten
1479ec2b103cSEd Schouten /// EmitComplexExpr - Emit the computation of the specified expression of
1480ec2b103cSEd Schouten /// complex type, ignoring the result.
EmitComplexExpr(const Expr * E,bool IgnoreReal,bool IgnoreImag)1481ec2b103cSEd Schouten ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal,
1482bca07a45SDimitry Andric bool IgnoreImag) {
1483809500fcSDimitry Andric assert(E && getComplexType(E->getType()) &&
1484ec2b103cSEd Schouten "Invalid complex expression to emit");
1485ec2b103cSEd Schouten
1486bca07a45SDimitry Andric return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag)
1487ec2b103cSEd Schouten .Visit(const_cast<Expr *>(E));
1488ec2b103cSEd Schouten }
1489ec2b103cSEd Schouten
EmitComplexExprIntoLValue(const Expr * E,LValue dest,bool isInit)1490809500fcSDimitry Andric void CodeGenFunction::EmitComplexExprIntoLValue(const Expr *E, LValue dest,
1491809500fcSDimitry Andric bool isInit) {
1492809500fcSDimitry Andric assert(E && getComplexType(E->getType()) &&
1493ec2b103cSEd Schouten "Invalid complex expression to emit");
1494ec2b103cSEd Schouten ComplexExprEmitter Emitter(*this);
1495ec2b103cSEd Schouten ComplexPairTy Val = Emitter.Visit(const_cast<Expr*>(E));
1496809500fcSDimitry Andric Emitter.EmitStoreOfComplex(Val, dest, isInit);
1497ec2b103cSEd Schouten }
1498ec2b103cSEd Schouten
1499809500fcSDimitry Andric /// EmitStoreOfComplex - Store a complex number into the specified l-value.
EmitStoreOfComplex(ComplexPairTy V,LValue dest,bool isInit)1500809500fcSDimitry Andric void CodeGenFunction::EmitStoreOfComplex(ComplexPairTy V, LValue dest,
1501809500fcSDimitry Andric bool isInit) {
1502809500fcSDimitry Andric ComplexExprEmitter(*this).EmitStoreOfComplex(V, dest, isInit);
1503ec2b103cSEd Schouten }
1504ec2b103cSEd Schouten
1505809500fcSDimitry Andric /// EmitLoadOfComplex - Load a complex number from the specified address.
EmitLoadOfComplex(LValue src,SourceLocation loc)1506bfef3995SDimitry Andric ComplexPairTy CodeGenFunction::EmitLoadOfComplex(LValue src,
1507bfef3995SDimitry Andric SourceLocation loc) {
1508bfef3995SDimitry Andric return ComplexExprEmitter(*this).EmitLoadOfLValue(src, loc);
1509ec2b103cSEd Schouten }
1510bca07a45SDimitry Andric
EmitComplexAssignmentLValue(const BinaryOperator * E)1511bca07a45SDimitry Andric LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) {
1512bca07a45SDimitry Andric assert(E->getOpcode() == BO_Assign);
1513bca07a45SDimitry Andric ComplexPairTy Val; // ignored
1514706b4fc4SDimitry Andric LValue LVal = ComplexExprEmitter(*this).EmitBinAssignLValue(E, Val);
1515706b4fc4SDimitry Andric if (getLangOpts().OpenMP)
1516706b4fc4SDimitry Andric CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(*this,
1517706b4fc4SDimitry Andric E->getLHS());
1518706b4fc4SDimitry Andric return LVal;
1519bca07a45SDimitry Andric }
1520bca07a45SDimitry Andric
1521bfef3995SDimitry Andric typedef ComplexPairTy (ComplexExprEmitter::*CompoundFunc)(
1522bfef3995SDimitry Andric const ComplexExprEmitter::BinOpInfo &);
1523bca07a45SDimitry Andric
getComplexOp(BinaryOperatorKind Op)1524bfef3995SDimitry Andric static CompoundFunc getComplexOp(BinaryOperatorKind Op) {
1525bfef3995SDimitry Andric switch (Op) {
1526bfef3995SDimitry Andric case BO_MulAssign: return &ComplexExprEmitter::EmitBinMul;
1527bfef3995SDimitry Andric case BO_DivAssign: return &ComplexExprEmitter::EmitBinDiv;
1528bfef3995SDimitry Andric case BO_SubAssign: return &ComplexExprEmitter::EmitBinSub;
1529bfef3995SDimitry Andric case BO_AddAssign: return &ComplexExprEmitter::EmitBinAdd;
1530bca07a45SDimitry Andric default:
1531bca07a45SDimitry Andric llvm_unreachable("unexpected complex compound assignment");
1532bca07a45SDimitry Andric }
1533bfef3995SDimitry Andric }
1534bca07a45SDimitry Andric
1535bfef3995SDimitry Andric LValue CodeGenFunction::
EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator * E)1536bfef3995SDimitry Andric EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) {
1537bfef3995SDimitry Andric CompoundFunc Op = getComplexOp(E->getOpcode());
1538bfef3995SDimitry Andric RValue Val;
1539bca07a45SDimitry Andric return ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
1540bca07a45SDimitry Andric }
1541bfef3995SDimitry Andric
1542bfef3995SDimitry Andric LValue CodeGenFunction::
EmitScalarCompoundAssignWithComplex(const CompoundAssignOperator * E,llvm::Value * & Result)15435e20cdd8SDimitry Andric EmitScalarCompoundAssignWithComplex(const CompoundAssignOperator *E,
1544bfef3995SDimitry Andric llvm::Value *&Result) {
1545bfef3995SDimitry Andric CompoundFunc Op = getComplexOp(E->getOpcode());
1546bfef3995SDimitry Andric RValue Val;
1547bfef3995SDimitry Andric LValue Ret = ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
1548bfef3995SDimitry Andric Result = Val.getScalarVal();
1549bfef3995SDimitry Andric return Ret;
1550bfef3995SDimitry Andric }
1551