Mercurial > projects > ldc
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 } |