comparison gen/toir.cpp @ 86:fd32135dca3e trunk

[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!! Lots of bugfixes. Added support for special foreach on strings. Added std.array, std.utf, std.ctype and std.uni to phobos. Changed all the .c files in the gen dir to .cpp (it *is* C++ after all)
author lindquist
date Sat, 03 Nov 2007 14:44:58 +0100
parents gen/toir.c@f869c636a113
children 058d3925950e
comparison
equal deleted inserted replaced
85:f869c636a113 86:fd32135dca3e
1 // Backend stubs
2
3 /* DMDFE backend stubs
4 * This file contains the implementations of the backend routines.
5 * For dmdfe these do nothing but print a message saying the module
6 * has been parsed. Substitute your own behaviors for these routimes.
7 */
8
9 #include <stdio.h>
10 #include <math.h>
11 #include <sstream>
12 #include <fstream>
13 #include <iostream>
14
15 #include "gen/llvm.h"
16
17 #include "total.h"
18 #include "init.h"
19 #include "symbol.h"
20 #include "mtype.h"
21 #include "hdrgen.h"
22 #include "port.h"
23
24 #include "gen/irstate.h"
25 #include "gen/elem.h"
26 #include "gen/logger.h"
27 #include "gen/tollvm.h"
28 #include "gen/runtime.h"
29 #include "gen/arrays.h"
30
31 #include "gen/dvalue.h"
32
33 //////////////////////////////////////////////////////////////////////////////////////////
34
35 DValue* DeclarationExp::toElem(IRState* p)
36 {
37 Logger::print("DeclarationExp::toElem: %s | T=%s\n", toChars(), type->toChars());
38 LOG_SCOPE;
39
40 // variable declaration
41 if (VarDeclaration* vd = declaration->isVarDeclaration())
42 {
43 Logger::println("VarDeclaration");
44
45 // static
46 if (vd->isDataseg())
47 {
48 vd->toObjFile();
49 }
50 else
51 {
52 Logger::println("vdtype = %s", vd->type->toChars());
53 // referenced by nested delegate?
54 if (vd->nestedref) {
55 Logger::println("has nestedref set");
56 vd->llvmValue = p->func().decl->llvmNested;
57 assert(vd->llvmValue);
58 assert(vd->llvmNestedIndex >= 0);
59 }
60 // normal stack variable
61 else {
62 // allocate storage on the stack
63 const llvm::Type* lltype = DtoType(vd->type);
64 llvm::AllocaInst* allocainst = new llvm::AllocaInst(lltype, vd->toChars(), p->topallocapoint());
65 //allocainst->setAlignment(vd->type->alignsize()); // TODO
66 vd->llvmValue = allocainst;
67 }
68 DValue* ie = DtoInitializer(vd->init);
69 delete ie;
70 }
71
72 return new DVarValue(vd, vd->llvmValue, true);
73 }
74 // struct declaration
75 else if (StructDeclaration* s = declaration->isStructDeclaration())
76 {
77 Logger::println("StructDeclaration");
78 s->toObjFile();
79 }
80 // function declaration
81 else if (FuncDeclaration* f = declaration->isFuncDeclaration())
82 {
83 Logger::println("FuncDeclaration");
84 f->toObjFile();
85 }
86 // alias declaration
87 else if (AliasDeclaration* a = declaration->isAliasDeclaration())
88 {
89 Logger::println("AliasDeclaration - no work");
90 // do nothing
91 }
92 else if (EnumDeclaration* e = declaration->isEnumDeclaration())
93 {
94 Logger::println("EnumDeclaration - no work");
95 // do nothing
96 }
97 // unsupported declaration
98 else
99 {
100 error("Only Var/Struct-Declaration is supported for DeclarationExp");
101 assert(0);
102 }
103 return 0;
104 }
105
106 //////////////////////////////////////////////////////////////////////////////////////////
107
108 DValue* VarExp::toElem(IRState* p)
109 {
110 Logger::print("VarExp::toElem: %s | %s\n", toChars(), type->toChars());
111 LOG_SCOPE;
112
113 assert(var);
114 if (VarDeclaration* vd = var->isVarDeclaration())
115 {
116 Logger::println("VarDeclaration %s", vd->toChars());
117
118 // _arguments
119 if (vd->ident == Id::_arguments)
120 {
121 Logger::println("Id::_arguments");
122 if (!vd->llvmValue)
123 vd->llvmValue = p->func().decl->llvmArguments;
124 assert(vd->llvmValue);
125 return new DVarValue(vd, vd->llvmValue, true);
126 }
127 // _argptr
128 else if (vd->ident == Id::_argptr)
129 {
130 Logger::println("Id::_argptr");
131 if (!vd->llvmValue)
132 vd->llvmValue = p->func().decl->llvmArgPtr;
133 assert(vd->llvmValue);
134 return new DVarValue(vd, vd->llvmValue, true);
135 }
136 // _dollar
137 else if (vd->ident == Id::dollar)
138 {
139 Logger::println("Id::dollar");
140 assert(!p->arrays.empty());
141 llvm::Value* tmp = DtoArrayLen(p->arrays.back());
142 return new DVarValue(vd, tmp, false);
143 }
144 // typeinfo
145 else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
146 {
147 Logger::println("TypeInfoDeclaration");
148 tid->toObjFile();
149 assert(tid->llvmValue);
150 const llvm::Type* vartype = DtoType(type);
151 llvm::Value* m;
152 if (tid->llvmValue->getType() != llvm::PointerType::get(vartype))
153 m = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp");
154 else
155 m = tid->llvmValue;
156 return new DVarValue(vd, m, true);
157 }
158 // nested variable
159 else if (vd->nestedref) {
160 Logger::println("nested variable");
161 return new DVarValue(vd, DtoNestedVariable(vd), true);
162 }
163 // function parameter
164 else if (vd->isParameter()) {
165 Logger::println("function param");
166 if (!vd->llvmValue) {
167 // TODO: determine this properly
168 // this happens when the DMD frontend generates by pointer wrappers for struct opEquals(S) and opCmp(S)
169 vd->llvmValue = &p->func().func->getArgumentList().back();
170 }
171 if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->llvmValue)) {
172 return new DVarValue(vd, vd->llvmValue, true);
173 }
174 else if (llvm::isa<llvm::Argument>(vd->llvmValue)) {
175 return new DImValue(type, vd->llvmValue);
176 }
177 else assert(0);
178 }
179 else {
180 // take care of forward references of global variables
181 if (!vd->llvmTouched && vd->isDataseg())
182 vd->toObjFile();
183 assert(vd->llvmValue);
184 return new DVarValue(vd, vd->llvmValue, true);
185 }
186 }
187 else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
188 {
189 Logger::println("FuncDeclaration");
190 if (fdecl->llvmInternal != LLVMva_arg)// && fdecl->llvmValue == 0)
191 fdecl->toObjFile();
192 return new DFuncValue(fdecl, fdecl->llvmValue);
193 }
194 else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
195 {
196 // this seems to be the static initialiser for structs
197 Type* sdecltype = DtoDType(sdecl->type);
198 Logger::print("Sym: type=%s\n", sdecltype->toChars());
199 assert(sdecltype->ty == Tstruct);
200 TypeStruct* ts = (TypeStruct*)sdecltype;
201 assert(ts->llvmInit);
202 return new DVarValue(type, ts->llvmInit, true);
203 }
204 else
205 {
206 assert(0 && "Unimplemented VarExp type");
207 }
208
209 return 0;
210 }
211
212 //////////////////////////////////////////////////////////////////////////////////////////
213
214 llvm::Constant* VarExp::toConstElem(IRState* p)
215 {
216 Logger::print("VarExp::toConstElem: %s | %s\n", toChars(), type->toChars());
217 LOG_SCOPE;
218 if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
219 {
220 // this seems to be the static initialiser for structs
221 Type* sdecltype = DtoDType(sdecl->type);
222 Logger::print("Sym: type=%s\n", sdecltype->toChars());
223 assert(sdecltype->ty == Tstruct);
224 TypeStruct* ts = (TypeStruct*)sdecltype;
225 assert(ts->sym->llvmInitZ);
226 return ts->sym->llvmInitZ;
227 }
228 assert(0 && "Only support const var exp is SymbolDeclaration");
229 return NULL;
230 }
231
232 //////////////////////////////////////////////////////////////////////////////////////////
233
234 DValue* IntegerExp::toElem(IRState* p)
235 {
236 Logger::print("IntegerExp::toElem: %s | %s\n", toChars(), type->toChars());
237 LOG_SCOPE;
238 llvm::Constant* c = toConstElem(p);
239 return new DConstValue(type, c);
240 }
241
242 //////////////////////////////////////////////////////////////////////////////////////////
243
244 llvm::Constant* IntegerExp::toConstElem(IRState* p)
245 {
246 Logger::print("IntegerExp::toConstElem: %s | %s\n", toChars(), type->toChars());
247 LOG_SCOPE;
248 const llvm::Type* t = DtoType(type);
249 if (llvm::isa<llvm::PointerType>(t)) {
250 llvm::Constant* i = llvm::ConstantInt::get(DtoSize_t(),(uint64_t)value,false);
251 return llvm::ConstantExpr::getIntToPtr(i, t);
252 }
253 else if (llvm::isa<llvm::IntegerType>(t)) {
254 return llvm::ConstantInt::get(t,(uint64_t)value,!type->isunsigned());
255 }
256 assert(0);
257 return NULL;
258 }
259
260 //////////////////////////////////////////////////////////////////////////////////////////
261
262 DValue* RealExp::toElem(IRState* p)
263 {
264 Logger::print("RealExp::toElem: %s | %s\n", toChars(), type->toChars());
265 LOG_SCOPE;
266 llvm::Constant* c = toConstElem(p);
267 return new DConstValue(type, c);
268 }
269
270 //////////////////////////////////////////////////////////////////////////////////////////
271
272 llvm::Constant* RealExp::toConstElem(IRState* p)
273 {
274 Logger::print("RealExp::toConstElem: %s | %s\n", toChars(), type->toChars());
275 LOG_SCOPE;
276 Type* t = DtoDType(type);
277 const llvm::Type* fty = DtoType(t);
278 if (t->ty == Tfloat32 || t->ty == Timaginary32)
279 return llvm::ConstantFP::get(fty,float(value));
280 else if (t->ty == Tfloat64 || t->ty == Timaginary64 || t->ty == Tfloat80 || t->ty == Timaginary80)
281 return llvm::ConstantFP::get(fty,double(value));
282 assert(0);
283 return NULL;
284 }
285
286 //////////////////////////////////////////////////////////////////////////////////////////
287
288 DValue* NullExp::toElem(IRState* p)
289 {
290 Logger::print("NullExp::toElem(type=%s): %s\n", type->toChars(),toChars());
291 LOG_SCOPE;
292 llvm::Constant* c = toConstElem(p);
293 return new DNullValue(type, c);
294 }
295
296 //////////////////////////////////////////////////////////////////////////////////////////
297
298 llvm::Constant* NullExp::toConstElem(IRState* p)
299 {
300 Logger::print("NullExp::toConstElem(type=%s): %s\n", type->toChars(),toChars());
301 LOG_SCOPE;
302 const llvm::Type* t = DtoType(type);
303 if (type->ty == Tarray) {
304 assert(llvm::isa<llvm::StructType>(t));
305 return llvm::ConstantAggregateZero::get(t);
306 }
307 else {
308 return llvm::Constant::getNullValue(t);
309 }
310 assert(0);
311 return NULL;
312 }
313
314 //////////////////////////////////////////////////////////////////////////////////////////
315
316 DValue* StringExp::toElem(IRState* p)
317 {
318 Logger::print("StringExp::toElem: %s | %s\n", toChars(), type->toChars());
319 LOG_SCOPE;
320
321 Type* dtype = DtoDType(type);
322 Type* cty = DtoDType(dtype->next);
323
324 const llvm::Type* ct = DtoType(dtype->next);
325 //printf("ct = %s\n", type->next->toChars());
326 const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1);
327
328 llvm::Constant* _init;
329 if (cty->ty == Tchar) {
330 uint8_t* str = (uint8_t*)string;
331 std::string cont((char*)str, len);
332 _init = llvm::ConstantArray::get(cont,true);
333 }
334 else if (cty->ty == Twchar) {
335 uint16_t* str = (uint16_t*)string;
336 std::vector<llvm::Constant*> vals;
337 for(size_t i=0; i<len; ++i) {
338 vals.push_back(llvm::ConstantInt::get(ct, str[i], false));;
339 }
340 vals.push_back(llvm::ConstantInt::get(ct, 0, false));
341 _init = llvm::ConstantArray::get(at,vals);
342 }
343 else if (cty->ty == Tdchar) {
344 uint32_t* str = (uint32_t*)string;
345 std::vector<llvm::Constant*> vals;
346 for(size_t i=0; i<len; ++i) {
347 vals.push_back(llvm::ConstantInt::get(ct, str[i], false));;
348 }
349 vals.push_back(llvm::ConstantInt::get(ct, 0, false));
350 _init = llvm::ConstantArray::get(at,vals);
351 }
352 else
353 assert(0);
354
355 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
356 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,"stringliteral",gIR->module);
357
358 llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
359 llvm::Constant* idxs[2] = { zero, zero };
360 llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
361
362 if (dtype->ty == Tarray) {
363 llvm::Constant* clen = llvm::ConstantInt::get(DtoSize_t(),len,false);
364 if (!p->topexp() || p->topexp()->e2 != this) {
365 llvm::Value* tmpmem = new llvm::AllocaInst(DtoType(dtype),"tempstring",p->topallocapoint());
366 DtoSetArray(tmpmem, clen, arrptr);
367 return new DVarValue(type, tmpmem, true);
368 }
369 else if (p->topexp()->e2 == this) {
370 DValue* arr = p->topexp()->v;
371 assert(arr);
372 DtoSetArray(arr->getLVal(), clen, arrptr);
373 return new DImValue(type, arr->getLVal(), true);
374 }
375 assert(0);
376 }
377 else if (dtype->ty == Tsarray) {
378 const llvm::Type* dstType = llvm::PointerType::get(llvm::ArrayType::get(ct, len));
379 llvm::Value* emem = (gvar->getType() == dstType) ? gvar : DtoBitCast(gvar, dstType);
380 return new DVarValue(type, emem, true);
381 }
382 else if (dtype->ty == Tpointer) {
383 return new DImValue(type, arrptr);
384 }
385
386 assert(0);
387 return 0;
388 }
389
390 //////////////////////////////////////////////////////////////////////////////////////////
391
392 llvm::Constant* StringExp::toConstElem(IRState* p)
393 {
394 Logger::print("StringExp::toConstElem: %s | %s\n", toChars(), type->toChars());
395 LOG_SCOPE;
396
397 uint8_t* str = (uint8_t*)string;
398 std::string cont((char*)str, len);
399
400 Type* t = DtoDType(type);
401
402 if (t->ty == Tsarray) {
403 return llvm::ConstantArray::get(cont,false);
404 }
405 llvm::Constant* _init = llvm::ConstantArray::get(cont,true);
406
407 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
408 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,"stringliteral",gIR->module);
409
410 llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
411 llvm::Constant* idxs[2] = { zero, zero };
412 llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
413
414 if (t->ty == Tpointer) {
415 return arrptr;
416 }
417
418 if (t->ty == Tarray) {
419 llvm::Constant* clen = llvm::ConstantInt::get(DtoSize_t(),len,false);
420 return DtoConstSlice(clen, arrptr);
421 }
422
423 assert(0);
424 return NULL;
425 }
426
427 //////////////////////////////////////////////////////////////////////////////////////////
428
429 DValue* AssignExp::toElem(IRState* p)
430 {
431 Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type ? e2->type->toChars() : 0);
432 LOG_SCOPE;
433
434 p->exps.push_back(IRExp(e1,e2,NULL));
435
436 DValue* l = e1->toElem(p);
437 p->topexp()->v = l;
438 DValue* r = e2->toElem(p);
439
440 p->exps.pop_back();
441
442 if (l->isArrayLen())
443 DtoResizeDynArray(l->getLVal(), r->getRVal());
444 else
445 DtoAssign(l, r);
446 return l;
447
448 /*
449 if (l->type == DValue::ARRAYLEN)
450 {
451 DtoResizeDynArray(l->mem, r->getValue());
452 delete r;
453 delete l;
454 return 0;
455 }
456
457 Type* e1type = DtoDType(e1->type);
458 Type* e2type = DtoDType(e2->type);
459 TY e1ty = e1type->ty;
460 TY e2ty = e2type->ty;
461
462 DValue* e = new DValue(this);
463 e->type = DValue::VAR;
464
465 // struct
466 if (e1ty == Tstruct) {
467 e->mem = l->mem;
468 // struct + struct
469 if (e2ty == Tstruct) {
470 // struct literals do the assignment themselvs (in place)
471 if (!r->inplace) {
472 DtoStructCopy(l->mem,r->getValue());
473 }
474 else {
475 e->inplace = true;
476 }
477 }
478 // struct + const int
479 else if (e2type->isintegral()){
480 IntegerExp* iexp = (IntegerExp*)e2;
481 assert(iexp->value == 0 && "Only integral struct initializer allowed is zero");
482 DtoStructZeroInit(l->mem);
483 }
484 // :x
485 else
486 assert(0 && "struct = unknown");
487 }
488 else if (e1ty == Tsarray) {
489 assert(0 && "static array not supported");
490 }
491 else if (e1ty == Tarray) {
492 if (e2type->isscalar() || e2type->ty == Tclass){
493 if (l->type == DValue::SLICE) {
494 DtoArrayInit(l->mem, l->arg, r->getValue());
495 }
496 else {
497 DtoArrayInit(l->mem, r->getValue());
498 }
499 }
500 else if (e2ty == Tarray) {
501 //new llvm::StoreInst(r->val,l->val,p->scopebb());
502 if (r->type == DValue::NUL) {
503 llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
504 assert(c->isNullValue());
505 DtoNullArray(l->mem);
506 e->mem = l->mem;
507 }
508 else if (r->type == DValue::SLICE) {
509 if (l->type == DValue::SLICE) {
510 DtoArrayCopy(l,r);
511 e->type = DValue::SLICE;
512 e->mem = l->mem;
513 e->arg = l->arg;
514 }
515 else {
516 DtoSetArray(l->mem,r->arg,r->mem);
517 e->mem = l->mem;
518 }
519 }
520 else {
521 // new expressions write directly to the array reference
522 // so do string literals
523 e->mem = l->mem;
524 if (!r->inplace) {
525 assert(r->mem);
526 DtoArrayAssign(l->mem, r->mem);
527 }
528 else {
529 e->inplace = true;
530 }
531 }
532 }
533 else
534 assert(0);
535 }
536 else if (e1ty == Tpointer) {
537 e->mem = l->mem;
538 if (e2ty == Tpointer) {
539 llvm::Value* v = r->field ? r->mem : r->getValue();
540 Logger::cout() << "*=*: " << *v << ", " << *l->mem << '\n';
541 new llvm::StoreInst(v, l->mem, p->scopebb());
542 }
543 else
544 assert(0);
545 }
546 else if (e1ty == Tclass) {
547 if (e2ty == Tclass) {
548 llvm::Value* tmp = r->getValue();
549 Logger::cout() << "tmp: " << *tmp << " ||| " << *l->mem << '\n';
550 // assignment to this in constructor special case
551 if (l->isthis) {
552 FuncDeclaration* fdecl = p->func().decl;
553 // respecify the this param
554 if (!llvm::isa<llvm::AllocaInst>(fdecl->llvmThisVar))
555 fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", p->topallocapoint());
556 new llvm::StoreInst(tmp, fdecl->llvmThisVar, p->scopebb());
557 e->mem = fdecl->llvmThisVar;
558 }
559 // regular class ref -> class ref assignment
560 else {
561 new llvm::StoreInst(tmp, l->mem, p->scopebb());
562 e->mem = l->mem;
563 }
564 }
565 else
566 assert(0);
567 }
568 else if (e1ty == Tdelegate) {
569 Logger::println("Assigning to delegate");
570 if (e2ty == Tdelegate) {
571 if (r->type == DValue::NUL) {
572 llvm::Constant* c = llvm::cast<llvm::Constant>(r->val);
573 if (c->isNullValue()) {
574 DtoNullDelegate(l->mem);
575 e->mem = l->mem;
576 }
577 else
578 assert(0);
579 }
580 else if (r->inplace) {
581 // do nothing
582 e->inplace = true;
583 e->mem = l->mem;
584 }
585 else {
586 DtoDelegateCopy(l->mem, r->getValue());
587 e->mem = l->mem;
588 }
589 }
590 else
591 assert(0);
592 }
593 // !struct && !array && !pointer && !class
594 else {
595 Logger::cout() << *l->mem << '\n';
596 new llvm::StoreInst(r->getValue(),l->mem,p->scopebb());
597 e->mem = l->mem;
598 }
599
600 delete r;
601 delete l;
602
603 return e;
604 */
605 }
606
607 //////////////////////////////////////////////////////////////////////////////////////////
608
609 DValue* AddExp::toElem(IRState* p)
610 {
611 Logger::print("AddExp::toElem: %s | %s\n", toChars(), type->toChars());
612 LOG_SCOPE;
613
614 DValue* l = e1->toElem(p);
615 DValue* r = e2->toElem(p);
616
617 Type* t = DtoDType(type);
618 Type* e1type = DtoDType(e1->type);
619 Type* e2type = DtoDType(e2->type);
620
621 if (e1type != e2type) {
622 if (e1type->ty == Tpointer && e1type->next->ty == Tstruct) {
623 assert(r->isConst());
624 llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
625
626 TypeStruct* ts = (TypeStruct*)e1type->next;
627 std::vector<unsigned> offsets;
628 llvm::Value* v = DtoIndexStruct(l->getRVal(), ts->sym, t->next, cofs->getZExtValue(), offsets);
629 return new DFieldValue(type, v, true);
630 }
631 else if (e1->type->ty == Tpointer) {
632 llvm::Value* v = new llvm::GetElementPtrInst(l->getRVal(), r->getRVal(), "tmp", p->scopebb());
633 return new DImValue(type, v);
634 }
635 assert(0);
636 }
637 else {
638 return DtoBinAdd(l,r);
639 }
640 }
641
642 //////////////////////////////////////////////////////////////////////////////////////////
643
644 DValue* AddAssignExp::toElem(IRState* p)
645 {
646 Logger::print("AddAssignExp::toElem: %s\n", toChars());
647 LOG_SCOPE;
648
649 p->exps.push_back(IRExp(e1,e2,NULL));
650 DValue* l = e1->toElem(p);
651 DValue* r = e2->toElem(p);
652 p->exps.pop_back();
653
654 DValue* res;
655 if (DtoDType(e1->type)->ty == Tpointer) {
656 llvm::Value* gep = new llvm::GetElementPtrInst(l->getRVal(),r->getRVal(),"tmp",p->scopebb());
657 res = new DImValue(type, gep);
658 }
659 else {
660 res = DtoBinAdd(l,r);
661 }
662 DtoAssign(l, res);
663
664 return l;
665
666 /*
667
668 Type* e1type = DtoDType(e1->type);
669
670 DValue* e = new DValue(this);
671 llvm::Value* val = 0;
672 if (e1type->ty == Tpointer) {
673 val = e->mem = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb());
674 }
675 else {
676 val = e->val = llvm::BinaryOperator::createAdd(l->getValue(),r->getValue(),"tmp",p->scopebb());
677 }
678
679 assert(l->mem);
680 new llvm::StoreInst(val,l->mem,p->scopebb());
681 e->type = DValue::VAR;
682
683 delete l;
684 delete r;
685 return e;
686 */
687 }
688
689 //////////////////////////////////////////////////////////////////////////////////////////
690
691 DValue* MinExp::toElem(IRState* p)
692 {
693 Logger::print("MinExp::toElem: %s | %s\n", toChars(), type->toChars());
694 LOG_SCOPE;
695
696 DValue* l = e1->toElem(p);
697 DValue* r = e2->toElem(p);
698
699 if (DtoDType(e1->type)->ty == Tpointer) {
700 llvm::Value* left = p->ir->CreatePtrToInt(l->getRVal(), DtoSize_t(), "tmp");
701 llvm::Value* right = p->ir->CreatePtrToInt(r->getRVal(), DtoSize_t(), "tmp");
702 llvm::Value* diff = p->ir->CreateSub(left,right,"tmp");
703 if (diff->getType() != DtoType(type))
704 diff = p->ir->CreateIntToPtr(diff, DtoType(type));
705 return new DImValue(type, diff);
706 }
707 else {
708 return DtoBinSub(l,r);
709 }
710
711 /*
712 llvm::Value* left = l->getValue();
713 if (llvm::isa<llvm::PointerType>(left->getType()))
714 left = new llvm::PtrToIntInst(left,DtoSize_t(),"tmp",p->scopebb());
715
716 llvm::Value* right = r->getValue();
717 if (llvm::isa<llvm::PointerType>(right->getType()))
718 right = new llvm::PtrToIntInst(right,DtoSize_t(),"tmp",p->scopebb());
719
720 e->val = llvm::BinaryOperator::createSub(left,right,"tmp",p->scopebb());
721 e->type = DValue::VAL;
722
723 const llvm::Type* totype = DtoType(type);
724 if (e->val->getType() != totype) {
725 assert(0);
726 assert(llvm::isa<llvm::PointerType>(e->val->getType()));
727 assert(llvm::isa<llvm::IntegerType>(totype));
728 e->val = new llvm::IntToPtrInst(e->val,totype,"tmp",p->scopebb());
729 }
730
731 delete l;
732 delete r;
733 return e;
734 */
735 }
736
737 //////////////////////////////////////////////////////////////////////////////////////////
738
739 DValue* MinAssignExp::toElem(IRState* p)
740 {
741 Logger::print("MinAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
742 LOG_SCOPE;
743
744 DValue* l = e1->toElem(p);
745 DValue* r = e2->toElem(p);
746
747 DValue* res;
748 if (DtoDType(e1->type)->ty == Tpointer) {
749 llvm::Value* tmp = r->getRVal();
750 llvm::Value* zero = llvm::ConstantInt::get(tmp->getType(),0,false);
751 tmp = llvm::BinaryOperator::createSub(zero,tmp,"tmp",p->scopebb());
752 tmp = new llvm::GetElementPtrInst(l->getRVal(),tmp,"tmp",p->scopebb());
753 res = new DImValue(type, tmp);
754 }
755 else {
756 res = DtoBinSub(l,r);
757 }
758 DtoAssign(l, res);
759
760 return l;
761
762 /*
763
764 Type* e1type = DtoDType(e1->type);
765
766 llvm::Value* tmp = 0;
767 if (e1type->ty == Tpointer) {
768 tmp = r->getValue();
769 llvm::Value* zero = llvm::ConstantInt::get(tmp->getType(),0,false);
770 tmp = llvm::BinaryOperator::createSub(zero,tmp,"tmp",p->scopebb());
771 tmp = new llvm::GetElementPtrInst(l->getValue(),tmp,"tmp",p->scopebb());
772 }
773 else {
774 tmp = llvm::BinaryOperator::createSub(l->getValue(),r->getValue(),"tmp",p->scopebb());
775 }
776
777 assert(l->mem);
778 new llvm::StoreInst(tmp, l->mem, p->scopebb());
779
780 delete l;
781 delete r;
782
783 DValue* e = new DValue(this);
784 e->val = tmp;
785 e->type = DValue::VAR;
786 return e;
787 */
788 }
789
790 //////////////////////////////////////////////////////////////////////////////////////////
791
792 DValue* MulExp::toElem(IRState* p)
793 {
794 Logger::print("MulExp::toElem: %s\n", toChars());
795 LOG_SCOPE;
796
797 DValue* l = e1->toElem(p);
798 DValue* r = e2->toElem(p);
799
800 return DtoBinMul(l,r);
801 /*
802 if (l->dvalue && r->dvalue) {
803 Logger::println("DVALUE PATH");
804 e->dvalue = DtoBinMul(l->dvalue, r->dvalue);
805 e->val = e->dvalue->getRVal();
806 }
807 else {
808 llvm::Value* vl = l->getValue();
809 llvm::Value* vr = r->getValue();
810 Logger::cout() << "mul: " << *vl << ", " << *vr << '\n';
811 e->val = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb());
812 e->dvalue = new DImValue(type, e->val);
813 }
814 e->type = DValue::VAL;
815 delete l;
816 delete r;
817 return e;
818 */
819 }
820
821 //////////////////////////////////////////////////////////////////////////////////////////
822
823 DValue* MulAssignExp::toElem(IRState* p)
824 {
825 Logger::print("MulAssignExp::toElem: %s\n", toChars());
826 LOG_SCOPE;
827
828 DValue* l = e1->toElem(p);
829 DValue* r = e2->toElem(p);
830
831 DValue* res = DtoBinMul(l,r);
832 DtoAssign(l, res);
833
834 return l;
835
836 /*
837 llvm::Value* vl = l->getValue();
838 llvm::Value* vr = r->getValue();
839 Logger::cout() << "mulassign: " << *vl << ", " << *vr << '\n';
840 llvm::Value* tmp = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb());
841
842 assert(l->mem);
843 new llvm::StoreInst(tmp,l->mem,p->scopebb());
844
845 delete l;
846 delete r;
847
848 DValue* e = new DValue(this);
849 e->val = tmp;
850 e->type = DValue::VAR;
851 return e;
852 */
853 }
854
855 //////////////////////////////////////////////////////////////////////////////////////////
856
857 DValue* DivExp::toElem(IRState* p)
858 {
859 Logger::print("DivExp::toElem: %s\n", toChars());
860 LOG_SCOPE;
861
862 DValue* l = e1->toElem(p);
863 DValue* r = e2->toElem(p);
864
865 return DtoBinDiv(l, r);
866 /*
867
868 Type* t = DtoDType(type);
869
870 if (t->isunsigned())
871 e->val = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
872 else if (t->isintegral())
873 e->val = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
874 else if (t->isfloating())
875 e->val = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
876 else
877 assert(0);
878 e->type = DValue::VAL;
879 delete l;
880 delete r;
881 return e;
882 */
883 }
884
885 //////////////////////////////////////////////////////////////////////////////////////////
886
887 DValue* DivAssignExp::toElem(IRState* p)
888 {
889 Logger::print("DivAssignExp::toElem: %s\n", toChars());
890 LOG_SCOPE;
891
892 DValue* l = e1->toElem(p);
893 DValue* r = e2->toElem(p);
894
895 DValue* res = DtoBinDiv(l,r);
896 DtoAssign(l, res);
897
898 return l;
899
900 /*
901
902 Type* t = DtoDType(type);
903
904 llvm::Value* tmp;
905 if (t->isunsigned())
906 tmp = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
907 else if (t->isintegral())
908 tmp = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
909 else if (t->isfloating())
910 tmp = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb());
911 else
912 assert(0);
913
914 assert(l->mem);
915 new llvm::StoreInst(tmp,l->mem,p->scopebb());
916
917 delete l;
918 delete r;
919
920 DValue* e = new DValue(this);
921 e->val = tmp;
922 e->type = DValue::VAR;
923 return e;
924 */
925 }
926
927 //////////////////////////////////////////////////////////////////////////////////////////
928
929 DValue* ModExp::toElem(IRState* p)
930 {
931 Logger::print("ModExp::toElem: %s\n", toChars());
932 LOG_SCOPE;
933
934 DValue* l = e1->toElem(p);
935 DValue* r = e2->toElem(p);
936
937 return DtoBinRem(l, r);
938 /*
939 Type* t = DtoDType(type);
940
941 if (t->isunsigned())
942 e->val = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
943 else if (t->isintegral())
944 e->val = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
945 else if (t->isfloating())
946 e->val = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
947 else
948 assert(0);
949 e->type = DValue::VAL;
950 delete l;
951 delete r;
952 return e;
953 */
954 }
955
956 //////////////////////////////////////////////////////////////////////////////////////////
957
958 DValue* ModAssignExp::toElem(IRState* p)
959 {
960 Logger::print("ModAssignExp::toElem: %s\n", toChars());
961 LOG_SCOPE;
962
963 DValue* l = e1->toElem(p);
964 DValue* r = e2->toElem(p);
965
966 DValue* res = DtoBinRem(l, r);
967 DtoAssign(l, res);
968
969 return l;
970
971 /*
972
973 Type* t = DtoDType(type);
974
975 llvm::Value* tmp;
976 if (t->isunsigned())
977 tmp = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb());
978 else if (t->isintegral())
979 tmp = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
980 else if (t->isfloating())
981 tmp = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb());
982 else
983 assert(0);
984
985 assert(l->mem);
986 new llvm::StoreInst(tmp,l->mem,p->scopebb());
987
988 delete l;
989 delete r;
990
991 DValue* e = new DValue(this);
992 e->val = tmp;
993 e->type = DValue::VAR;
994 return e;
995 */
996 }
997
998 //////////////////////////////////////////////////////////////////////////////////////////
999
1000 DValue* CallExp::toElem(IRState* p)
1001 {
1002 Logger::print("CallExp::toElem: %s\n", toChars());
1003 LOG_SCOPE;
1004
1005 DValue* fn = e1->toElem(p);
1006
1007 TypeFunction* tf = 0;
1008 Type* e1type = DtoDType(e1->type);
1009
1010 bool delegateCall = false;
1011 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false);
1012 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty,1,false);
1013 LINK dlink = LINKdefault;
1014
1015 // hidden struct return parameter handling
1016 bool retinptr = false;
1017
1018 // regular functions
1019 if (e1type->ty == Tfunction) {
1020 tf = (TypeFunction*)e1type;
1021 if (tf->llvmRetInPtr) {
1022 retinptr = true;
1023 }
1024 dlink = tf->linkage;
1025 }
1026
1027 // delegates
1028 else if (e1type->ty == Tdelegate) {
1029 Logger::println("delegateTy = %s\n", e1type->toChars());
1030 assert(e1type->next->ty == Tfunction);
1031 tf = (TypeFunction*)e1type->next;
1032 if (tf->llvmRetInPtr) {
1033 retinptr = true;
1034 }
1035 dlink = tf->linkage;
1036 delegateCall = true;
1037 }
1038
1039 // invalid
1040 else {
1041 assert(tf);
1042 }
1043
1044 // va args
1045 bool va_magic = false;
1046 bool va_intrinsic = false;
1047 DFuncValue* dfv = fn->isFunc();
1048 if (dfv && dfv->func) {
1049 FuncDeclaration* fndecl = dfv->func;
1050 if (fndecl->llvmInternal == LLVMva_intrinsic) {
1051 va_magic = true;
1052 va_intrinsic = true;
1053 }
1054 else if (fndecl->llvmInternal == LLVMva_start) {
1055 va_magic = true;
1056 }
1057 else if (fndecl->llvmInternal == LLVMva_arg) {
1058 //Argument* fnarg = Argument::getNth(tf->parameters, 0);
1059 Expression* exp = (Expression*)arguments->data[0];
1060 DValue* expelem = exp->toElem(p);
1061 Type* t = DtoDType(type);
1062 const llvm::Type* llt = DtoType(type);
1063 if (DtoIsPassedByRef(t))
1064 llt = llvm::PointerType::get(llt);
1065 return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp"));
1066 }
1067 }
1068
1069 // args
1070 size_t n = arguments->dim;
1071 DFuncValue* dfn = fn->isFunc();
1072 if (dfn && dfn->func && dfn->func->llvmInternal == LLVMva_start)
1073 n = 1;
1074 if (delegateCall || (dfn && dfn->vthis)) n++;
1075 if (retinptr) n++;
1076 if (tf->linkage == LINKd && tf->varargs == 1) n+=2;
1077 if (dfn && dfn->func && dfn->func->isNested()) n++;
1078
1079 llvm::Value* funcval = fn->getRVal();
1080 assert(funcval != 0);
1081 std::vector<llvm::Value*> llargs(n, 0);
1082
1083 const llvm::FunctionType* llfnty = 0;
1084
1085 // normal function call
1086 if (llvm::isa<llvm::FunctionType>(funcval->getType())) {
1087 llfnty = llvm::cast<llvm::FunctionType>(funcval->getType());
1088 }
1089 // pointer to something
1090 else if (llvm::isa<llvm::PointerType>(funcval->getType())) {
1091 // pointer to function pointer - I think this not really supposed to happen, but does :/
1092 // seems like sometimes we get a func* other times a func**
1093 if (llvm::isa<llvm::PointerType>(funcval->getType()->getContainedType(0))) {
1094 funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
1095 }
1096 // function pointer
1097 if (llvm::isa<llvm::FunctionType>(funcval->getType()->getContainedType(0))) {
1098 //Logger::cout() << "function pointer type:\n" << *funcval << '\n';
1099 llfnty = llvm::cast<llvm::FunctionType>(funcval->getType()->getContainedType(0));
1100 }
1101 // struct pointer - delegate
1102 else if (llvm::isa<llvm::StructType>(funcval->getType()->getContainedType(0))) {
1103 funcval = DtoGEP(funcval,zero,one,"tmp",p->scopebb());
1104 funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
1105 const llvm::Type* ty = funcval->getType()->getContainedType(0);
1106 llfnty = llvm::cast<llvm::FunctionType>(ty);
1107 }
1108 // unknown
1109 else {
1110 Logger::cout() << "what kind of pointer are we calling? : " << *funcval->getType() << '\n';
1111 }
1112 }
1113 else {
1114 Logger::cout() << "what are we calling? : " << *funcval << '\n';
1115 }
1116 assert(llfnty);
1117 //Logger::cout() << "Function LLVM type: " << *llfnty << '\n';
1118
1119 // argument handling
1120 llvm::FunctionType::param_iterator argiter = llfnty->param_begin();
1121 int j = 0;
1122
1123 IRExp* topexp = p->topexp();
1124
1125 bool isInPlace = false;
1126
1127 // hidden struct return arguments
1128 if (retinptr) {
1129 if (topexp && topexp->e2 == this) {
1130 assert(topexp->v);
1131 llvm::Value* tlv = topexp->v->getLVal();
1132 assert(llvm::isa<llvm::StructType>(tlv->getType()->getContainedType(0)));
1133 llargs[j] = tlv;
1134 if (DtoIsPassedByRef(tf->next)) {
1135 isInPlace = true;
1136 }
1137 else
1138 assert(0);
1139 }
1140 else {
1141 llargs[j] = new llvm::AllocaInst(argiter->get()->getContainedType(0),"rettmp",p->topallocapoint());
1142 }
1143 ++j;
1144 ++argiter;
1145 }
1146
1147 // this arguments
1148 if (dfn && dfn->vthis) {
1149 Logger::println("This Call");
1150 if (dfn->vthis->getType() != argiter->get()) {
1151 //Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n';
1152 llargs[j] = new llvm::BitCastInst(dfn->vthis, argiter->get(), "tmp", p->scopebb());
1153 }
1154 else {
1155 llargs[j] = dfn->vthis;
1156 }
1157 ++j;
1158 ++argiter;
1159 }
1160 // delegate context arguments
1161 else if (delegateCall) {
1162 Logger::println("Delegate Call");
1163 llvm::Value* contextptr = DtoGEP(fn->getRVal(),zero,zero,"tmp",p->scopebb());
1164 llargs[j] = new llvm::LoadInst(contextptr,"tmp",p->scopebb());
1165 ++j;
1166 ++argiter;
1167 }
1168 // nested call
1169 else if (dfn && dfn->func && dfn->func->isNested()) {
1170 Logger::println("Nested Call");
1171 llvm::Value* contextptr = p->func().decl->llvmNested;
1172 assert(contextptr);
1173 llargs[j] = p->ir->CreateBitCast(contextptr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
1174 ++j;
1175 ++argiter;
1176 }
1177
1178 // va arg function special argument passing
1179 if (va_magic) {
1180 size_t n = va_intrinsic ? arguments->dim : 1;
1181 for (int i=0; i<n; i++,j++)
1182 {
1183 Argument* fnarg = Argument::getNth(tf->parameters, i);
1184 Expression* exp = (Expression*)arguments->data[i];
1185 DValue* expelem = exp->toElem(p);
1186 llargs[j] = p->ir->CreateBitCast(expelem->getLVal(), llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
1187 }
1188 }
1189 // regular arguments
1190 else {
1191 if (tf->linkage == LINKd && tf->varargs == 1)
1192 {
1193 Logger::println("doing d-style variadic arguments");
1194
1195 std::vector<const llvm::Type*> vtypes;
1196 std::vector<llvm::Value*> vvalues;
1197 std::vector<llvm::Value*> vtypeinfos;
1198
1199 for (int i=0; i<arguments->dim; i++) {
1200 Argument* fnarg = Argument::getNth(tf->parameters, i);
1201 Expression* argexp = (Expression*)arguments->data[i];
1202 vvalues.push_back(DtoArgument(NULL, fnarg, argexp));
1203 vtypes.push_back(vvalues.back()->getType());
1204
1205 TypeInfoDeclaration* tidecl = argexp->type->getTypeInfoDeclaration();
1206 tidecl->toObjFile();
1207 assert(tidecl->llvmValue);
1208 vtypeinfos.push_back(tidecl->llvmValue);
1209 }
1210
1211 const llvm::StructType* vtype = llvm::StructType::get(vtypes);
1212 llvm::Value* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint());
1213 for (unsigned i=0; i<vtype->getNumElements(); ++i)
1214 p->ir->CreateStore(vvalues[i], DtoGEPi(mem,0,i,"tmp"));
1215
1216 //llvm::Constant* typeinfoparam = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(llfnty->getParamType(j)));
1217 assert(Type::typeinfo->llvmInitZ);
1218 const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmInitZ->getType());
1219 Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n';
1220 const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements());
1221 llvm::Value* typeinfomem = new llvm::AllocaInst(typeinfoarraytype,"_arguments_storage",p->topallocapoint());
1222 for (unsigned i=0; i<vtype->getNumElements(); ++i) {
1223 llvm::Value* v = p->ir->CreateBitCast(vtypeinfos[i], typeinfotype, "tmp");
1224 p->ir->CreateStore(v, DtoGEPi(typeinfomem,0,i,"tmp"));
1225 }
1226
1227 llvm::Value* typeinfoarrayparam = new llvm::AllocaInst(llfnty->getParamType(j)->getContainedType(0),"_arguments_array",p->topallocapoint());
1228 p->ir->CreateStore(DtoConstSize_t(vtype->getNumElements()), DtoGEPi(typeinfoarrayparam,0,0,"tmp"));
1229 llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, llvm::PointerType::get(typeinfotype), "tmp");
1230 p->ir->CreateStore(casttypeinfomem, DtoGEPi(typeinfoarrayparam,0,1,"tmp"));
1231
1232 llargs[j] = typeinfoarrayparam;;
1233 j++;
1234 llargs[j] = p->ir->CreateBitCast(mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
1235 j++;
1236 llargs.resize(2);
1237 }
1238 else {
1239 Logger::println("doing normal arguments");
1240 for (int i=0; i<arguments->dim; i++,j++) {
1241 Argument* fnarg = Argument::getNth(tf->parameters, i);
1242 llargs[j] = DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]);
1243 // this hack is necessary :/
1244 if (dfn && dfn->func && dfn->func->llvmRunTimeHack) {
1245 if (llargs[j]->getType() != llfnty->getParamType(j))
1246 llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
1247 }
1248 }
1249 Logger::println("%d params passed", n);
1250 for (int i=0; i<n; ++i) {
1251 assert(llargs[i]);
1252 Logger::cout() << *llargs[i] << '\n';
1253 }
1254 }
1255 }
1256
1257 // void returns cannot not be named
1258 const char* varname = "";
1259 if (llfnty->getReturnType() != llvm::Type::VoidTy)
1260 varname = "tmp";
1261
1262 Logger::cout() << "Calling: " << *funcval->getType() << '\n';
1263
1264 // call the function
1265 llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb());
1266 llvm::Value* retllval = (retinptr) ? llargs[0] : call;
1267
1268 // set calling convention
1269 if (dfn && dfn->func) {
1270 int li = dfn->func->llvmInternal;
1271 if (li != LLVMintrinsic && li != LLVMva_start && li != LLVMva_intrinsic) {
1272 call->setCallingConv(DtoCallingConv(dlink));
1273 }
1274 }
1275 else if (delegateCall) {
1276 call->setCallingConv(DtoCallingConv(dlink));
1277 }
1278 else if (dfn && dfn->cc != (unsigned)-1) {
1279 call->setCallingConv(dfn->cc);
1280 }
1281
1282 return new DImValue(type, retllval, isInPlace);
1283 }
1284
1285 //////////////////////////////////////////////////////////////////////////////////////////
1286
1287 DValue* CastExp::toElem(IRState* p)
1288 {
1289 Logger::print("CastExp::toElem: %s | %s\n", toChars(), type->toChars());
1290 LOG_SCOPE;
1291
1292 DValue* u = e1->toElem(p);
1293
1294 const llvm::Type* tolltype = DtoType(to);
1295 Type* fromtype = DtoDType(e1->type);
1296 Type* totype = DtoDType(to);
1297 int lsz = fromtype->size();
1298 int rsz = totype->size();
1299
1300 // this makes sure the strange lvalue casts don't screw things up
1301 llvm::Value* rval = 0;
1302 llvm::Value* rval2 = 0;
1303 bool isslice = false;
1304
1305 if (fromtype->isintegral()) {
1306 if (totype->isintegral()) {
1307 if (lsz < rsz) {
1308 Logger::cout() << "cast to: " << *tolltype << '\n';
1309 if (fromtype->isunsigned() || fromtype->ty == Tbool) {
1310 rval = new llvm::ZExtInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1311 } else {
1312 rval = new llvm::SExtInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1313 }
1314 }
1315 else if (lsz > rsz) {
1316 rval = new llvm::TruncInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1317 }
1318 else {
1319 rval = new llvm::BitCastInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1320 }
1321 }
1322 else if (totype->isfloating()) {
1323 if (fromtype->isunsigned()) {
1324 rval = new llvm::UIToFPInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1325 }
1326 else {
1327 rval = new llvm::SIToFPInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1328 }
1329 }
1330 else if (totype->ty == Tpointer) {
1331 rval = p->ir->CreateIntToPtr(u->getRVal(), tolltype, "tmp");
1332 }
1333 else {
1334 assert(0);
1335 }
1336 }
1337 else if (fromtype->isfloating()) {
1338 if (totype->isfloating()) {
1339 if ((fromtype->ty == Tfloat80 || fromtype->ty == Tfloat64) && (totype->ty == Tfloat80 || totype->ty == Tfloat64)) {
1340 rval = u->getRVal();
1341 }
1342 else if (lsz < rsz) {
1343 rval = new llvm::FPExtInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1344 }
1345 else if (lsz > rsz) {
1346 rval = new llvm::FPTruncInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1347 }
1348 else {
1349 assert(0);
1350 }
1351 }
1352 else if (totype->isintegral()) {
1353 if (totype->isunsigned()) {
1354 rval = new llvm::FPToUIInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1355 }
1356 else {
1357 rval = new llvm::FPToSIInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1358 }
1359 }
1360 else {
1361 assert(0);
1362 }
1363 }
1364 else if (fromtype->ty == Tclass) {
1365 //assert(to->ty == Tclass);
1366 rval = new llvm::BitCastInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1367 }
1368 else if (fromtype->ty == Tarray || fromtype->ty == Tsarray) {
1369 Logger::cout() << "from array or sarray" << '\n';
1370 if (totype->ty == Tpointer) {
1371 Logger::cout() << "to pointer" << '\n';
1372 assert(fromtype->next == totype->next || totype->next->ty == Tvoid);
1373 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
1374 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
1375 llvm::Value* ptr = DtoGEP(u->getRVal(),zero,one,"tmp",p->scopebb());
1376 rval = new llvm::LoadInst(ptr, "tmp", p->scopebb());
1377 if (fromtype->next != totype->next)
1378 rval = p->ir->CreateBitCast(rval, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
1379 }
1380 else if (totype->ty == Tarray) {
1381 Logger::cout() << "to array" << '\n';
1382 const llvm::Type* ptrty = DtoType(totype->next);
1383 if (ptrty == llvm::Type::VoidTy)
1384 ptrty = llvm::Type::Int8Ty;
1385 ptrty = llvm::PointerType::get(ptrty);
1386
1387 const llvm::Type* ety = DtoType(fromtype->next);
1388 if (ety == llvm::Type::VoidTy)
1389 ety = llvm::Type::Int8Ty;
1390
1391 if (DSliceValue* usl = u->isSlice()) {
1392 rval = new llvm::BitCastInst(usl->ptr, ptrty, "tmp", p->scopebb());
1393 if (fromtype->next->size() == totype->next->size())
1394 rval2 = usl->len;
1395 else
1396 rval2 = DtoArrayCastLength(usl->len, ety, ptrty->getContainedType(0));
1397 }
1398 else {
1399 llvm::Value* uval = u->getRVal();
1400 if (fromtype->ty == Tsarray) {
1401 Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
1402 assert(llvm::isa<llvm::PointerType>(uval->getType()));
1403 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(uval->getType()->getContainedType(0));
1404 rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
1405 rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
1406 rval = new llvm::BitCastInst(uval, ptrty, "tmp", p->scopebb());
1407 }
1408 else {
1409 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
1410 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
1411 rval2 = DtoGEP(uval,zero,zero,"tmp",p->scopebb());
1412 rval2 = new llvm::LoadInst(rval2, "tmp", p->scopebb());
1413 rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
1414
1415 rval = DtoGEP(uval,zero,one,"tmp",p->scopebb());
1416 rval = new llvm::LoadInst(rval, "tmp", p->scopebb());
1417 //Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n';
1418 rval = new llvm::BitCastInst(rval, ptrty, "tmp", p->scopebb());
1419 }
1420 }
1421 isslice = true;
1422 }
1423 else if (totype->ty == Tsarray) {
1424 Logger::cout() << "to sarray" << '\n';
1425 assert(0);
1426 }
1427 else {
1428 assert(0);
1429 }
1430 }
1431 else if (fromtype->ty == Tpointer) {
1432 if (totype->ty == Tpointer || totype->ty == Tclass) {
1433 llvm::Value* src = u->getRVal();
1434 Logger::cout() << "src: " << *src << "to type: " << *tolltype << '\n';
1435 rval = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb());
1436 }
1437 else if (totype->isintegral()) {
1438 rval = new llvm::PtrToIntInst(u->getRVal(), tolltype, "tmp", p->scopebb());
1439 }
1440 else
1441 assert(0);
1442 }
1443 else {
1444 assert(0);
1445 }
1446
1447 if (isslice) {
1448 return new DSliceValue(type, rval2, rval);
1449 }
1450 else if (u->isLValueCast() || u->isVar()) {
1451 return new DLValueCast(type, u->getLVal(), rval);
1452 }
1453 else if (p->topexp() && p->topexp()->e1 == this) {
1454 llvm::Value* lval = u->getLVal();
1455 Logger::cout() << "lval: " << *lval << "rval: " << *rval << '\n';
1456 return new DLValueCast(type, lval, rval);
1457 }
1458 else {
1459 Logger::cout() << "im rval: " << *rval << '\n';
1460 return new DImValue(type, rval);
1461 }
1462 }
1463
1464 //////////////////////////////////////////////////////////////////////////////////////////
1465
1466 DValue* SymOffExp::toElem(IRState* p)
1467 {
1468 Logger::print("SymOffExp::toElem: %s | %s\n", toChars(), type->toChars());
1469 LOG_SCOPE;
1470
1471 if (VarDeclaration* vd = var->isVarDeclaration())
1472 {
1473 Logger::println("VarDeclaration");
1474 if (!vd->llvmTouched && vd->isDataseg())
1475 vd->toObjFile();
1476
1477 // TODO
1478 /*
1479 if (vd->isTypedefDeclaration()) {
1480 e->istypeinfo = true;
1481 }
1482 */
1483
1484 assert(vd->llvmValue);
1485 Type* t = DtoDType(type);
1486 Type* tnext = DtoDType(t->next);
1487 Type* vdtype = DtoDType(vd->type);
1488
1489 llvm::Value* llvalue = vd->nestedref ? DtoNestedVariable(vd) : vd->llvmValue;
1490 llvm::Value* varmem = 0;
1491
1492 if (vdtype->ty == Tstruct && !(t->ty == Tpointer && t->next == vdtype)) {
1493 Logger::println("struct");
1494 TypeStruct* vdt = (TypeStruct*)vdtype;
1495 assert(vdt->sym);
1496
1497 const llvm::Type* llt = DtoType(t);
1498 if (offset == 0) {
1499 varmem = p->ir->CreateBitCast(llvalue, llt, "tmp");
1500 }
1501 else {
1502 std::vector<unsigned> dst;
1503 varmem = DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst);
1504 }
1505 }
1506 else if (vdtype->ty == Tsarray) {
1507 Logger::println("sarray");
1508
1509 assert(llvalue);
1510 //e->arg = llvalue; // TODO
1511
1512 const llvm::Type* llt = DtoType(t);
1513 llvm::Value* off = 0;
1514 if (offset != 0) {
1515 Logger::println("offset = %d\n", offset);
1516 }
1517 if (llvalue->getType() != llt) {
1518 varmem = p->ir->CreateBitCast(llvalue, llt, "tmp");
1519 if (offset != 0)
1520 varmem = DtoGEPi(varmem, offset, "tmp");
1521 }
1522 else {
1523 assert(offset == 0);
1524 varmem = DtoGEPi(llvalue,0,0,"tmp");
1525 }
1526 }
1527 else if (offset == 0) {
1528 Logger::println("normal symoff");
1529
1530 assert(llvalue);
1531 varmem = llvalue;
1532
1533 const llvm::Type* llt = DtoType(t);
1534 if (llvalue->getType() != llt) {
1535 varmem = p->ir->CreateBitCast(varmem, llt, "tmp");
1536 }
1537 }
1538 else {
1539 assert(0);
1540 }
1541 return new DFieldValue(type, varmem, true);
1542 }
1543 else if (FuncDeclaration* fd = var->isFuncDeclaration())
1544 {
1545 Logger::println("FuncDeclaration");
1546
1547 if (fd->llvmValue == 0)
1548 fd->toObjFile();
1549 return new DFuncValue(fd, fd->llvmValue);
1550 }
1551
1552 assert(0);
1553 return 0;
1554 }
1555
1556 //////////////////////////////////////////////////////////////////////////////////////////
1557
1558 DValue* PtrExp::toElem(IRState* p)
1559 {
1560 Logger::print("PtrExp::toElem: %s | %s\n", toChars(), type->toChars());
1561 LOG_SCOPE;
1562
1563 DValue* a = e1->toElem(p);
1564
1565 if (p->topexp() && p->topexp()->e1 == this) {
1566 Logger::println("lval PtrExp");
1567 //if (a->isField()) return a;
1568 return new DVarValue(type, a->getRVal(), true);
1569 }
1570
1571 llvm::Value* lv = a->getRVal();
1572 llvm::Value* v = lv;
1573 if (DtoCanLoad(v))
1574 v = DtoLoad(v);
1575 return new DLValueCast(type, lv, v);
1576 }
1577
1578 //////////////////////////////////////////////////////////////////////////////////////////
1579
1580 DValue* DotVarExp::toElem(IRState* p)
1581 {
1582 Logger::print("DotVarExp::toElem: %s | %s\n", toChars(), type->toChars());
1583 LOG_SCOPE;
1584
1585 DValue* l = e1->toElem(p);
1586
1587 Type* t = DtoDType(type);
1588 Type* e1type = DtoDType(e1->type);
1589
1590 Logger::print("e1->type=%s\n", e1type->toChars());
1591
1592 if (VarDeclaration* vd = var->isVarDeclaration()) {
1593 llvm::Value* arrptr;
1594 if (e1type->ty == Tpointer) {
1595 assert(e1type->next->ty == Tstruct);
1596 TypeStruct* ts = (TypeStruct*)e1type->next;
1597 Logger::println("Struct member offset:%d", vd->offset);
1598 llvm::Value* src = l->getRVal();
1599 std::vector<unsigned> vdoffsets;
1600 arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
1601 }
1602 else if (e1->type->ty == Tclass) {
1603 TypeClass* tc = (TypeClass*)e1type;
1604 Logger::println("Class member offset: %d", vd->offset);
1605 std::vector<unsigned> vdoffsets(1,0);
1606 tc->sym->offsetToIndex(vd->type, vd->offset, vdoffsets);
1607 llvm::Value* src = l->getRVal();
1608 Logger::cout() << "src: " << *src << '\n';
1609 arrptr = DtoGEP(src,vdoffsets,"tmp",p->scopebb());
1610 }
1611 else
1612 assert(0);
1613
1614 Logger::cout() << "mem: " << *arrptr << '\n';
1615 return new DVarValue(vd, arrptr, true);
1616 }
1617 else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
1618 {
1619 if (fdecl->llvmValue == 0)
1620 {
1621 fdecl->toObjFile();
1622 }
1623
1624 llvm::Value* funcval = fdecl->llvmValue;
1625 llvm::Value* vthis = l->getRVal();
1626 unsigned cc = (unsigned)-1;
1627
1628 // virtual call
1629 if (fdecl->isVirtual()) {
1630 assert(fdecl->vtblIndex > 0);
1631 assert(e1type->ty == Tclass);
1632
1633 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
1634 llvm::Value* vtblidx = llvm::ConstantInt::get(llvm::Type::Int32Ty, (size_t)fdecl->vtblIndex, false);
1635 funcval = DtoGEP(vthis, zero, zero, "tmp", p->scopebb());
1636 funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
1637 funcval = DtoGEP(funcval, zero, vtblidx, toChars(), p->scopebb());
1638 funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
1639 assert(funcval->getType() == fdecl->llvmValue->getType());
1640 cc = DtoCallingConv(fdecl->linkage);
1641 }
1642 return new DFuncValue(fdecl, funcval, vthis);
1643 }
1644 else {
1645 printf("unknown: %s\n", var->toChars());
1646 }
1647
1648 assert(0);
1649 return 0;
1650 }
1651
1652 //////////////////////////////////////////////////////////////////////////////////////////
1653
1654 DValue* ThisExp::toElem(IRState* p)
1655 {
1656 Logger::print("ThisExp::toElem: %s | %s\n", toChars(), type->toChars());
1657 LOG_SCOPE;
1658
1659 if (VarDeclaration* vd = var->isVarDeclaration()) {
1660 llvm::Value* v = p->func().decl->llvmThisVar;
1661 if (llvm::isa<llvm::AllocaInst>(v))
1662 v = new llvm::LoadInst(v, "tmp", p->scopebb());
1663 return new DThisValue(vd, v);
1664 }
1665
1666 assert(0);
1667 return 0;
1668 }
1669
1670 //////////////////////////////////////////////////////////////////////////////////////////
1671
1672 DValue* AddrExp::toElem(IRState* p)
1673 {
1674 Logger::print("AddrExp::toElem: %s | %s\n", toChars(), type->toChars());
1675 LOG_SCOPE;
1676 DValue* v = e1->toElem(p);
1677 if (v->isField())
1678 return v;
1679 return new DFieldValue(type, v->getLVal(), false);
1680 }
1681
1682 //////////////////////////////////////////////////////////////////////////////////////////
1683
1684 DValue* IndexExp::toElem(IRState* p)
1685 {
1686 Logger::print("IndexExp::toElem: %s | %s\n", toChars(), type->toChars());
1687 LOG_SCOPE;
1688
1689 DValue* l = e1->toElem(p);
1690
1691 Type* e1type = DtoDType(e1->type);
1692
1693 p->arrays.push_back(l); // if $ is used it must be an array so this is fine.
1694 DValue* r = e2->toElem(p);
1695 p->arrays.pop_back();
1696
1697 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
1698 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
1699
1700 llvm::Value* arrptr = 0;
1701 if (e1type->ty == Tpointer) {
1702 arrptr = new llvm::GetElementPtrInst(l->getRVal(),r->getRVal(),"tmp",p->scopebb());
1703 }
1704 else if (e1type->ty == Tsarray) {
1705 arrptr = DtoGEP(l->getRVal(), zero, r->getRVal(),"tmp",p->scopebb());
1706 }
1707 else if (e1type->ty == Tarray) {
1708 arrptr = DtoGEP(l->getLVal(),zero,one,"tmp",p->scopebb());
1709 arrptr = new llvm::LoadInst(arrptr,"tmp",p->scopebb());
1710 arrptr = new llvm::GetElementPtrInst(arrptr,r->getRVal(),"tmp",p->scopebb());
1711 }
1712 assert(arrptr);
1713 return new DVarValue(type, arrptr, true);
1714 }
1715
1716 //////////////////////////////////////////////////////////////////////////////////////////
1717
1718 DValue* SliceExp::toElem(IRState* p)
1719 {
1720 Logger::print("SliceExp::toElem: %s | %s\n", toChars(), type->toChars());
1721 LOG_SCOPE;
1722
1723 Type* t = DtoDType(type);
1724 Type* e1type = DtoDType(e1->type);
1725
1726 DValue* v = e1->toElem(p);
1727 llvm::Value* vmem = v->getLVal();
1728 assert(vmem);
1729
1730 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
1731 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
1732
1733 llvm::Value* emem = 0;
1734 llvm::Value* earg = 0;
1735
1736 // partial slice
1737 if (lwr)
1738 {
1739 assert(upr);
1740 p->arrays.push_back(v);
1741 DValue* lo = lwr->toElem(p);
1742
1743 bool lwr_is_zero = false;
1744 if (DConstValue* cv = lo->isConst())
1745 {
1746 assert(llvm::isa<llvm::ConstantInt>(cv->c));
1747
1748 if (e1type->ty == Tpointer) {
1749 emem = v->getRVal();
1750 }
1751 else if (e1type->ty == Tarray) {
1752 llvm::Value* tmp = DtoGEP(vmem,zero,one,"tmp",p->scopebb());
1753 emem = new llvm::LoadInst(tmp,"tmp",p->scopebb());
1754 }
1755 else if (e1type->ty == Tsarray) {
1756 emem = DtoGEP(vmem,zero,zero,"tmp",p->scopebb());
1757 }
1758 else
1759 assert(emem);
1760
1761 llvm::ConstantInt* c = llvm::cast<llvm::ConstantInt>(cv->c);
1762 if (!(lwr_is_zero = c->isZero())) {
1763 emem = new llvm::GetElementPtrInst(emem,cv->c,"tmp",p->scopebb());
1764 }
1765 }
1766 else
1767 {
1768 if (e1type->ty == Tarray) {
1769 llvm::Value* tmp = DtoGEP(vmem,zero,one,"tmp",p->scopebb());
1770 tmp = new llvm::LoadInst(tmp,"tmp",p->scopebb());
1771 emem = new llvm::GetElementPtrInst(tmp,lo->getRVal(),"tmp",p->scopebb());
1772 }
1773 else if (e1type->ty == Tsarray) {
1774 emem = DtoGEP(vmem,zero,lo->getRVal(),"tmp",p->scopebb());
1775 }
1776 else if (e1type->ty == Tpointer) {
1777 emem = new llvm::GetElementPtrInst(v->getRVal(),lo->getRVal(),"tmp",p->scopebb());
1778 }
1779 else {
1780 Logger::println("type = %s", e1type->toChars());
1781 assert(0);
1782 }
1783 }
1784
1785 DValue* up = upr->toElem(p);
1786 p->arrays.pop_back();
1787
1788 if (DConstValue* cv = up->isConst())
1789 {
1790 assert(llvm::isa<llvm::ConstantInt>(cv->c));
1791 if (lwr_is_zero) {
1792 earg = cv->c;
1793 }
1794 else {
1795 if (lo->isConst()) {
1796 llvm::Constant* clo = llvm::cast<llvm::Constant>(lo->getRVal());
1797 llvm::Constant* cup = llvm::cast<llvm::Constant>(cv->c);
1798 earg = llvm::ConstantExpr::getSub(cup, clo);
1799 }
1800 else {
1801 earg = llvm::BinaryOperator::createSub(cv->c, lo->getRVal(), "tmp", p->scopebb());
1802 }
1803 }
1804 }
1805 else
1806 {
1807 if (lwr_is_zero) {
1808 earg = up->getRVal();
1809 }
1810 else {
1811 earg = llvm::BinaryOperator::createSub(up->getRVal(), lo->getRVal(), "tmp", p->scopebb());
1812 }
1813 }
1814 }
1815 // full slice
1816 else
1817 {
1818 emem = vmem;
1819 }
1820
1821 return new DSliceValue(type,earg,emem);
1822 }
1823
1824 //////////////////////////////////////////////////////////////////////////////////////////
1825
1826 DValue* CmpExp::toElem(IRState* p)
1827 {
1828 Logger::print("CmpExp::toElem: %s | %s\n", toChars(), type->toChars());
1829 LOG_SCOPE;
1830
1831 DValue* l = e1->toElem(p);
1832 DValue* r = e2->toElem(p);
1833
1834 Type* t = DtoDType(e1->type);
1835 Type* e2t = DtoDType(e2->type);
1836 assert(t == e2t);
1837
1838 llvm::Value* eval = 0;
1839
1840 if (t->isintegral() || t->ty == Tpointer)
1841 {
1842 llvm::ICmpInst::Predicate cmpop;
1843 bool skip = false;
1844 switch(op)
1845 {
1846 case TOKlt:
1847 case TOKul:
1848 cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_ULT : llvm::ICmpInst::ICMP_SLT;
1849 break;
1850 case TOKle:
1851 case TOKule:
1852 cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_ULE : llvm::ICmpInst::ICMP_SLE;
1853 break;
1854 case TOKgt:
1855 case TOKug:
1856 cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_UGT : llvm::ICmpInst::ICMP_SGT;
1857 break;
1858 case TOKge:
1859 case TOKuge:
1860 cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_UGE : llvm::ICmpInst::ICMP_SGE;
1861 break;
1862 case TOKue:
1863 cmpop = llvm::ICmpInst::ICMP_EQ;
1864 break;
1865 case TOKlg:
1866 cmpop = llvm::ICmpInst::ICMP_NE;
1867 break;
1868 case TOKleg:
1869 skip = true;
1870 eval = llvm::ConstantInt::getTrue();
1871 break;
1872 case TOKunord:
1873 skip = true;
1874 eval = llvm::ConstantInt::getFalse();
1875 break;
1876
1877 default:
1878 assert(0);
1879 }
1880 if (!skip)
1881 {
1882 eval = new llvm::ICmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb());
1883 }
1884 }
1885 else if (t->isfloating())
1886 {
1887 llvm::FCmpInst::Predicate cmpop;
1888 switch(op)
1889 {
1890 case TOKlt:
1891 cmpop = llvm::FCmpInst::FCMP_OLT;break;
1892 case TOKle:
1893 cmpop = llvm::FCmpInst::FCMP_OLE;break;
1894 case TOKgt:
1895 cmpop = llvm::FCmpInst::FCMP_OGT;break;
1896 case TOKge:
1897 cmpop = llvm::FCmpInst::FCMP_OGE;break;
1898 case TOKunord:
1899 cmpop = llvm::FCmpInst::FCMP_UNO;break;
1900 case TOKule:
1901 cmpop = llvm::FCmpInst::FCMP_ULE;break;
1902 case TOKul:
1903 cmpop = llvm::FCmpInst::FCMP_ULT;break;
1904 case TOKuge:
1905 cmpop = llvm::FCmpInst::FCMP_UGE;break;
1906 case TOKug:
1907 cmpop = llvm::FCmpInst::FCMP_UGT;break;
1908 case TOKue:
1909 cmpop = llvm::FCmpInst::FCMP_UEQ;break;
1910 case TOKlg:
1911 cmpop = llvm::FCmpInst::FCMP_ONE;break;
1912 case TOKleg:
1913 cmpop = llvm::FCmpInst::FCMP_ORD;break;
1914
1915 default:
1916 assert(0);
1917 }
1918 eval = new llvm::FCmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb());
1919 }
1920 else
1921 {
1922 assert(0 && "Unsupported CmpExp type");
1923 }
1924
1925 return new DImValue(type, eval);
1926 }
1927
1928 //////////////////////////////////////////////////////////////////////////////////////////
1929
1930 DValue* EqualExp::toElem(IRState* p)
1931 {
1932 Logger::print("EqualExp::toElem: %s | %s\n", toChars(), type->toChars());
1933 LOG_SCOPE;
1934
1935 DValue* l = e1->toElem(p);
1936 DValue* r = e2->toElem(p);
1937
1938 Type* t = DtoDType(e1->type);
1939 Type* e2t = DtoDType(e2->type);
1940 assert(t == e2t);
1941
1942 llvm::Value* eval = 0;
1943
1944 if (t->isintegral() || t->ty == Tpointer)
1945 {
1946 Logger::println("integral or pointer");
1947 llvm::ICmpInst::Predicate cmpop;
1948 switch(op)
1949 {
1950 case TOKequal:
1951 cmpop = llvm::ICmpInst::ICMP_EQ;
1952 break;
1953 case TOKnotequal:
1954 cmpop = llvm::ICmpInst::ICMP_NE;
1955 break;
1956 default:
1957 assert(0);
1958 }
1959 eval = new llvm::ICmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb());
1960 }
1961 else if (t->isfloating())
1962 {
1963 Logger::println("floating");
1964 llvm::FCmpInst::Predicate cmpop;
1965 switch(op)
1966 {
1967 case TOKequal:
1968 cmpop = llvm::FCmpInst::FCMP_OEQ;
1969 break;
1970 case TOKnotequal:
1971 cmpop = llvm::FCmpInst::FCMP_UNE;
1972 break;
1973 default:
1974 assert(0);
1975 }
1976 eval = new llvm::FCmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb());
1977 }
1978 else if (t->ty == Tsarray)
1979 {
1980 Logger::println("static array");
1981 eval = DtoStaticArrayCompare(op,l->getRVal(),r->getRVal());
1982 }
1983 else if (t->ty == Tarray)
1984 {
1985 Logger::println("dynamic array");
1986 eval = DtoDynArrayCompare(op,l->getRVal(),r->getRVal());
1987 }
1988 else if (t->ty == Tdelegate)
1989 {
1990 Logger::println("delegate");
1991 eval = DtoCompareDelegate(op,l->getRVal(),r->getRVal());
1992 }
1993 else
1994 {
1995 assert(0 && "Unsupported EqualExp type");
1996 }
1997
1998 return new DImValue(type, eval);
1999 }
2000
2001 //////////////////////////////////////////////////////////////////////////////////////////
2002
2003 DValue* PostExp::toElem(IRState* p)
2004 {
2005 Logger::print("PostExp::toElem: %s | %s\n", toChars(), type->toChars());
2006 LOG_SCOPE;
2007
2008 DValue* l = e1->toElem(p);
2009 DValue* r = e2->toElem(p);
2010
2011 llvm::Value* val = l->getRVal();
2012 llvm::Value* post = 0;
2013
2014 Type* e1type = DtoDType(e1->type);
2015 Type* e2type = DtoDType(e2->type);
2016
2017 if (e1type->isintegral())
2018 {
2019 assert(e2type->isintegral());
2020 llvm::Value* one = llvm::ConstantInt::get(val->getType(), 1, !e2type->isunsigned());
2021 if (op == TOKplusplus) {
2022 post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb());
2023 }
2024 else if (op == TOKminusminus) {
2025 post = llvm::BinaryOperator::createSub(val,one,"tmp",p->scopebb());
2026 }
2027 }
2028 else if (e1type->ty == Tpointer)
2029 {
2030 assert(e2type->isintegral());
2031 llvm::Constant* minusone = llvm::ConstantInt::get(DtoSize_t(),(uint64_t)-1,true);
2032 llvm::Constant* plusone = llvm::ConstantInt::get(DtoSize_t(),(uint64_t)1,false);
2033 llvm::Constant* whichone = (op == TOKplusplus) ? plusone : minusone;
2034 post = new llvm::GetElementPtrInst(val, whichone, "tmp", p->scopebb());
2035 }
2036 else if (e1type->isfloating())
2037 {
2038 assert(e2type->isfloating());
2039 llvm::Value* one = llvm::ConstantFP::get(val->getType(), 1.0f);
2040 if (op == TOKplusplus) {
2041 post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb());
2042 }
2043 else if (op == TOKminusminus) {
2044 post = llvm::BinaryOperator::createSub(val,one,"tmp",p->scopebb());
2045 }
2046 }
2047 else
2048 assert(post);
2049
2050 DtoStore(post,l->getLVal());
2051
2052 return new DImValue(type,val,true);
2053 }
2054
2055 //////////////////////////////////////////////////////////////////////////////////////////
2056
2057 DValue* NewExp::toElem(IRState* p)
2058 {
2059 Logger::print("NewExp::toElem: %s | %s\n", toChars(), type->toChars());
2060 LOG_SCOPE;
2061
2062 assert(!thisexp);
2063 assert(!newargs);
2064 assert(newtype);
2065 assert(!allocator);
2066
2067 Type* ntype = DtoDType(newtype);
2068
2069 const llvm::Type* t = DtoType(ntype);
2070
2071 llvm::Value* emem = 0;
2072 bool inplace = true;
2073
2074 if (onstack) {
2075 assert(ntype->ty == Tclass);
2076 emem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint());
2077 }
2078 else {
2079 if (ntype->ty == Tclass) {
2080 emem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb());
2081 }
2082 else if (ntype->ty == Tarray) {
2083 assert(arguments);
2084 if (arguments->dim == 1) {
2085 DValue* sz = ((Expression*)arguments->data[0])->toElem(p);
2086 llvm::Value* dimval = sz->getRVal();
2087 Type* nnt = DtoDType(ntype->next);
2088 if (nnt->ty == Tvoid)
2089 nnt = Type::tint8;
2090 if (!p->topexp() || p->topexp()->e2 != this) {
2091 const llvm::Type* restype = DtoType(type);
2092 Logger::cout() << "restype = " << *restype << '\n';
2093 emem = new llvm::AllocaInst(restype,"tmp",p->topallocapoint());
2094 DtoNewDynArray(emem, dimval, nnt);
2095 inplace = false;
2096 }
2097 else if (p->topexp() || p->topexp()->e2 != this) {
2098 assert(p->topexp()->v);
2099 emem = p->topexp()->v->getLVal();
2100 DtoNewDynArray(emem, dimval, nnt);
2101 }
2102 else
2103 assert(0);
2104 }
2105 else {
2106 assert(0);
2107 }
2108 }
2109 else {
2110 emem = new llvm::MallocInst(t,"tmp",p->scopebb());
2111 }
2112 }
2113
2114 if (ntype->ty == Tclass) {
2115 // first apply the static initializer
2116 DtoInitClass((TypeClass*)ntype, emem);
2117
2118 // then call constructor
2119 if (arguments) {
2120 assert(member);
2121 assert(member->llvmValue);
2122 llvm::Function* fn = llvm::cast<llvm::Function>(member->llvmValue);
2123 TypeFunction* tf = (TypeFunction*)DtoDType(member->type);
2124
2125 std::vector<llvm::Value*> ctorargs;
2126 ctorargs.push_back(emem);
2127 for (size_t i=0; i<arguments->dim; ++i)
2128 {
2129 Expression* ex = (Expression*)arguments->data[i];
2130 Argument* fnarg = Argument::getNth(tf->parameters, i);
2131 llvm::Value* a = DtoArgument(fn->getFunctionType()->getParamType(i+1), fnarg, ex);
2132 ctorargs.push_back(a);
2133 }
2134 emem = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
2135 }
2136 }
2137 else if (ntype->ty == Tstruct) {
2138 TypeStruct* ts = (TypeStruct*)ntype;
2139 if (ts->isZeroInit()) {
2140 DtoStructZeroInit(emem);
2141 }
2142 else {
2143 DtoStructCopy(emem,ts->llvmInit);
2144 }
2145 }
2146
2147 if (inplace)
2148 return new DImValue(type, emem, true);
2149
2150 return new DVarValue(type, emem, true);
2151 }
2152
2153 //////////////////////////////////////////////////////////////////////////////////////////
2154
2155 DValue* DeleteExp::toElem(IRState* p)
2156 {
2157 Logger::print("DeleteExp::toElem: %s | %s\n", toChars(), type->toChars());
2158 LOG_SCOPE;
2159
2160 //assert(e1->type->ty != Tclass);
2161
2162 DValue* v = e1->toElem(p);
2163 llvm::Value* val = v->getRVal();
2164 llvm::Value* ldval = 0;
2165
2166 const llvm::Type* t = val->getType();
2167 llvm::Constant* z = llvm::Constant::getNullValue(t);
2168
2169 Type* e1type = DtoDType(e1->type);
2170
2171 if (e1type->ty == Tpointer) {
2172 Logger::cout() << *z << '\n';
2173 Logger::cout() << *val << '\n';
2174 new llvm::FreeInst(val, p->scopebb());
2175 new llvm::StoreInst(z, v->getLVal(), p->scopebb());
2176 }
2177 else if (e1type->ty == Tclass) {
2178 TypeClass* tc = (TypeClass*)e1type;
2179 DtoCallClassDtors(tc, val);
2180
2181 if (DVarValue* vv = v->isVar()) {
2182 if (vv->var && !vv->var->onstack)
2183 new llvm::FreeInst(val, p->scopebb());
2184 }
2185 new llvm::StoreInst(z, v->getLVal(), p->scopebb());
2186 }
2187 else if (e1type->ty == Tarray) {
2188 // must be on the heap (correct?)
2189 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
2190 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
2191 llvm::Value* ptr = DtoGEP(val,zero,one,"tmp",p->scopebb());
2192 ptr = new llvm::LoadInst(ptr,"tmp",p->scopebb());
2193 new llvm::FreeInst(ptr, p->scopebb());
2194 DtoNullArray(val);
2195 }
2196 else {
2197 assert(0);
2198 }
2199
2200 // this expression produces no useful data
2201 return 0;
2202 }
2203
2204 //////////////////////////////////////////////////////////////////////////////////////////
2205
2206 DValue* ArrayLengthExp::toElem(IRState* p)
2207 {
2208 Logger::print("ArrayLengthExp::toElem: %s | %s\n", toChars(), type->toChars());
2209 LOG_SCOPE;
2210
2211 DValue* u = e1->toElem(p);
2212
2213 if (p->topexp() && p->topexp()->e1 == this)
2214 {
2215 return new DArrayLenValue(type, u->getLVal());
2216 }
2217 else
2218 {
2219 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
2220 llvm::Value* ptr = DtoGEP(u->getRVal(),zero,zero,"tmp",p->scopebb());
2221 ptr = new llvm::LoadInst(ptr, "tmp", p->scopebb());
2222 return new DImValue(type, ptr);
2223 }
2224 }
2225
2226 //////////////////////////////////////////////////////////////////////////////////////////
2227
2228 DValue* AssertExp::toElem(IRState* p)
2229 {
2230 Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars());
2231 LOG_SCOPE;
2232
2233 DValue* u = e1->toElem(p);
2234 DValue* m = msg ? msg->toElem(p) : NULL;
2235
2236 llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
2237 DtoAssert(u->getRVal(), loca, m ? m->getRVal() : NULL);
2238
2239 return 0;
2240 }
2241
2242 //////////////////////////////////////////////////////////////////////////////////////////
2243
2244 DValue* NotExp::toElem(IRState* p)
2245 {
2246 Logger::print("NotExp::toElem: %s | %s\n", toChars(), type->toChars());
2247 LOG_SCOPE;
2248
2249 DValue* u = e1->toElem(p);
2250
2251 llvm::Value* b = DtoBoolean(u->getRVal());
2252
2253 llvm::Constant* zero = llvm::ConstantInt::get(llvm::Type::Int1Ty, 0, true);
2254 b = p->ir->CreateICmpEQ(b,zero);
2255
2256 return new DImValue(type, b);
2257 }
2258
2259 //////////////////////////////////////////////////////////////////////////////////////////
2260
2261 DValue* AndAndExp::toElem(IRState* p)
2262 {
2263 Logger::print("AndAndExp::toElem: %s | %s\n", toChars(), type->toChars());
2264 LOG_SCOPE;
2265
2266 // allocate a temporary for the final result. failed to come up with a better way :/
2267 llvm::Value* resval = 0;
2268 llvm::BasicBlock* entryblock = &p->topfunc()->front();
2269 resval = new llvm::AllocaInst(llvm::Type::Int1Ty,"andandtmp",p->topallocapoint());
2270
2271 DValue* u = e1->toElem(p);
2272
2273 llvm::BasicBlock* oldend = p->scopeend();
2274 llvm::BasicBlock* andand = new llvm::BasicBlock("andand", gIR->topfunc(), oldend);
2275 llvm::BasicBlock* andandend = new llvm::BasicBlock("andandend", gIR->topfunc(), oldend);
2276
2277 llvm::Value* ubool = DtoBoolean(u->getRVal());
2278 new llvm::StoreInst(ubool,resval,p->scopebb());
2279 new llvm::BranchInst(andand,andandend,ubool,p->scopebb());
2280
2281 p->scope() = IRScope(andand, andandend);
2282 DValue* v = e2->toElem(p);
2283
2284 llvm::Value* vbool = DtoBoolean(v->getRVal());
2285 llvm::Value* uandvbool = llvm::BinaryOperator::create(llvm::BinaryOperator::And, ubool, vbool,"tmp",p->scopebb());
2286 new llvm::StoreInst(uandvbool,resval,p->scopebb());
2287 new llvm::BranchInst(andandend,p->scopebb());
2288
2289 p->scope() = IRScope(andandend, oldend);
2290
2291 resval = new llvm::LoadInst(resval,"tmp",p->scopebb());
2292 return new DImValue(type, resval);
2293 }
2294
2295 //////////////////////////////////////////////////////////////////////////////////////////
2296
2297 DValue* OrOrExp::toElem(IRState* p)
2298 {
2299 Logger::print("OrOrExp::toElem: %s | %s\n", toChars(), type->toChars());
2300 LOG_SCOPE;
2301
2302 // allocate a temporary for the final result. failed to come up with a better way :/
2303 llvm::Value* resval = 0;
2304 llvm::BasicBlock* entryblock = &p->topfunc()->front();
2305 resval = new llvm::AllocaInst(llvm::Type::Int1Ty,"orortmp",p->topallocapoint());
2306
2307 DValue* u = e1->toElem(p);
2308
2309 llvm::BasicBlock* oldend = p->scopeend();
2310 llvm::BasicBlock* oror = new llvm::BasicBlock("oror", gIR->topfunc(), oldend);
2311 llvm::BasicBlock* ororend = new llvm::BasicBlock("ororend", gIR->topfunc(), oldend);
2312
2313 llvm::Value* ubool = DtoBoolean(u->getRVal());
2314 new llvm::StoreInst(ubool,resval,p->scopebb());
2315 new llvm::BranchInst(ororend,oror,ubool,p->scopebb());
2316
2317 p->scope() = IRScope(oror, ororend);
2318 DValue* v = e2->toElem(p);
2319
2320 llvm::Value* vbool = DtoBoolean(v->getRVal());
2321 new llvm::StoreInst(vbool,resval,p->scopebb());
2322 new llvm::BranchInst(ororend,p->scopebb());
2323
2324 p->scope() = IRScope(ororend, oldend);
2325
2326 resval = new llvm::LoadInst(resval,"tmp",p->scopebb());
2327 return new DImValue(type, resval);
2328 }
2329
2330 //////////////////////////////////////////////////////////////////////////////////////////
2331
2332 #define BinBitExp(X,Y) \
2333 DValue* X##Exp::toElem(IRState* p) \
2334 { \
2335 Logger::print("%sExp::toElem: %s | %s\n", #X, toChars(), type->toChars()); \
2336 LOG_SCOPE; \
2337 DValue* u = e1->toElem(p); \
2338 DValue* v = e2->toElem(p); \
2339 llvm::Value* x = llvm::BinaryOperator::create(llvm::Instruction::Y, u->getRVal(), v->getRVal(), "tmp", p->scopebb()); \
2340 return new DImValue(type, x); \
2341 } \
2342 \
2343 DValue* X##AssignExp::toElem(IRState* p) \
2344 { \
2345 Logger::print("%sAssignExp::toElem: %s | %s\n", #X, toChars(), type->toChars()); \
2346 LOG_SCOPE; \
2347 p->exps.push_back(IRExp(e1,e2,NULL)); \
2348 DValue* u = e1->toElem(p); \
2349 p->topexp()->v = u; \
2350 DValue* v = e2->toElem(p); \
2351 p->exps.pop_back(); \
2352 llvm::Value* uval = u->getRVal(); \
2353 llvm::Value* vval = v->getRVal(); \
2354 llvm::Value* tmp = llvm::BinaryOperator::create(llvm::Instruction::Y, uval, vval, "tmp", p->scopebb()); \
2355 new llvm::StoreInst(DtoPointedType(u->getLVal(), tmp), u->getLVal(), p->scopebb()); \
2356 return u; \
2357 }
2358
2359 BinBitExp(And,And);
2360 BinBitExp(Or,Or);
2361 BinBitExp(Xor,Xor);
2362 BinBitExp(Shl,Shl);
2363 BinBitExp(Shr,AShr);
2364 BinBitExp(Ushr,LShr);
2365
2366 //////////////////////////////////////////////////////////////////////////////////////////
2367
2368 DValue* HaltExp::toElem(IRState* p)
2369 {
2370 Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars());
2371 LOG_SCOPE;
2372
2373 llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
2374 DtoAssert(llvm::ConstantInt::getFalse(), loca, NULL);
2375
2376 new llvm::UnreachableInst(p->scopebb());
2377 return 0;
2378 }
2379
2380 //////////////////////////////////////////////////////////////////////////////////////////
2381
2382 DValue* DelegateExp::toElem(IRState* p)
2383 {
2384 Logger::print("DelegateExp::toElem: %s | %s\n", toChars(), type->toChars());
2385 LOG_SCOPE;
2386
2387 DValue* u = e1->toElem(p);
2388
2389 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
2390 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
2391
2392 const llvm::Type* int8ptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
2393
2394 assert(p->topexp() && p->topexp()->e2 == this && p->topexp()->v);
2395 llvm::Value* lval = p->topexp()->v->getLVal();
2396
2397 llvm::Value* context = DtoGEP(lval,zero,zero,"tmp",p->scopebb());
2398 llvm::Value* castcontext = new llvm::BitCastInst(u->getRVal(),int8ptrty,"tmp",p->scopebb());
2399 new llvm::StoreInst(castcontext, context, p->scopebb());
2400
2401 llvm::Value* fptr = DtoGEP(lval,zero,one,"tmp",p->scopebb());
2402
2403 assert(func->llvmValue);
2404 llvm::Value* castfptr = new llvm::BitCastInst(func->llvmValue,fptr->getType()->getContainedType(0),"tmp",p->scopebb());
2405 new llvm::StoreInst(castfptr, fptr, p->scopebb());
2406
2407 return new DImValue(type, u->getRVal(), true);
2408 }
2409
2410 //////////////////////////////////////////////////////////////////////////////////////////
2411
2412 DValue* IdentityExp::toElem(IRState* p)
2413 {
2414 Logger::print("IdentityExp::toElem: %s | %s\n", toChars(), type->toChars());
2415 LOG_SCOPE;
2416
2417 DValue* u = e1->toElem(p);
2418 DValue* v = e2->toElem(p);
2419
2420 llvm::Value* l = u->getRVal();
2421 llvm::Value* r = v->getRVal();
2422
2423 Type* t1 = DtoDType(e1->type);
2424
2425 llvm::Value* eval = 0;
2426
2427 if (t1->ty == Tarray) {
2428 if (v->isNull()) {
2429 r = NULL;
2430 }
2431 else {
2432 assert(l->getType() == r->getType());
2433 }
2434 eval = DtoDynArrayIs(op,l,r);
2435 }
2436 else {
2437 llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
2438 if (t1->ty == Tpointer && v->isNull() && l->getType() != r->getType()) {
2439 r = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(l->getType()));
2440 }
2441 Logger::cout() << "l = " << *l << " r = " << *r << '\n';
2442 eval = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
2443 }
2444 return new DImValue(type, eval);
2445 }
2446
2447 //////////////////////////////////////////////////////////////////////////////////////////
2448
2449 DValue* CommaExp::toElem(IRState* p)
2450 {
2451 Logger::print("CommaExp::toElem: %s | %s\n", toChars(), type->toChars());
2452 LOG_SCOPE;
2453
2454 DValue* u = e1->toElem(p);
2455 DValue* v = e2->toElem(p);
2456 return v;
2457 }
2458
2459 //////////////////////////////////////////////////////////////////////////////////////////
2460
2461 DValue* CondExp::toElem(IRState* p)
2462 {
2463 Logger::print("CondExp::toElem: %s | %s\n", toChars(), type->toChars());
2464 LOG_SCOPE;
2465
2466 Type* dtype = DtoDType(type);
2467 const llvm::Type* resty = DtoType(dtype);
2468
2469 // allocate a temporary for the final result. failed to come up with a better way :/
2470 llvm::BasicBlock* entryblock = &p->topfunc()->front();
2471 llvm::Value* resval = new llvm::AllocaInst(resty,"condtmp",p->topallocapoint());
2472 DVarValue* dvv = new DVarValue(type, resval, true);
2473
2474 llvm::BasicBlock* oldend = p->scopeend();
2475 llvm::BasicBlock* condtrue = new llvm::BasicBlock("condtrue", gIR->topfunc(), oldend);
2476 llvm::BasicBlock* condfalse = new llvm::BasicBlock("condfalse", gIR->topfunc(), oldend);
2477 llvm::BasicBlock* condend = new llvm::BasicBlock("condend", gIR->topfunc(), oldend);
2478
2479 DValue* c = econd->toElem(p);
2480 llvm::Value* cond_val = DtoBoolean(c->getRVal());
2481 new llvm::BranchInst(condtrue,condfalse,cond_val,p->scopebb());
2482
2483 p->scope() = IRScope(condtrue, condfalse);
2484 DValue* u = e1->toElem(p);
2485 DtoAssign(dvv, u);
2486 new llvm::BranchInst(condend,p->scopebb());
2487
2488 p->scope() = IRScope(condfalse, condend);
2489 DValue* v = e2->toElem(p);
2490 DtoAssign(dvv, v);
2491 new llvm::BranchInst(condend,p->scopebb());
2492
2493 p->scope() = IRScope(condend, oldend);
2494 return dvv;
2495 }
2496
2497 //////////////////////////////////////////////////////////////////////////////////////////
2498
2499 DValue* ComExp::toElem(IRState* p)
2500 {
2501 Logger::print("ComExp::toElem: %s | %s\n", toChars(), type->toChars());
2502 LOG_SCOPE;
2503
2504 DValue* u = e1->toElem(p);
2505
2506 llvm::Value* value = u->getRVal();
2507 llvm::Value* minusone = llvm::ConstantInt::get(value->getType(), -1, true);
2508 value = llvm::BinaryOperator::create(llvm::Instruction::Xor, value, minusone, "tmp", p->scopebb());
2509
2510 return new DImValue(type, value);
2511 }
2512
2513 //////////////////////////////////////////////////////////////////////////////////////////
2514
2515 DValue* NegExp::toElem(IRState* p)
2516 {
2517 Logger::print("NegExp::toElem: %s | %s\n", toChars(), type->toChars());
2518 LOG_SCOPE;
2519
2520 DValue* l = e1->toElem(p);
2521 llvm::Value* val = l->getRVal();
2522
2523 Type* t = DtoDType(type);
2524
2525 llvm::Value* zero = 0;
2526 if (t->isintegral())
2527 zero = llvm::ConstantInt::get(val->getType(), 0, true);
2528 else if (t->isfloating()) {
2529 if (t->ty == Tfloat32)
2530 zero = llvm::ConstantFP::get(val->getType(), float(0));
2531 else if (t->ty == Tfloat64 || t->ty == Tfloat80)
2532 zero = llvm::ConstantFP::get(val->getType(), double(0));
2533 else
2534 assert(0);
2535 }
2536 else
2537 assert(0);
2538
2539 val = llvm::BinaryOperator::createSub(zero,val,"tmp",p->scopebb());
2540 return new DImValue(type, val);
2541 }
2542
2543 //////////////////////////////////////////////////////////////////////////////////////////
2544
2545 DValue* CatExp::toElem(IRState* p)
2546 {
2547 Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars());
2548 LOG_SCOPE;
2549
2550 Type* t = DtoDType(type);
2551
2552 IRExp* ex = p->topexp();
2553 if (ex && ex->e2 == this) {
2554 assert(ex->v);
2555 DtoCatArrays(ex->v->getLVal(),e1,e2);
2556 return new DImValue(type, ex->v->getLVal(), true);
2557 }
2558 else {
2559 assert(t->ty == Tarray);
2560 const llvm::Type* arrty = DtoType(t);
2561 llvm::Value* dst = new llvm::AllocaInst(arrty, "tmpmem", p->topallocapoint());
2562 DtoCatArrays(dst,e1,e2);
2563 return new DVarValue(type, dst, true);
2564 }
2565 }
2566
2567 //////////////////////////////////////////////////////////////////////////////////////////
2568
2569 DValue* CatAssignExp::toElem(IRState* p)
2570 {
2571 Logger::print("CatAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
2572 LOG_SCOPE;
2573
2574 DValue* l = e1->toElem(p);
2575
2576 Type* e1type = DtoDType(e1->type);
2577 Type* elemtype = DtoDType(e1type->next);
2578 Type* e2type = DtoDType(e2->type);
2579
2580 if (e2type == elemtype) {
2581 DtoCatAssignElement(l->getLVal(),e2);
2582 }
2583 else if (e1type == e2type) {
2584 DtoCatAssignArray(l->getLVal(),e2);
2585 }
2586 else
2587 assert(0 && "only one element at a time right now");
2588
2589 return 0;
2590 }
2591
2592 //////////////////////////////////////////////////////////////////////////////////////////
2593
2594 DValue* FuncExp::toElem(IRState* p)
2595 {
2596 Logger::print("FuncExp::toElem: %s | %s\n", toChars(), type->toChars());
2597 LOG_SCOPE;
2598
2599 assert(fd);
2600
2601 if (fd->isNested()) Logger::println("nested");
2602 Logger::println("kind = %s\n", fd->kind());
2603
2604 fd->toObjFile();
2605
2606 llvm::Value* lval = NULL;
2607 if (!p->topexp() || p->topexp()->e2 != this) {
2608 const llvm::Type* dgty = DtoType(type);
2609 Logger::cout() << "delegate without explicit storage:" << '\n' << *dgty << '\n';
2610 lval = new llvm::AllocaInst(dgty,"dgstorage",p->topallocapoint());
2611 }
2612 else if (p->topexp()->e2 == this) {
2613 assert(p->topexp()->v);
2614 lval = p->topexp()->v->getLVal();;
2615 }
2616 else
2617 assert(0);
2618
2619 llvm::Value* context = DtoGEPi(lval,0,0,"tmp",p->scopebb());
2620 const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(context->getType()->getContainedType(0));
2621 llvm::Value* llvmNested = p->func().decl->llvmNested;
2622 if (llvmNested == NULL) {
2623 llvm::Value* nullcontext = llvm::ConstantPointerNull::get(pty);
2624 p->ir->CreateStore(nullcontext, context);
2625 }
2626 else {
2627 llvm::Value* nestedcontext = p->ir->CreateBitCast(llvmNested, pty, "tmp");
2628 p->ir->CreateStore(nestedcontext, context);
2629 }
2630
2631 llvm::Value* fptr = DtoGEPi(lval,0,1,"tmp",p->scopebb());
2632
2633 assert(fd->llvmValue);
2634 llvm::Value* castfptr = new llvm::BitCastInst(fd->llvmValue,fptr->getType()->getContainedType(0),"tmp",p->scopebb());
2635 new llvm::StoreInst(castfptr, fptr, p->scopebb());
2636
2637 return new DImValue(type, lval, true);
2638 }
2639
2640 //////////////////////////////////////////////////////////////////////////////////////////
2641
2642 DValue* ArrayLiteralExp::toElem(IRState* p)
2643 {
2644 Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
2645 LOG_SCOPE;
2646
2647 const llvm::Type* t = DtoType(type);
2648 Logger::cout() << "array literal has llvm type: " << *t << '\n';
2649
2650 llvm::Value* mem = 0;
2651 if (!p->topexp() || p->topexp()->e2 != this) {
2652 assert(DtoDType(type)->ty == Tsarray);
2653 mem = new llvm::AllocaInst(t,"tmparrayliteral",p->topallocapoint());
2654 }
2655 else if (p->topexp()->e2 == this) {
2656 DValue* tlv = p->topexp()->v;
2657 if (DSliceValue* sv = tlv->isSlice()) {
2658 assert(sv->len == 0);
2659 mem = sv->ptr;
2660 }
2661 else {
2662 mem = p->topexp()->v->getLVal();
2663 }
2664 assert(mem);
2665 if (!llvm::isa<llvm::PointerType>(mem->getType()) ||
2666 !llvm::isa<llvm::ArrayType>(mem->getType()->getContainedType(0)))
2667 {
2668 error("TODO array literals can currently only be used to initialise static arrays");
2669 fatal();
2670 }
2671 }
2672 else
2673 assert(0);
2674
2675 for (unsigned i=0; i<elements->dim; ++i)
2676 {
2677 Expression* expr = (Expression*)elements->data[i];
2678 llvm::Value* elemAddr = DtoGEPi(mem,0,i,"tmp",p->scopebb());
2679 DValue* e = expr->toElem(p);
2680 new llvm::StoreInst(e->getRVal(), elemAddr, p->scopebb());
2681 }
2682
2683 return new DImValue(type, mem, true);
2684 }
2685
2686 //////////////////////////////////////////////////////////////////////////////////////////
2687
2688 llvm::Constant* ArrayLiteralExp::toConstElem(IRState* p)
2689 {
2690 Logger::print("ArrayLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
2691 LOG_SCOPE;
2692
2693 const llvm::Type* t = DtoType(type);
2694 Logger::cout() << "array literal has llvm type: " << *t << '\n';
2695 assert(llvm::isa<llvm::ArrayType>(t));
2696 const llvm::ArrayType* arrtype = llvm::cast<llvm::ArrayType>(t);
2697
2698 assert(arrtype->getNumElements() == elements->dim);
2699 std::vector<llvm::Constant*> vals(elements->dim, NULL);
2700 for (unsigned i=0; i<elements->dim; ++i)
2701 {
2702 Expression* expr = (Expression*)elements->data[i];
2703 vals[i] = expr->toConstElem(p);
2704 }
2705
2706 return llvm::ConstantArray::get(arrtype, vals);
2707 }
2708
2709 //////////////////////////////////////////////////////////////////////////////////////////
2710
2711 DValue* StructLiteralExp::toElem(IRState* p)
2712 {
2713 Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
2714 LOG_SCOPE;
2715
2716 llvm::Value* sptr;
2717 const llvm::Type* llt = DtoType(type);
2718
2719 llvm::Value* mem = 0;
2720
2721 // temporary struct literal
2722 if (!p->topexp() || p->topexp()->e2 != this)
2723 {
2724 sptr = new llvm::AllocaInst(llt,"tmpstructliteral",p->topallocapoint());
2725 }
2726 // already has memory
2727 else
2728 {
2729 assert(p->topexp()->e2 == this);
2730 sptr = p->topexp()->v->getLVal();
2731 }
2732
2733 // num elements in literal
2734 unsigned n = elements->dim;
2735
2736 // unions might have different types for each literal
2737 if (sd->llvmHasUnions) {
2738 // build the type of the literal
2739 std::vector<const llvm::Type*> tys;
2740 for (unsigned i=0; i<n; ++i) {
2741 Expression* vx = (Expression*)elements->data[i];
2742 if (!vx) continue;
2743 tys.push_back(DtoType(vx->type));
2744 }
2745 const llvm::StructType* t = llvm::StructType::get(tys);
2746 if (t != llt) {
2747 if (gTargetData->getTypeSize(t) != gTargetData->getTypeSize(llt)) {
2748 Logger::cout() << "got size " << gTargetData->getTypeSize(t) << ", expected " << gTargetData->getTypeSize(llt) << '\n';
2749 assert(0 && "type size mismatch");
2750 }
2751 sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp");
2752 Logger::cout() << "sptr type is now: " << *t << '\n';
2753 }
2754 }
2755
2756 // build
2757 unsigned j = 0;
2758 for (unsigned i=0; i<n; ++i)
2759 {
2760 Expression* vx = (Expression*)elements->data[i];
2761 if (!vx) continue;
2762
2763 Logger::cout() << "getting index " << j << " of " << *sptr << '\n';
2764 llvm::Value* arrptr = DtoGEPi(sptr,0,j,"tmp",p->scopebb());
2765 DValue* darrptr = new DVarValue(vx->type, arrptr, true);
2766
2767 p->exps.push_back(IRExp(NULL,vx,darrptr));
2768 DValue* ve = vx->toElem(p);
2769 p->exps.pop_back();
2770
2771 if (!ve->inPlace())
2772 DtoAssign(darrptr, ve);
2773
2774 j++;
2775 }
2776
2777 return new DImValue(type, sptr, true);
2778 }
2779
2780 //////////////////////////////////////////////////////////////////////////////////////////
2781
2782 llvm::Constant* StructLiteralExp::toConstElem(IRState* p)
2783 {
2784 Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
2785 LOG_SCOPE;
2786
2787 unsigned n = elements->dim;
2788 std::vector<llvm::Constant*> vals(n, NULL);
2789
2790 for (unsigned i=0; i<n; ++i)
2791 {
2792 Expression* vx = (Expression*)elements->data[i];
2793 vals[i] = vx->toConstElem(p);
2794 }
2795
2796 assert(DtoDType(type)->ty == Tstruct);
2797 const llvm::Type* t = DtoType(type);
2798 const llvm::StructType* st = llvm::cast<llvm::StructType>(t);
2799 return llvm::ConstantStruct::get(st,vals);
2800 }
2801
2802 //////////////////////////////////////////////////////////////////////////////////////////
2803
2804 #define STUB(x) DValue *x::toElem(IRState * p) {error("Exp type "#x" not implemented: %s", toChars()); fatal(); return 0; }
2805 //STUB(IdentityExp);
2806 //STUB(CondExp);
2807 //STUB(EqualExp);
2808 STUB(InExp);
2809 //STUB(CmpExp);
2810 //STUB(AndAndExp);
2811 //STUB(OrOrExp);
2812 //STUB(AndExp);
2813 //STUB(AndAssignExp);
2814 //STUB(OrExp);
2815 //STUB(OrAssignExp);
2816 //STUB(XorExp);
2817 //STUB(XorAssignExp);
2818 //STUB(ShrExp);
2819 //STUB(ShrAssignExp);
2820 //STUB(ShlExp);
2821 //STUB(ShlAssignExp);
2822 //STUB(UshrExp);
2823 //STUB(UshrAssignExp);
2824 //STUB(DivExp);
2825 //STUB(DivAssignExp);
2826 //STUB(MulExp);
2827 //STUB(MulAssignExp);
2828 //STUB(ModExp);
2829 //STUB(ModAssignExp);
2830 //STUB(CatExp);
2831 //STUB(CatAssignExp);
2832 //STUB(AddExp);
2833 //STUB(AddAssignExp);
2834 STUB(Expression);
2835 //STUB(MinExp);
2836 //STUB(MinAssignExp);
2837 //STUB(PostExp);
2838 //STUB(NullExp);
2839 //STUB(ThisExp);
2840 //STUB(CallExp);
2841 STUB(DotTypeExp);
2842 STUB(TypeDotIdExp);
2843 //STUB(DotVarExp);
2844 //STUB(AssertExp);
2845 //STUB(FuncExp);
2846 //STUB(DelegateExp);
2847 //STUB(VarExp);
2848 //STUB(DeclarationExp);
2849 //STUB(NewExp);
2850 //STUB(SymOffExp);
2851 STUB(ScopeExp);
2852 //STUB(AssignExp);
2853
2854 STUB(TypeExp);
2855 //STUB(RealExp);
2856 STUB(ComplexExp);
2857 //STUB(StringExp);
2858 //STUB(IntegerExp);
2859 STUB(BoolExp);
2860
2861 //STUB(NotExp);
2862 //STUB(ComExp);
2863 //STUB(NegExp);
2864 //STUB(PtrExp);
2865 //STUB(AddrExp);
2866 //STUB(SliceExp);
2867 //STUB(CastExp);
2868 //STUB(DeleteExp);
2869 //STUB(IndexExp);
2870 //STUB(CommaExp);
2871 //STUB(ArrayLengthExp);
2872 //STUB(HaltExp);
2873 STUB(RemoveExp);
2874 //STUB(ArrayLiteralExp);
2875 STUB(AssocArrayLiteralExp);
2876 //STUB(StructLiteralExp);
2877
2878 #define CONSTSTUB(x) llvm::Constant* x::toConstElem(IRState * p) {error("const Exp type "#x" not implemented: '%s' type: '%s'", toChars(), type->toChars()); assert(0); fatal(); return NULL; }
2879 CONSTSTUB(Expression);
2880 //CONSTSTUB(IntegerExp);
2881 //CONSTSTUB(RealExp);
2882 //CONSTSTUB(NullExp);
2883 //CONSTSTUB(StringExp);
2884 //CONSTSTUB(VarExp);
2885 //CONSTSTUB(ArrayLiteralExp);
2886 CONSTSTUB(AssocArrayLiteralExp);
2887 //CONSTSTUB(StructLiteralExp);
2888
2889 unsigned Type::totym() { return 0; }
2890
2891 type * Type::toCtype()
2892 {
2893 assert(0);
2894 return 0;
2895 }
2896
2897 type * Type::toCParamtype()
2898 {
2899 assert(0);
2900 return 0;
2901 }
2902 Symbol * Type::toSymbol()
2903 {
2904 assert(0);
2905 return 0;
2906 }
2907
2908 type *
2909 TypeTypedef::toCtype()
2910 {
2911 assert(0);
2912 return 0;
2913 }
2914
2915 type *
2916 TypeTypedef::toCParamtype()
2917 {
2918 assert(0);
2919 return 0;
2920 }
2921
2922 void
2923 TypedefDeclaration::toDebug()
2924 {
2925 assert(0);
2926 }
2927
2928
2929 type *
2930 TypeEnum::toCtype()
2931 {
2932 assert(0);
2933 return 0;
2934 }
2935
2936 type *
2937 TypeStruct::toCtype()
2938 {
2939 assert(0);
2940 return 0;
2941 }
2942
2943 void
2944 StructDeclaration::toDebug()
2945 {
2946 assert(0);
2947 }
2948
2949 Symbol * TypeClass::toSymbol()
2950 {
2951 assert(0);
2952 return 0;
2953 }
2954
2955 unsigned TypeFunction::totym()
2956 {
2957 assert(0);
2958 return 0;
2959 }
2960
2961 type * TypeFunction::toCtype()
2962 {
2963 assert(0);
2964 return 0;
2965 }
2966
2967 type * TypeSArray::toCtype()
2968 {
2969 assert(0);
2970 return 0;
2971 }
2972
2973 type *TypeSArray::toCParamtype()
2974 {
2975 assert(0);
2976 return 0;
2977 }
2978
2979 type * TypeDArray::toCtype()
2980 {
2981 assert(0);
2982 return 0;
2983 }
2984
2985 type * TypeAArray::toCtype()
2986 {
2987 assert(0);
2988 return 0;
2989 }
2990
2991 type * TypePointer::toCtype()
2992 {
2993 assert(0);
2994 return 0;
2995 }
2996
2997 type * TypeDelegate::toCtype()
2998 {
2999 assert(0);
3000 return 0;
3001 }
3002
3003 type * TypeClass::toCtype()
3004 {
3005 assert(0);
3006 return 0;
3007 }
3008
3009 void ClassDeclaration::toDebug()
3010 {
3011 assert(0);
3012 }
3013
3014 //////////////////////////////////////////////////////////////////////////////
3015
3016 void
3017 EnumDeclaration::toDebug()
3018 {
3019 assert(0);
3020 }
3021
3022 int Dsymbol::cvMember(unsigned char*)
3023 {
3024 assert(0);
3025 return 0;
3026 }
3027 int EnumDeclaration::cvMember(unsigned char*)
3028 {
3029 assert(0);
3030 return 0;
3031 }
3032 int FuncDeclaration::cvMember(unsigned char*)
3033 {
3034 assert(0);
3035 return 0;
3036 }
3037 int VarDeclaration::cvMember(unsigned char*)
3038 {
3039 assert(0);
3040 return 0;
3041 }
3042 int TypedefDeclaration::cvMember(unsigned char*)
3043 {
3044 assert(0);
3045 return 0;
3046 }
3047
3048 void obj_includelib(char*){}
3049
3050 AsmStatement::AsmStatement(Loc loc, Token *tokens) :
3051 Statement(loc)
3052 {
3053 assert(0);
3054 }
3055 Statement *AsmStatement::syntaxCopy()
3056 {
3057 assert(0);
3058 return 0;
3059 }
3060
3061 Statement *AsmStatement::semantic(Scope *sc)
3062 {
3063 return Statement::semantic(sc);
3064 }
3065
3066
3067 void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3068 {
3069 Statement::toCBuffer(buf, hgs);
3070 }
3071
3072 int AsmStatement::comeFrom()
3073 {
3074 assert(0);
3075 return FALSE;
3076 }
3077
3078 void
3079 backend_init()
3080 {
3081 // now lazily loaded
3082 //LLVM_D_InitRuntime();
3083 }
3084
3085 void
3086 backend_term()
3087 {
3088 LLVM_D_FreeRuntime();
3089 }