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