Mercurial > projects > ldc
comparison gen/tollvm.c @ 1:c53b6e3fe49a trunk
[svn r5] Initial commit. Most things are very rough.
author | lindquist |
---|---|
date | Sat, 01 Sep 2007 21:43:27 +0200 |
parents | |
children | e116aa1488e6 |
comparison
equal
deleted
inserted
replaced
0:a9e71648e74d | 1:c53b6e3fe49a |
---|---|
1 #include <iostream> | |
2 | |
3 #include "llvm/Constants.h" | |
4 #include "llvm/Type.h" | |
5 #include "llvm/DerivedTypes.h" | |
6 #include "llvm/GlobalValue.h" | |
7 #include "llvm/Instructions.h" | |
8 #include "llvm/CallingConv.h" | |
9 | |
10 #include "mtype.h" | |
11 #include "dsymbol.h" | |
12 #include "aggregate.h" | |
13 #include "declaration.h" | |
14 #include "init.h" | |
15 | |
16 #include "tollvm.h" | |
17 #include "irstate.h" | |
18 #include "logger.h" | |
19 #include "runtime.h" | |
20 #include "elem.h" | |
21 | |
22 const llvm::Type* LLVM_DtoType(Type* t) | |
23 { | |
24 assert(t); | |
25 switch (t->ty) | |
26 { | |
27 // integers | |
28 case Tint8: | |
29 case Tuns8: | |
30 case Tchar: | |
31 return (const llvm::Type*)llvm::Type::Int8Ty; | |
32 case Tint16: | |
33 case Tuns16: | |
34 case Twchar: | |
35 return (const llvm::Type*)llvm::Type::Int16Ty; | |
36 case Tint32: | |
37 case Tuns32: | |
38 case Tdchar: | |
39 return (const llvm::Type*)llvm::Type::Int32Ty; | |
40 case Tint64: | |
41 case Tuns64: | |
42 return (const llvm::Type*)llvm::Type::Int64Ty; | |
43 | |
44 case Tbool: | |
45 return (const llvm::Type*)llvm::ConstantInt::getTrue()->getType(); | |
46 | |
47 // floats | |
48 case Tfloat32: | |
49 return llvm::Type::FloatTy; | |
50 case Tfloat64: | |
51 case Tfloat80: | |
52 return llvm::Type::DoubleTy; | |
53 | |
54 // pointers | |
55 case Tpointer: { | |
56 assert(t->next); | |
57 if (t->next->ty == Tvoid) | |
58 return (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty); | |
59 else | |
60 return (const llvm::Type*)llvm::PointerType::get(LLVM_DtoType(t->next)); | |
61 } | |
62 | |
63 // arrays | |
64 case Tarray: | |
65 return LLVM_DtoArrayType(t); | |
66 case Tsarray: | |
67 return LLVM_DtoStaticArrayType(t); | |
68 | |
69 // void | |
70 case Tvoid: | |
71 return llvm::Type::VoidTy; | |
72 | |
73 // aggregates | |
74 case Tstruct: { | |
75 if (t->llvmType == 0) | |
76 { | |
77 // recursive or cyclic declaration | |
78 if (!gIR->structs.empty()) | |
79 { | |
80 IRStruct* found = 0; | |
81 for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i) | |
82 { | |
83 if (t == i->type) | |
84 { | |
85 return i->recty.get(); | |
86 } | |
87 } | |
88 } | |
89 | |
90 // forward declaration | |
91 TypeStruct* ts = (TypeStruct*)t; | |
92 assert(ts->sym); | |
93 ts->sym->toObjFile(); | |
94 } | |
95 return t->llvmType; | |
96 } | |
97 | |
98 case Tclass: { | |
99 if (t->llvmType == 0) | |
100 { | |
101 TypeClass* tc = (TypeClass*)t; | |
102 assert(tc->sym); | |
103 if (!tc->sym->llvmInProgress) { | |
104 tc->sym->toObjFile(); | |
105 } | |
106 else { | |
107 //assert(0 && "circular class referencing"); | |
108 return llvm::OpaqueType::get(); | |
109 } | |
110 } | |
111 return llvm::PointerType::get(t->llvmType); | |
112 } | |
113 | |
114 // functions | |
115 case Tfunction: | |
116 { | |
117 if (t->llvmType == 0) { | |
118 return LLVM_DtoFunctionType(t); | |
119 } | |
120 else { | |
121 return t->llvmType; | |
122 } | |
123 } | |
124 | |
125 // delegates | |
126 case Tdelegate: | |
127 { | |
128 if (t->llvmType == 0) { | |
129 return LLVM_DtoDelegateType(t); | |
130 } | |
131 else { | |
132 return t->llvmType; | |
133 } | |
134 } | |
135 | |
136 // typedefs | |
137 case Ttypedef: | |
138 { | |
139 Type* bt = t->toBasetype(); | |
140 assert(bt); | |
141 return LLVM_DtoType(bt); | |
142 } | |
143 | |
144 default: | |
145 printf("trying to convert unknown type with value %d\n", t->ty); | |
146 assert(0); | |
147 } | |
148 return 0; | |
149 } | |
150 | |
151 ////////////////////////////////////////////////////////////////////////////////////////// | |
152 | |
153 llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam) | |
154 { | |
155 TypeFunction* f = (TypeFunction*)t; | |
156 | |
157 // parameter types | |
158 const llvm::Type* rettype; | |
159 std::vector<const llvm::Type*> paramvec; | |
160 | |
161 TY retty = f->next->ty; | |
162 | |
163 if (retty == Tstruct || retty == Tdelegate || retty == Tarray) { | |
164 rettype = llvm::PointerType::get(LLVM_DtoType(f->next)); | |
165 paramvec.push_back(rettype); | |
166 rettype = llvm::Type::VoidTy; | |
167 } | |
168 else { | |
169 Type* rt = f->next; | |
170 if (rt) | |
171 rettype = LLVM_DtoType(rt); | |
172 else | |
173 assert(0); | |
174 } | |
175 | |
176 if (thisparam) { | |
177 paramvec.push_back(thisparam); | |
178 } | |
179 | |
180 size_t n = Argument::dim(f->parameters); | |
181 for (int i=0; i < n; ++i) { | |
182 Argument* arg = Argument::getNth(f->parameters, i); | |
183 // ensure scalar | |
184 Type* argT = arg->type; | |
185 assert(argT); | |
186 paramvec.push_back(LLVM_DtoType(argT)); | |
187 } | |
188 | |
189 Logger::cout() << "Return type: " << *rettype << '\n'; | |
190 | |
191 llvm::FunctionType* functype = llvm::FunctionType::get(rettype, paramvec, f->varargs); | |
192 return functype; | |
193 } | |
194 | |
195 ////////////////////////////////////////////////////////////////////////////////////////// | |
196 | |
197 llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl) | |
198 { | |
199 TypeFunction* f = (TypeFunction*)fdecl->type; | |
200 assert(f != 0); | |
201 | |
202 // has already been pulled in by a reference to ( | |
203 if (f->llvmType != 0) { | |
204 return llvm::cast<llvm::FunctionType>(f->llvmType); | |
205 } | |
206 | |
207 // return value type | |
208 const llvm::Type* rettype; | |
209 const llvm::Type* actualRettype; | |
210 Type* rt = f->next; | |
211 bool retinptr = false; | |
212 bool usesthis = false; | |
213 | |
214 if (fdecl->isMain()) { | |
215 rettype = llvm::Type::Int32Ty; | |
216 actualRettype = rettype; | |
217 } | |
218 else if (rt) { | |
219 if (rt->ty == Tstruct || rt->ty == Tdelegate || rt->ty == Tarray) { | |
220 rettype = llvm::PointerType::get(LLVM_DtoType(rt)); | |
221 actualRettype = llvm::Type::VoidTy; | |
222 f->llvmRetInPtr = retinptr = true; | |
223 } | |
224 else { | |
225 rettype = LLVM_DtoType(rt); | |
226 actualRettype = rettype; | |
227 } | |
228 } | |
229 else { | |
230 assert(0); | |
231 } | |
232 | |
233 // parameter types | |
234 std::vector<const llvm::Type*> paramvec; | |
235 | |
236 if (retinptr) { | |
237 Logger::print("returning through pointer parameter\n"); | |
238 paramvec.push_back(rettype); | |
239 } | |
240 | |
241 if (fdecl->needThis() && fdecl->vthis) { | |
242 Logger::print("this is: %s\n", fdecl->vthis->type->toChars()); | |
243 paramvec.push_back(LLVM_DtoType(fdecl->vthis->type)); | |
244 usesthis = true; | |
245 } | |
246 | |
247 size_t n = Argument::dim(f->parameters); | |
248 for (int i=0; i < n; ++i) { | |
249 Argument* arg = Argument::getNth(f->parameters, i); | |
250 // ensure scalar | |
251 Type* argT = arg->type; | |
252 assert(argT); | |
253 | |
254 if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { | |
255 //assert(arg->vardecl); | |
256 //arg->vardecl->refparam = true; | |
257 } | |
258 else | |
259 arg->llvmCopy = true; | |
260 | |
261 const llvm::Type* at = LLVM_DtoType(argT); | |
262 if (llvm::isa<llvm::StructType>(at)) { | |
263 Logger::println("struct param"); | |
264 paramvec.push_back(llvm::PointerType::get(at)); | |
265 } | |
266 else if (llvm::isa<llvm::ArrayType>(at)) { | |
267 Logger::println("sarray param"); | |
268 assert(argT->ty == Tsarray); | |
269 //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0))); | |
270 paramvec.push_back(llvm::PointerType::get(at)); | |
271 } | |
272 else { | |
273 if (!arg->llvmCopy) { | |
274 Logger::println("ref param"); | |
275 at = llvm::PointerType::get(at); | |
276 } | |
277 else { | |
278 Logger::println("in param"); | |
279 } | |
280 paramvec.push_back(at); | |
281 } | |
282 } | |
283 | |
284 // construct function type | |
285 bool isvararg = f->varargs; | |
286 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); | |
287 | |
288 f->llvmType = functype; | |
289 return functype; | |
290 } | |
291 | |
292 ////////////////////////////////////////////////////////////////////////////////////////// | |
293 | |
294 llvm::StructType* LLVM_DtoDelegateType(Type* t) | |
295 { | |
296 const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty); | |
297 const llvm::Type* func = LLVM_DtoFunctionType(t->next, i8ptr); | |
298 const llvm::Type* funcptr = llvm::PointerType::get(func); | |
299 | |
300 std::vector<const llvm::Type*> types; | |
301 types.push_back(i8ptr); | |
302 types.push_back(funcptr); | |
303 return llvm::StructType::get(types); | |
304 } | |
305 | |
306 ////////////////////////////////////////////////////////////////////////////////////////// | |
307 | |
308 llvm::Type* LLVM_DtoStructType(Type* t) | |
309 { | |
310 assert(0); | |
311 std::vector<const llvm::Type*> types; | |
312 return llvm::StructType::get(types); | |
313 } | |
314 | |
315 ////////////////////////////////////////////////////////////////////////////////////////// | |
316 | |
317 llvm::StructType* LLVM_DtoArrayType(Type* t) | |
318 { | |
319 assert(t->next); | |
320 const llvm::Type* at = LLVM_DtoType(t->next); | |
321 const llvm::Type* arrty; | |
322 | |
323 /*if (t->ty == Tsarray) { | |
324 TypeSArray* tsa = (TypeSArray*)t; | |
325 assert(tsa->dim->type->isintegral()); | |
326 arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger()); | |
327 } | |
328 else { | |
329 arrty = llvm::ArrayType::get(at,0); | |
330 }*/ | |
331 if (at == llvm::Type::VoidTy) { | |
332 at = llvm::Type::Int8Ty; | |
333 } | |
334 arrty = llvm::PointerType::get(at); | |
335 | |
336 std::vector<const llvm::Type*> members; | |
337 if (global.params.is64bit) | |
338 members.push_back(llvm::Type::Int64Ty); | |
339 else | |
340 members.push_back(llvm::Type::Int32Ty); | |
341 | |
342 members.push_back(arrty); | |
343 | |
344 return llvm::StructType::get(members); | |
345 } | |
346 | |
347 ////////////////////////////////////////////////////////////////////////////////////////// | |
348 | |
349 llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t) | |
350 { | |
351 if (t->llvmType) | |
352 return llvm::cast<llvm::ArrayType>(t->llvmType); | |
353 | |
354 assert(t->ty == Tsarray); | |
355 assert(t->next); | |
356 | |
357 const llvm::Type* at = LLVM_DtoType(t->next); | |
358 | |
359 TypeSArray* tsa = (TypeSArray*)t; | |
360 assert(tsa->dim->type->isintegral()); | |
361 llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger()); | |
362 | |
363 tsa->llvmType = arrty; | |
364 return arrty; | |
365 } | |
366 | |
367 ////////////////////////////////////////////////////////////////////////////////////////// | |
368 | |
369 static llvm::Function* LLVM_DeclareMemIntrinsic(const char* name, int bits, bool set=false) | |
370 { | |
371 assert(bits == 32 || bits == 64); | |
372 const llvm::Type* int8ty = (const llvm::Type*)llvm::Type::Int8Ty; | |
373 const llvm::Type* int32ty = (const llvm::Type*)llvm::Type::Int32Ty; | |
374 const llvm::Type* int64ty = (const llvm::Type*)llvm::Type::Int64Ty; | |
375 const llvm::Type* int8ptrty = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty); | |
376 const llvm::Type* voidty = (const llvm::Type*)llvm::Type::VoidTy; | |
377 | |
378 assert(gIR); | |
379 assert(gIR->module); | |
380 | |
381 // parameter types | |
382 std::vector<const llvm::Type*> pvec; | |
383 pvec.push_back(int8ptrty); | |
384 pvec.push_back(set?int8ty:int8ptrty); | |
385 pvec.push_back(bits==32?int32ty:int64ty); | |
386 pvec.push_back(int32ty); | |
387 llvm::FunctionType* functype = llvm::FunctionType::get(voidty, pvec, false); | |
388 return new llvm::Function(functype, llvm::GlobalValue::ExternalLinkage, name, gIR->module); | |
389 } | |
390 | |
391 ////////////////////////////////////////////////////////////////////////////////////////// | |
392 | |
393 // llvm.memset.i32 | |
394 static llvm::Function* LLVM_DeclareMemSet32() | |
395 { | |
396 static llvm::Function* _func = 0; | |
397 if (_func == 0) { | |
398 _func = LLVM_DeclareMemIntrinsic("llvm.memset.i32", 32, true); | |
399 } | |
400 return _func; | |
401 } | |
402 | |
403 ////////////////////////////////////////////////////////////////////////////////////////// | |
404 | |
405 static llvm::Function* LLVM_DeclareMemSet64() | |
406 { | |
407 static llvm::Function* _func = 0; | |
408 if (_func == 0) { | |
409 _func = LLVM_DeclareMemIntrinsic("llvm.memset.i64", 64, true); | |
410 } | |
411 return _func; | |
412 } | |
413 | |
414 ////////////////////////////////////////////////////////////////////////////////////////// | |
415 | |
416 // llvm.memcpy.i32 | |
417 static llvm::Function* LLVM_DeclareMemCpy32() | |
418 { | |
419 static llvm::Function* _func = 0; | |
420 if (_func == 0) { | |
421 _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i32", 32); | |
422 } | |
423 return _func; | |
424 } | |
425 | |
426 ////////////////////////////////////////////////////////////////////////////////////////// | |
427 | |
428 // llvm.memcpy.i64 | |
429 static llvm::Function* LLVM_DeclareMemCpy64() | |
430 { | |
431 static llvm::Function* _func = 0; | |
432 if (_func == 0) { | |
433 _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i64", 64); | |
434 } | |
435 return _func; | |
436 } | |
437 | |
438 ////////////////////////////////////////////////////////////////////////////////////////// | |
439 | |
440 llvm::Value* LLVM_DtoStructZeroInit(TypeStruct* t, llvm::Value* v) | |
441 { | |
442 assert(gIR); | |
443 uint64_t n = gTargetData->getTypeSize(t->llvmType); | |
444 //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n)); | |
445 llvm::Type* sarrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
446 | |
447 llvm::Value* sarr = new llvm::BitCastInst(v,sarrty,"tmp",gIR->scopebb()); | |
448 | |
449 llvm::Function* fn = LLVM_DeclareMemSet32(); | |
450 std::vector<llvm::Value*> llargs; | |
451 llargs.resize(4); | |
452 llargs[0] = sarr; | |
453 llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false); | |
454 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
455 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
456 | |
457 llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
458 | |
459 return ret; | |
460 } | |
461 | |
462 ////////////////////////////////////////////////////////////////////////////////////////// | |
463 | |
464 llvm::Value* LLVM_DtoStructCopy(TypeStruct* t, llvm::Value* dst, llvm::Value* src) | |
465 { | |
466 assert(dst->getType() == src->getType()); | |
467 assert(gIR); | |
468 | |
469 uint64_t n = gTargetData->getTypeSize(t->llvmType); | |
470 //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n)); | |
471 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
472 | |
473 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
474 llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb()); | |
475 | |
476 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
477 std::vector<llvm::Value*> llargs; | |
478 llargs.resize(4); | |
479 llargs[0] = dstarr; | |
480 llargs[1] = srcarr; | |
481 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
482 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
483 | |
484 return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
485 } | |
486 | |
487 ////////////////////////////////////////////////////////////////////////////////////////// | |
488 llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si) | |
489 { | |
490 llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType); | |
491 size_t n = structtype->getNumElements(); | |
492 | |
493 assert(si->value.dim == si->vars.dim); | |
494 | |
495 std::vector<llvm::Constant*> inits; | |
496 inits.resize(n, NULL); | |
497 for (int i = 0; i < si->value.dim; ++i) | |
498 { | |
499 Initializer* ini = (Initializer*)si->value.data[i]; | |
500 assert(ini); | |
501 | |
502 VarDeclaration* vd = (VarDeclaration*)si->vars.data[i]; | |
503 assert(vd); | |
504 Logger::println("vars[%d] = %s", i, vd->toChars()); | |
505 unsigned idx = si->ad->offsetToIndex(vd->offset); | |
506 | |
507 llvm::Constant* v = 0; | |
508 | |
509 if (ExpInitializer* ex = ini->isExpInitializer()) | |
510 { | |
511 elem* e = ex->exp->toElem(gIR); | |
512 v = llvm::cast<llvm::Constant>(e->val); | |
513 delete e; | |
514 } | |
515 else if (StructInitializer* si = ini->isStructInitializer()) | |
516 { | |
517 v = LLVM_DtoStructInitializer(si); | |
518 } | |
519 else if (ArrayInitializer* ai = ini->isArrayInitializer()) | |
520 { | |
521 v = LLVM_DtoArrayInitializer(ai); | |
522 } | |
523 else if (ini->isVoidInitializer()) | |
524 { | |
525 v = llvm::UndefValue::get(structtype->getElementType(idx)); | |
526 } | |
527 else | |
528 assert(v); | |
529 | |
530 inits[idx] = v; | |
531 } | |
532 | |
533 // fill out nulls | |
534 assert(si->ad->llvmInitZ); | |
535 if (si->ad->llvmInitZ->isNullValue()) | |
536 { | |
537 for (int i = 0; i < n; ++i) | |
538 { | |
539 if (inits[i] == 0) | |
540 { | |
541 inits[i] = llvm::Constant::getNullValue(structtype->getElementType(i)); | |
542 } | |
543 } | |
544 } | |
545 else | |
546 { | |
547 for (int i = 0; i < n; ++i) | |
548 { | |
549 if (inits[i] == 0) | |
550 { | |
551 inits[i] = si->ad->llvmInitZ->getOperand(i); | |
552 } | |
553 } | |
554 } | |
555 | |
556 return llvm::ConstantStruct::get(structtype, inits); | |
557 } | |
558 | |
559 ////////////////////////////////////////////////////////////////////////////////////////// | |
560 | |
561 llvm::Value* LLVM_DtoNullArray(llvm::Value* v) | |
562 { | |
563 assert(gIR); | |
564 d_uns64 n = (global.params.is64bit) ? 16 : 8; | |
565 | |
566 llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
567 | |
568 llvm::Value* arr = new llvm::BitCastInst(v,i8p_ty,"tmp",gIR->scopebb()); | |
569 | |
570 llvm::Function* fn = LLVM_DeclareMemSet32(); | |
571 std::vector<llvm::Value*> llargs; | |
572 llargs.resize(4); | |
573 llargs[0] = arr; | |
574 llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false); | |
575 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
576 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
577 | |
578 //Logger::cout() << *fn << '|' << *fn->getType() << '\n'; | |
579 //Logger::cout() << "to null array call: " << *llargs[0] << '|' << *llargs[1] << '|' << *llargs[2] << '|' << *llargs[3] << '\n'; | |
580 | |
581 llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
582 | |
583 return ret; | |
584 } | |
585 | |
586 ////////////////////////////////////////////////////////////////////////////////////////// | |
587 | |
588 llvm::Value* LLVM_DtoNullDelegate(llvm::Value* v) | |
589 { | |
590 assert(gIR); | |
591 d_uns64 n = (global.params.is64bit) ? 16 : 8; | |
592 | |
593 llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
594 | |
595 llvm::Value* arr = new llvm::BitCastInst(v,i8p_ty,"tmp",gIR->scopebb()); | |
596 | |
597 llvm::Function* fn = LLVM_DeclareMemSet32(); | |
598 std::vector<llvm::Value*> llargs; | |
599 llargs.resize(4); | |
600 llargs[0] = arr; | |
601 llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false); | |
602 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
603 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
604 | |
605 llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
606 | |
607 return ret; | |
608 } | |
609 | |
610 ////////////////////////////////////////////////////////////////////////////////////////// | |
611 | |
612 llvm::Value* LLVM_DtoDelegateCopy(llvm::Value* dst, llvm::Value* src) | |
613 { | |
614 assert(dst->getType() == src->getType()); | |
615 assert(gIR); | |
616 | |
617 d_uns64 n = (global.params.is64bit) ? 16 : 8; | |
618 | |
619 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
620 | |
621 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
622 llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb()); | |
623 | |
624 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
625 std::vector<llvm::Value*> llargs; | |
626 llargs.resize(4); | |
627 llargs[0] = dstarr; | |
628 llargs[1] = srcarr; | |
629 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
630 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
631 | |
632 return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
633 } | |
634 | |
635 ////////////////////////////////////////////////////////////////////////////////////////// | |
636 | |
637 llvm::Value* LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src) | |
638 { | |
639 assert(gIR); | |
640 if (dst->getType() == src->getType()) | |
641 { | |
642 d_uns64 n = (global.params.is64bit) ? 16 : 8; | |
643 | |
644 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
645 | |
646 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
647 llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb()); | |
648 | |
649 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
650 std::vector<llvm::Value*> llargs; | |
651 llargs.resize(4); | |
652 llargs[0] = dstarr; | |
653 llargs[1] = srcarr; | |
654 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
655 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
656 | |
657 return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
658 } | |
659 else | |
660 { | |
661 if (!llvm::isa<llvm::ArrayType>(src->getType()->getContainedType(0))) | |
662 { | |
663 Logger::cout() << "invalid: " << *src << '\n'; | |
664 assert(0); | |
665 } | |
666 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(src->getType()->getContainedType(0)); | |
667 llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType()); | |
668 | |
669 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
670 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); | |
671 | |
672 llvm::Value* dstlen = new llvm::GetElementPtrInst(dst,zero,zero,"tmp",gIR->scopebb()); | |
673 llvm::Value* srclen = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false); | |
674 new llvm::StoreInst(srclen, dstlen, gIR->scopebb()); | |
675 | |
676 llvm::Value* dstptr = new llvm::GetElementPtrInst(dst,zero,one,"tmp",gIR->scopebb()); | |
677 llvm::Value* srcptr = new llvm::BitCastInst(src,dstty,"tmp",gIR->scopebb()); | |
678 new llvm::StoreInst(srcptr, dstptr, gIR->scopebb()); | |
679 } | |
680 } | |
681 | |
682 ////////////////////////////////////////////////////////////////////////////////////////// | |
683 | |
684 void LLVM_DtoArrayInit(llvm::Value* l, llvm::Value* r) | |
685 { | |
686 const llvm::PointerType* ptrty = llvm::cast<llvm::PointerType>(l->getType()); | |
687 if (llvm::isa<llvm::ArrayType>(ptrty->getContainedType(0))) | |
688 { | |
689 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(ptrty->getContainedType(0)); | |
690 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
691 | |
692 std::vector<llvm::Value*> args; | |
693 args.resize(3); | |
694 args[0] = new llvm::GetElementPtrInst(l,zero,zero,"tmp",gIR->scopebb()); | |
695 args[1] = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false); | |
696 args[2] = r; | |
697 | |
698 const char* funcname = NULL; | |
699 | |
700 if (llvm::isa<llvm::PointerType>(arrty->getElementType())) { | |
701 funcname = "_d_array_init_pointer"; | |
702 | |
703 const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); | |
704 if (args[0]->getType() != dstty) | |
705 args[0] = new llvm::BitCastInst(args[0],dstty,"tmp",gIR->scopebb()); | |
706 | |
707 const llvm::Type* valty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
708 if (args[2]->getType() != valty) | |
709 args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb()); | |
710 } | |
711 else if (r->getType() == llvm::Type::Int1Ty) { | |
712 funcname = "_d_array_init_i1"; | |
713 } | |
714 else if (r->getType() == llvm::Type::Int8Ty) { | |
715 funcname = "_d_array_init_i8"; | |
716 } | |
717 else if (r->getType() == llvm::Type::Int16Ty) { | |
718 funcname = "_d_array_init_i16"; | |
719 } | |
720 else if (r->getType() == llvm::Type::Int32Ty) { | |
721 funcname = "_d_array_init_i32"; | |
722 } | |
723 else if (r->getType() == llvm::Type::Int64Ty) { | |
724 funcname = "_d_array_init_i64"; | |
725 } | |
726 else if (r->getType() == llvm::Type::FloatTy) { | |
727 funcname = "_d_array_init_float"; | |
728 } | |
729 else if (r->getType() == llvm::Type::DoubleTy) { | |
730 funcname = "_d_array_init_double"; | |
731 } | |
732 else { | |
733 assert(0); | |
734 } | |
735 | |
736 Logger::cout() << *args[0] << '|' << *args[2] << '\n'; | |
737 | |
738 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname); | |
739 assert(fn); | |
740 llvm::CallInst* call = new llvm::CallInst(fn, args.begin(), args.end(), "", gIR->scopebb()); | |
741 call->setCallingConv(llvm::CallingConv::C); | |
742 | |
743 Logger::println("array init call ok"); | |
744 } | |
745 else if (llvm::isa<llvm::StructType>(ptrty->getContainedType(0))) | |
746 { | |
747 assert(0 && "Only static arrays support initialisers atm"); | |
748 } | |
749 else | |
750 assert(0); | |
751 } | |
752 | |
753 ////////////////////////////////////////////////////////////////////////////////////////// | |
754 | |
755 void LLVM_DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr) | |
756 { | |
757 const llvm::StructType* st = llvm::cast<llvm::StructType>(arr->getType()->getContainedType(0)); | |
758 //const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(r->getType()); | |
759 | |
760 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
761 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); | |
762 | |
763 llvm::Value* arrdim = new llvm::GetElementPtrInst(arr,zero,zero,"tmp",gIR->scopebb()); | |
764 new llvm::StoreInst(dim, arrdim, gIR->scopebb()); | |
765 | |
766 llvm::Value* arrptr = new llvm::GetElementPtrInst(arr,zero,one,"tmp",gIR->scopebb()); | |
767 new llvm::StoreInst(ptr, arrptr, gIR->scopebb()); | |
768 } | |
769 | |
770 ////////////////////////////////////////////////////////////////////////////////////////// | |
771 llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* arrinit) | |
772 { | |
773 Logger::println("arr init begin"); | |
774 assert(arrinit->type->ty == Tsarray); | |
775 TypeSArray* t = (TypeSArray*)arrinit->type; | |
776 integer_t tdim = t->dim->toInteger(); | |
777 | |
778 std::vector<llvm::Constant*> inits(tdim, 0); | |
779 | |
780 const llvm::Type* elemty = LLVM_DtoType(arrinit->type->next); | |
781 | |
782 assert(arrinit->index.dim == arrinit->value.dim); | |
783 for (int i=0,j=0; i < tdim; ++i) | |
784 { | |
785 Initializer* init = 0; | |
786 Expression* idx = (Expression*)arrinit->index.data[j]; | |
787 | |
788 if (idx) | |
789 { | |
790 integer_t k = idx->toInteger(); | |
791 if (i == k) | |
792 { | |
793 init = (Initializer*)arrinit->value.data[j]; | |
794 assert(init); | |
795 ++j; | |
796 } | |
797 } | |
798 else | |
799 { | |
800 init = (Initializer*)arrinit->value.data[j]; | |
801 ++j; | |
802 } | |
803 | |
804 llvm::Constant* v = 0; | |
805 | |
806 if (!init) | |
807 { | |
808 elem* e = t->next->defaultInit()->toElem(gIR); | |
809 v = llvm::cast<llvm::Constant>(e->val); | |
810 delete e; | |
811 } | |
812 else if (ExpInitializer* ex = init->isExpInitializer()) | |
813 { | |
814 elem* e = ex->exp->toElem(gIR); | |
815 v = llvm::cast<llvm::Constant>(e->val); | |
816 delete e; | |
817 } | |
818 else if (StructInitializer* si = init->isStructInitializer()) | |
819 { | |
820 v = LLVM_DtoStructInitializer(si); | |
821 } | |
822 else if (ArrayInitializer* ai = init->isArrayInitializer()) | |
823 { | |
824 v = LLVM_DtoArrayInitializer(ai); | |
825 } | |
826 else if (init->isVoidInitializer()) | |
827 { | |
828 v = llvm::UndefValue::get(elemty); | |
829 } | |
830 else | |
831 assert(v); | |
832 | |
833 inits[i] = v; | |
834 } | |
835 | |
836 llvm::ArrayType* arrty = LLVM_DtoStaticArrayType(t); | |
837 return llvm::ConstantArray::get(arrty, inits); | |
838 } | |
839 | |
840 ////////////////////////////////////////////////////////////////////////////////////////// | |
841 void LLVM_DtoArrayCopy(elem* dst, elem* src) | |
842 { | |
843 assert(0); | |
844 } | |
845 | |
846 ////////////////////////////////////////////////////////////////////////////////////////// | |
847 | |
848 llvm::GlobalValue::LinkageTypes LLVM_DtoLinkage(PROT prot, uint stc) | |
849 { | |
850 switch(prot) | |
851 { | |
852 case PROTprivate: | |
853 return llvm::GlobalValue::InternalLinkage; | |
854 | |
855 case PROTpublic: | |
856 case PROTpackage: | |
857 case PROTprotected: | |
858 case PROTexport: | |
859 return llvm::GlobalValue::ExternalLinkage; | |
860 | |
861 case PROTundefined: | |
862 case PROTnone: | |
863 assert(0 && "Unsupported linkage type"); | |
864 } | |
865 return llvm::GlobalValue::ExternalLinkage; | |
866 | |
867 /* ExternalLinkage = 0, LinkOnceLinkage, WeakLinkage, AppendingLinkage, | |
868 InternalLinkage, DLLImportLinkage, DLLExportLinkage, ExternalWeakLinkage, | |
869 GhostLinkage */ | |
870 } | |
871 | |
872 ////////////////////////////////////////////////////////////////////////////////////////// | |
873 | |
874 unsigned LLVM_DtoCallingConv(LINK l) | |
875 { | |
876 if (l == LINKc) | |
877 return llvm::CallingConv::C; | |
878 else if (l == LINKd || l == LINKdefault) | |
879 return llvm::CallingConv::Fast; | |
880 else if (l == LINKwindows) | |
881 return llvm::CallingConv::X86_StdCall; | |
882 else | |
883 assert(0 && "Unsupported calling convention"); | |
884 } | |
885 | |
886 ////////////////////////////////////////////////////////////////////////////////////////// | |
887 | |
888 llvm::Value* LLVM_DtoPointedType(llvm::Value* ptr, llvm::Value* val) | |
889 { | |
890 const llvm::Type* ptrTy = ptr->getType()->getContainedType(0); | |
891 const llvm::Type* valTy = val->getType(); | |
892 // ptr points to val's type | |
893 if (ptrTy == valTy) | |
894 { | |
895 return val; | |
896 } | |
897 // ptr is integer pointer | |
898 else if (ptrTy->isInteger()) | |
899 { | |
900 // val is integer | |
901 assert(valTy->isInteger()); | |
902 const llvm::IntegerType* pt = llvm::cast<const llvm::IntegerType>(ptrTy); | |
903 const llvm::IntegerType* vt = llvm::cast<const llvm::IntegerType>(valTy); | |
904 if (pt->getBitWidth() < vt->getBitWidth()) { | |
905 return new llvm::TruncInst(val, pt, "tmp", gIR->scopebb()); | |
906 } | |
907 else | |
908 assert(0); | |
909 } | |
910 // something else unsupported | |
911 else | |
912 { | |
913 Logger::cout() << *ptrTy << '|' << *valTy << '\n'; | |
914 assert(0); | |
915 } | |
916 return 0; | |
917 } | |
918 | |
919 ////////////////////////////////////////////////////////////////////////////////////////// | |
920 | |
921 llvm::Value* LLVM_DtoBoolean(llvm::Value* val) | |
922 { | |
923 const llvm::Type* t = val->getType(); | |
924 if (t->isInteger()) | |
925 { | |
926 if (t == llvm::Type::Int1Ty) | |
927 return val; | |
928 else { | |
929 llvm::Value* zero = llvm::ConstantInt::get(t, 0, false); | |
930 return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, val, zero, "tmp", gIR->scopebb()); | |
931 } | |
932 } | |
933 else if (llvm::isa<llvm::PointerType>(t)) { | |
934 const llvm::Type* st = LLVM_DtoSize_t(); | |
935 llvm::Value* ptrasint = new llvm::PtrToIntInst(val,st,"tmp",gIR->scopebb()); | |
936 llvm::Value* zero = llvm::ConstantInt::get(st, 0, false); | |
937 return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, ptrasint, zero, "tmp", gIR->scopebb()); | |
938 } | |
939 else | |
940 { | |
941 Logger::cout() << *t << '\n'; | |
942 } | |
943 assert(0); | |
944 return 0; | |
945 } | |
946 | |
947 ////////////////////////////////////////////////////////////////////////////////////////// | |
948 | |
949 const llvm::Type* LLVM_DtoSize_t() | |
950 { | |
951 if (global.params.is64bit) | |
952 return llvm::Type::Int64Ty; | |
953 else | |
954 return llvm::Type::Int32Ty; | |
955 } | |
956 | |
957 ////////////////////////////////////////////////////////////////////////////////////////// | |
958 | |
959 void LLVM_DtoMain() | |
960 { | |
961 // emit main function llvm style | |
962 // int main(int argc, char**argv, char**env); | |
963 | |
964 assert(gIR != 0); | |
965 IRState& ir = *gIR; | |
966 | |
967 assert(ir.emitMain && ir.mainFunc); | |
968 | |
969 // parameter types | |
970 std::vector<const llvm::Type*> pvec; | |
971 pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty); | |
972 const llvm::Type* chPtrType = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty); | |
973 pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType)); | |
974 pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType)); | |
975 const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty; | |
976 | |
977 llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false); | |
978 llvm::Function* func = new llvm::Function(functype,llvm::GlobalValue::ExternalLinkage,"main",ir.module); | |
979 | |
980 llvm::BasicBlock* bb = new llvm::BasicBlock("entry",func); | |
981 | |
982 // call static ctors | |
983 llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_ctors"); | |
984 new llvm::CallInst(fn,"",bb); | |
985 | |
986 // call user main function | |
987 llvm::CallInst* call = new llvm::CallInst(ir.mainFunc,"ret",bb); | |
988 call->setCallingConv(ir.mainFunc->getCallingConv()); | |
989 | |
990 // call static dtors | |
991 fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors"); | |
992 new llvm::CallInst(fn,"",bb); | |
993 | |
994 // return | |
995 new llvm::ReturnInst(call,bb); | |
996 | |
997 /* | |
998 // return value type | |
999 const llvm::Type* rettype; | |
1000 Type* rt = f->next; | |
1001 if (rt) { | |
1002 rettype = LLVM_DtoType(rt); | |
1003 } | |
1004 else { | |
1005 assert(0); | |
1006 } | |
1007 | |
1008 llvm::FunctionType* functype = llvm::FunctionType::get(rettype, paramvec, false); | |
1009 */ | |
1010 } | |
1011 | |
1012 ////////////////////////////////////////////////////////////////////////////////////////// | |
1013 | |
1014 void LLVM_DtoCallClassDtors(TypeClass* tc, llvm::Value* instance) | |
1015 { | |
1016 Array* arr = &tc->sym->dtors; | |
1017 for (size_t i=0; i<arr->dim; i++) | |
1018 { | |
1019 FuncDeclaration* fd = (FuncDeclaration*)arr->data[i]; | |
1020 assert(fd->llvmValue); | |
1021 new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb()); | |
1022 } | |
1023 } | |
1024 | |
1025 ////////////////////////////////////////////////////////////////////////////////////////// | |
1026 | |
1027 void LLVM_DtoInitClass(TypeClass* tc, llvm::Value* dst) | |
1028 { | |
1029 assert(tc->llvmInit); | |
1030 assert(dst->getType() == tc->llvmInit->getType()); | |
1031 assert(gIR); | |
1032 | |
1033 assert(tc->llvmType); | |
1034 uint64_t n = gTargetData->getTypeSize(tc->llvmType); | |
1035 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
1036 | |
1037 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
1038 llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb()); | |
1039 | |
1040 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
1041 std::vector<llvm::Value*> llargs; | |
1042 llargs.resize(4); | |
1043 llargs[0] = dstarr; | |
1044 llargs[1] = srcarr; | |
1045 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
1046 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
1047 | |
1048 new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
1049 } | |
1050 | |
1051 ////////////////////////////////////////////////////////////////////////////////////////// | |
1052 | |
1053 llvm::Constant* LLVM_DtoInitializer(Type* type, Initializer* init) | |
1054 { | |
1055 llvm::Constant* _init = 0; | |
1056 if (!init) | |
1057 { | |
1058 elem* e = type->defaultInit()->toElem(gIR); | |
1059 if (!e->inplace && !e->isNull()) { | |
1060 _init = llvm::cast<llvm::Constant>(e->getValue()); | |
1061 } | |
1062 delete e; | |
1063 } | |
1064 else if (ExpInitializer* ex = init->isExpInitializer()) | |
1065 { | |
1066 elem* e = ex->exp->toElem(gIR); | |
1067 if (!e->inplace && !e->isNull()) { | |
1068 _init = llvm::cast<llvm::Constant>(e->getValue()); | |
1069 } | |
1070 delete e; | |
1071 } | |
1072 else if (StructInitializer* si = init->isStructInitializer()) | |
1073 { | |
1074 _init = LLVM_DtoStructInitializer(si); | |
1075 } | |
1076 else if (ArrayInitializer* ai = init->isArrayInitializer()) | |
1077 { | |
1078 _init = LLVM_DtoArrayInitializer(ai); | |
1079 } | |
1080 else if (init->isVoidInitializer()) | |
1081 { | |
1082 const llvm::Type* ty = LLVM_DtoType(type); | |
1083 _init = llvm::Constant::getNullValue(ty); | |
1084 } | |
1085 else { | |
1086 Logger::println("unsupported initializer: %s", init->toChars()); | |
1087 } | |
1088 return _init; | |
1089 } |