Mercurial > projects > ldc
comparison gen/complex.cpp @ 585:fbb1a366cfbc
Complex number should now follow the D ABI on x86. They're also treated as first class values now. Big change.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 09 Sep 2008 16:49:47 -0700 |
parents | a34078905d01 |
children | 192b82878b78 |
comparison
equal
deleted
inserted
replaced
584:c7d7e2282ba3 | 585:fbb1a366cfbc |
---|---|
6 #include "gen/complex.h" | 6 #include "gen/complex.h" |
7 #include "gen/tollvm.h" | 7 #include "gen/tollvm.h" |
8 #include "gen/llvmhelpers.h" | 8 #include "gen/llvmhelpers.h" |
9 #include "gen/irstate.h" | 9 #include "gen/irstate.h" |
10 #include "gen/dvalue.h" | 10 #include "gen/dvalue.h" |
11 #include "gen/logger.h" | |
11 | 12 |
12 ////////////////////////////////////////////////////////////////////////////////////////// | 13 ////////////////////////////////////////////////////////////////////////////////////////// |
13 | 14 |
14 const llvm::StructType* DtoComplexType(Type* type) | 15 const llvm::StructType* DtoComplexType(Type* type) |
15 { | 16 { |
16 Type* t = type->toBasetype(); | 17 Type* t = type->toBasetype(); |
17 | |
18 const LLType* base = DtoComplexBaseType(t); | 18 const LLType* base = DtoComplexBaseType(t); |
19 | 19 return llvm::StructType::get(base, base, NULL); |
20 std::vector<const LLType*> types; | |
21 types.push_back(base); | |
22 types.push_back(base); | |
23 | |
24 return llvm::StructType::get(types); | |
25 } | 20 } |
26 | 21 |
27 const LLType* DtoComplexBaseType(Type* t) | 22 const LLType* DtoComplexBaseType(Type* t) |
28 { | 23 { |
29 TY ty = t->toBasetype()->ty; | 24 TY ty = t->toBasetype()->ty; |
45 } | 40 } |
46 } | 41 } |
47 | 42 |
48 ////////////////////////////////////////////////////////////////////////////////////////// | 43 ////////////////////////////////////////////////////////////////////////////////////////// |
49 | 44 |
50 LLConstant* DtoConstComplex(Type* ty, LLConstant* re, LLConstant* im) | |
51 { | |
52 assert(0); | |
53 const LLType* base = DtoComplexBaseType(ty); | |
54 | |
55 std::vector<LLConstant*> inits; | |
56 inits.push_back(re); | |
57 inits.push_back(im); | |
58 | |
59 const llvm::VectorType* vt = llvm::VectorType::get(base, 2); | |
60 return llvm::ConstantVector::get(vt, inits); | |
61 } | |
62 | |
63 LLConstant* DtoConstComplex(Type* _ty, long double re, long double im) | 45 LLConstant* DtoConstComplex(Type* _ty, long double re, long double im) |
64 { | 46 { |
65 TY ty = _ty->toBasetype()->ty; | 47 TY ty = _ty->toBasetype()->ty; |
66 | 48 |
67 llvm::ConstantFP* fre; | 49 llvm::ConstantFP* fre; |
106 | 88 |
107 DValue* DtoComplex(Loc& loc, Type* to, DValue* val) | 89 DValue* DtoComplex(Loc& loc, Type* to, DValue* val) |
108 { | 90 { |
109 Type* t = val->getType()->toBasetype(); | 91 Type* t = val->getType()->toBasetype(); |
110 | 92 |
111 if (val->isComplex() || t->iscomplex()) { | 93 if (t->iscomplex()) { |
112 return DtoCastComplex(loc, val, to); | 94 return DtoCastComplex(loc, val, to); |
113 } | 95 } |
114 | 96 |
115 const LLType* base = DtoComplexBaseType(to); | 97 const LLType* base = DtoComplexBaseType(to); |
116 | 98 |
125 baseimty = Type::timaginary64; | 107 baseimty = Type::timaginary64; |
126 } else if (ty == Tcomplex80) { | 108 } else if (ty == Tcomplex80) { |
127 baserety = Type::tfloat80; | 109 baserety = Type::tfloat80; |
128 baseimty = Type::timaginary80; | 110 baseimty = Type::timaginary80; |
129 } | 111 } |
112 else { | |
113 assert(0); | |
114 } | |
115 | |
116 const LLType* complexTy = DtoType(to); | |
117 LLValue* res; | |
130 | 118 |
131 if (t->isimaginary()) { | 119 if (t->isimaginary()) { |
132 return new DComplexValue(to, LLConstant::getNullValue(DtoType(baserety)), DtoCastFloat(loc, val, baseimty)->getRVal()); | 120 res = DtoAggrPair(complexTy, LLConstant::getNullValue(DtoType(baserety)), DtoCastFloat(loc, val, baseimty)->getRVal()); |
133 } | 121 } |
134 else if (t->isfloating()) { | 122 else if (t->isfloating() || t->isintegral()) { |
135 return new DComplexValue(to, DtoCastFloat(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty))); | 123 res = DtoAggrPair(complexTy, DtoCastFloat(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty))); |
136 } | 124 } |
137 else if (t->isintegral()) { | 125 else { |
138 return new DComplexValue(to, DtoCastInt(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty))); | 126 assert(0); |
139 } | 127 } |
140 assert(0); | 128 return new DImValue(to, res); |
141 } | 129 } |
142 | 130 |
143 ////////////////////////////////////////////////////////////////////////////////////////// | 131 ////////////////////////////////////////////////////////////////////////////////////////// |
144 | |
145 void DtoComplexAssign(LLValue* l, LLValue* r) | |
146 { | |
147 DtoStore(DtoLoad(DtoGEPi(r, 0,0, "tmp")), DtoGEPi(l,0,0,"tmp")); | |
148 DtoStore(DtoLoad(DtoGEPi(r, 0,1, "tmp")), DtoGEPi(l,0,1,"tmp")); | |
149 } | |
150 | 132 |
151 void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im) | 133 void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im) |
152 { | 134 { |
153 DtoStore(re, DtoGEPi(c,0,0,"tmp")); | 135 DtoStore(re, DtoGEPi(c,0,0,"tmp")); |
154 DtoStore(im, DtoGEPi(c,0,1,"tmp")); | 136 DtoStore(im, DtoGEPi(c,0,1,"tmp")); |
156 | 138 |
157 ////////////////////////////////////////////////////////////////////////////////////////// | 139 ////////////////////////////////////////////////////////////////////////////////////////// |
158 | 140 |
159 void DtoGetComplexParts(DValue* c, LLValue*& re, LLValue*& im) | 141 void DtoGetComplexParts(DValue* c, LLValue*& re, LLValue*& im) |
160 { | 142 { |
161 // get LLValues | 143 LLValue* v = c->getRVal(); |
162 if (DComplexValue* cx = c->isComplex()) { | 144 Logger::cout() << "extracting real and imaginary parts from: " << *v << '\n'; |
163 re = cx->re; | 145 re = gIR->ir->CreateExtractValue(v, 0, ".re_part"); |
164 im = cx->im; | 146 im = gIR->ir->CreateExtractValue(v, 1, ".im_part"); |
165 } | |
166 else { | |
167 re = DtoLoad(DtoGEPi(c->getRVal(),0,0,"tmp")); | |
168 im = DtoLoad(DtoGEPi(c->getRVal(),0,1,"tmp")); | |
169 } | |
170 } | 147 } |
171 | 148 |
172 DValue* resolveLR(DValue* val, bool getlval) | 149 DValue* resolveLR(DValue* val, bool getlval) |
173 { | 150 { |
174 if (DLRValue* lr = val->isLRValue()) { | 151 if (DLRValue* lr = val->isLRValue()) { |
230 else if(hasIm(lhstype)) | 207 else if(hasIm(lhstype)) |
231 res_im = lhs_im; | 208 res_im = lhs_im; |
232 else // either hasIm(rhstype) or no im at all (then use any) | 209 else // either hasIm(rhstype) or no im at all (then use any) |
233 res_im = rhs_im; | 210 res_im = rhs_im; |
234 | 211 |
235 return new DComplexValue(type, res_re, res_im); | 212 LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im); |
213 return new DImValue(type, res); | |
236 } | 214 } |
237 | 215 |
238 ////////////////////////////////////////////////////////////////////////////////////////// | 216 ////////////////////////////////////////////////////////////////////////////////////////// |
239 | 217 |
240 DValue* DtoComplexSub(Loc& loc, Type* type, DValue* lhs, DValue* rhs) | 218 DValue* DtoComplexSub(Loc& loc, Type* type, DValue* lhs, DValue* rhs) |
260 if(hasIm(rhstype)) | 238 if(hasIm(rhstype)) |
261 res_im = gIR->ir->CreateSub(lhs_im, rhs_im, "tmp"); | 239 res_im = gIR->ir->CreateSub(lhs_im, rhs_im, "tmp"); |
262 else | 240 else |
263 res_im = lhs_im; | 241 res_im = lhs_im; |
264 | 242 |
265 return new DComplexValue(type, res_re, res_im); | 243 LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im); |
244 return new DImValue(type, res); | |
266 } | 245 } |
267 | 246 |
268 ////////////////////////////////////////////////////////////////////////////////////////// | 247 ////////////////////////////////////////////////////////////////////////////////////////// |
269 | 248 |
270 DValue* DtoComplexMul(Loc& loc, Type* type, DValue* lhs, DValue* rhs) | 249 DValue* DtoComplexMul(Loc& loc, Type* type, DValue* lhs, DValue* rhs) |
312 else if(imre) | 291 else if(imre) |
313 res_im = imre; | 292 res_im = imre; |
314 else | 293 else |
315 res_im = hasRe(lhstype) ? rhs_im : lhs_re; // null! | 294 res_im = hasRe(lhstype) ? rhs_im : lhs_re; // null! |
316 | 295 |
317 return new DComplexValue(type, res_re, res_im); | 296 LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im); |
297 return new DImValue(type, res); | |
318 } | 298 } |
319 | 299 |
320 ////////////////////////////////////////////////////////////////////////////////////////// | 300 ////////////////////////////////////////////////////////////////////////////////////////// |
321 | 301 |
322 DValue* DtoComplexDiv(Loc& loc, Type* type, DValue* lhs, DValue* rhs) | 302 DValue* DtoComplexDiv(Loc& loc, Type* type, DValue* lhs, DValue* rhs) |
388 | 368 |
389 res_re = gIR->ir->CreateFDiv(res_re, denom, "res_re"); | 369 res_re = gIR->ir->CreateFDiv(res_re, denom, "res_re"); |
390 res_im = gIR->ir->CreateFDiv(res_im, denom, "res_im"); | 370 res_im = gIR->ir->CreateFDiv(res_im, denom, "res_im"); |
391 } | 371 } |
392 | 372 |
393 return new DComplexValue(type, res_re, res_im); | 373 LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im); |
374 return new DImValue(type, res); | |
394 } | 375 } |
395 | 376 |
396 ////////////////////////////////////////////////////////////////////////////////////////// | 377 ////////////////////////////////////////////////////////////////////////////////////////// |
397 | 378 |
398 DValue* DtoComplexNeg(Loc& loc, Type* type, DValue* val) | 379 DValue* DtoComplexNeg(Loc& loc, Type* type, DValue* val) |
406 | 387 |
407 // sub up | 388 // sub up |
408 re = gIR->ir->CreateNeg(a, "tmp"); | 389 re = gIR->ir->CreateNeg(a, "tmp"); |
409 im = gIR->ir->CreateNeg(b, "tmp"); | 390 im = gIR->ir->CreateNeg(b, "tmp"); |
410 | 391 |
411 return new DComplexValue(type, re, im); | 392 LLValue* res = DtoAggrPair(DtoType(type), re, im); |
393 return new DImValue(type, res); | |
412 } | 394 } |
413 | 395 |
414 ////////////////////////////////////////////////////////////////////////////////////////// | 396 ////////////////////////////////////////////////////////////////////////////////////////// |
415 | 397 |
416 LLValue* DtoComplexEquals(Loc& loc, TOK op, DValue* lhs, DValue* rhs) | 398 LLValue* DtoComplexEquals(Loc& loc, TOK op, DValue* lhs, DValue* rhs) |
460 | 442 |
461 if (to->size() < vty->size()) { | 443 if (to->size() < vty->size()) { |
462 re = gIR->ir->CreateFPTrunc(re, toty, "tmp"); | 444 re = gIR->ir->CreateFPTrunc(re, toty, "tmp"); |
463 im = gIR->ir->CreateFPTrunc(im, toty, "tmp"); | 445 im = gIR->ir->CreateFPTrunc(im, toty, "tmp"); |
464 } | 446 } |
465 else if (to->size() > vty->size()) { | 447 else { |
466 re = gIR->ir->CreateFPExt(re, toty, "tmp"); | 448 re = gIR->ir->CreateFPExt(re, toty, "tmp"); |
467 im = gIR->ir->CreateFPExt(im, toty, "tmp"); | 449 im = gIR->ir->CreateFPExt(im, toty, "tmp"); |
468 } | 450 } |
469 else { | 451 |
470 return val; | 452 LLValue* pair = DtoAggrPair(DtoType(_to), re, im); |
471 } | 453 DValue* rval = new DImValue(_to, pair); |
472 | 454 |
473 if (val->isComplex()) | 455 // if the value we're casting is not a lvalue, the cast value can't be either |
474 return new DComplexValue(_to, re, im); | 456 if (!val->isLVal()) { |
457 return rval; | |
458 } | |
475 | 459 |
476 // unfortunately at this point, the cast value can show up as the lvalue for += and similar expressions. | 460 // unfortunately at this point, the cast value can show up as the lvalue for += and similar expressions. |
477 // so we need to give it storage, or fix the system that handles this stuff (DLRValue) | 461 // so we need to maintain the storage |
478 LLValue* mem = DtoAlloca(DtoType(_to), "castcomplextmp"); | 462 return new DLRValue(val, rval); |
479 DtoComplexSet(mem, re, im); | |
480 return new DLRValue(val, new DImValue(_to, mem)); | |
481 } | 463 } |
482 else if (to->isimaginary()) { | 464 else if (to->isimaginary()) { |
483 if (val->isComplex()) | 465 // FIXME: this loads both values, even when we only need one |
484 return new DImValue(to, val->isComplex()->im); | |
485 LLValue* v = val->getRVal(); | 466 LLValue* v = val->getRVal(); |
486 DImValue* im = new DImValue(to, DtoLoad(DtoGEPi(v,0,1,"tmp"))); | 467 LLValue* impart = gIR->ir->CreateExtractValue(v, 1, ".im_part"); |
468 DImValue* im = new DImValue(to, impart); | |
487 return DtoCastFloat(loc, im, to); | 469 return DtoCastFloat(loc, im, to); |
488 } | 470 } |
489 else if (to->isfloating()) { | 471 else if (to->isfloating()) { |
490 if (val->isComplex()) | 472 // FIXME: this loads both values, even when we only need one |
491 return new DImValue(to, val->isComplex()->re); | |
492 LLValue* v = val->getRVal(); | 473 LLValue* v = val->getRVal(); |
493 DImValue* re = new DImValue(to, DtoLoad(DtoGEPi(v,0,0,"tmp"))); | 474 LLValue* repart = gIR->ir->CreateExtractValue(v, 0, ".re_part"); |
475 DImValue* re = new DImValue(to, repart); | |
494 return DtoCastFloat(loc, re, to); | 476 return DtoCastFloat(loc, re, to); |
495 } | 477 } |
496 else | 478 else |
497 assert(0); | 479 assert(0); |
498 } | 480 } |