comparison gen/arrays.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/arrays.c@3587401b6eeb
children 058d3925950e
comparison
equal deleted inserted replaced
85:f869c636a113 86:fd32135dca3e
1 #include "gen/llvm.h"
2
3 #include "mtype.h"
4 #include "dsymbol.h"
5 #include "aggregate.h"
6 #include "declaration.h"
7 #include "init.h"
8
9 #include "gen/irstate.h"
10 #include "gen/tollvm.h"
11 #include "gen/arrays.h"
12 #include "gen/runtime.h"
13 #include "gen/logger.h"
14 #include "gen/dvalue.h"
15
16 //////////////////////////////////////////////////////////////////////////////////////////
17
18 const llvm::StructType* DtoArrayType(Type* t)
19 {
20 assert(t->next);
21 const llvm::Type* at = DtoType(t->next);
22 const llvm::Type* arrty;
23
24 /*if (t->ty == Tsarray) {
25 TypeSArray* tsa = (TypeSArray*)t;
26 assert(tsa->dim->type->isintegral());
27 arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger());
28 }
29 else {
30 arrty = llvm::ArrayType::get(at,0);
31 }*/
32 if (at == llvm::Type::VoidTy) {
33 at = llvm::Type::Int8Ty;
34 }
35 arrty = llvm::PointerType::get(at);
36
37 std::vector<const llvm::Type*> members;
38 if (global.params.is64bit)
39 members.push_back(llvm::Type::Int64Ty);
40 else
41 members.push_back(llvm::Type::Int32Ty);
42
43 members.push_back(arrty);
44
45 return llvm::StructType::get(members);
46 }
47
48 //////////////////////////////////////////////////////////////////////////////////////////
49
50 const llvm::ArrayType* DtoStaticArrayType(Type* t)
51 {
52 if (t->llvmType)
53 return llvm::cast<llvm::ArrayType>(t->llvmType);
54
55 assert(t->ty == Tsarray);
56 assert(t->next);
57
58 const llvm::Type* at = DtoType(t->next);
59
60 TypeSArray* tsa = (TypeSArray*)t;
61 assert(tsa->dim->type->isintegral());
62 const llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger());
63
64 tsa->llvmType = arrty;
65 return arrty;
66 }
67
68 //////////////////////////////////////////////////////////////////////////////////////////
69
70 void DtoNullArray(llvm::Value* v)
71 {
72 assert(gIR);
73
74 llvm::Value* len = DtoGEPi(v,0,0,"tmp",gIR->scopebb());
75 llvm::Value* zerolen = llvm::ConstantInt::get(len->getType()->getContainedType(0), 0, false);
76 new llvm::StoreInst(zerolen, len, gIR->scopebb());
77
78 llvm::Value* ptr = DtoGEPi(v,0,1,"tmp",gIR->scopebb());
79 const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(ptr->getType()->getContainedType(0));
80 llvm::Value* nullptr = llvm::ConstantPointerNull::get(pty);
81 new llvm::StoreInst(nullptr, ptr, gIR->scopebb());
82 }
83
84 //////////////////////////////////////////////////////////////////////////////////////////
85
86 void DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
87 {
88 assert(gIR);
89 if (dst->getType() == src->getType())
90 {
91 llvm::Value* ptr = DtoGEPi(src,0,0,"tmp",gIR->scopebb());
92 llvm::Value* val = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
93 ptr = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
94 new llvm::StoreInst(val, ptr, gIR->scopebb());
95
96 ptr = DtoGEPi(src,0,1,"tmp",gIR->scopebb());
97 val = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
98 ptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
99 new llvm::StoreInst(val, ptr, gIR->scopebb());
100 }
101 else
102 {
103 Logger::cout() << "array assignment type dont match: " << *dst->getType() << '\n' << *src->getType() << '\n';
104 if (!llvm::isa<llvm::ArrayType>(src->getType()->getContainedType(0)))
105 {
106 Logger::cout() << "invalid: " << *src << '\n';
107 assert(0);
108 }
109 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(src->getType()->getContainedType(0));
110 llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType());
111
112 llvm::Value* dstlen = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
113 llvm::Value* srclen = DtoConstSize_t(arrty->getNumElements());
114 new llvm::StoreInst(srclen, dstlen, gIR->scopebb());
115
116 llvm::Value* dstptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
117 llvm::Value* srcptr = new llvm::BitCastInst(src,dstty,"tmp",gIR->scopebb());
118 new llvm::StoreInst(srcptr, dstptr, gIR->scopebb());
119 }
120 }
121
122 //////////////////////////////////////////////////////////////////////////////////////////
123
124 void DtoArrayInit(llvm::Value* l, llvm::Value* r)
125 {
126 const llvm::PointerType* ptrty = llvm::cast<llvm::PointerType>(l->getType());
127 const llvm::Type* t = ptrty->getContainedType(0);
128 const llvm::ArrayType* arrty = llvm::dyn_cast<llvm::ArrayType>(t);
129 if (arrty)
130 {
131 llvm::Value* ptr = DtoGEPi(l,0,0,"tmp",gIR->scopebb());
132 llvm::Value* dim = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
133 DtoArrayInit(ptr, dim, r);
134 }
135 else if (llvm::isa<llvm::StructType>(t))
136 {
137 llvm::Value* dim = DtoLoad(DtoGEPi(l, 0,0, "tmp"));
138 llvm::Value* ptr = DtoLoad(DtoGEPi(l, 0,1, "tmp"));
139 DtoArrayInit(ptr, dim, r);
140 }
141 else
142 assert(0);
143 }
144
145 //////////////////////////////////////////////////////////////////////////////////////////
146
147 typedef const llvm::Type* constLLVMTypeP;
148
149 static size_t checkRectArrayInit(const llvm::Type* pt, constLLVMTypeP& finalty)
150 {
151 if (llvm::isa<llvm::ArrayType>(pt)) {
152 size_t n = checkRectArrayInit(pt->getContainedType(0), finalty);
153 size_t ne = llvm::cast<llvm::ArrayType>(pt)->getNumElements();
154 if (n) return n * ne;
155 return ne;
156 }
157 finalty = pt;
158 return 0;
159 }
160
161 void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
162 {
163 Logger::println("HELLO");
164 Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n';
165 const llvm::Type* pt = ptr->getType()->getContainedType(0);
166 const llvm::Type* t = val->getType();
167 const llvm::Type* finalTy;
168 if (size_t arrsz = checkRectArrayInit(pt, finalTy)) {
169 assert(finalTy == t);
170 llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(dim);
171 assert(c);
172 dim = llvm::ConstantExpr::getMul(c, DtoConstSize_t(arrsz));
173 ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(finalTy), "tmp");
174 }
175 else if (llvm::isa<llvm::StructType>(t)) {
176 assert(0);
177 }
178 else {
179 assert(t == pt);
180 }
181
182 std::vector<llvm::Value*> args;
183 args.push_back(ptr);
184 args.push_back(dim);
185 args.push_back(val);
186
187 const char* funcname = NULL;
188
189 if (llvm::isa<llvm::PointerType>(t)) {
190 funcname = "_d_array_init_pointer";
191
192 const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
193 if (args[0]->getType() != dstty)
194 args[0] = new llvm::BitCastInst(args[0],dstty,"tmp",gIR->scopebb());
195
196 const llvm::Type* valty = llvm::PointerType::get(llvm::Type::Int8Ty);
197 if (args[2]->getType() != valty)
198 args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb());
199 }
200 else if (t == llvm::Type::Int1Ty) {
201 funcname = "_d_array_init_i1";
202 }
203 else if (t == llvm::Type::Int8Ty) {
204 funcname = "_d_array_init_i8";
205 }
206 else if (t == llvm::Type::Int16Ty) {
207 funcname = "_d_array_init_i16";
208 }
209 else if (t == llvm::Type::Int32Ty) {
210 funcname = "_d_array_init_i32";
211 }
212 else if (t == llvm::Type::Int64Ty) {
213 funcname = "_d_array_init_i64";
214 }
215 else if (t == llvm::Type::FloatTy) {
216 funcname = "_d_array_init_float";
217 }
218 else if (t == llvm::Type::DoubleTy) {
219 funcname = "_d_array_init_double";
220 }
221 else {
222 Logger::cout() << *ptr->getType() << " = " << *val->getType() << '\n';
223 assert(0);
224 }
225
226 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname);
227 assert(fn);
228 Logger::cout() << "calling array init function: " << *fn <<'\n';
229 llvm::CallInst* call = new llvm::CallInst(fn, args.begin(), args.end(), "", gIR->scopebb());
230 call->setCallingConv(llvm::CallingConv::C);
231 }
232
233 //////////////////////////////////////////////////////////////////////////////////////////
234
235 void DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr)
236 {
237 Logger::cout() << "DtoSetArray(" << *arr << ", " << *dim << ", " << *ptr << ")\n";
238 const llvm::StructType* st = llvm::cast<llvm::StructType>(arr->getType()->getContainedType(0));
239 //const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(r->getType());
240
241 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
242 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
243
244 llvm::Value* arrdim = DtoGEP(arr,zero,zero,"tmp",gIR->scopebb());
245 new llvm::StoreInst(dim, arrdim, gIR->scopebb());
246
247 llvm::Value* arrptr = DtoGEP(arr,zero,one,"tmp",gIR->scopebb());
248 new llvm::StoreInst(ptr, arrptr, gIR->scopebb());
249 }
250
251 //////////////////////////////////////////////////////////////////////////////////////////
252 llvm::Constant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
253 {
254 Logger::println("arr init begin");
255 Type* arrinittype = DtoDType(arrinit->type);
256
257 Type* t;
258 integer_t tdim;
259 if (arrinittype->ty == Tsarray) {
260 TypeSArray* tsa = (TypeSArray*)arrinittype;
261 tdim = tsa->dim->toInteger();
262 t = tsa;
263 }
264 else if (arrinittype->ty == Tarray) {
265 t = arrinittype;
266 tdim = arrinit->dim;
267 }
268 else
269 assert(0);
270
271 std::vector<llvm::Constant*> inits(tdim, 0);
272
273 const llvm::Type* elemty = DtoType(arrinittype->next);
274
275 assert(arrinit->index.dim == arrinit->value.dim);
276 for (int i=0,j=0; i < tdim; ++i)
277 {
278 Initializer* init = 0;
279 Expression* idx = (Expression*)arrinit->index.data[j];
280
281 if (idx)
282 {
283 integer_t k = idx->toInteger();
284 if (i == k)
285 {
286 init = (Initializer*)arrinit->value.data[j];
287 assert(init);
288 ++j;
289 }
290 }
291 else
292 {
293 init = (Initializer*)arrinit->value.data[j];
294 ++j;
295 }
296
297 llvm::Constant* v = 0;
298
299 if (!init)
300 {
301 v = t->next->defaultInit()->toConstElem(gIR);
302 }
303 else if (ExpInitializer* ex = init->isExpInitializer())
304 {
305 v = ex->exp->toConstElem(gIR);
306 }
307 else if (StructInitializer* si = init->isStructInitializer())
308 {
309 v = DtoConstStructInitializer(si);
310 }
311 else if (ArrayInitializer* ai = init->isArrayInitializer())
312 {
313 v = DtoConstArrayInitializer(ai);
314 }
315 else if (init->isVoidInitializer())
316 {
317 v = llvm::UndefValue::get(elemty);
318 }
319 else
320 assert(v);
321
322 inits[i] = v;
323 }
324
325 const llvm::ArrayType* arrty = llvm::ArrayType::get(elemty,tdim);
326 llvm::Constant* constarr = llvm::ConstantArray::get(arrty, inits);
327
328 if (arrinittype->ty == Tsarray)
329 return constarr;
330 else
331 assert(arrinittype->ty == Tarray);
332
333 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrty,true,llvm::GlobalValue::InternalLinkage,constarr,"constarray",gIR->module);
334 llvm::Constant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
335 llvm::Constant* gep = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
336 return DtoConstSlice(DtoConstSize_t(tdim),gep);
337 }
338
339 //////////////////////////////////////////////////////////////////////////////////////////
340 static llvm::Value* get_slice_ptr(DSliceValue* e, llvm::Value*& sz)
341 {
342 const llvm::Type* t = e->ptr->getType()->getContainedType(0);
343 llvm::Value* ret = 0;
344 if (e->len != 0) {
345 // this means it's a real slice
346 ret = e->ptr;
347
348 size_t elembsz = gTargetData->getTypeSize(ret->getType());
349 llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
350
351 if (llvm::isa<llvm::ConstantInt>(e->len)) {
352 sz = llvm::ConstantExpr::getMul(elemsz, llvm::cast<llvm::Constant>(e->len));
353 }
354 else {
355 sz = llvm::BinaryOperator::createMul(elemsz,e->len,"tmp",gIR->scopebb());
356 }
357 }
358 else if (llvm::isa<llvm::ArrayType>(t)) {
359 ret = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb());
360
361 size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0));
362 llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
363
364 size_t numelements = llvm::cast<llvm::ArrayType>(t)->getNumElements();
365 llvm::ConstantInt* nelems = llvm::ConstantInt::get(DtoSize_t(), numelements, false);
366
367 sz = llvm::ConstantExpr::getMul(elemsz, nelems);
368 }
369 else if (llvm::isa<llvm::StructType>(t)) {
370 ret = DtoGEPi(e->ptr, 0, 1, "tmp", gIR->scopebb());
371 ret = new llvm::LoadInst(ret, "tmp", gIR->scopebb());
372
373 size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0));
374 llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
375
376 llvm::Value* len = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb());
377 len = new llvm::LoadInst(len, "tmp", gIR->scopebb());
378 sz = llvm::BinaryOperator::createMul(len,elemsz,"tmp",gIR->scopebb());
379 }
380 else {
381 assert(0);
382 }
383 return ret;
384 }
385
386 void DtoArrayCopy(DSliceValue* dst, DSliceValue* src)
387 {
388 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
389
390 llvm::Value* sz1;
391 llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb());
392
393 llvm::Value* sz2;
394 llvm::Value* srcarr = new llvm::BitCastInst(get_slice_ptr(src,sz2),arrty,"tmp",gIR->scopebb());
395
396 llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
397 std::vector<llvm::Value*> llargs;
398 llargs.resize(4);
399 llargs[0] = dstarr;
400 llargs[1] = srcarr;
401 llargs[2] = sz1;
402 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
403
404 new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
405 }
406
407 //////////////////////////////////////////////////////////////////////////////////////////
408 void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src)
409 {
410 assert(dst->getType() == src->getType());
411 size_t arrsz = gTargetData->getTypeSize(dst->getType()->getContainedType(0));
412 llvm::Value* n = llvm::ConstantInt::get(DtoSize_t(), arrsz, false);
413
414 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
415 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
416 llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb());
417
418 llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
419 std::vector<llvm::Value*> llargs;
420 llargs.resize(4);
421 llargs[0] = dstarr;
422 llargs[1] = srcarr;
423 llargs[2] = n;
424 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
425
426 new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
427 }
428
429 //////////////////////////////////////////////////////////////////////////////////////////
430 llvm::Constant* DtoConstSlice(llvm::Constant* dim, llvm::Constant* ptr)
431 {
432 std::vector<const llvm::Type*> types;
433 types.push_back(dim->getType());
434 types.push_back(ptr->getType());
435 const llvm::StructType* type = llvm::StructType::get(types);
436 std::vector<llvm::Constant*> values;
437 values.push_back(dim);
438 values.push_back(ptr);
439 return llvm::ConstantStruct::get(type,values);
440 }
441
442 //////////////////////////////////////////////////////////////////////////////////////////
443 llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit)
444 {
445 const llvm::Type* ty = DtoType(dty);
446 assert(ty != llvm::Type::VoidTy);
447 size_t sz = gTargetData->getTypeSize(ty);
448 llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false);
449 llvm::Value* bytesize = (sz == 1) ? dim : llvm::BinaryOperator::createMul(n,dim,"tmp",gIR->scopebb());
450
451 llvm::Value* nullptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(ty));
452
453 llvm::Value* newptr = DtoRealloc(nullptr, bytesize);
454
455 if (doinit) {
456 DValue* e = dty->defaultInit()->toElem(gIR);
457 DtoArrayInit(newptr,dim,e->getRVal());
458 }
459
460 llvm::Value* lenptr = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
461 new llvm::StoreInst(dim,lenptr,gIR->scopebb());
462 llvm::Value* ptrptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
463 new llvm::StoreInst(newptr,ptrptr,gIR->scopebb());
464
465 return newptr;
466 }
467
468 //////////////////////////////////////////////////////////////////////////////////////////
469 llvm::Value* DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz)
470 {
471 llvm::Value* ptr = DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb());
472 llvm::Value* ptrld = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
473
474 size_t isz = gTargetData->getTypeSize(ptrld->getType()->getContainedType(0));
475 llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), isz, false);
476 llvm::Value* bytesz = (isz == 1) ? sz : llvm::BinaryOperator::createMul(n,sz,"tmp",gIR->scopebb());
477
478 llvm::Value* newptr = DtoRealloc(ptrld, bytesz);
479 new llvm::StoreInst(newptr,ptr,gIR->scopebb());
480
481 llvm::Value* len = DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb());
482 new llvm::StoreInst(sz,len,gIR->scopebb());
483
484 return newptr;
485 }
486
487 //////////////////////////////////////////////////////////////////////////////////////////
488 void DtoCatAssignElement(llvm::Value* arr, Expression* exp)
489 {
490 llvm::Value* ptr = DtoGEPi(arr, 0, 0, "tmp");
491 llvm::Value* idx = DtoLoad(ptr);
492 llvm::Value* one = llvm::ConstantInt::get(idx->getType(),1,false);
493 llvm::Value* len = llvm::BinaryOperator::createAdd(idx, one, "tmp", gIR->scopebb());
494 DtoResizeDynArray(arr,len);
495
496 ptr = DtoLoad(DtoGEPi(arr, 0, 1, "tmp"));
497 ptr = new llvm::GetElementPtrInst(ptr, idx, "tmp", gIR->scopebb());
498
499 DValue* dptr = new DVarValue(exp->type, ptr, true);
500
501 gIR->exps.push_back(IRExp(0,exp,dptr));
502 DValue* e = exp->toElem(gIR);
503 gIR->exps.pop_back();
504
505 if (!e->inPlace())
506 DtoAssign(dptr, e);
507 }
508
509 //////////////////////////////////////////////////////////////////////////////////////////
510 void DtoCatAssignArray(llvm::Value* arr, Expression* exp)
511 {
512 DValue* e = exp->toElem(gIR);
513
514 llvm::Value *len1, *len2, *src1, *src2, *res;
515
516 DValue* darr = new DVarValue(exp->type, arr, true);
517
518 len1 = DtoArrayLen(darr);
519 len2 = DtoArrayLen(e);
520 res = gIR->ir->CreateAdd(len1,len2,"tmp");
521
522 llvm::Value* mem = DtoResizeDynArray(arr,res);
523
524 src1 = DtoArrayPtr(darr);
525 src2 = DtoArrayPtr(e);
526
527 mem = gIR->ir->CreateGEP(mem,len1,"tmp");
528 DtoMemCpy(mem,src2,len2);
529 }
530
531 //////////////////////////////////////////////////////////////////////////////////////////
532 void DtoCatArrays(llvm::Value* arr, Expression* exp1, Expression* exp2)
533 {
534 Type* t1 = DtoDType(exp1->type);
535 Type* t2 = DtoDType(exp2->type);
536
537 assert(t1->ty == Tarray);
538 assert(t1->ty == t2->ty);
539
540 DValue* e1 = exp1->toElem(gIR);
541 llvm::Value* a = e1->getRVal();
542
543 DValue* e2 = exp2->toElem(gIR);
544 llvm::Value* b = e2->getRVal();
545
546 llvm::Value *len1, *len2, *src1, *src2, *res;
547 len1 = gIR->ir->CreateLoad(DtoGEPi(a,0,0,"tmp"),"tmp");
548 len2 = gIR->ir->CreateLoad(DtoGEPi(b,0,0,"tmp"),"tmp");
549 res = gIR->ir->CreateAdd(len1,len2,"tmp");
550
551 llvm::Value* mem = DtoNewDynArray(arr, res, DtoDType(t1->next), false);
552
553 src1 = gIR->ir->CreateLoad(DtoGEPi(a,0,1,"tmp"),"tmp");
554 src2 = gIR->ir->CreateLoad(DtoGEPi(b,0,1,"tmp"),"tmp");
555
556 DtoMemCpy(mem,src1,len1);
557 mem = gIR->ir->CreateGEP(mem,len1,"tmp");
558 DtoMemCpy(mem,src2,len2);
559 }
560
561 //////////////////////////////////////////////////////////////////////////////////////////
562 llvm::Value* DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r)
563 {
564 const char* fname;
565 if (op == TOKequal)
566 fname = "_d_static_array_eq";
567 else if (op == TOKnotequal)
568 fname = "_d_static_array_neq";
569 else
570 assert(0);
571 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
572 assert(fn);
573
574 assert(l->getType() == r->getType());
575 assert(llvm::isa<llvm::PointerType>(l->getType()));
576 const llvm::Type* arrty = l->getType()->getContainedType(0);
577 assert(llvm::isa<llvm::ArrayType>(arrty));
578
579 llvm::Value* ll = new llvm::BitCastInst(l, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
580 llvm::Value* rr = new llvm::BitCastInst(r, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
581 llvm::Value* n = llvm::ConstantInt::get(DtoSize_t(),gTargetData->getTypeSize(arrty),false);
582
583 std::vector<llvm::Value*> args;
584 args.push_back(ll);
585 args.push_back(rr);
586 args.push_back(n);
587 return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
588 }
589
590 //////////////////////////////////////////////////////////////////////////////////////////
591
592 llvm::Value* DtoDynArrayCompare(TOK op, llvm::Value* l, llvm::Value* r)
593 {
594 const char* fname;
595 if (op == TOKequal)
596 fname = "_d_dyn_array_eq";
597 else if (op == TOKnotequal)
598 fname = "_d_dyn_array_neq";
599 else
600 assert(0);
601 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
602 assert(fn);
603
604 Logger::cout() << "lhsType:" << *l->getType() << "\nrhsType:" << *r->getType() << '\n';
605 assert(l->getType() == r->getType());
606 assert(llvm::isa<llvm::PointerType>(l->getType()));
607 const llvm::Type* arrty = l->getType()->getContainedType(0);
608 assert(llvm::isa<llvm::StructType>(arrty));
609 const llvm::StructType* structType = llvm::cast<llvm::StructType>(arrty);
610 const llvm::Type* elemType = structType->getElementType(1)->getContainedType(0);
611
612 std::vector<const llvm::Type*> arrTypes;
613 arrTypes.push_back(DtoSize_t());
614 arrTypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
615 const llvm::StructType* arrType = llvm::StructType::get(arrTypes);
616
617 llvm::Value* llmem = l;
618 llvm::Value* rrmem = r;
619
620 if (arrty != arrType) {
621 llmem= new llvm::AllocaInst(arrType,"tmparr",gIR->topallocapoint());
622
623 llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
624 ll = DtoArrayCastLength(ll, elemType, llvm::Type::Int8Ty);
625 llvm::Value* lllen = DtoGEPi(llmem, 0,0, "tmp");
626 gIR->ir->CreateStore(ll,lllen);
627
628 ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
629 ll = new llvm::BitCastInst(ll, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
630 llvm::Value* llptr = DtoGEPi(llmem, 0,1, "tmp");
631 gIR->ir->CreateStore(ll,llptr);
632
633 rrmem = new llvm::AllocaInst(arrType,"tmparr",gIR->topallocapoint());
634
635 llvm::Value* rr = gIR->ir->CreateLoad(DtoGEPi(r, 0,0, "tmp"),"tmp");
636 rr = DtoArrayCastLength(rr, elemType, llvm::Type::Int8Ty);
637 llvm::Value* rrlen = DtoGEPi(rrmem, 0,0, "tmp");
638 gIR->ir->CreateStore(rr,rrlen);
639
640 rr = gIR->ir->CreateLoad(DtoGEPi(r, 0,1, "tmp"),"tmp");
641 rr = new llvm::BitCastInst(rr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
642 llvm::Value* rrptr = DtoGEPi(rrmem, 0,1, "tmp");
643 gIR->ir->CreateStore(rr,rrptr);
644 }
645
646 std::vector<llvm::Value*> args;
647 args.push_back(llmem);
648 args.push_back(rrmem);
649 return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
650 }
651
652 //////////////////////////////////////////////////////////////////////////////////////////
653 llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty)
654 {
655 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_cast_len");
656 assert(fn);
657 std::vector<llvm::Value*> args;
658 args.push_back(len);
659 args.push_back(llvm::ConstantInt::get(DtoSize_t(), gTargetData->getTypeSize(elemty), false));
660 args.push_back(llvm::ConstantInt::get(DtoSize_t(), gTargetData->getTypeSize(newelemty), false));
661 return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
662 }
663
664 //////////////////////////////////////////////////////////////////////////////////////////
665 llvm::Value* DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r)
666 {
667 llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
668
669 if (r == NULL) {
670 llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
671 llvm::Value* rl = DtoConstSize_t(0);
672 llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
673
674 llvm::Value* lp = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
675 const llvm::PointerType* pty = llvm::cast<llvm::PointerType>(lp->getType());
676 llvm::Value* rp = llvm::ConstantPointerNull::get(pty);
677 llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
678
679 llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
680 return b;
681 }
682 else {
683 assert(l->getType() == r->getType());
684
685 llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp");
686 llvm::Value* rl = gIR->ir->CreateLoad(DtoGEPi(r, 0,0, "tmp"),"tmp");
687 llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
688
689 llvm::Value* lp = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp");
690 llvm::Value* rp = gIR->ir->CreateLoad(DtoGEPi(r, 0,1, "tmp"),"tmp");
691 llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
692
693 llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
694 return b;
695 }
696 }
697
698 //////////////////////////////////////////////////////////////////////////////////////////
699 llvm::Constant* DtoConstStaticArray(const llvm::Type* t, llvm::Constant* c)
700 {
701 assert(llvm::isa<llvm::ArrayType>(t));
702 const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(t);
703
704 if (llvm::isa<llvm::ArrayType>(at->getElementType()))
705 {
706 c = DtoConstStaticArray(at->getElementType(), c);
707 }
708 else {
709 assert(at->getElementType() == c->getType());
710 }
711 std::vector<llvm::Constant*> initvals;
712 initvals.resize(at->getNumElements(), c);
713 return llvm::ConstantArray::get(at, initvals);
714 }
715
716 //////////////////////////////////////////////////////////////////////////////////////////
717 llvm::Value* DtoArrayLen(DValue* v)
718 {
719 Type* t = DtoDType(v->getType());
720 if (t->ty == Tarray) {
721 if (DSliceValue* s = v->isSlice()) {
722 if (s->len) return s->len;
723 DValue* next = new DVarValue(t,s->ptr,true);
724 return DtoArrayLen(next);
725 }
726 return DtoLoad(DtoGEPi(v->getRVal(), 0,0, "tmp"));
727 }
728 else if (t->ty == Tsarray) {
729 const llvm::ArrayType* t = llvm::cast<llvm::ArrayType>(v->getLVal()->getType());
730 return DtoConstSize_t(t->getNumElements());
731 }
732 assert(0);
733 return 0;
734 }
735
736 //////////////////////////////////////////////////////////////////////////////////////////
737 llvm::Value* DtoArrayPtr(DValue* v)
738 {
739 Type* t = DtoDType(v->getType());
740 if (t->ty == Tarray) {
741 if (DSliceValue* s = v->isSlice()) {
742 if (s->len) return s->ptr;
743 DValue* next = new DVarValue(t,s->ptr,true);
744 return DtoArrayPtr(next);
745 }
746 return DtoLoad(DtoGEPi(v->getRVal(), 0,1, "tmp"));
747 }
748 else if (t->ty == Tsarray) {
749 return DtoGEPi(v->getRVal(), 0,0, "tmp");
750 }
751 assert(0);
752 return 0;
753 }
754