Mercurial > projects > ldc
comparison gen/arrays.c @ 4:e116aa1488e6 trunk
[svn r8] changed backend includes to always use the gen/<foo>.h prefix
fixed passing string literals as array parameters
few other fixes
moved some array routines into gen/arrays
author | lindquist |
---|---|
date | Mon, 03 Sep 2007 17:34:30 +0200 |
parents | |
children | 35d93ce68cf4 |
comparison
equal
deleted
inserted
replaced
3:069cf4b0ec67 | 4:e116aa1488e6 |
---|---|
1 #include "llvm/Constants.h" | |
2 #include "llvm/Type.h" | |
3 #include "llvm/DerivedTypes.h" | |
4 #include "llvm/Instructions.h" | |
5 #include "llvm/CallingConv.h" | |
6 | |
7 #include "mtype.h" | |
8 #include "dsymbol.h" | |
9 #include "aggregate.h" | |
10 #include "declaration.h" | |
11 #include "init.h" | |
12 | |
13 #include "gen/irstate.h" | |
14 #include "gen/tollvm.h" | |
15 #include "gen/arrays.h" | |
16 #include "gen/runtime.h" | |
17 #include "gen/logger.h" | |
18 #include "gen/elem.h" | |
19 | |
20 ////////////////////////////////////////////////////////////////////////////////////////// | |
21 | |
22 llvm::StructType* LLVM_DtoArrayType(Type* t) | |
23 { | |
24 assert(t->next); | |
25 const llvm::Type* at = LLVM_DtoType(t->next); | |
26 const llvm::Type* arrty; | |
27 | |
28 /*if (t->ty == Tsarray) { | |
29 TypeSArray* tsa = (TypeSArray*)t; | |
30 assert(tsa->dim->type->isintegral()); | |
31 arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger()); | |
32 } | |
33 else { | |
34 arrty = llvm::ArrayType::get(at,0); | |
35 }*/ | |
36 if (at == llvm::Type::VoidTy) { | |
37 at = llvm::Type::Int8Ty; | |
38 } | |
39 arrty = llvm::PointerType::get(at); | |
40 | |
41 std::vector<const llvm::Type*> members; | |
42 if (global.params.is64bit) | |
43 members.push_back(llvm::Type::Int64Ty); | |
44 else | |
45 members.push_back(llvm::Type::Int32Ty); | |
46 | |
47 members.push_back(arrty); | |
48 | |
49 return llvm::StructType::get(members); | |
50 } | |
51 | |
52 ////////////////////////////////////////////////////////////////////////////////////////// | |
53 | |
54 llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t) | |
55 { | |
56 if (t->llvmType) | |
57 return llvm::cast<llvm::ArrayType>(t->llvmType); | |
58 | |
59 assert(t->ty == Tsarray); | |
60 assert(t->next); | |
61 | |
62 const llvm::Type* at = LLVM_DtoType(t->next); | |
63 | |
64 TypeSArray* tsa = (TypeSArray*)t; | |
65 assert(tsa->dim->type->isintegral()); | |
66 llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger()); | |
67 | |
68 tsa->llvmType = arrty; | |
69 return arrty; | |
70 } | |
71 | |
72 ////////////////////////////////////////////////////////////////////////////////////////// | |
73 | |
74 llvm::Value* LLVM_DtoNullArray(llvm::Value* v) | |
75 { | |
76 assert(gIR); | |
77 d_uns64 n = (global.params.is64bit) ? 16 : 8; | |
78 | |
79 llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
80 | |
81 llvm::Value* arr = new llvm::BitCastInst(v,i8p_ty,"tmp",gIR->scopebb()); | |
82 | |
83 llvm::Function* fn = LLVM_DeclareMemSet32(); | |
84 std::vector<llvm::Value*> llargs; | |
85 llargs.resize(4); | |
86 llargs[0] = arr; | |
87 llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false); | |
88 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
89 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
90 | |
91 //Logger::cout() << *fn << '|' << *fn->getType() << '\n'; | |
92 //Logger::cout() << "to null array call: " << *llargs[0] << '|' << *llargs[1] << '|' << *llargs[2] << '|' << *llargs[3] << '\n'; | |
93 | |
94 llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
95 | |
96 return ret; | |
97 } | |
98 | |
99 ////////////////////////////////////////////////////////////////////////////////////////// | |
100 | |
101 llvm::Value* LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src) | |
102 { | |
103 assert(gIR); | |
104 if (dst->getType() == src->getType()) | |
105 { | |
106 d_uns64 n = (global.params.is64bit) ? 16 : 8; | |
107 | |
108 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
109 | |
110 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
111 llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb()); | |
112 | |
113 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
114 std::vector<llvm::Value*> llargs; | |
115 llargs.resize(4); | |
116 llargs[0] = dstarr; | |
117 llargs[1] = srcarr; | |
118 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
119 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
120 | |
121 return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
122 } | |
123 else | |
124 { | |
125 if (!llvm::isa<llvm::ArrayType>(src->getType()->getContainedType(0))) | |
126 { | |
127 Logger::cout() << "invalid: " << *src << '\n'; | |
128 assert(0); | |
129 } | |
130 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(src->getType()->getContainedType(0)); | |
131 llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType()); | |
132 | |
133 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
134 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); | |
135 | |
136 llvm::Value* dstlen = new llvm::GetElementPtrInst(dst,zero,zero,"tmp",gIR->scopebb()); | |
137 llvm::Value* srclen = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false); | |
138 new llvm::StoreInst(srclen, dstlen, gIR->scopebb()); | |
139 | |
140 llvm::Value* dstptr = new llvm::GetElementPtrInst(dst,zero,one,"tmp",gIR->scopebb()); | |
141 llvm::Value* srcptr = new llvm::BitCastInst(src,dstty,"tmp",gIR->scopebb()); | |
142 new llvm::StoreInst(srcptr, dstptr, gIR->scopebb()); | |
143 } | |
144 } | |
145 | |
146 ////////////////////////////////////////////////////////////////////////////////////////// | |
147 | |
148 void LLVM_DtoArrayInit(llvm::Value* l, llvm::Value* r) | |
149 { | |
150 const llvm::PointerType* ptrty = llvm::cast<llvm::PointerType>(l->getType()); | |
151 if (llvm::isa<llvm::ArrayType>(ptrty->getContainedType(0))) | |
152 { | |
153 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(ptrty->getContainedType(0)); | |
154 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
155 | |
156 std::vector<llvm::Value*> args; | |
157 args.resize(3); | |
158 args[0] = new llvm::GetElementPtrInst(l,zero,zero,"tmp",gIR->scopebb()); | |
159 args[1] = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false); | |
160 args[2] = r; | |
161 | |
162 const char* funcname = NULL; | |
163 | |
164 if (llvm::isa<llvm::PointerType>(arrty->getElementType())) { | |
165 funcname = "_d_array_init_pointer"; | |
166 | |
167 const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); | |
168 if (args[0]->getType() != dstty) | |
169 args[0] = new llvm::BitCastInst(args[0],dstty,"tmp",gIR->scopebb()); | |
170 | |
171 const llvm::Type* valty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
172 if (args[2]->getType() != valty) | |
173 args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb()); | |
174 } | |
175 else if (r->getType() == llvm::Type::Int1Ty) { | |
176 funcname = "_d_array_init_i1"; | |
177 } | |
178 else if (r->getType() == llvm::Type::Int8Ty) { | |
179 funcname = "_d_array_init_i8"; | |
180 } | |
181 else if (r->getType() == llvm::Type::Int16Ty) { | |
182 funcname = "_d_array_init_i16"; | |
183 } | |
184 else if (r->getType() == llvm::Type::Int32Ty) { | |
185 funcname = "_d_array_init_i32"; | |
186 } | |
187 else if (r->getType() == llvm::Type::Int64Ty) { | |
188 funcname = "_d_array_init_i64"; | |
189 } | |
190 else if (r->getType() == llvm::Type::FloatTy) { | |
191 funcname = "_d_array_init_float"; | |
192 } | |
193 else if (r->getType() == llvm::Type::DoubleTy) { | |
194 funcname = "_d_array_init_double"; | |
195 } | |
196 else { | |
197 assert(0); | |
198 } | |
199 | |
200 Logger::cout() << *args[0] << '|' << *args[2] << '\n'; | |
201 | |
202 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname); | |
203 assert(fn); | |
204 llvm::CallInst* call = new llvm::CallInst(fn, args.begin(), args.end(), "", gIR->scopebb()); | |
205 call->setCallingConv(llvm::CallingConv::C); | |
206 | |
207 Logger::println("array init call ok"); | |
208 } | |
209 else if (llvm::isa<llvm::StructType>(ptrty->getContainedType(0))) | |
210 { | |
211 assert(0 && "Only static arrays support initialisers atm"); | |
212 } | |
213 else | |
214 assert(0); | |
215 } | |
216 | |
217 ////////////////////////////////////////////////////////////////////////////////////////// | |
218 | |
219 void LLVM_DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr) | |
220 { | |
221 Logger::cout() << "LLVM_DtoSetArray(" << *arr << ", " << *dim << ", " << *ptr << ")\n"; | |
222 const llvm::StructType* st = llvm::cast<llvm::StructType>(arr->getType()->getContainedType(0)); | |
223 //const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(r->getType()); | |
224 | |
225 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
226 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); | |
227 | |
228 llvm::Value* arrdim = new llvm::GetElementPtrInst(arr,zero,zero,"tmp",gIR->scopebb()); | |
229 new llvm::StoreInst(dim, arrdim, gIR->scopebb()); | |
230 | |
231 llvm::Value* arrptr = new llvm::GetElementPtrInst(arr,zero,one,"tmp",gIR->scopebb()); | |
232 new llvm::StoreInst(ptr, arrptr, gIR->scopebb()); | |
233 } | |
234 | |
235 ////////////////////////////////////////////////////////////////////////////////////////// | |
236 llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* arrinit) | |
237 { | |
238 Logger::println("arr init begin"); | |
239 assert(arrinit->type->ty == Tsarray); | |
240 TypeSArray* t = (TypeSArray*)arrinit->type; | |
241 integer_t tdim = t->dim->toInteger(); | |
242 | |
243 std::vector<llvm::Constant*> inits(tdim, 0); | |
244 | |
245 const llvm::Type* elemty = LLVM_DtoType(arrinit->type->next); | |
246 | |
247 assert(arrinit->index.dim == arrinit->value.dim); | |
248 for (int i=0,j=0; i < tdim; ++i) | |
249 { | |
250 Initializer* init = 0; | |
251 Expression* idx = (Expression*)arrinit->index.data[j]; | |
252 | |
253 if (idx) | |
254 { | |
255 integer_t k = idx->toInteger(); | |
256 if (i == k) | |
257 { | |
258 init = (Initializer*)arrinit->value.data[j]; | |
259 assert(init); | |
260 ++j; | |
261 } | |
262 } | |
263 else | |
264 { | |
265 init = (Initializer*)arrinit->value.data[j]; | |
266 ++j; | |
267 } | |
268 | |
269 llvm::Constant* v = 0; | |
270 | |
271 if (!init) | |
272 { | |
273 elem* e = t->next->defaultInit()->toElem(gIR); | |
274 v = llvm::cast<llvm::Constant>(e->val); | |
275 delete e; | |
276 } | |
277 else if (ExpInitializer* ex = init->isExpInitializer()) | |
278 { | |
279 elem* e = ex->exp->toElem(gIR); | |
280 v = llvm::cast<llvm::Constant>(e->val); | |
281 delete e; | |
282 } | |
283 else if (StructInitializer* si = init->isStructInitializer()) | |
284 { | |
285 v = LLVM_DtoStructInitializer(si); | |
286 } | |
287 else if (ArrayInitializer* ai = init->isArrayInitializer()) | |
288 { | |
289 v = LLVM_DtoArrayInitializer(ai); | |
290 } | |
291 else if (init->isVoidInitializer()) | |
292 { | |
293 v = llvm::UndefValue::get(elemty); | |
294 } | |
295 else | |
296 assert(v); | |
297 | |
298 inits[i] = v; | |
299 } | |
300 | |
301 llvm::ArrayType* arrty = LLVM_DtoStaticArrayType(t); | |
302 return llvm::ConstantArray::get(arrty, inits); | |
303 } | |
304 | |
305 ////////////////////////////////////////////////////////////////////////////////////////// | |
306 void LLVM_DtoArrayCopy(elem* dst, elem* src) | |
307 { | |
308 assert(0); | |
309 } |