blob: 20451698e5463ffd0b901c66ad7f1fe4605aa67f [file] [log] [blame]
Chris Lattnerb6ef18a2007-08-21 05:54:00 +00001//===--- CGComplexExpr.cpp - Emit LLVM Code for Complex Exprs -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This contains code to emit Expr nodes with complex types as LLVM code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenFunction.h"
15#include "CodeGenModule.h"
16#include "clang/AST/AST.h"
17#include "llvm/Constants.h"
18#include "llvm/Function.h"
19#include "llvm/Support/Compiler.h"
20using namespace clang;
21using namespace CodeGen;
22
23//===----------------------------------------------------------------------===//
Chris Lattner05ba49c2007-08-21 05:54:53 +000024// Complex Expression Emitter
Chris Lattnerb6ef18a2007-08-21 05:54:00 +000025//===----------------------------------------------------------------------===//
26
Chris Lattner58dee102007-08-21 16:57:55 +000027typedef CodeGenFunction::ComplexPairTy ComplexPairTy;
Chris Lattnerb6ef18a2007-08-21 05:54:00 +000028
29namespace {
30class VISIBILITY_HIDDEN ComplexExprEmitter
31 : public StmtVisitor<ComplexExprEmitter, ComplexPairTy> {
32 CodeGenFunction &CGF;
33public:
34 ComplexExprEmitter(CodeGenFunction &cgf) : CGF(cgf) {
35 }
36
37
38 //===--------------------------------------------------------------------===//
39 // Utilities
40 //===--------------------------------------------------------------------===//
41
42 /// EmitLoadOfLValue - Given an expression with complex type that represents a
43 /// value l-value, this method emits the address of the l-value, then loads
44 /// and returns the result.
Chris Lattner46d7d9f2007-08-21 17:28:34 +000045 ComplexPairTy EmitLoadOfLValue(const Expr *E) {
46 return EmitLoadOfComplex(CGF.EmitLValue(E).getAddress());
47 }
Chris Lattnerb6ef18a2007-08-21 05:54:00 +000048
Chris Lattner46d7d9f2007-08-21 17:28:34 +000049 /// EmitLoadOfComplex - Given a pointer to a complex value, emit code to load
50 /// the real and imaginary pieces.
51 ComplexPairTy EmitLoadOfComplex(llvm::Value *SrcPtr);
52
53 /// EmitStoreOfComplex - Store the specified real/imag parts into the
54 /// specified value pointer.
55 void EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *ResPtr);
Chris Lattnerb6ef18a2007-08-21 05:54:00 +000056
57 //===--------------------------------------------------------------------===//
58 // Visitor Methods
59 //===--------------------------------------------------------------------===//
60
61 ComplexPairTy VisitStmt(Stmt *S) {
62 fprintf(stderr, "Unimplemented agg expr!\n");
63 S->dump();
64 return ComplexPairTy();
65 }
66 ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());}
67
68 // l-values.
69 ComplexPairTy VisitDeclRefExpr(DeclRefExpr *DRE) {
70 return EmitLoadOfLValue(DRE);
71 }
72 // case Expr::ArraySubscriptExprClass:
73
74 // Operators.
75 // case Expr::UnaryOperatorClass:
76 // case Expr::ImplicitCastExprClass:
77 // case Expr::CastExprClass:
78 // case Expr::CallExprClass:
79 ComplexPairTy VisitBinaryOperator(const BinaryOperator *BO);
Chris Lattner2823c192007-08-21 16:34:16 +000080 ComplexPairTy VisitBinMul (const BinaryOperator *E);
Chris Lattnerb6ef18a2007-08-21 05:54:00 +000081 ComplexPairTy VisitBinAdd (const BinaryOperator *E);
Chris Lattner4034edb2007-08-21 17:12:50 +000082 // FIXME: div/rem
83 // GCC rejects and/or/xor for integer complex.
84 // Logical and/or always return int, never complex.
Chris Lattner58dee102007-08-21 16:57:55 +000085
86 // No comparisons produce a complex result.
Chris Lattnerb6ef18a2007-08-21 05:54:00 +000087 ComplexPairTy VisitBinAssign (const BinaryOperator *E);
88
Chris Lattner756a4d82007-08-21 17:15:50 +000089 ComplexPairTy VisitBinComma (const BinaryOperator *E);
90
Chris Lattnerb6ef18a2007-08-21 05:54:00 +000091
92 ComplexPairTy VisitConditionalOperator(const ConditionalOperator *CO);
93 // case Expr::ChooseExprClass:
94};
95} // end anonymous namespace.
96
97//===----------------------------------------------------------------------===//
98// Utilities
99//===----------------------------------------------------------------------===//
100
Chris Lattner46d7d9f2007-08-21 17:28:34 +0000101/// EmitLoadOfComplex - Given an RValue reference for a complex, emit code to
102/// load the real and imaginary pieces, returning them as Real/Imag.
103ComplexPairTy ComplexExprEmitter::EmitLoadOfComplex(llvm::Value *SrcPtr) {
104 llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
105 llvm::Constant *One = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1);
106 // FIXME: It would be nice to make this "Ptr->getName()+realp"
107 llvm::Value *RealPtr = CGF.Builder.CreateGEP(SrcPtr, Zero, Zero, "realp");
108 llvm::Value *ImagPtr = CGF.Builder.CreateGEP(SrcPtr, Zero, One, "imagp");
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000109
Chris Lattner46d7d9f2007-08-21 17:28:34 +0000110 // FIXME: Handle volatility.
111 // FIXME: It would be nice to make this "Ptr->getName()+real"
112 llvm::Value *Real = CGF.Builder.CreateLoad(RealPtr, "real");
113 llvm::Value *Imag = CGF.Builder.CreateLoad(ImagPtr, "imag");
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000114 return ComplexPairTy(Real, Imag);
115}
116
Chris Lattner46d7d9f2007-08-21 17:28:34 +0000117/// EmitStoreOfComplex - Store the specified real/imag parts into the
118/// specified value pointer.
119void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy V, llvm::Value *Ptr) {
120 llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
121 llvm::Constant *One = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1);
122 llvm::Value *RealPtr = CGF.Builder.CreateGEP(Ptr, Zero, Zero, "real");
123 llvm::Value *ImagPtr = CGF.Builder.CreateGEP(Ptr, Zero, One, "imag");
124
125 // FIXME: Handle volatility.
126 CGF.Builder.CreateStore(V.first, RealPtr);
127 CGF.Builder.CreateStore(V.second, ImagPtr);
128}
129
130
131
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000132//===----------------------------------------------------------------------===//
133// Visitor Methods
134//===----------------------------------------------------------------------===//
135
136ComplexPairTy ComplexExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
Chris Lattner05ba49c2007-08-21 05:54:53 +0000137 fprintf(stderr, "Unimplemented complex binary expr!\n");
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000138 E->dump();
139 return ComplexPairTy();
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000140}
141
142ComplexPairTy ComplexExprEmitter::VisitBinAdd(const BinaryOperator *E) {
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000143 ComplexPairTy LHS = Visit(E->getLHS());
144 ComplexPairTy RHS = Visit(E->getRHS());
145
146 llvm::Value *ResR = CGF.Builder.CreateAdd(LHS.first, RHS.first, "add.r");
147 llvm::Value *ResI = CGF.Builder.CreateAdd(LHS.second, RHS.second, "add.i");
148
149 return ComplexPairTy(ResR, ResI);
150}
151
Chris Lattner2823c192007-08-21 16:34:16 +0000152ComplexPairTy ComplexExprEmitter::VisitBinMul(const BinaryOperator *E) {
153 ComplexPairTy LHS = Visit(E->getLHS());
154 ComplexPairTy RHS = Visit(E->getRHS());
155
156 llvm::Value *ResRl = CGF.Builder.CreateMul(LHS.first, RHS.first, "mul.rl");
157 llvm::Value *ResRr = CGF.Builder.CreateMul(LHS.second, RHS.second, "mul.rr");
158 llvm::Value *ResR = CGF.Builder.CreateSub(ResRl, ResRr, "mul.r");
159
160 llvm::Value *ResIl = CGF.Builder.CreateMul(LHS.second, RHS.first, "mul.il");
161 llvm::Value *ResIr = CGF.Builder.CreateMul(LHS.first, RHS.second, "mul.ir");
162 llvm::Value *ResI = CGF.Builder.CreateAdd(ResIl, ResIr, "mul.i");
163
164 return ComplexPairTy(ResR, ResI);
165}
166
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000167ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
168 assert(E->getLHS()->getType().getCanonicalType() ==
169 E->getRHS()->getType().getCanonicalType() && "Invalid assignment");
170 // Emit the RHS.
171 ComplexPairTy Val = Visit(E->getRHS());
172
173 // Compute the address to store into.
174 LValue LHS = CGF.EmitLValue(E->getLHS());
175
176 // Store into it.
177 // FIXME: Volatility!
Chris Lattner46d7d9f2007-08-21 17:28:34 +0000178 EmitStoreOfComplex(Val, LHS.getAddress());
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000179 return Val;
180}
181
Chris Lattner756a4d82007-08-21 17:15:50 +0000182ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
183 CGF.EmitStmt(E->getLHS());
184 return Visit(E->getRHS());
185}
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000186
187ComplexPairTy ComplexExprEmitter::
188VisitConditionalOperator(const ConditionalOperator *E) {
189 llvm::BasicBlock *LHSBlock = new llvm::BasicBlock("cond.?");
190 llvm::BasicBlock *RHSBlock = new llvm::BasicBlock("cond.:");
191 llvm::BasicBlock *ContBlock = new llvm::BasicBlock("cond.cont");
192
193 llvm::Value *Cond = CGF.EvaluateExprAsBool(E->getCond());
194 CGF.Builder.CreateCondBr(Cond, LHSBlock, RHSBlock);
195
196 CGF.EmitBlock(LHSBlock);
197
198 // Handle the GNU extension for missing LHS.
Chris Lattner05ba49c2007-08-21 05:54:53 +0000199 assert(E->getLHS() && "Must have LHS for complex value");
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000200
201 ComplexPairTy LHS = Visit(E->getLHS());
202 CGF.Builder.CreateBr(ContBlock);
203 LHSBlock = CGF.Builder.GetInsertBlock();
204
205 CGF.EmitBlock(RHSBlock);
206
207 ComplexPairTy RHS = Visit(E->getRHS());
208 CGF.Builder.CreateBr(ContBlock);
209 RHSBlock = CGF.Builder.GetInsertBlock();
210
211 CGF.EmitBlock(ContBlock);
212
213 // Create a PHI node for the real part.
214 llvm::PHINode *RealPN = CGF.Builder.CreatePHI(LHS.first->getType(), "cond.r");
215 RealPN->reserveOperandSpace(2);
216 RealPN->addIncoming(LHS.first, LHSBlock);
217 RealPN->addIncoming(RHS.first, RHSBlock);
218
219 // Create a PHI node for the imaginary part.
220 llvm::PHINode *ImagPN = CGF.Builder.CreatePHI(LHS.first->getType(), "cond.i");
221 ImagPN->reserveOperandSpace(2);
222 ImagPN->addIncoming(LHS.second, LHSBlock);
223 ImagPN->addIncoming(RHS.second, RHSBlock);
224
225 return ComplexPairTy(RealPN, ImagPN);
226}
227
228//===----------------------------------------------------------------------===//
229// Entry Point into this File
230//===----------------------------------------------------------------------===//
231
232/// EmitComplexExpr - Emit the computation of the specified expression of
233/// complex type, ignoring the result.
Chris Lattner58dee102007-08-21 16:57:55 +0000234ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E) {
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000235 assert(E && E->getType()->isComplexType() &&
236 "Invalid complex expression to emit");
237
Chris Lattner58dee102007-08-21 16:57:55 +0000238 return ComplexExprEmitter(*this).Visit(const_cast<Expr*>(E));
Chris Lattnerb6ef18a2007-08-21 05:54:00 +0000239}
240