Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

root/gen/arrays.cpp

Revision 1650:40bd4a0d4870, 33.6 kB (checked in by Tomas Lindquist Olsen, 2 years ago)

Update to work with LLVM 2.7.

Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).

Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.

Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.

Line 
1 #include "gen/llvm.h"
2
3 #include "mtype.h"
4 #include "module.h"
5 #include "dsymbol.h"
6 #include "aggregate.h"
7 #include "declaration.h"
8 #include "init.h"
9
10 #include "gen/irstate.h"
11 #include "gen/tollvm.h"
12 #include "gen/llvmhelpers.h"
13 #include "gen/arrays.h"
14 #include "gen/runtime.h"
15 #include "gen/logger.h"
16 #include "gen/dvalue.h"
17 #include "ir/irmodule.h"
18
19 #include "gen/cl_options.h"
20
21 //////////////////////////////////////////////////////////////////////////////////////////
22
23 const LLStructType* DtoArrayType(Type* arrayTy)
24 {
25     assert(arrayTy->nextOf());
26     const LLType* elemty = DtoType(arrayTy->nextOf());
27     if (elemty == LLType::getVoidTy(gIR->context()))
28         elemty = LLType::getInt8Ty(gIR->context());
29     return LLStructType::get(gIR->context(), DtoSize_t(), getPtrToType(elemty), NULL);
30 }
31
32 const LLStructType* DtoArrayType(const LLType* t)
33 {
34     return LLStructType::get(gIR->context(), DtoSize_t(), getPtrToType(t), NULL);
35 }
36
37 //////////////////////////////////////////////////////////////////////////////////////////
38
39 const LLArrayType* DtoStaticArrayType(Type* t)
40 {
41     t = t->toBasetype();
42     assert(t->ty == Tsarray);
43     TypeSArray* tsa = (TypeSArray*)t;
44     Type* tnext = tsa->nextOf();
45
46     const LLType* elemty = DtoType(tnext);
47     if (elemty == LLType::getVoidTy(gIR->context()))
48         elemty = LLType::getInt8Ty(gIR->context());
49
50     return LLArrayType::get(elemty, tsa->dim->toUInteger());
51 }
52
53 //////////////////////////////////////////////////////////////////////////////////////////
54
55 void DtoSetArrayToNull(LLValue* v)
56 {
57     Logger::println("DtoSetArrayToNull");
58     LOG_SCOPE;
59
60     assert(isaPointer(v));
61     const LLType* t = v->getType()->getContainedType(0);
62
63     DtoStore(LLConstant::getNullValue(t), v);
64 }
65
66 //////////////////////////////////////////////////////////////////////////////////////////
67
68 void DtoArrayInit(Loc& loc, DValue* array, DValue* value)
69 {
70     Logger::println("DtoArrayInit");
71     LOG_SCOPE;
72
73     LLValue* dim = DtoArrayLen(array);
74     LLValue* ptr = DtoArrayPtr(array);
75     LLValue* val;
76
77     // give slices and complex values storage (and thus an address to pass)
78     if (value->isSlice())
79     {
80         val = DtoAlloca(value->getType(), ".tmpparam");
81         DVarValue lval(value->getType(), val);
82         DtoAssign(loc, &lval, value);
83     }
84     else
85     {
86         val = value->getRVal();
87     }
88     assert(val);
89
90     // prepare runtime call
91     LLSmallVector<LLValue*, 4> args;
92     args.push_back(ptr);
93     args.push_back(dim);
94     args.push_back(val);
95
96     // determine the right runtime function to call
97     const char* funcname = NULL;
98     Type* arrayelemty = array->getType()->nextOf()->toBasetype();
99     Type* valuety = value->getType()->toBasetype();
100
101     // lets first optimize all zero initializations down to a memset.
102     // this simplifies codegen later on as llvm null's have no address!
103     if (isaConstant(val) && isaConstant(val)->isNullValue())
104     {
105         size_t X = getTypePaddedSize(val->getType());
106         LLValue* nbytes = gIR->ir->CreateMul(dim, DtoConstSize_t(X), ".nbytes");
107         DtoMemSetZero(ptr, nbytes);
108         return;
109     }
110
111     // if not a zero initializer, call the appropriate runtime function!
112     switch (arrayelemty->ty)
113     {
114     case Tbool:
115         val = gIR->ir->CreateZExt(val, LLType::getInt8Ty(gIR->context()), ".bool");
116         // fall through
117
118     case Tvoid:
119     case Tchar:
120     case Tint8:
121     case Tuns8:
122         Logger::println("Using memset for array init");
123         DtoMemSet(ptr, val, dim);
124         return;
125
126     case Twchar:
127     case Tint16:
128     case Tuns16:
129         funcname = "_d_array_init_i16";
130         break;
131
132     case Tdchar:
133     case Tint32:
134     case Tuns32:
135         funcname = "_d_array_init_i32";
136         break;
137
138     case Tint64:
139     case Tuns64:
140         funcname = "_d_array_init_i64";
141         break;
142
143     case Tfloat32:
144     case Timaginary32:
145         funcname = "_d_array_init_float";
146         break;
147
148     case Tfloat64:
149     case Timaginary64:
150         funcname = "_d_array_init_double";
151         break;
152
153     case Tfloat80:
154     case Timaginary80:
155         funcname = "_d_array_init_real";
156         break;
157
158     case Tcomplex32:
159         funcname = "_d_array_init_cfloat";
160         break;
161
162     case Tcomplex64:
163         funcname = "_d_array_init_cdouble";
164         break;
165
166     case Tcomplex80:
167         funcname = "_d_array_init_creal";
168         break;
169
170     case Tpointer:
171     case Tclass:
172         funcname = "_d_array_init_pointer";
173         args[0] = DtoBitCast(args[0], getPtrToType(getVoidPtrType()));
174         args[2] = DtoBitCast(args[2], getVoidPtrType());
175         break;
176
177     // this currently acts as a kind of fallback for all the bastards...
178     // FIXME: this is probably too slow.
179     case Tstruct:
180     case Tdelegate:
181     case Tarray:
182     case Tsarray:
183         funcname = "_d_array_init_mem";
184         assert(arrayelemty == valuety && "ArrayInit doesn't work on elem-initialized static arrays");
185         args[0] = DtoBitCast(args[0], getVoidPtrType());
186         args[2] = DtoBitCast(args[2], getVoidPtrType());
187         args.push_back(DtoConstSize_t(getTypePaddedSize(DtoTypeNotVoid(arrayelemty))));
188         break;
189
190     default:
191         error("unhandled array init: %s = %s", array->getType()->toChars(), value->getType()->toChars());
192         assert(0 && "unhandled array init");
193     }
194
195     if (Logger::enabled())
196     {
197         Logger::cout() << "ptr = " << *args[0] << std::endl;
198         Logger::cout() << "dim = " << *args[1] << std::endl;
199         Logger::cout() << "val = " << *args[2] << std::endl;
200     }
201
202     LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname);
203     assert(fn);
204     if (Logger::enabled())
205         Logger::cout() << "calling array init function: " << *fn <<'\n';
206     LLCallSite call = gIR->CreateCallOrInvoke(fn, args.begin(), args.end());
207     call.setCallingConv(llvm::CallingConv::C);
208 }
209
210 //////////////////////////////////////////////////////////////////////////////////////////
211
212 void DtoSetArray(LLValue* arr, LLValue* dim, LLValue* ptr)
213 {
214     Logger::println("SetArray");
215     assert(isaStruct(arr->getType()->getContainedType(0)));
216     DtoStore(dim, DtoGEPi(arr,0,0));
217     DtoStore(ptr, DtoGEPi(arr,0,1));
218 }
219
220 //////////////////////////////////////////////////////////////////////////////////////////
221
222 LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
223 {
224     Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars());
225     LOG_SCOPE;
226
227     assert(arrinit->value.dim == arrinit->index.dim);
228
229     // get base array type
230     Type* arrty = arrinit->type->toBasetype();
231     size_t arrlen = arrinit->dim;
232
233     // for statis arrays, dmd does not include any trailing default
234     // initialized elements in the value/index lists
235     if (arrty->ty == Tsarray)
236     {
237         TypeSArray* tsa = (TypeSArray*)arrty;
238         arrlen = (size_t)tsa->dim->toInteger();
239     }
240
241     // make sure the number of initializers is sane
242     if (arrinit->index.dim > arrlen || arrinit->dim > arrlen)
243     {
244         error(arrinit->loc, "too many initializers, %u, for array[%zu]", arrinit->index.dim, arrlen);
245         fatal();
246     }
247
248     // get elem type
249     Type* elemty = arrty->nextOf();
250     const LLType* llelemty = DtoTypeNotVoid(elemty);
251
252     // true if array elements differ in type, can happen with array of unions
253     bool mismatch = false;
254
255     // allocate room for initializers
256     std::vector<LLConstant*> initvals(arrlen, NULL);
257
258     // go through each initializer, they're not sorted by index by the frontend
259     size_t j = 0;
260     for (size_t i = 0; i < arrinit->index.dim; i++)
261     {
262         // get index
263         Expression* idx = (Expression*)arrinit->index.data[i];
264
265         // idx can be null, then it's just the next element
266         if (idx)
267             j = idx->toInteger();
268         assert(j < arrlen);
269
270         // get value
271         Initializer* val = (Initializer*)arrinit->value.data[i];
272         assert(val);
273
274         // error check from dmd
275         if (initvals[j] != NULL)
276         {
277             error(arrinit->loc, "duplicate initialization for index %zu", j);
278         }
279
280         LLConstant* c = DtoConstInitializer(val->loc, elemty, val);
281         assert(c);
282         if (c->getType() != llelemty)
283             mismatch = true;
284
285         initvals[j] = c;
286         j++;
287     }
288
289     // die now if there was errors
290     if (global.errors)
291         fatal();
292
293     // fill out any null entries still left with default values
294
295     // element default initializer
296     LLConstant* defelem = DtoConstExpInit(arrinit->loc, elemty, elemty->defaultInit(arrinit->loc));
297     bool mismatch2 =  (defelem->getType() != llelemty);
298
299     for (size_t i = 0; i < arrlen; i++)
300     {
301         if (initvals[i] != NULL)
302             continue;
303
304         initvals[i] = defelem;
305
306         if (mismatch2)
307             mismatch = true;
308     }
309
310     LLConstant* constarr;
311     if (mismatch)
312         constarr = LLConstantStruct::get(gIR->context(), initvals, false); // FIXME should this pack?
313     else
314         constarr = LLConstantArray::get(LLArrayType::get(llelemty, arrlen), initvals);
315
316 //     std::cout << "constarr: " << *constarr << std::endl;
317
318     // if the type is a static array, we're done
319     if (arrty->ty == Tsarray)
320         return constarr;
321
322     // for dynamic array we need to make a global with the data, so we have a pointer for the dynamic array
323     // Important: don't make the gvar constant, since this const initializer might
324     // be used as an initializer for a static T[] - where modifying contents is allowed.
325     LLGlobalVariable* gvar = new LLGlobalVariable(*gIR->module, constarr->getType(), false, LLGlobalValue::InternalLinkage, constarr, ".constarray");
326     LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
327
328     LLConstant* gep = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
329     gep = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(llelemty));
330
331     return DtoConstSlice(DtoConstSize_t(arrlen),gep);
332 }
333
334 //////////////////////////////////////////////////////////////////////////////////////////
335 static LLValue* get_slice_ptr(DSliceValue* e, LLValue*& sz)
336 {
337     assert(e->len != 0);
338     const LLType* t = e->ptr->getType()->getContainedType(0);
339     sz = gIR->ir->CreateMul(DtoConstSize_t(getTypePaddedSize(t)), e->len, "tmp");
340     return DtoBitCast(e->ptr, getVoidPtrType());
341 }
342
343 void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
344 {
345     Logger::println("ArrayCopySlices");
346
347     LLValue *sz1,*sz2;
348     LLValue* dstarr = get_slice_ptr(dst,sz1);
349     LLValue* srcarr = get_slice_ptr(src,sz2);
350
351     if (global.params.useAssert || global.params.useArrayBounds)
352     {
353         LLValue* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_slice_copy");
354         gIR->CreateCallOrInvoke4(fn, dstarr, sz1, srcarr, sz2);
355     }
356     else
357     {
358         DtoMemCpy(dstarr, srcarr, sz1);
359     }
360 }
361
362 void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
363 {
364     Logger::println("ArrayCopyToSlice");
365
366     LLValue* sz1;
367     LLValue* dstarr = get_slice_ptr(dst,sz1);
368
369     LLValue* srcarr = DtoBitCast(DtoArrayPtr(src), getVoidPtrType());
370     const LLType* arrayelemty = DtoTypeNotVoid(src->getType()->nextOf()->toBasetype());
371     LLValue* sz2 = gIR->ir->CreateMul(DtoConstSize_t(getTypePaddedSize(arrayelemty)), DtoArrayLen(src), "tmp");
372
373     if (global.params.useAssert || global.params.useArrayBounds)
374     {
375         LLValue* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_slice_copy");
376         gIR->CreateCallOrInvoke4(fn, dstarr, sz1, srcarr, sz2);
377     }
378     else
379     {
380         DtoMemCpy(dstarr, srcarr, sz1);
381     }
382 }
383
384 //////////////////////////////////////////////////////////////////////////////////////////
385 void DtoStaticArrayCopy(LLValue* dst, LLValue* src)
386 {
387     Logger::println("StaticArrayCopy");
388
389     size_t n = getTypePaddedSize(dst->getType()->getContainedType(0));
390     DtoMemCpy(dst, src, DtoConstSize_t(n));
391 }
392
393 //////////////////////////////////////////////////////////////////////////////////////////
394 LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr)
395 {
396     LLConstant* values[2] = { dim, ptr };
397     return LLConstantStruct::get(gIR->context(), values, 2, false);
398 }
399
400 //////////////////////////////////////////////////////////////////////////////////////////
401 static bool isInitialized(Type* et) {
402     // Strip static array types from element type
403     Type* bt = et->toBasetype();
404     while (bt->ty == Tsarray) {
405         et = bt->nextOf();
406         bt = et->toBasetype();
407     }
408     // If it's a typedef with "= void" initializer then don't initialize.
409     if (et->ty == Ttypedef) {
410         Logger::println("Typedef: %s", et->toChars());
411         TypedefDeclaration* tdd = ((TypeTypedef*)et)->sym;
412         if (tdd && tdd->init && tdd->init->isVoidInitializer())
413             return false;
414     }
415     // Otherwise, it's always initialized.
416     return true;
417 }
418
419 //////////////////////////////////////////////////////////////////////////////////////////
420 DSliceValue* DtoNewDynArray(Loc& loc, Type* arrayType, DValue* dim, bool defaultInit)
421 {
422     Logger::println("DtoNewDynArray : %s", arrayType->toChars());
423     LOG_SCOPE;
424
425     // typeinfo arg
426     LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType);
427
428     // dim arg
429     assert(DtoType(dim->getType()) == DtoSize_t());
430     LLValue* arrayLen = dim->getRVal();
431
432     // get runtime function
433     Type* eltType = arrayType->toBasetype()->nextOf();
434     if (defaultInit && !isInitialized(eltType))
435         defaultInit = false;
436     bool zeroInit = eltType->isZeroInit();
437     const char* fnname = defaultInit ? (zeroInit ? "_d_newarrayT" : "_d_newarrayiT") : "_d_newarrayvT";
438     LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, fnname);
439
440     // call allocator
441     LLValue* newptr = gIR->CreateCallOrInvoke2(fn, arrayTypeInfo, arrayLen, ".gc_mem").getInstruction();
442
443     // cast to wanted type
444     const LLType* dstType = DtoType(arrayType)->getContainedType(1);
445     if (newptr->getType() != dstType)
446         newptr = DtoBitCast(newptr, dstType, ".gc_mem");
447
448     if (Logger::enabled())
449         Logger::cout() << "final ptr = " << *newptr << '\n';
450
451     return new DSliceValue(arrayType, arrayLen, newptr);
452 }
453
454 //////////////////////////////////////////////////////////////////////////////////////////
455 DSliceValue* DtoNewMulDimDynArray(Loc& loc, Type* arrayType, DValue** dims, size_t ndims, bool defaultInit)
456 {
457     Logger::println("DtoNewMulDimDynArray : %s", arrayType->toChars());
458     LOG_SCOPE;
459
460     // typeinfo arg
461     LLValue* arrayTypeInfo = DtoTypeInfoOf(arrayType);
462
463     // get value type
464     Type* vtype = arrayType->toBasetype();
465     for (size_t i=0; i<ndims; ++i)
466         vtype = vtype->nextOf();
467
468     // get runtime function
469     bool zeroInit = vtype->isZeroInit();
470     if (defaultInit && !isInitialized(vtype))
471         defaultInit = false;
472     const char* fnname = defaultInit ? (zeroInit ? "_d_newarraymT" : "_d_newarraymiT") : "_d_newarraymvT";
473     LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, fnname);
474
475     // build dims
476     LLValue* dimsArg = DtoArrayAlloca(Type::tsize_t, ndims, ".newdims");
477     LLValue* firstDim = NULL;
478     for (size_t i=0; i<ndims; ++i)
479     {
480         LLValue* dim = dims[i]->getRVal();
481         if (!firstDim) firstDim = dim;
482         DtoStore(dim, DtoGEPi1(dimsArg, i));
483     }
484
485     // call allocator
486     LLValue* newptr = gIR->CreateCallOrInvoke3(fn, arrayTypeInfo, DtoConstSize_t(ndims), dimsArg, ".gc_mem").getInstruction();
487
488     // cast to wanted type
489     const LLType* dstType = DtoType(arrayType)->getContainedType(1);
490     if (newptr->getType() != dstType)
491         newptr = DtoBitCast(newptr, dstType, ".gc_mem");
492
493     if (Logger::enabled())
494         Logger::cout() << "final ptr = " << *newptr << '\n';
495
496     assert(firstDim);
497     return new DSliceValue(arrayType, firstDim, newptr);
498 }
499
500 //////////////////////////////////////////////////////////////////////////////////////////
501 DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, DValue* newdim)
502 {
503     Logger::println("DtoResizeDynArray : %s", arrayType->toChars());
504     LOG_SCOPE;
505
506     assert(array);
507     assert(newdim);
508     assert(arrayType);
509     assert(arrayType->toBasetype()->ty == Tarray);
510
511     // decide on what runtime function to call based on whether the type is zero initialized
512     bool zeroInit = arrayType->toBasetype()->nextOf()->isZeroInit();
513
514     // call runtime
515     LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_arraysetlengthT" : "_d_arraysetlengthiT" );
516
517     LLSmallVector<LLValue*,4> args;
518     args.push_back(DtoTypeInfoOf(arrayType));
519     args.push_back(newdim->getRVal());
520     args.push_back(DtoArrayLen(array));
521
522     LLValue* arrPtr = DtoArrayPtr(array);
523     if (Logger::enabled())
524         Logger::cout() << "arrPtr = " << *arrPtr << '\n';
525     args.push_back(DtoBitCast(arrPtr, fn->getFunctionType()->getParamType(3), "tmp"));
526
527     LLValue* newptr = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".gc_mem").getInstruction();
528     if (newptr->getType() != arrPtr->getType())
529         newptr = DtoBitCast(newptr, arrPtr->getType(), ".gc_mem");
530
531     return new DSliceValue(arrayType, newdim->getRVal(), newptr);
532 }
533
534 //////////////////////////////////////////////////////////////////////////////////////////
535 void DtoCatAssignElement(Loc& loc, Type* arrayType, DValue* array, Expression* exp)
536 {
537     Logger::println("DtoCatAssignElement");
538     LOG_SCOPE;
539
540     assert(array);
541
542     LLValue *valueToAppend = makeLValue(loc, exp->toElem(gIR));
543
544     LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_arrayappendcT");
545     LLSmallVector<LLValue*,3> args;
546     args.push_back(DtoTypeInfoOf(arrayType));
547     args.push_back(DtoBitCast(array->getLVal(), getVoidPtrType()));
548     args.push_back(DtoBitCast(valueToAppend, getVoidPtrType()));
549
550     gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".appendedArray");
551 }
552
553 //////////////////////////////////////////////////////////////////////////////////////////
554 DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp)
555 {
556     Logger::println("DtoCatAssignArray");
557     LOG_SCOPE;
558
559     DValue* e = exp->toElem(gIR);
560
561     llvm::Value *len1, *len2, *src1, *src2, *res;
562
563     len1 = DtoArrayLen(arr);
564     len2 = DtoArrayLen(e);
565     res = gIR->ir->CreateAdd(len1,len2,"tmp");
566
567     DValue* newdim = new DImValue(Type::tsize_t, res);
568     DSliceValue* slice = DtoResizeDynArray(arr->getType(), arr, newdim);
569
570     src1 = slice->ptr;
571     src2 = DtoArrayPtr(e);
572
573     // advance ptr
574     src1 = gIR->ir->CreateGEP(src1,len1,"tmp");
575
576     // memcpy
577     LLValue* elemSize = DtoConstSize_t(getTypePaddedSize(src2->getType()->getContainedType(0)));
578     LLValue* bytelen = gIR->ir->CreateMul(len2, elemSize, "tmp");
579     DtoMemCpy(src1,src2,bytelen);
580
581     return slice;
582 }
583
584 //////////////////////////////////////////////////////////////////////////////////////////
585 DSliceValue* DtoCatArrays(Type* type, Expression* exp1, Expression* exp2)
586 {
587     Logger::println("DtoCatArrays");
588     LOG_SCOPE;
589
590     Type* t1 = exp1->type->toBasetype();
591     Type* t2 = exp2->type->toBasetype();
592
593     assert(t1->ty == Tarray || t1->ty == Tsarray);
594     assert(t2->ty == Tarray || t2->ty == Tsarray);
595
596     DValue* e1 = exp1->toElem(gIR);
597     DValue* e2 = exp2->toElem(gIR);
598
599     llvm::Value *len1, *len2, *src1, *src2, *res;
600
601     len1 = DtoArrayLen(e1);
602     len2 = DtoArrayLen(e2);
603     res = gIR->ir->CreateAdd(len1,len2,"tmp");
604
605     DValue* lenval = new DImValue(Type::tsize_t, res);
606     DSliceValue* slice = DtoNewDynArray(exp1->loc, type, lenval, false);
607     LLValue* mem = slice->ptr;
608
609     src1 = DtoArrayPtr(e1);
610     src2 = DtoArrayPtr(e2);
611
612     // first memcpy
613     LLValue* elemSize = DtoConstSize_t(getTypePaddedSize(src1->getType()->getContainedType(0)));
614     LLValue* bytelen = gIR->ir->CreateMul(len1, elemSize, "tmp");
615     DtoMemCpy(mem,src1,bytelen);
616
617     // second memcpy
618     mem = gIR->ir->CreateGEP(mem,len1,"tmp");
619     bytelen = gIR->ir->CreateMul(len2, elemSize, "tmp");
620     DtoMemCpy(mem,src2,bytelen);
621
622     return slice;
623 }
624
625 //////////////////////////////////////////////////////////////////////////////////////////
626 DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2)
627 {
628     Logger::println("DtoCatArrayElement");
629     LOG_SCOPE;
630
631     Type* t1 = exp1->type->toBasetype();
632     Type* t2 = exp2->type->toBasetype();
633
634     DValue* e1 = exp1->toElem(gIR);
635     DValue* e2 = exp2->toElem(gIR);
636
637     llvm::Value *len1, *src1, *res;
638
639     // handle prefix case, eg. int~int[]
640     if (t2->nextOf() && t1 == t2->nextOf()->toBasetype())
641     {
642         len1 = DtoArrayLen(e2);
643         res = gIR->ir->CreateAdd(len1,DtoConstSize_t(1),"tmp");
644
645         DValue* lenval = new DImValue(Type::tsize_t, res);
646         DSliceValue* slice = DtoNewDynArray(exp1->loc, type, lenval, false);
647         LLValue* mem = slice->ptr;
648
649         DVarValue* memval = new DVarValue(e1->getType(), mem);
650         DtoAssign(exp1->loc, memval, e1);
651
652         src1 = DtoArrayPtr(e2);
653
654         mem = gIR->ir->CreateGEP(mem,DtoConstSize_t(1),"tmp");
655
656         LLValue* elemSize = DtoConstSize_t(getTypePaddedSize(src1->getType()->getContainedType(0)));
657         LLValue* bytelen = gIR->ir->CreateMul(len1, elemSize, "tmp");
658         DtoMemCpy(mem,src1,bytelen);
659
660
661         return slice;
662     }
663     // handle suffix case, eg. int[]~int
664     else
665     {
666         len1 = DtoArrayLen(e1);
667         res = gIR->ir->CreateAdd(len1,DtoConstSize_t(1),"tmp");
668
669         DValue* lenval = new DImValue(Type::tsize_t, res);
670         DSliceValue* slice = DtoNewDynArray(exp1->loc, type, lenval, false);
671         LLValue* mem = slice->ptr;
672
673         src1 = DtoArrayPtr(e1);
674
675         LLValue* elemSize = DtoConstSize_t(getTypePaddedSize(src1->getType()->getContainedType(0)));
676         LLValue* bytelen = gIR->ir->CreateMul(len1, elemSize, "tmp");
677         DtoMemCpy(mem,src1,bytelen);
678
679         mem = gIR->ir->CreateGEP(mem,len1,"tmp");
680         DVarValue* memval = new DVarValue(e2->getType(), mem);
681         DtoAssign(exp1->loc, memval, e2);
682
683         return slice;
684     }
685 }
686
687 //////////////////////////////////////////////////////////////////////////////////////////
688 // helper for eq and cmp
689 static LLValue* DtoArrayEqCmp_impl(Loc& loc, const char* func, DValue* l, DValue* r, bool useti)
690 {
691     Logger::println("comparing arrays");
692     LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, func);
693     assert(fn);
694
695     // find common dynamic array type
696     Type* commonType = l->getType()->toBasetype()->nextOf()->arrayOf();
697
698     // cast static arrays to dynamic ones, this turns them into DSliceValues
699     Logger::println("casting to dynamic arrays");
700     l = DtoCastArray(loc, l, commonType);
701     r = DtoCastArray(loc, r, commonType);
702
703     LLValue* lmem;
704     LLValue* rmem;
705     LLSmallVector<LLValue*, 3> args;
706
707     // get values, reinterpret cast to void[]
708     lmem = DtoAggrPaint(l->getRVal(), DtoArrayType(LLType::getInt8Ty(gIR->context())));
709     args.push_back(lmem);
710
711     rmem = DtoAggrPaint(r->getRVal(), DtoArrayType(LLType::getInt8Ty(gIR->context())));
712     args.push_back(rmem);
713
714     // pass array typeinfo ?
715     if (useti) {
716         Type* t = l->getType();
717         LLValue* tival = DtoTypeInfoOf(t);
718         // DtoTypeInfoOf only does declare, not enough in this case :/
719         t->vtinfo->codegen(Type::sir);
720
721 #if 0
722         if (Logger::enabled())
723             Logger::cout() << "typeinfo decl: " << *tival << '\n';
724 #endif
725
726         args.push_back(DtoBitCast(tival, fn->getFunctionType()->getParamType(2)));
727     }
728
729     LLCallSite call = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), "tmp");
730
731     return call.getInstruction();
732 }
733
734 //////////////////////////////////////////////////////////////////////////////////////////
735 LLValue* DtoArrayEquals(Loc& loc, TOK op, DValue* l, DValue* r)
736 {
737     LLValue* res = DtoArrayEqCmp_impl(loc, "_adEq", l, r, true);
738     res = gIR->ir->CreateICmpNE(res, DtoConstInt(0), "tmp");
739     if (op == TOKnotequal)
740         res = gIR->ir->CreateNot(res, "tmp");
741
742     return res;
743 }
744
745 //////////////////////////////////////////////////////////////////////////////////////////
746 LLValue* DtoArrayCompare(Loc& loc, TOK op, DValue* l, DValue* r)
747 {
748     LLValue* res = 0;
749
750     llvm::ICmpInst::Predicate cmpop;
751     bool skip = false;
752
753     switch(op)
754     {
755     case TOKlt:
756     case TOKul:
757         cmpop = llvm::ICmpInst::ICMP_SLT;
758         break;
759     case TOKle:
760     case TOKule:
761         cmpop = llvm::ICmpInst::ICMP_SLE;
762         break;
763     case TOKgt:
764     case TOKug:
765         cmpop = llvm::ICmpInst::ICMP_SGT;
766         break;
767     case TOKge:
768     case TOKuge:
769         cmpop = llvm::ICmpInst::ICMP_SGE;
770         break;
771     case TOKue:
772         cmpop = llvm::ICmpInst::ICMP_EQ;
773         break;
774     case TOKlg:
775         cmpop = llvm::ICmpInst::ICMP_NE;
776         break;
777     case TOKleg:
778         skip = true;
779         res = LLConstantInt::getTrue(gIR->context());
780         break;
781     case TOKunord:
782         skip = true;
783         res = LLConstantInt::getFalse(gIR->context());
784         break;
785
786     default:
787         assert(0);
788     }
789
790     if (!skip)
791     {
792         Type* t = l->getType()->toBasetype()->nextOf()->toBasetype();
793         if (t->ty == Tchar)
794             res = DtoArrayEqCmp_impl(loc, "_adCmpChar", l, r, false);
795         else
796             res = DtoArrayEqCmp_impl(loc, "_adCmp", l, r, true);
797         res = gIR->ir->CreateICmp(cmpop, res, DtoConstInt(0), "tmp");
798     }
799
800     assert(res);
801     return res;
802 }
803
804 //////////////////////////////////////////////////////////////////////////////////////////
805 LLValue* DtoArrayCastLength(LLValue* len, const LLType* elemty, const LLType* newelemty)
806 {
807     Logger::println("DtoArrayCastLength");
808     LOG_SCOPE;
809
810     assert(len);
811     assert(elemty);
812     assert(newelemty);
813
814     size_t esz = getTypePaddedSize(elemty);
815     size_t nsz = getTypePaddedSize(newelemty);
816     if (esz == nsz)
817         return len;
818
819     LLSmallVector<LLValue*, 3> args;
820     args.push_back(len);
821     args.push_back(LLConstantInt::get(DtoSize_t(), esz, false));
822     args.push_back(LLConstantInt::get(DtoSize_t(), nsz, false));
823
824     LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_cast_len");
825     return gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), "tmp").getInstruction();
826 }
827
828 //////////////////////////////////////////////////////////////////////////////////////////
829 LLValue* DtoDynArrayIs(TOK op, DValue* l, DValue* r)
830 {
831     LLValue *len1, *ptr1, *len2, *ptr2;
832
833     assert(l);
834     assert(r);
835
836     // compare lengths
837     len1 = DtoArrayLen(l);
838     len2 = DtoArrayLen(r);
839     LLValue* b1 = gIR->ir->CreateICmpEQ(len1,len2,"tmp");
840
841     // compare pointers
842     ptr1 = DtoArrayPtr(l);
843     ptr2 = DtoArrayPtr(r);
844     LLValue* b2 = gIR->ir->CreateICmpEQ(ptr1,ptr2,"tmp");
845
846     // combine
847     LLValue* res = gIR->ir->CreateAnd(b1,b2,"tmp");
848
849     // return result
850     return (op == TOKnotidentity) ? gIR->ir->CreateNot(res) : res;
851 }
852
853 //////////////////////////////////////////////////////////////////////////////////////////
854 LLValue* DtoArrayLen(DValue* v)
855 {
856     Logger::println("DtoArrayLen");
857     LOG_SCOPE;
858
859     Type* t = v->getType()->toBasetype();
860     if (t->ty == Tarray) {
861         if (DSliceValue* s = v->isSlice())
862             return s->len;
863         else if (v->isNull())
864             return DtoConstSize_t(0);
865         else if (v->isLVal())
866             return DtoLoad(DtoGEPi(v->getLVal(), 0,0), ".len");
867         return gIR->ir->CreateExtractValue(v->getRVal(), 0, ".len");
868     }
869     else if (t->ty == Tsarray) {
870         assert(!v->isSlice());
871         assert(!v->isNull());
872         LLValue* rv = v->getRVal();
873         const LLArrayType* t = isaArray(rv->getType()->getContainedType(0));
874         assert(t);
875         return DtoConstSize_t(t->getNumElements());
876     }
877     assert(0 && "unsupported array for len");
878     return 0;
879 }
880
881 //////////////////////////////////////////////////////////////////////////////////////////
882 LLValue* DtoArrayPtr(DValue* v)
883 {
884     Logger::println("DtoArrayPtr");
885     LOG_SCOPE;
886
887     Type* t = v->getType()->toBasetype();
888     if (t->ty == Tarray) {
889         if (DSliceValue* s = v->isSlice())
890             return s->ptr;
891         else if (v->isNull())
892             return getNullPtr(getPtrToType(DtoType(t->nextOf())));
893         else if (v->isLVal())
894             return DtoLoad(DtoGEPi(v->getLVal(), 0,1), ".ptr");
895         return gIR->ir->CreateExtractValue(v->getRVal(), 1, ".ptr");
896     }
897     else if (t->ty == Tsarray) {
898         assert(!v->isSlice());
899         assert(!v->isNull());
900         return DtoGEPi(v->getRVal(), 0,0);
901     }
902     assert(0);
903     return 0;
904 }
905
906 //////////////////////////////////////////////////////////////////////////////////////////
907 DValue* DtoCastArray(Loc& loc, DValue* u, Type* to)
908 {
909     Logger::println("DtoCastArray");
910     LOG_SCOPE;
911
912     const LLType* tolltype = DtoType(to);
913
914     Type* totype = to->toBasetype();
915     Type* fromtype = u->getType()->toBasetype();
916     if (fromtype->ty != Tarray && fromtype->ty != Tsarray) {
917         error(loc, "can't cast %s to %s", u->getType()->toChars(), to->toChars());
918         fatal();
919     }
920
921     LLValue* rval;
922     LLValue* rval2;
923     bool isslice = false;
924
925     if (Logger::enabled())
926         Logger::cout() << "from array or sarray" << '\n';
927
928     if (totype->ty == Tpointer) {
929         if (Logger::enabled())
930             Logger::cout() << "to pointer" << '\n';
931         rval = DtoArrayPtr(u);
932         if (rval->getType() != tolltype)
933             rval = gIR->ir->CreateBitCast(rval, tolltype, "tmp");
934     }
935     else if (totype->ty == Tarray) {
936         if (Logger::enabled())
937             Logger::cout() << "to array" << '\n';
938
939         const LLType* ptrty = DtoArrayType(totype)->getContainedType(1);
940         const LLType* ety = DtoTypeNotVoid(fromtype->nextOf());
941
942         if (fromtype->ty == Tsarray) {
943             LLValue* uval = u->getRVal();
944
945             if (Logger::enabled())
946                 Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
947
948             assert(isaPointer(uval->getType()));
949             const LLArrayType* arrty = isaArray(uval->getType()->getContainedType(0));
950
951             if(arrty->getNumElements()*fromtype->nextOf()->size() % totype->nextOf()->size() != 0)
952             {
953                 error(loc, "invalid cast from '%s' to '%s', the element sizes don't line up", fromtype->toChars(), totype->toChars());
954                 fatal();
955             }
956
957             rval2 = LLConstantInt::get(DtoSize_t(), arrty->getNumElements(), false);
958             if (fromtype->nextOf()->size() != totype->nextOf()->size())
959                 rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
960             rval = DtoBitCast(uval, ptrty);
961         }
962         else {
963             rval2 = DtoArrayLen(u);
964             if (fromtype->nextOf()->size() != totype->nextOf()->size())
965                 rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0));
966
967             rval = DtoArrayPtr(u);
968             rval = DtoBitCast(rval, ptrty);
969         }
970         isslice = true;
971     }
972     else if (totype->ty == Tsarray) {
973         if (Logger::enabled())
974             Logger::cout() << "to sarray" << '\n';
975
976         size_t tosize = ((TypeSArray*)totype)->dim->toInteger();
977
978         if (fromtype->ty == Tsarray) {
979             LLValue* uval = u->getRVal();
980
981             if (Logger::enabled())
982                 Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
983
984             assert(isaPointer(uval->getType()));
985             const LLArrayType* arrty = isaArray(uval->getType()->getContainedType(0));
986
987             /*if(arrty->getNumElements()*fromtype->nextOf()->size() != tosize*totype->nextOf()->size())
988             {
989                 error(loc, "invalid cast from '%s' to '%s', the sizes are not the same", fromtype->toChars(), totype->toChars());
990                 fatal();
991             }*/
992
993             rval = DtoBitCast(uval, getPtrToType(tolltype));
994         }
995         else {
996             size_t i = (tosize * totype->nextOf()->size() - 1) / fromtype->nextOf()->size();
997             DConstValue index(Type::tsize_t, DtoConstSize_t(i));
998             DtoArrayBoundsCheck(loc, u, &index, false);
999
1000             rval = DtoArrayPtr(u);
1001             rval = DtoBitCast(rval, getPtrToType(tolltype));
1002         }
1003     }
1004     else if (totype->ty == Tbool) {
1005         // return (arr.ptr !is null)
1006         LLValue* ptr = DtoArrayPtr(u);
1007         LLConstant* nul = getNullPtr(ptr->getType());
1008         rval = gIR->ir->CreateICmpNE(ptr, nul, "tmp");
1009     }
1010     else {
1011         assert(0);
1012     }
1013
1014     if (isslice) {
1015         Logger::println("isslice");
1016         return new DSliceValue(to, rval2, rval);
1017     }
1018
1019     return new DImValue(to, rval);
1020 }
1021
1022 //////////////////////////////////////////////////////////////////////////////////////////
1023 void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, bool isslice)
1024 {
1025     Type* arrty = arr->getType()->toBasetype();
1026     assert((arrty->ty == Tsarray || arrty->ty == Tarray) &&
1027         "Can only array bounds check for static or dynamic arrays");
1028
1029     // static arrays could get static checks for static indices
1030     // but shouldn't since it might be generic code that's never executed
1031
1032     // runtime check
1033
1034     llvm::BasicBlock* oldend = gIR->scopeend();
1035     llvm::BasicBlock* failbb = llvm::BasicBlock::Create(gIR->context(), "arrayboundscheckfail", gIR->topfunc(), oldend);
1036     llvm::BasicBlock* okbb = llvm::BasicBlock::Create(gIR->context(), "arrayboundsok", gIR->topfunc(), oldend);
1037
1038     llvm::ICmpInst::Predicate cmpop = isslice ? llvm::ICmpInst::ICMP_ULE : llvm::ICmpInst::ICMP_ULT;
1039     LLValue* cond = gIR->ir->CreateICmp(cmpop, index->getRVal(), DtoArrayLen(arr), "boundscheck");
1040     gIR->ir->CreateCondBr(cond, okbb, failbb);
1041
1042     // set up failbb to call the array bounds error runtime function
1043
1044     gIR->scope() = IRScope(failbb, okbb);
1045
1046     std::vector<LLValue*> args;
1047
1048     // file param
1049     // we might be generating for an imported template function
1050     Module* funcmodule = gIR->func()->decl->getModule();
1051     const char* cur_file = funcmodule->srcfile->name->toChars();
1052     if (loc.filename && strcmp(loc.filename, cur_file) != 0)
1053     {
1054         args.push_back(DtoConstString(loc.filename));
1055     }
1056     else
1057     {
1058         IrModule* irmod = getIrModule(funcmodule);
1059         args.push_back(DtoLoad(irmod->fileName));
1060     }
1061
1062     // line param
1063     LLConstant* c = DtoConstUint(loc.linnum);
1064     args.push_back(c);
1065
1066     // call
1067     llvm::Function* errorfn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_bounds");
1068     gIR->CreateCallOrInvoke(errorfn, args.begin(), args.end());
1069
1070     // the function does not return
1071     gIR->ir->CreateUnreachable();
1072
1073     // if ok, proceed in okbb
1074     gIR->scope() = IRScope(okbb, oldend);
1075 }
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.