Mercurial > projects > ldc
comparison gen/tollvm.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/tollvm.c@f869c636a113 |
children | 058d3925950e |
comparison
equal
deleted
inserted
replaced
85:f869c636a113 | 86:fd32135dca3e |
---|---|
1 #include <iostream> | |
2 | |
3 #include "gen/llvm.h" | |
4 | |
5 #include "mtype.h" | |
6 #include "dsymbol.h" | |
7 #include "aggregate.h" | |
8 #include "declaration.h" | |
9 #include "init.h" | |
10 | |
11 #include "gen/tollvm.h" | |
12 #include "gen/irstate.h" | |
13 #include "gen/logger.h" | |
14 #include "gen/runtime.h" | |
15 #include "gen/arrays.h" | |
16 #include "gen/dvalue.h" | |
17 | |
18 bool DtoIsPassedByRef(Type* type) | |
19 { | |
20 TY t = DtoDType(type)->ty; | |
21 return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray); | |
22 } | |
23 | |
24 Type* DtoDType(Type* t) | |
25 { | |
26 if (t->ty == Ttypedef) { | |
27 Type* bt = t->toBasetype(); | |
28 assert(bt); | |
29 return DtoDType(bt); | |
30 } | |
31 return t; | |
32 } | |
33 | |
34 const llvm::Type* DtoType(Type* t) | |
35 { | |
36 assert(t); | |
37 switch (t->ty) | |
38 { | |
39 // integers | |
40 case Tint8: | |
41 case Tuns8: | |
42 case Tchar: | |
43 return (const llvm::Type*)llvm::Type::Int8Ty; | |
44 case Tint16: | |
45 case Tuns16: | |
46 case Twchar: | |
47 return (const llvm::Type*)llvm::Type::Int16Ty; | |
48 case Tint32: | |
49 case Tuns32: | |
50 case Tdchar: | |
51 return (const llvm::Type*)llvm::Type::Int32Ty; | |
52 case Tint64: | |
53 case Tuns64: | |
54 return (const llvm::Type*)llvm::Type::Int64Ty; | |
55 | |
56 case Tbool: | |
57 return (const llvm::Type*)llvm::ConstantInt::getTrue()->getType(); | |
58 | |
59 // floats | |
60 case Tfloat32: | |
61 case Timaginary32: | |
62 return llvm::Type::FloatTy; | |
63 case Tfloat64: | |
64 case Timaginary64: | |
65 case Tfloat80: | |
66 case Timaginary80: | |
67 return llvm::Type::DoubleTy; | |
68 | |
69 // complex | |
70 case Tcomplex32: | |
71 case Tcomplex64: | |
72 case Tcomplex80: | |
73 assert(0 && "complex number types not yet implemented"); | |
74 | |
75 // pointers | |
76 case Tpointer: { | |
77 assert(t->next); | |
78 if (t->next->ty == Tvoid) | |
79 return (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty); | |
80 else | |
81 return (const llvm::Type*)llvm::PointerType::get(DtoType(t->next)); | |
82 } | |
83 | |
84 // arrays | |
85 case Tarray: | |
86 return DtoArrayType(t); | |
87 case Tsarray: | |
88 return DtoStaticArrayType(t); | |
89 | |
90 // void | |
91 case Tvoid: | |
92 return llvm::Type::VoidTy; | |
93 | |
94 // aggregates | |
95 case Tstruct: { | |
96 if (t->llvmType == 0) | |
97 { | |
98 // recursive or cyclic declaration | |
99 if (!gIR->structs.empty()) | |
100 { | |
101 IRStruct* found = 0; | |
102 for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i) | |
103 { | |
104 if (t == i->type) | |
105 { | |
106 return i->recty.get(); | |
107 } | |
108 } | |
109 } | |
110 | |
111 // forward declaration | |
112 TypeStruct* ts = (TypeStruct*)t; | |
113 assert(ts->sym); | |
114 ts->sym->toObjFile(); | |
115 } | |
116 return t->llvmType; | |
117 } | |
118 | |
119 case Tclass: { | |
120 if (t->llvmType == 0) | |
121 { | |
122 // recursive or cyclic declaration | |
123 if (!gIR->structs.empty()) | |
124 { | |
125 IRStruct* found = 0; | |
126 for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i) | |
127 { | |
128 if (t == i->type) | |
129 { | |
130 return llvm::PointerType::get(i->recty.get()); | |
131 } | |
132 } | |
133 } | |
134 | |
135 // forward declaration | |
136 TypeClass* tc = (TypeClass*)t; | |
137 assert(tc->sym); | |
138 tc->sym->toObjFile(); | |
139 } | |
140 return llvm::PointerType::get(t->llvmType); | |
141 } | |
142 | |
143 // functions | |
144 case Tfunction: | |
145 { | |
146 if (t->llvmType == 0) { | |
147 return DtoFunctionType(t,NULL); | |
148 } | |
149 else { | |
150 return t->llvmType; | |
151 } | |
152 } | |
153 | |
154 // delegates | |
155 case Tdelegate: | |
156 { | |
157 if (t->llvmType == 0) { | |
158 return DtoDelegateType(t); | |
159 } | |
160 else { | |
161 return t->llvmType; | |
162 } | |
163 } | |
164 | |
165 // typedefs | |
166 // enum | |
167 case Ttypedef: | |
168 case Tenum: | |
169 { | |
170 Type* bt = t->toBasetype(); | |
171 assert(bt); | |
172 return DtoType(bt); | |
173 } | |
174 | |
175 default: | |
176 printf("trying to convert unknown type with value %d\n", t->ty); | |
177 assert(0); | |
178 } | |
179 return 0; | |
180 } | |
181 | |
182 ////////////////////////////////////////////////////////////////////////////////////////// | |
183 | |
184 const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain) | |
185 { | |
186 TypeFunction* f = (TypeFunction*)type; | |
187 assert(f != 0); | |
188 | |
189 bool typesafeVararg = false; | |
190 if (f->linkage == LINKd && f->varargs == 1) { | |
191 typesafeVararg = true; | |
192 } | |
193 | |
194 // return value type | |
195 const llvm::Type* rettype; | |
196 const llvm::Type* actualRettype; | |
197 Type* rt = f->next; | |
198 bool retinptr = false; | |
199 bool usesthis = false; | |
200 | |
201 if (ismain) { | |
202 rettype = llvm::Type::Int32Ty; | |
203 actualRettype = rettype; | |
204 } | |
205 else { | |
206 assert(rt); | |
207 if (DtoIsPassedByRef(rt)) { | |
208 rettype = llvm::PointerType::get(DtoType(rt)); | |
209 actualRettype = llvm::Type::VoidTy; | |
210 f->llvmRetInPtr = retinptr = true; | |
211 } | |
212 else { | |
213 rettype = DtoType(rt); | |
214 actualRettype = rettype; | |
215 } | |
216 } | |
217 | |
218 // parameter types | |
219 std::vector<const llvm::Type*> paramvec; | |
220 | |
221 if (retinptr) { | |
222 Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; | |
223 paramvec.push_back(rettype); | |
224 } | |
225 | |
226 if (thistype) { | |
227 paramvec.push_back(thistype); | |
228 usesthis = true; | |
229 } | |
230 | |
231 if (typesafeVararg) { | |
232 ClassDeclaration* ti = Type::typeinfo; | |
233 if (!ti->llvmInitZ) | |
234 ti->toObjFile(); | |
235 assert(ti->llvmInitZ); | |
236 std::vector<const llvm::Type*> types; | |
237 types.push_back(DtoSize_t()); | |
238 types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType()))); | |
239 const llvm::Type* t1 = llvm::StructType::get(types); | |
240 paramvec.push_back(llvm::PointerType::get(t1)); | |
241 paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); | |
242 } | |
243 | |
244 size_t n = Argument::dim(f->parameters); | |
245 | |
246 for (int i=0; i < n; ++i) { | |
247 Argument* arg = Argument::getNth(f->parameters, i); | |
248 // ensure scalar | |
249 Type* argT = DtoDType(arg->type); | |
250 assert(argT); | |
251 | |
252 if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { | |
253 //assert(arg->vardecl); | |
254 //arg->vardecl->refparam = true; | |
255 } | |
256 else | |
257 arg->llvmCopy = true; | |
258 | |
259 const llvm::Type* at = DtoType(argT); | |
260 if (llvm::isa<llvm::StructType>(at)) { | |
261 Logger::println("struct param"); | |
262 paramvec.push_back(llvm::PointerType::get(at)); | |
263 } | |
264 else if (llvm::isa<llvm::ArrayType>(at)) { | |
265 Logger::println("sarray param"); | |
266 assert(argT->ty == Tsarray); | |
267 //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0))); | |
268 paramvec.push_back(llvm::PointerType::get(at)); | |
269 } | |
270 else if (llvm::isa<llvm::OpaqueType>(at)) { | |
271 Logger::println("opaque param"); | |
272 if (argT->ty == Tstruct || argT->ty == Tclass) | |
273 paramvec.push_back(llvm::PointerType::get(at)); | |
274 else | |
275 assert(0); | |
276 } | |
277 /*if (llvm::isa<llvm::StructType>(at) || argT->ty == Tstruct || argT->ty == Tsarray) { | |
278 paramvec.push_back(llvm::PointerType::get(at)); | |
279 }*/ | |
280 else { | |
281 if (!arg->llvmCopy) { | |
282 Logger::println("ref param"); | |
283 at = llvm::PointerType::get(at); | |
284 } | |
285 else { | |
286 Logger::println("in param"); | |
287 } | |
288 paramvec.push_back(at); | |
289 } | |
290 } | |
291 | |
292 // construct function type | |
293 bool isvararg = !typesafeVararg && f->varargs; | |
294 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); | |
295 | |
296 f->llvmRetInPtr = retinptr; | |
297 f->llvmUsesThis = usesthis; | |
298 return functype; | |
299 } | |
300 | |
301 ////////////////////////////////////////////////////////////////////////////////////////// | |
302 | |
303 static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl) | |
304 { | |
305 TypeFunction* f = (TypeFunction*)fdecl->type; | |
306 assert(f != 0); | |
307 | |
308 const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
309 std::vector<const llvm::Type*> args; | |
310 | |
311 if (fdecl->llvmInternal == LLVMva_start) { | |
312 args.push_back(i8pty); | |
313 } | |
314 else if (fdecl->llvmInternal == LLVMva_intrinsic) { | |
315 size_t n = Argument::dim(f->parameters); | |
316 for (size_t i=0; i<n; ++i) { | |
317 args.push_back(i8pty); | |
318 } | |
319 } | |
320 else | |
321 assert(0); | |
322 | |
323 const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false); | |
324 f->llvmType = fty; | |
325 return fty; | |
326 } | |
327 | |
328 ////////////////////////////////////////////////////////////////////////////////////////// | |
329 | |
330 const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl) | |
331 { | |
332 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) { | |
333 return DtoVaFunctionType(fdecl); | |
334 } | |
335 | |
336 // type has already been resolved | |
337 if (fdecl->type->llvmType != 0) { | |
338 return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType); | |
339 } | |
340 | |
341 const llvm::Type* thisty = NULL; | |
342 if (fdecl->needThis()) { | |
343 if (AggregateDeclaration* ad = fdecl->isMember()) { | |
344 Logger::print("isMember = this is: %s\n", ad->type->toChars()); | |
345 thisty = DtoType(ad->type); | |
346 Logger::cout() << "this llvm type: " << *thisty << '\n'; | |
347 if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get()) | |
348 thisty = llvm::PointerType::get(thisty); | |
349 } | |
350 else | |
351 assert(0); | |
352 } | |
353 else if (fdecl->isNested()) { | |
354 thisty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
355 } | |
356 | |
357 const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain()); | |
358 fdecl->type->llvmType = functype; | |
359 return functype; | |
360 } | |
361 | |
362 ////////////////////////////////////////////////////////////////////////////////////////// | |
363 | |
364 const llvm::StructType* DtoDelegateType(Type* t) | |
365 { | |
366 const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty); | |
367 const llvm::Type* func = DtoFunctionType(t->next, i8ptr); | |
368 const llvm::Type* funcptr = llvm::PointerType::get(func); | |
369 | |
370 std::vector<const llvm::Type*> types; | |
371 types.push_back(i8ptr); | |
372 types.push_back(funcptr); | |
373 return llvm::StructType::get(types); | |
374 } | |
375 | |
376 ////////////////////////////////////////////////////////////////////////////////////////// | |
377 | |
378 const llvm::Type* DtoStructType(Type* t) | |
379 { | |
380 assert(0); | |
381 std::vector<const llvm::Type*> types; | |
382 return llvm::StructType::get(types); | |
383 } | |
384 | |
385 | |
386 ////////////////////////////////////////////////////////////////////////////////////////// | |
387 | |
388 static llvm::Function* LLVM_DeclareMemIntrinsic(const char* name, int bits, bool set=false) | |
389 { | |
390 assert(bits == 32 || bits == 64); | |
391 const llvm::Type* int8ty = (const llvm::Type*)llvm::Type::Int8Ty; | |
392 const llvm::Type* int32ty = (const llvm::Type*)llvm::Type::Int32Ty; | |
393 const llvm::Type* int64ty = (const llvm::Type*)llvm::Type::Int64Ty; | |
394 const llvm::Type* int8ptrty = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty); | |
395 const llvm::Type* voidty = (const llvm::Type*)llvm::Type::VoidTy; | |
396 | |
397 assert(gIR); | |
398 assert(gIR->module); | |
399 | |
400 // parameter types | |
401 std::vector<const llvm::Type*> pvec; | |
402 pvec.push_back(int8ptrty); | |
403 pvec.push_back(set?int8ty:int8ptrty); | |
404 pvec.push_back(bits==32?int32ty:int64ty); | |
405 pvec.push_back(int32ty); | |
406 llvm::FunctionType* functype = llvm::FunctionType::get(voidty, pvec, false); | |
407 return new llvm::Function(functype, llvm::GlobalValue::ExternalLinkage, name, gIR->module); | |
408 } | |
409 | |
410 ////////////////////////////////////////////////////////////////////////////////////////// | |
411 | |
412 // llvm.memset.i32 | |
413 llvm::Function* LLVM_DeclareMemSet32() | |
414 { | |
415 static llvm::Function* _func = 0; | |
416 if (_func == 0) { | |
417 _func = LLVM_DeclareMemIntrinsic("llvm.memset.i32", 32, true); | |
418 } | |
419 return _func; | |
420 } | |
421 | |
422 ////////////////////////////////////////////////////////////////////////////////////////// | |
423 | |
424 llvm::Function* LLVM_DeclareMemSet64() | |
425 { | |
426 static llvm::Function* _func = 0; | |
427 if (_func == 0) { | |
428 _func = LLVM_DeclareMemIntrinsic("llvm.memset.i64", 64, true); | |
429 } | |
430 return _func; | |
431 } | |
432 | |
433 ////////////////////////////////////////////////////////////////////////////////////////// | |
434 | |
435 // llvm.memcpy.i32 | |
436 llvm::Function* LLVM_DeclareMemCpy32() | |
437 { | |
438 static llvm::Function* _func = 0; | |
439 if (_func == 0) { | |
440 _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i32", 32); | |
441 } | |
442 return _func; | |
443 } | |
444 | |
445 ////////////////////////////////////////////////////////////////////////////////////////// | |
446 | |
447 // llvm.memcpy.i64 | |
448 llvm::Function* LLVM_DeclareMemCpy64() | |
449 { | |
450 static llvm::Function* _func = 0; | |
451 if (_func == 0) { | |
452 _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i64", 64); | |
453 } | |
454 return _func; | |
455 } | |
456 | |
457 ////////////////////////////////////////////////////////////////////////////////////////// | |
458 | |
459 llvm::Value* DtoStructZeroInit(llvm::Value* v) | |
460 { | |
461 assert(gIR); | |
462 uint64_t n = gTargetData->getTypeSize(v->getType()->getContainedType(0)); | |
463 //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n)); | |
464 llvm::Type* sarrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
465 | |
466 llvm::Value* sarr = new llvm::BitCastInst(v,sarrty,"tmp",gIR->scopebb()); | |
467 | |
468 llvm::Function* fn = LLVM_DeclareMemSet32(); | |
469 std::vector<llvm::Value*> llargs; | |
470 llargs.resize(4); | |
471 llargs[0] = sarr; | |
472 llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false); | |
473 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
474 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
475 | |
476 llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
477 | |
478 return ret; | |
479 } | |
480 | |
481 ////////////////////////////////////////////////////////////////////////////////////////// | |
482 | |
483 llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src) | |
484 { | |
485 Logger::cout() << "dst = " << *dst << " src = " << *src << '\n'; | |
486 assert(dst->getType() == src->getType()); | |
487 assert(gIR); | |
488 | |
489 uint64_t n = gTargetData->getTypeSize(dst->getType()->getContainedType(0)); | |
490 //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n)); | |
491 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
492 | |
493 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
494 llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb()); | |
495 | |
496 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
497 std::vector<llvm::Value*> llargs; | |
498 llargs.resize(4); | |
499 llargs[0] = dstarr; | |
500 llargs[1] = srcarr; | |
501 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
502 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
503 | |
504 return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
505 } | |
506 | |
507 ////////////////////////////////////////////////////////////////////////////////////////// | |
508 llvm::Constant* DtoConstStructInitializer(StructInitializer* si) | |
509 { | |
510 llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType); | |
511 size_t n = structtype->getNumElements(); | |
512 | |
513 assert(si->value.dim == si->vars.dim); | |
514 | |
515 std::vector<llvm::Constant*> inits; | |
516 inits.resize(n, NULL); | |
517 for (int i = 0; i < si->value.dim; ++i) | |
518 { | |
519 Initializer* ini = (Initializer*)si->value.data[i]; | |
520 assert(ini); | |
521 | |
522 VarDeclaration* vd = (VarDeclaration*)si->vars.data[i]; | |
523 Type* vdtype = DtoDType(vd->type); | |
524 assert(vd); | |
525 Logger::println("vars[%d] = %s", i, vd->toChars()); | |
526 | |
527 llvm::Constant* v = 0; | |
528 | |
529 assert(vd->llvmFieldIndex >= 0); | |
530 unsigned idx = vd->llvmFieldIndex; | |
531 | |
532 if (ExpInitializer* ex = ini->isExpInitializer()) | |
533 { | |
534 v = ex->exp->toConstElem(gIR); | |
535 } | |
536 else if (StructInitializer* si = ini->isStructInitializer()) | |
537 { | |
538 v = DtoConstStructInitializer(si); | |
539 } | |
540 else if (ArrayInitializer* ai = ini->isArrayInitializer()) | |
541 { | |
542 v = DtoConstArrayInitializer(ai); | |
543 } | |
544 else if (ini->isVoidInitializer()) | |
545 { | |
546 v = llvm::UndefValue::get(structtype->getElementType(idx)); | |
547 } | |
548 else | |
549 assert(v); | |
550 | |
551 inits[idx] = v; | |
552 Logger::cout() << "init[" << idx << "] = " << *v << '\n'; | |
553 } | |
554 | |
555 // fill out nulls | |
556 assert(si->ad->llvmInitZ); | |
557 if (si->ad->llvmInitZ->isNullValue()) | |
558 { | |
559 for (int i = 0; i < n; ++i) | |
560 { | |
561 if (inits[i] == 0) | |
562 { | |
563 inits[i] = llvm::Constant::getNullValue(structtype->getElementType(i)); | |
564 } | |
565 } | |
566 } | |
567 else | |
568 { | |
569 for (int i = 0; i < n; ++i) | |
570 { | |
571 if (inits[i] == 0) | |
572 { | |
573 inits[i] = si->ad->llvmInitZ->getOperand(i); | |
574 } | |
575 } | |
576 } | |
577 | |
578 return llvm::ConstantStruct::get(structtype, inits); | |
579 } | |
580 | |
581 | |
582 | |
583 ////////////////////////////////////////////////////////////////////////////////////////// | |
584 | |
585 llvm::Value* DtoNullDelegate(llvm::Value* v) | |
586 { | |
587 assert(gIR); | |
588 d_uns64 n = (global.params.is64bit) ? 16 : 8; | |
589 | |
590 llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
591 | |
592 llvm::Value* arr = new llvm::BitCastInst(v,i8p_ty,"tmp",gIR->scopebb()); | |
593 | |
594 llvm::Function* fn = LLVM_DeclareMemSet32(); | |
595 std::vector<llvm::Value*> llargs; | |
596 llargs.resize(4); | |
597 llargs[0] = arr; | |
598 llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false); | |
599 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
600 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
601 | |
602 llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
603 | |
604 return ret; | |
605 } | |
606 | |
607 ////////////////////////////////////////////////////////////////////////////////////////// | |
608 | |
609 llvm::Value* DtoDelegateCopy(llvm::Value* dst, llvm::Value* src) | |
610 { | |
611 assert(dst->getType() == src->getType()); | |
612 assert(gIR); | |
613 | |
614 d_uns64 n = (global.params.is64bit) ? 16 : 8; | |
615 | |
616 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
617 | |
618 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
619 llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb()); | |
620 | |
621 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
622 std::vector<llvm::Value*> llargs; | |
623 llargs.resize(4); | |
624 llargs[0] = dstarr; | |
625 llargs[1] = srcarr; | |
626 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
627 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
628 | |
629 return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
630 } | |
631 | |
632 ////////////////////////////////////////////////////////////////////////////////////////// | |
633 | |
634 llvm::Value* DtoCompareDelegate(TOK op, llvm::Value* lhs, llvm::Value* rhs) | |
635 { | |
636 llvm::ICmpInst::Predicate pred = (op == TOKequal) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE; | |
637 llvm::Value* l = gIR->ir->CreateLoad(DtoGEPi(lhs,0,0,"tmp"),"tmp"); | |
638 llvm::Value* r = gIR->ir->CreateLoad(DtoGEPi(rhs,0,0,"tmp"),"tmp"); | |
639 llvm::Value* b1 = gIR->ir->CreateICmp(pred,l,r,"tmp"); | |
640 l = gIR->ir->CreateLoad(DtoGEPi(lhs,0,1,"tmp"),"tmp"); | |
641 r = gIR->ir->CreateLoad(DtoGEPi(rhs,0,1,"tmp"),"tmp"); | |
642 llvm::Value* b2 = gIR->ir->CreateICmp(pred,l,r,"tmp"); | |
643 llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp"); | |
644 if (op == TOKnotequal) | |
645 return gIR->ir->CreateNot(b,"tmp"); | |
646 return b; | |
647 } | |
648 | |
649 ////////////////////////////////////////////////////////////////////////////////////////// | |
650 | |
651 llvm::GlobalValue::LinkageTypes DtoLinkage(PROT prot, uint stc) | |
652 { | |
653 switch(prot) | |
654 { | |
655 case PROTprivate: | |
656 return llvm::GlobalValue::InternalLinkage; | |
657 | |
658 case PROTpublic: | |
659 case PROTpackage: | |
660 case PROTprotected: | |
661 case PROTexport: | |
662 return llvm::GlobalValue::ExternalLinkage; | |
663 | |
664 case PROTundefined: | |
665 case PROTnone: | |
666 assert(0 && "Unsupported linkage type"); | |
667 } | |
668 return llvm::GlobalValue::ExternalLinkage; | |
669 | |
670 /* ExternalLinkage = 0, LinkOnceLinkage, WeakLinkage, AppendingLinkage, | |
671 InternalLinkage, DLLImportLinkage, DLLExportLinkage, ExternalWeakLinkage, | |
672 GhostLinkage */ | |
673 } | |
674 | |
675 ////////////////////////////////////////////////////////////////////////////////////////// | |
676 | |
677 unsigned DtoCallingConv(LINK l) | |
678 { | |
679 if (l == LINKc) | |
680 return llvm::CallingConv::C; | |
681 else if (l == LINKd || l == LINKdefault) | |
682 return llvm::CallingConv::Fast; | |
683 else if (l == LINKwindows) | |
684 return llvm::CallingConv::X86_StdCall; | |
685 else | |
686 assert(0 && "Unsupported calling convention"); | |
687 } | |
688 | |
689 ////////////////////////////////////////////////////////////////////////////////////////// | |
690 | |
691 llvm::Value* DtoPointedType(llvm::Value* ptr, llvm::Value* val) | |
692 { | |
693 const llvm::Type* ptrTy = ptr->getType()->getContainedType(0); | |
694 const llvm::Type* valTy = val->getType(); | |
695 // ptr points to val's type | |
696 if (ptrTy == valTy) | |
697 { | |
698 return val; | |
699 } | |
700 // ptr is integer pointer | |
701 else if (ptrTy->isInteger()) | |
702 { | |
703 // val is integer | |
704 assert(valTy->isInteger()); | |
705 const llvm::IntegerType* pt = llvm::cast<const llvm::IntegerType>(ptrTy); | |
706 const llvm::IntegerType* vt = llvm::cast<const llvm::IntegerType>(valTy); | |
707 if (pt->getBitWidth() < vt->getBitWidth()) { | |
708 return new llvm::TruncInst(val, pt, "tmp", gIR->scopebb()); | |
709 } | |
710 else | |
711 assert(0); | |
712 } | |
713 // something else unsupported | |
714 else | |
715 { | |
716 Logger::cout() << *ptrTy << '|' << *valTy << '\n'; | |
717 assert(0); | |
718 } | |
719 return 0; | |
720 } | |
721 | |
722 ////////////////////////////////////////////////////////////////////////////////////////// | |
723 | |
724 llvm::Value* DtoBoolean(llvm::Value* val) | |
725 { | |
726 const llvm::Type* t = val->getType(); | |
727 if (t->isInteger()) | |
728 { | |
729 if (t == llvm::Type::Int1Ty) | |
730 return val; | |
731 else { | |
732 llvm::Value* zero = llvm::ConstantInt::get(t, 0, false); | |
733 return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, val, zero, "tmp", gIR->scopebb()); | |
734 } | |
735 } | |
736 else if (llvm::isa<llvm::PointerType>(t)) { | |
737 const llvm::Type* st = DtoSize_t(); | |
738 llvm::Value* ptrasint = new llvm::PtrToIntInst(val,st,"tmp",gIR->scopebb()); | |
739 llvm::Value* zero = llvm::ConstantInt::get(st, 0, false); | |
740 return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, ptrasint, zero, "tmp", gIR->scopebb()); | |
741 } | |
742 else | |
743 { | |
744 Logger::cout() << *t << '\n'; | |
745 } | |
746 assert(0); | |
747 return 0; | |
748 } | |
749 | |
750 ////////////////////////////////////////////////////////////////////////////////////////// | |
751 | |
752 const llvm::Type* DtoSize_t() | |
753 { | |
754 if (global.params.is64bit) | |
755 return llvm::Type::Int64Ty; | |
756 else | |
757 return llvm::Type::Int32Ty; | |
758 } | |
759 | |
760 ////////////////////////////////////////////////////////////////////////////////////////// | |
761 | |
762 void DtoMain() | |
763 { | |
764 // emit main function llvm style | |
765 // int main(int argc, char**argv, char**env); | |
766 | |
767 assert(gIR != 0); | |
768 IRState& ir = *gIR; | |
769 | |
770 assert(ir.emitMain && ir.mainFunc); | |
771 | |
772 // parameter types | |
773 std::vector<const llvm::Type*> pvec; | |
774 pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty); | |
775 const llvm::Type* chPtrType = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty); | |
776 pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType)); | |
777 pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType)); | |
778 const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty; | |
779 | |
780 llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false); | |
781 llvm::Function* func = new llvm::Function(functype,llvm::GlobalValue::ExternalLinkage,"main",ir.module); | |
782 | |
783 llvm::BasicBlock* bb = new llvm::BasicBlock("entry",func); | |
784 | |
785 // call static ctors | |
786 llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_ctors"); | |
787 new llvm::CallInst(fn,"",bb); | |
788 | |
789 // call user main function | |
790 llvm::CallInst* call = new llvm::CallInst(ir.mainFunc,"ret",bb); | |
791 call->setCallingConv(ir.mainFunc->getCallingConv()); | |
792 | |
793 // call static dtors | |
794 fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors"); | |
795 new llvm::CallInst(fn,"",bb); | |
796 | |
797 // return | |
798 new llvm::ReturnInst(call,bb); | |
799 } | |
800 | |
801 ////////////////////////////////////////////////////////////////////////////////////////// | |
802 | |
803 void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance) | |
804 { | |
805 Array* arr = &tc->sym->dtors; | |
806 for (size_t i=0; i<arr->dim; i++) | |
807 { | |
808 FuncDeclaration* fd = (FuncDeclaration*)arr->data[i]; | |
809 assert(fd->llvmValue); | |
810 new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb()); | |
811 } | |
812 } | |
813 | |
814 ////////////////////////////////////////////////////////////////////////////////////////// | |
815 | |
816 void DtoInitClass(TypeClass* tc, llvm::Value* dst) | |
817 { | |
818 assert(gIR); | |
819 | |
820 assert(tc->llvmType); | |
821 uint64_t size_t_size = gTargetData->getTypeSize(DtoSize_t()); | |
822 uint64_t n = gTargetData->getTypeSize(tc->llvmType) - size_t_size; | |
823 | |
824 // set vtable field | |
825 llvm::Value* vtblvar = DtoGEPi(dst,0,0,"tmp",gIR->scopebb()); | |
826 assert(tc->sym->llvmVtbl); | |
827 new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb()); | |
828 | |
829 // copy the static initializer | |
830 if (n > 0) { | |
831 assert(tc->llvmInit); | |
832 assert(dst->getType() == tc->llvmInit->getType()); | |
833 | |
834 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
835 | |
836 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
837 dstarr = DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb()); | |
838 | |
839 llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb()); | |
840 srcarr = DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb()); | |
841 | |
842 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
843 std::vector<llvm::Value*> llargs; | |
844 llargs.resize(4); | |
845 llargs[0] = dstarr; | |
846 llargs[1] = srcarr; | |
847 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
848 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
849 | |
850 new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
851 } | |
852 } | |
853 | |
854 ////////////////////////////////////////////////////////////////////////////////////////// | |
855 | |
856 llvm::Constant* DtoConstInitializer(Type* type, Initializer* init) | |
857 { | |
858 llvm::Constant* _init = 0; // may return zero | |
859 if (!init) | |
860 { | |
861 Logger::println("const default initializer for %s", type->toChars()); | |
862 _init = type->defaultInit()->toConstElem(gIR); | |
863 } | |
864 else if (ExpInitializer* ex = init->isExpInitializer()) | |
865 { | |
866 Logger::println("const expression initializer"); | |
867 _init = ex->exp->toConstElem(gIR); | |
868 } | |
869 else if (StructInitializer* si = init->isStructInitializer()) | |
870 { | |
871 Logger::println("const struct initializer"); | |
872 _init = DtoConstStructInitializer(si); | |
873 } | |
874 else if (ArrayInitializer* ai = init->isArrayInitializer()) | |
875 { | |
876 Logger::println("const array initializer"); | |
877 _init = DtoConstArrayInitializer(ai); | |
878 } | |
879 else if (init->isVoidInitializer()) | |
880 { | |
881 Logger::println("const void initializer"); | |
882 const llvm::Type* ty = DtoType(type); | |
883 _init = llvm::Constant::getNullValue(ty); | |
884 } | |
885 else { | |
886 Logger::println("unsupported const initializer: %s", init->toChars()); | |
887 } | |
888 return _init; | |
889 } | |
890 | |
891 ////////////////////////////////////////////////////////////////////////////////////////// | |
892 | |
893 DValue* DtoInitializer(Initializer* init) | |
894 { | |
895 if (ExpInitializer* ex = init->isExpInitializer()) | |
896 { | |
897 Logger::println("expression initializer"); | |
898 return ex->exp->toElem(gIR); | |
899 } | |
900 else if (init->isVoidInitializer()) | |
901 { | |
902 // do nothing | |
903 } | |
904 else { | |
905 Logger::println("unsupported initializer: %s", init->toChars()); | |
906 assert(0); | |
907 } | |
908 return 0; | |
909 } | |
910 | |
911 ////////////////////////////////////////////////////////////////////////////////////////// | |
912 | |
913 llvm::Value* DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb) | |
914 { | |
915 std::vector<llvm::Value*> v(2); | |
916 v[0] = i0; | |
917 v[1] = i1; | |
918 Logger::cout() << "DtoGEP: " << *ptr << '\n'; | |
919 return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb()); | |
920 } | |
921 | |
922 ////////////////////////////////////////////////////////////////////////////////////////// | |
923 | |
924 llvm::Value* DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb) | |
925 { | |
926 size_t n = src.size(); | |
927 std::vector<llvm::Value*> dst(n); | |
928 std::ostream& ostr = Logger::cout(); | |
929 ostr << "indices for '" << *ptr << "':"; | |
930 for (size_t i=0; i<n; ++i) | |
931 { | |
932 ostr << ' ' << i; | |
933 dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false); | |
934 } | |
935 ostr << '\n'; | |
936 return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb?bb:gIR->scopebb()); | |
937 } | |
938 | |
939 ////////////////////////////////////////////////////////////////////////////////////////// | |
940 | |
941 llvm::Value* DtoGEPi(llvm::Value* ptr, unsigned i, const std::string& var, llvm::BasicBlock* bb) | |
942 { | |
943 return new llvm::GetElementPtrInst(ptr, llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false), var, bb?bb:gIR->scopebb()); | |
944 } | |
945 | |
946 ////////////////////////////////////////////////////////////////////////////////////////// | |
947 | |
948 llvm::Value* DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb) | |
949 { | |
950 std::vector<llvm::Value*> v(2); | |
951 v[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i0, false); | |
952 v[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i1, false); | |
953 return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb()); | |
954 } | |
955 | |
956 ////////////////////////////////////////////////////////////////////////////////////////// | |
957 | |
958 static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl) | |
959 { | |
960 TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type); | |
961 const llvm::FunctionType* fty = DtoVaFunctionType(fdecl); | |
962 llvm::Constant* fn = 0; | |
963 | |
964 if (fdecl->llvmInternal == LLVMva_start) { | |
965 fn = gIR->module->getOrInsertFunction("llvm.va_start", fty); | |
966 assert(fn); | |
967 } | |
968 else if (fdecl->llvmInternal == LLVMva_intrinsic) { | |
969 fn = gIR->module->getOrInsertFunction(fdecl->llvmInternal1, fty); | |
970 assert(fn); | |
971 } | |
972 else | |
973 assert(0); | |
974 | |
975 llvm::Function* func = llvm::cast_or_null<llvm::Function>(fn); | |
976 assert(func); | |
977 assert(func->isIntrinsic()); | |
978 fdecl->llvmValue = func; | |
979 return func; | |
980 } | |
981 | |
982 ////////////////////////////////////////////////////////////////////////////////////////// | |
983 | |
984 llvm::Function* DtoDeclareFunction(FuncDeclaration* fdecl) | |
985 { | |
986 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) { | |
987 return DtoDeclareVaFunction(fdecl); | |
988 } | |
989 | |
990 // mangled name | |
991 char* mangled_name; | |
992 if (fdecl->llvmInternal == LLVMintrinsic) | |
993 mangled_name = fdecl->llvmInternal1; | |
994 else | |
995 mangled_name = fdecl->mangle(); | |
996 | |
997 // unit test special handling | |
998 if (fdecl->isUnitTestDeclaration()) | |
999 { | |
1000 assert(0 && "no unittests yet"); | |
1001 /*const llvm::FunctionType* fnty = llvm::FunctionType::get(llvm::Type::VoidTy, std::vector<const llvm::Type*>(), false); | |
1002 // make the function | |
1003 llvm::Function* func = gIR->module->getFunction(mangled_name); | |
1004 if (func == 0) | |
1005 func = new llvm::Function(fnty,llvm::GlobalValue::InternalLinkage,mangled_name,gIR->module); | |
1006 func->setCallingConv(llvm::CallingConv::Fast); | |
1007 fdecl->llvmValue = func; | |
1008 return func; | |
1009 */ | |
1010 } | |
1011 | |
1012 // regular function | |
1013 TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type); | |
1014 assert(f != 0); | |
1015 | |
1016 if (fdecl->llvmValue != 0) { | |
1017 if (!llvm::isa<llvm::Function>(fdecl->llvmValue)) | |
1018 { | |
1019 Logger::cout() << *fdecl->llvmValue << '\n'; | |
1020 assert(0); | |
1021 } | |
1022 return llvm::cast<llvm::Function>(fdecl->llvmValue); | |
1023 } | |
1024 | |
1025 Logger::print("FuncDeclaration::toObjFile(%s): %s\n", fdecl->needThis()?"this":"static",fdecl->toChars()); | |
1026 LOG_SCOPE; | |
1027 | |
1028 if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) { | |
1029 error("intrinsics cannot have function bodies"); | |
1030 fatal(); | |
1031 } | |
1032 | |
1033 // construct function | |
1034 const llvm::FunctionType* functype = (f->llvmType == 0) ? DtoFunctionType(fdecl) : llvm::cast<llvm::FunctionType>(f->llvmType); | |
1035 | |
1036 // make the function | |
1037 llvm::Function* func = gIR->module->getFunction(mangled_name); | |
1038 if (func == 0) { | |
1039 func = new llvm::Function(functype,DtoLinkage(fdecl->protection, fdecl->storage_class),mangled_name,gIR->module); | |
1040 } | |
1041 | |
1042 if (fdecl->llvmInternal != LLVMintrinsic) | |
1043 func->setCallingConv(DtoCallingConv(f->linkage)); | |
1044 | |
1045 fdecl->llvmValue = func; | |
1046 f->llvmType = functype; | |
1047 assert(llvm::isa<llvm::FunctionType>(f->llvmType)); | |
1048 | |
1049 if (fdecl->isMain()) { | |
1050 gIR->mainFunc = func; | |
1051 } | |
1052 | |
1053 // name parameters | |
1054 llvm::Function::arg_iterator iarg = func->arg_begin(); | |
1055 int k = 0; | |
1056 if (f->llvmRetInPtr) { | |
1057 iarg->setName("retval"); | |
1058 f->llvmRetArg = iarg; | |
1059 ++iarg; | |
1060 } | |
1061 if (f->llvmUsesThis) { | |
1062 iarg->setName("this"); | |
1063 ++iarg; | |
1064 } | |
1065 int varargs = -1; | |
1066 if (f->linkage == LINKd && f->varargs == 1) | |
1067 varargs = 0; | |
1068 for (; iarg != func->arg_end(); ++iarg) | |
1069 { | |
1070 Argument* arg = Argument::getNth(f->parameters, k++); | |
1071 //arg->llvmValue = iarg; | |
1072 //Logger::println("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident); | |
1073 if (arg && arg->ident != 0) { | |
1074 if (arg->vardecl) { | |
1075 arg->vardecl->llvmValue = iarg; | |
1076 } | |
1077 iarg->setName(arg->ident->toChars()); | |
1078 } | |
1079 else if (!arg && varargs >= 0) { | |
1080 if (varargs == 0) { | |
1081 iarg->setName("_arguments"); | |
1082 fdecl->llvmArguments = iarg; | |
1083 } | |
1084 else if (varargs == 1) { | |
1085 iarg->setName("_argptr"); | |
1086 fdecl->llvmArgPtr = iarg; | |
1087 } | |
1088 else | |
1089 assert(0); | |
1090 varargs++; | |
1091 } | |
1092 else { | |
1093 iarg->setName("unnamed"); | |
1094 } | |
1095 } | |
1096 | |
1097 Logger::cout() << "func decl: " << *func << '\n'; | |
1098 | |
1099 return func; | |
1100 } | |
1101 | |
1102 ////////////////////////////////////////////////////////////////////////////////////////// | |
1103 | |
1104 llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty) | |
1105 { | |
1106 /*size_t sz = gTargetData->getTypeSize(ty); | |
1107 llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false); | |
1108 if (ptr == 0) { | |
1109 llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
1110 ptr = llvm::ConstantPointerNull::get(i8pty); | |
1111 } | |
1112 return DtoRealloc(ptr, n);*/ | |
1113 return NULL; | |
1114 } | |
1115 | |
1116 ////////////////////////////////////////////////////////////////////////////////////////// | |
1117 | |
1118 llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* n) | |
1119 { | |
1120 assert(ptr); | |
1121 assert(n); | |
1122 | |
1123 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_realloc"); | |
1124 assert(fn); | |
1125 | |
1126 llvm::Value* newptr = ptr; | |
1127 | |
1128 llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
1129 if (ptr->getType() != i8pty) { | |
1130 newptr = new llvm::BitCastInst(ptr,i8pty,"tmp",gIR->scopebb()); | |
1131 } | |
1132 | |
1133 std::vector<llvm::Value*> args; | |
1134 args.push_back(newptr); | |
1135 args.push_back(n); | |
1136 llvm::Value* ret = new llvm::CallInst(fn, args.begin(), args.end(), "tmprealloc", gIR->scopebb()); | |
1137 | |
1138 return ret->getType() == ptr->getType() ? ret : new llvm::BitCastInst(ret,ptr->getType(),"tmp",gIR->scopebb()); | |
1139 } | |
1140 | |
1141 ////////////////////////////////////////////////////////////////////////////////////////// | |
1142 | |
1143 void DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg) | |
1144 { | |
1145 assert(loc); | |
1146 std::vector<llvm::Value*> llargs; | |
1147 llargs.resize(3); | |
1148 llargs[0] = cond ? DtoBoolean(cond) : llvm::ConstantInt::getFalse(); | |
1149 llargs[1] = loc; | |
1150 llargs[2] = msg ? msg : llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)); | |
1151 | |
1152 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_assert"); | |
1153 assert(fn); | |
1154 llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
1155 call->setCallingConv(llvm::CallingConv::C); | |
1156 } | |
1157 | |
1158 ////////////////////////////////////////////////////////////////////////////////////////// | |
1159 | |
1160 llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp) | |
1161 { | |
1162 llvm::Value* retval = 0; | |
1163 | |
1164 bool haslvals = !gIR->exps.empty(); | |
1165 if (haslvals) | |
1166 gIR->exps.push_back(IRExp(NULL,NULL,NULL)); | |
1167 | |
1168 DValue* arg = argexp->toElem(gIR); | |
1169 | |
1170 if (haslvals) | |
1171 gIR->exps.pop_back(); | |
1172 | |
1173 if (arg->inPlace()) { | |
1174 retval = arg->getRVal(); | |
1175 return retval; | |
1176 } | |
1177 | |
1178 Type* realtype = DtoDType(argexp->type); | |
1179 TY argty = realtype->ty; | |
1180 if (DtoIsPassedByRef(realtype)) { | |
1181 if (!fnarg || !fnarg->llvmCopy) { | |
1182 if (DSliceValue* sv = arg->isSlice()) { | |
1183 retval = new llvm::AllocaInst(DtoType(realtype), "tmpparam", gIR->topallocapoint()); | |
1184 DtoSetArray(retval, DtoArrayLen(sv), DtoArrayPtr(sv)); | |
1185 } | |
1186 else { | |
1187 retval = arg->getRVal(); | |
1188 } | |
1189 } | |
1190 else { | |
1191 llvm::Value* allocaInst = 0; | |
1192 llvm::BasicBlock* entryblock = &gIR->topfunc()->front(); | |
1193 //const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(arg->mem->getType()); | |
1194 const llvm::Type* realtypell = DtoType(realtype); | |
1195 const llvm::PointerType* pty = llvm::PointerType::get(realtypell); | |
1196 if (argty == Tstruct) { | |
1197 allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); | |
1198 DValue* dst = new DVarValue(realtype, allocaInst, true); | |
1199 DtoAssign(dst,arg); | |
1200 delete dst; | |
1201 } | |
1202 else if (argty == Tdelegate) { | |
1203 allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); | |
1204 DValue* dst = new DVarValue(realtype, allocaInst, true); | |
1205 DtoAssign(dst,arg); | |
1206 delete dst; | |
1207 } | |
1208 else if (argty == Tarray) { | |
1209 if (arg->isSlice()) { | |
1210 allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint()); | |
1211 } | |
1212 else { | |
1213 allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); | |
1214 } | |
1215 } | |
1216 else | |
1217 assert(0); | |
1218 | |
1219 DValue* dst = new DVarValue(realtype, allocaInst, true); | |
1220 DtoAssign(dst,arg); | |
1221 delete dst; | |
1222 | |
1223 retval = allocaInst; | |
1224 } | |
1225 } | |
1226 else if (!fnarg || fnarg->llvmCopy) { | |
1227 Logger::println("regular arg"); | |
1228 if (DSliceValue* sl = arg->isSlice()) { | |
1229 if (sl->ptr) Logger::cout() << "ptr = " << *sl->ptr << '\n'; | |
1230 if (sl->len) Logger::cout() << "len = " << *sl->len << '\n'; | |
1231 assert(0); | |
1232 } | |
1233 else { | |
1234 retval = arg->getRVal(); | |
1235 } | |
1236 } | |
1237 else { | |
1238 Logger::println("as ptr arg"); | |
1239 retval = arg->getLVal(); | |
1240 if (paramtype && retval->getType() != paramtype) | |
1241 { | |
1242 assert(0); | |
1243 /*assert(retval->getType() == paramtype->getContainedType(0)); | |
1244 new llvm::StoreInst(retval, arg->getLVal(), gIR->scopebb()); | |
1245 retval = arg->getLVal();*/ | |
1246 } | |
1247 } | |
1248 | |
1249 if (fnarg && paramtype && retval->getType() != paramtype) { | |
1250 // this is unfortunately needed with the way SymOffExp is overused | |
1251 // and static arrays can end up being a pointer to their element type | |
1252 if (arg->isField()) { | |
1253 retval = gIR->ir->CreateBitCast(retval, paramtype, "tmp"); | |
1254 } | |
1255 else { | |
1256 Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n"; | |
1257 assert(0 && "parameter type that was actually passed is invalid"); | |
1258 } | |
1259 } | |
1260 | |
1261 delete arg; | |
1262 | |
1263 return retval; | |
1264 } | |
1265 | |
1266 ////////////////////////////////////////////////////////////////////////////////////////// | |
1267 | |
1268 llvm::Value* DtoNestedVariable(VarDeclaration* vd) | |
1269 { | |
1270 FuncDeclaration* fd = vd->toParent()->isFuncDeclaration(); | |
1271 assert(fd != NULL); | |
1272 | |
1273 IRFunction* fcur = &gIR->func(); | |
1274 FuncDeclaration* f = fcur->decl; | |
1275 | |
1276 // on this stack | |
1277 if (fd == f) { | |
1278 llvm::Value* v = DtoGEPi(vd->llvmValue,0,unsigned(vd->llvmNestedIndex),"tmp"); | |
1279 if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) { | |
1280 Logger::cout() << "1267 loading: " << *v << '\n'; | |
1281 v = gIR->ir->CreateLoad(v,"tmp"); | |
1282 } | |
1283 return v; | |
1284 } | |
1285 | |
1286 // on a caller stack | |
1287 llvm::Value* ptr = f->llvmThisVar; | |
1288 assert(ptr); | |
1289 | |
1290 f = f->toParent()->isFuncDeclaration(); | |
1291 assert(f); | |
1292 assert(f->llvmNested); | |
1293 const llvm::Type* nesttype = f->llvmNested->getType(); | |
1294 assert(nesttype); | |
1295 | |
1296 ptr = gIR->ir->CreateBitCast(ptr, nesttype, "tmp"); | |
1297 | |
1298 Logger::cout() << "nested var reference:" << '\n' << *ptr << *nesttype << '\n'; | |
1299 | |
1300 while (f) { | |
1301 if (fd == f) { | |
1302 llvm::Value* v = DtoGEPi(ptr,0,vd->llvmNestedIndex,"tmp"); | |
1303 if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) { | |
1304 Logger::cout() << "1291 loading: " << *v << '\n'; | |
1305 v = gIR->ir->CreateLoad(v,"tmp"); | |
1306 } | |
1307 return v; | |
1308 } | |
1309 else { | |
1310 ptr = DtoGEPi(ptr,0,0,"tmp"); | |
1311 ptr = gIR->ir->CreateLoad(ptr,"tmp"); | |
1312 } | |
1313 f = f->toParent()->isFuncDeclaration(); | |
1314 } | |
1315 | |
1316 assert(0 && "nested var not found"); | |
1317 return NULL; | |
1318 } | |
1319 | |
1320 ////////////////////////////////////////////////////////////////////////////////////////// | |
1321 | |
1322 void DtoAssign(DValue* lhs, DValue* rhs) | |
1323 { | |
1324 Type* t = DtoDType(lhs->getType()); | |
1325 Type* t2 = DtoDType(rhs->getType()); | |
1326 | |
1327 if (t->ty == Tstruct) { | |
1328 if (t2 != t) { | |
1329 // TODO: fix this, use 'rhs' for something | |
1330 DtoStructZeroInit(lhs->getLVal()); | |
1331 } | |
1332 else if (!rhs->inPlace()) { | |
1333 DtoStructCopy(lhs->getLVal(),rhs->getRVal()); | |
1334 } | |
1335 } | |
1336 else if (t->ty == Tarray) { | |
1337 // lhs is slice | |
1338 if (DSliceValue* s = lhs->isSlice()) { | |
1339 if (DSliceValue* s2 = rhs->isSlice()) { | |
1340 DtoArrayCopy(s, s2); | |
1341 } | |
1342 else if (t->next == t2) { | |
1343 if (s->len) | |
1344 DtoArrayInit(s->ptr, s->len, rhs->getRVal()); | |
1345 else | |
1346 DtoArrayInit(s->ptr, rhs->getRVal()); | |
1347 } | |
1348 else | |
1349 assert(rhs->inPlace()); | |
1350 } | |
1351 // rhs is slice | |
1352 else if (DSliceValue* s = rhs->isSlice()) { | |
1353 DtoSetArray(lhs->getLVal(),s->len,s->ptr); | |
1354 } | |
1355 // null | |
1356 else if (rhs->isNull()) { | |
1357 DtoNullArray(lhs->getLVal()); | |
1358 } | |
1359 // reference assignment | |
1360 else { | |
1361 DtoArrayAssign(lhs->getLVal(), rhs->getRVal()); | |
1362 } | |
1363 } | |
1364 else if (t->ty == Tsarray) { | |
1365 DtoStaticArrayCopy(lhs->getLVal(), rhs->getRVal()); | |
1366 } | |
1367 else if (t->ty == Tdelegate) { | |
1368 if (rhs->isNull()) | |
1369 DtoNullDelegate(lhs->getLVal()); | |
1370 else if (!rhs->inPlace()) | |
1371 DtoDelegateCopy(lhs->getLVal(), rhs->getRVal()); | |
1372 } | |
1373 else if (t->ty == Tclass) { | |
1374 assert(t2->ty == Tclass); | |
1375 // assignment to this in constructor special case | |
1376 if (lhs->isThis()) { | |
1377 llvm::Value* tmp = rhs->getRVal(); | |
1378 FuncDeclaration* fdecl = gIR->func().decl; | |
1379 // respecify the this param | |
1380 if (!llvm::isa<llvm::AllocaInst>(fdecl->llvmThisVar)) | |
1381 fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", gIR->topallocapoint()); | |
1382 DtoStore(tmp, fdecl->llvmThisVar); | |
1383 } | |
1384 // regular class ref -> class ref assignment | |
1385 else { | |
1386 DtoStore(rhs->getRVal(), lhs->getLVal()); | |
1387 } | |
1388 } | |
1389 else { | |
1390 llvm::Value* r = rhs->getRVal(); | |
1391 llvm::Value* l = lhs->getLVal(); | |
1392 Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n'; | |
1393 gIR->ir->CreateStore(r, l); | |
1394 } | |
1395 } | |
1396 | |
1397 ////////////////////////////////////////////////////////////////////////////////////////// | |
1398 | |
1399 llvm::ConstantInt* DtoConstSize_t(size_t i) | |
1400 { | |
1401 return llvm::ConstantInt::get(DtoSize_t(), i, false); | |
1402 } | |
1403 llvm::ConstantInt* DtoConstUint(unsigned i) | |
1404 { | |
1405 return llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false); | |
1406 } | |
1407 llvm::ConstantInt* DtoConstInt(int i) | |
1408 { | |
1409 return llvm::ConstantInt::get(llvm::Type::Int32Ty, i, true); | |
1410 } | |
1411 llvm::Constant* DtoConstBool(bool b) | |
1412 { | |
1413 return llvm::ConstantInt::get(llvm::Type::Int1Ty, b, false); | |
1414 } | |
1415 | |
1416 ////////////////////////////////////////////////////////////////////////////////////////// | |
1417 | |
1418 llvm::Constant* DtoConstString(const char* str) | |
1419 { | |
1420 std::string s(str); | |
1421 llvm::Constant* init = llvm::ConstantArray::get(s, true); | |
1422 llvm::GlobalVariable* gvar = new llvm::GlobalVariable( | |
1423 init->getType(), true,llvm::GlobalValue::InternalLinkage, init, "stringliteral", gIR->module); | |
1424 llvm::Constant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) }; | |
1425 return DtoConstSlice( | |
1426 DtoConstSize_t(s.length()), | |
1427 llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2) | |
1428 ); | |
1429 } | |
1430 llvm::Constant* DtoConstStringPtr(const char* str, const char* section) | |
1431 { | |
1432 std::string s(str); | |
1433 llvm::Constant* init = llvm::ConstantArray::get(s, true); | |
1434 llvm::GlobalVariable* gvar = new llvm::GlobalVariable( | |
1435 init->getType(), true,llvm::GlobalValue::InternalLinkage, init, "stringliteral", gIR->module); | |
1436 if (section) gvar->setSection(section); | |
1437 llvm::Constant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) }; | |
1438 return llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); | |
1439 } | |
1440 | |
1441 ////////////////////////////////////////////////////////////////////////////////////////// | |
1442 | |
1443 void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes) | |
1444 { | |
1445 assert(dst->getType() == src->getType()); | |
1446 | |
1447 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
1448 llvm::Value *dstarr, *srcarr; | |
1449 if (dst->getType() == arrty) | |
1450 { | |
1451 dstarr = dst; | |
1452 srcarr = src; | |
1453 } | |
1454 else | |
1455 { | |
1456 dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
1457 srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb()); | |
1458 } | |
1459 | |
1460 llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32(); | |
1461 std::vector<llvm::Value*> llargs; | |
1462 llargs.resize(4); | |
1463 llargs[0] = dstarr; | |
1464 llargs[1] = srcarr; | |
1465 llargs[2] = nbytes; | |
1466 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
1467 | |
1468 new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
1469 } | |
1470 | |
1471 ////////////////////////////////////////////////////////////////////////////////////////// | |
1472 | |
1473 llvm::Value* DtoLoad(llvm::Value* src) | |
1474 { | |
1475 return gIR->ir->CreateLoad(src,"tmp"); | |
1476 } | |
1477 | |
1478 void DtoStore(llvm::Value* src, llvm::Value* dst) | |
1479 { | |
1480 gIR->ir->CreateStore(src,dst); | |
1481 } | |
1482 | |
1483 bool DtoCanLoad(llvm::Value* ptr) | |
1484 { | |
1485 if (llvm::isa<llvm::PointerType>(ptr->getType())) { | |
1486 return ptr->getType()->getContainedType(0)->isFirstClassType(); | |
1487 } | |
1488 return false; | |
1489 } | |
1490 | |
1491 llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t) | |
1492 { | |
1493 return gIR->ir->CreateBitCast(v, t, "tmp"); | |
1494 } | |
1495 | |
1496 ////////////////////////////////////////////////////////////////////////////////////////// | |
1497 | |
1498 llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs) | |
1499 { | |
1500 Logger::println("checking for offset %u type %s:", os, t->toChars()); | |
1501 LOG_SCOPE; | |
1502 | |
1503 if (idxs.empty()) | |
1504 idxs.push_back(0); | |
1505 | |
1506 const llvm::Type* llt = llvm::PointerType::get(DtoType(t)); | |
1507 | |
1508 for (unsigned i=0; i<sd->fields.dim; ++i) { | |
1509 VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i]; | |
1510 Type* vdtype = DtoDType(vd->type); | |
1511 Logger::println("found %u type %s", vd->offset, vdtype->toChars()); | |
1512 assert(vd->llvmFieldIndex >= 0); | |
1513 if (os == vd->offset && vdtype == t) { | |
1514 idxs.push_back(vd->llvmFieldIndex); | |
1515 ptr = DtoGEP(ptr, idxs, "tmp"); | |
1516 if (ptr->getType() != llt) | |
1517 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); | |
1518 if (vd->llvmFieldIndexOffset) | |
1519 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); | |
1520 return ptr; | |
1521 } | |
1522 else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { | |
1523 TypeStruct* ts = (TypeStruct*)vdtype; | |
1524 StructDeclaration* ssd = ts->sym; | |
1525 idxs.push_back(vd->llvmFieldIndex); | |
1526 if (vd->llvmFieldIndexOffset) { | |
1527 Logger::println("has union field offset"); | |
1528 ptr = DtoGEP(ptr, idxs, "tmp"); | |
1529 if (ptr->getType() != llt) | |
1530 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); | |
1531 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); | |
1532 std::vector<unsigned> tmp; | |
1533 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); | |
1534 } | |
1535 else { | |
1536 const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type)); | |
1537 if (ptr->getType() != sty) { | |
1538 ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp"); | |
1539 std::vector<unsigned> tmp; | |
1540 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); | |
1541 } | |
1542 else { | |
1543 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs); | |
1544 } | |
1545 } | |
1546 } | |
1547 } | |
1548 | |
1549 size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0)); | |
1550 assert(os % llt_sz == 0); | |
1551 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); | |
1552 return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb()); | |
1553 } | |
1554 | |
1555 ////////////////////////////////////////////////////////////////////////////////////////// | |
1556 | |
1557 bool DtoIsTemplateInstance(Dsymbol* s) | |
1558 { | |
1559 if (!s) return false; | |
1560 if (s->isTemplateInstance() && !s->isTemplateMixin()) | |
1561 return true; | |
1562 else if (s->parent) | |
1563 return DtoIsTemplateInstance(s->parent); | |
1564 return false; | |
1565 } |