Mercurial > projects > ldc
comparison gen/complex.cpp @ 104:4d1e9eb001e0 trunk
[svn r108] Now basic suppport for complex types. =,+,-,*,/ are supported.
author | lindquist |
---|---|
date | Mon, 19 Nov 2007 02:58:58 +0100 |
parents | |
children | 3efbcc81ba45 |
comparison
equal
deleted
inserted
replaced
103:855adfdb8d38 | 104:4d1e9eb001e0 |
---|---|
1 #include "gen/llvm.h" | |
2 | |
3 #include "mtype.h" | |
4 #include "declaration.h" | |
5 | |
6 #include "gen/complex.h" | |
7 #include "gen/tollvm.h" | |
8 #include "gen/irstate.h" | |
9 #include "gen/dvalue.h" | |
10 | |
11 ////////////////////////////////////////////////////////////////////////////////////////// | |
12 | |
13 const llvm::StructType* DtoComplexType(Type* type) | |
14 { | |
15 Type* t = DtoDType(type); | |
16 | |
17 const llvm::Type* base = DtoComplexBaseType(t); | |
18 | |
19 std::vector<const llvm::Type*> types; | |
20 types.push_back(base); | |
21 types.push_back(base); | |
22 | |
23 return llvm::StructType::get(types); | |
24 } | |
25 | |
26 const llvm::Type* DtoComplexBaseType(Type* t) | |
27 { | |
28 TY ty = DtoDType(t)->ty; | |
29 const llvm::Type* base; | |
30 if (ty == Tcomplex32) { | |
31 return llvm::Type::FloatTy; | |
32 } | |
33 else if (ty == Tcomplex64 || ty == Tcomplex80) { | |
34 return llvm::Type::DoubleTy; | |
35 } | |
36 else { | |
37 assert(0); | |
38 } | |
39 } | |
40 | |
41 ////////////////////////////////////////////////////////////////////////////////////////// | |
42 | |
43 llvm::Constant* DtoConstComplex(Type* ty, llvm::Constant* re, llvm::Constant* im) | |
44 { | |
45 assert(0); | |
46 const llvm::Type* base = DtoComplexBaseType(ty); | |
47 | |
48 std::vector<llvm::Constant*> inits; | |
49 inits.push_back(re); | |
50 inits.push_back(im); | |
51 | |
52 const llvm::VectorType* vt = llvm::VectorType::get(base, 2); | |
53 return llvm::ConstantVector::get(vt, inits); | |
54 } | |
55 | |
56 llvm::Constant* DtoConstComplex(Type* _ty, long double re, long double im) | |
57 { | |
58 TY ty = DtoDType(_ty)->ty; | |
59 | |
60 llvm::ConstantFP* fre; | |
61 llvm::ConstantFP* fim; | |
62 | |
63 const llvm::Type* base; | |
64 | |
65 if (ty == Tcomplex32) { | |
66 fre = DtoConstFP(Type::tfloat32, re); | |
67 fim = DtoConstFP(Type::tfloat32, im); | |
68 base = llvm::Type::FloatTy; | |
69 } | |
70 else if (ty == Tcomplex64 || ty == Tcomplex80) { | |
71 fre = DtoConstFP(Type::tfloat64, re); | |
72 fim = DtoConstFP(Type::tfloat64, im); | |
73 base = llvm::Type::DoubleTy; | |
74 } | |
75 else | |
76 assert(0); | |
77 | |
78 std::vector<llvm::Constant*> inits; | |
79 inits.push_back(fre); | |
80 inits.push_back(fim); | |
81 return llvm::ConstantStruct::get(DtoComplexType(_ty), inits); | |
82 } | |
83 | |
84 llvm::Constant* DtoUndefComplex(Type* _ty) | |
85 { | |
86 assert(0); | |
87 TY ty = DtoDType(_ty)->ty; | |
88 const llvm::Type* base; | |
89 if (ty == Tcomplex32) { | |
90 base = llvm::Type::FloatTy; | |
91 } | |
92 else if (ty == Tcomplex64 || ty == Tcomplex80) { | |
93 base = llvm::Type::DoubleTy; | |
94 } | |
95 else | |
96 assert(0); | |
97 | |
98 std::vector<llvm::Constant*> inits; | |
99 inits.push_back(llvm::UndefValue::get(base)); | |
100 inits.push_back(llvm::UndefValue::get(base)); | |
101 | |
102 const llvm::VectorType* vt = llvm::VectorType::get(base, 2); | |
103 return llvm::ConstantVector::get(vt, inits); | |
104 } | |
105 | |
106 ////////////////////////////////////////////////////////////////////////////////////////// | |
107 | |
108 llvm::Value* DtoRealPart(DValue* val) | |
109 { | |
110 assert(0); | |
111 return gIR->ir->CreateExtractElement(val->getRVal(), DtoConstUint(0), "tmp"); | |
112 } | |
113 | |
114 ////////////////////////////////////////////////////////////////////////////////////////// | |
115 | |
116 llvm::Value* DtoImagPart(DValue* val) | |
117 { | |
118 assert(0); | |
119 return gIR->ir->CreateExtractElement(val->getRVal(), DtoConstUint(1), "tmp"); | |
120 } | |
121 | |
122 ////////////////////////////////////////////////////////////////////////////////////////// | |
123 | |
124 DValue* DtoComplex(Type* to, DValue* val) | |
125 { | |
126 Type* t = DtoDType(val->getType()); | |
127 TY ty = t->ty; | |
128 | |
129 if (val->isComplex() || t->iscomplex()) { | |
130 assert(DtoDType(to) == t); | |
131 return val; | |
132 } | |
133 | |
134 const llvm::Type* base = DtoComplexBaseType(to); | |
135 | |
136 llvm::Constant* undef = llvm::UndefValue::get(base); | |
137 llvm::Constant* zero; | |
138 if (ty == Tfloat32 || ty == Timaginary32 || ty == Tcomplex32) | |
139 zero = llvm::ConstantFP::get(llvm::Type::FloatTy, float(0)); | |
140 else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64 || ty == Tfloat80 || ty == Timaginary80 || ty == Tcomplex80) | |
141 zero = llvm::ConstantFP::get(llvm::Type::DoubleTy, double(0)); | |
142 | |
143 if (t->isimaginary()) { | |
144 return new DComplexValue(to, zero, val->getRVal()); | |
145 } | |
146 else if (t->isfloating()) { | |
147 return new DComplexValue(to, val->getRVal(), zero); | |
148 } | |
149 else | |
150 assert(0); | |
151 } | |
152 | |
153 ////////////////////////////////////////////////////////////////////////////////////////// | |
154 | |
155 void DtoComplexAssign(llvm::Value* l, llvm::Value* r) | |
156 { | |
157 DtoStore(DtoLoad(DtoGEPi(r, 0,0, "tmp")), DtoGEPi(l,0,0,"tmp")); | |
158 DtoStore(DtoLoad(DtoGEPi(r, 0,1, "tmp")), DtoGEPi(l,0,1,"tmp")); | |
159 } | |
160 | |
161 void DtoComplexSet(llvm::Value* c, llvm::Value* re, llvm::Value* im) | |
162 { | |
163 DtoStore(re, DtoGEPi(c,0,0,"tmp")); | |
164 DtoStore(im, DtoGEPi(c,0,1,"tmp")); | |
165 } | |
166 | |
167 ////////////////////////////////////////////////////////////////////////////////////////// | |
168 | |
169 DValue* DtoComplexAdd(Type* type, DValue* lhs, DValue* rhs) | |
170 { | |
171 lhs = DtoComplex(type, lhs); | |
172 rhs = DtoComplex(type, rhs); | |
173 | |
174 llvm::Value *a, *b, *c, *d, *re, *im; | |
175 | |
176 // lhs values | |
177 if (DComplexValue* cx = lhs->isComplex()) { | |
178 a = cx->re; | |
179 b = cx->im; | |
180 } | |
181 else { | |
182 a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp")); | |
183 b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp")); | |
184 } | |
185 | |
186 // rhs values | |
187 if (DComplexValue* cx = rhs->isComplex()) { | |
188 c = cx->re; | |
189 d = cx->im; | |
190 } | |
191 else { | |
192 c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp")); | |
193 d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp")); | |
194 } | |
195 | |
196 // add up | |
197 re = gIR->ir->CreateAdd(a, c, "tmp"); | |
198 im = gIR->ir->CreateAdd(b, d, "tmp"); | |
199 | |
200 return new DComplexValue(type, re, im); | |
201 } | |
202 | |
203 ////////////////////////////////////////////////////////////////////////////////////////// | |
204 | |
205 DValue* DtoComplexSub(Type* type, DValue* lhs, DValue* rhs) | |
206 { | |
207 lhs = DtoComplex(type, lhs); | |
208 rhs = DtoComplex(type, rhs); | |
209 | |
210 llvm::Value *a, *b, *c, *d, *re, *im; | |
211 | |
212 // lhs values | |
213 if (DComplexValue* cx = lhs->isComplex()) { | |
214 a = cx->re; | |
215 b = cx->im; | |
216 } | |
217 else { | |
218 a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp")); | |
219 b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp")); | |
220 } | |
221 | |
222 // rhs values | |
223 if (DComplexValue* cx = rhs->isComplex()) { | |
224 c = cx->re; | |
225 d = cx->im; | |
226 } | |
227 else { | |
228 c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp")); | |
229 d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp")); | |
230 } | |
231 | |
232 // add up | |
233 re = gIR->ir->CreateSub(a, c, "tmp"); | |
234 im = gIR->ir->CreateSub(b, d, "tmp"); | |
235 | |
236 return new DComplexValue(type, re, im); | |
237 } | |
238 | |
239 ////////////////////////////////////////////////////////////////////////////////////////// | |
240 | |
241 DValue* DtoComplexMul(Type* type, DValue* lhs, DValue* rhs) | |
242 { | |
243 lhs = DtoComplex(type, lhs); | |
244 rhs = DtoComplex(type, rhs); | |
245 | |
246 llvm::Value *a, *b, *c, *d, *re, *im; | |
247 | |
248 // lhs values | |
249 if (DComplexValue* cx = lhs->isComplex()) { | |
250 a = cx->re; | |
251 b = cx->im; | |
252 } | |
253 else { | |
254 a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp")); | |
255 b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp")); | |
256 } | |
257 | |
258 // rhs values | |
259 if (DComplexValue* cx = rhs->isComplex()) { | |
260 c = cx->re; | |
261 d = cx->im; | |
262 } | |
263 else { | |
264 c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp")); | |
265 d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp")); | |
266 } | |
267 | |
268 llvm::Value *tmp1, *tmp2; | |
269 | |
270 tmp1 = gIR->ir->CreateMul(a, c, "tmp"); | |
271 tmp2 = gIR->ir->CreateMul(b, d, "tmp"); | |
272 re = gIR->ir->CreateSub(tmp1, tmp2, "tmp"); | |
273 | |
274 tmp1 = gIR->ir->CreateMul(b, c, "tmp"); | |
275 tmp2 = gIR->ir->CreateMul(a, d, "tmp"); | |
276 im = gIR->ir->CreateAdd(tmp1, tmp2, "tmp"); | |
277 | |
278 return new DComplexValue(type, re, im); | |
279 } | |
280 | |
281 ////////////////////////////////////////////////////////////////////////////////////////// | |
282 | |
283 DValue* DtoComplexDiv(Type* type, DValue* lhs, DValue* rhs) | |
284 { | |
285 lhs = DtoComplex(type, lhs); | |
286 rhs = DtoComplex(type, rhs); | |
287 | |
288 llvm::Value *a, *b, *c, *d, *re, *im; | |
289 | |
290 // lhs values | |
291 if (DComplexValue* cx = lhs->isComplex()) { | |
292 a = cx->re; | |
293 b = cx->im; | |
294 } | |
295 else { | |
296 a = DtoLoad(DtoGEPi(lhs->getRVal(),0,0,"tmp")); | |
297 b = DtoLoad(DtoGEPi(lhs->getRVal(),0,1,"tmp")); | |
298 } | |
299 | |
300 // rhs values | |
301 if (DComplexValue* cx = rhs->isComplex()) { | |
302 c = cx->re; | |
303 d = cx->im; | |
304 } | |
305 else { | |
306 c = DtoLoad(DtoGEPi(rhs->getRVal(),0,0,"tmp")); | |
307 d = DtoLoad(DtoGEPi(rhs->getRVal(),0,1,"tmp")); | |
308 } | |
309 | |
310 llvm::Value *tmp1, *tmp2, *denom; | |
311 | |
312 tmp1 = gIR->ir->CreateMul(c, c, "tmp"); | |
313 tmp2 = gIR->ir->CreateMul(d, d, "tmp"); | |
314 denom = gIR->ir->CreateAdd(tmp1, tmp2, "tmp"); | |
315 | |
316 tmp1 = gIR->ir->CreateMul(a, c, "tmp"); | |
317 tmp2 = gIR->ir->CreateMul(b, d, "tmp"); | |
318 re = gIR->ir->CreateAdd(tmp1, tmp2, "tmp"); | |
319 re = gIR->ir->CreateFDiv(re, denom, "tmp"); | |
320 | |
321 tmp1 = gIR->ir->CreateMul(b, c, "tmp"); | |
322 tmp2 = gIR->ir->CreateMul(a, d, "tmp"); | |
323 im = gIR->ir->CreateSub(tmp1, tmp2, "tmp"); | |
324 im = gIR->ir->CreateFDiv(im, denom, "tmp"); | |
325 | |
326 return new DComplexValue(type, re, im); | |
327 } | |
328 | |
329 ////////////////////////////////////////////////////////////////////////////////////////// | |
330 | |
331 llvm::Value* DtoComplexEquals(TOK op, DValue* lhs, DValue* rhs) | |
332 { | |
333 llvm::Value* lvec = lhs->getRVal(); | |
334 llvm::Value* rvec = rhs->getRVal(); | |
335 | |
336 llvm::FCmpInst::Predicate cmpop; | |
337 switch(op) | |
338 { | |
339 case TOKequal: | |
340 cmpop = llvm::FCmpInst::FCMP_OEQ; | |
341 break; | |
342 case TOKnotequal: | |
343 cmpop = llvm::FCmpInst::FCMP_UNE; | |
344 break; | |
345 default: | |
346 assert(0); | |
347 } | |
348 | |
349 llvm::Value* l1 = gIR->ir->CreateExtractElement(lvec, DtoConstUint(0), "re"); | |
350 llvm::Value* r1 = gIR->ir->CreateExtractElement(rvec, DtoConstUint(0), "re"); | |
351 llvm::Value* b1 = new llvm::FCmpInst(cmpop, l1, r1, "tmp", gIR->scopebb()); | |
352 | |
353 llvm::Value* l2 = gIR->ir->CreateExtractElement(lvec, DtoConstUint(1), "im"); | |
354 llvm::Value* r2 = gIR->ir->CreateExtractElement(rvec, DtoConstUint(1), "im"); | |
355 llvm::Value* b2 = new llvm::FCmpInst(cmpop, l2, r2, "tmp", gIR->scopebb()); | |
356 | |
357 return gIR->ir->CreateAnd(b1,b2,"tmp"); | |
358 } |