comparison gen/arrays.cpp @ 339:385a18242485 trunk

[svn r360] Another mostly rewrite of DtoArrayInit. Should be much more robust now, and probably faster code generated for the most common cases too! Fixed issues with slice initialization (!!!) of multidimensional static arrays. Attempt to fix issue with referencing nested 'this' pointers introduced in DMD 1.033 merge.
author lindquist
date Sun, 13 Jul 2008 01:29:49 +0200
parents 0c90d816394f
children 351c0077d0b3
comparison
equal deleted inserted replaced
338:0c90d816394f 339:385a18242485
128 128
129 LLValue* dim = DtoArrayLen(array); 129 LLValue* dim = DtoArrayLen(array);
130 LLValue* ptr = DtoArrayPtr(array); 130 LLValue* ptr = DtoArrayPtr(array);
131 LLValue* val = value->getRVal(); 131 LLValue* val = value->getRVal();
132 132
133 Logger::cout() << "llvm values:\n" << " ptr: " << *ptr << " dim: " << *dim << " val: " << *val << '\n'; 133 // prepare runtime call
134
135 const LLType* pt = ptr->getType()->getContainedType(0);
136 const LLType* t = val->getType();
137
138 size_t aggrsz = 0;
139 Type* valtype = value->getType()->toBasetype();
140
141 const char* funcname = NULL;
142
143 LLSmallVector<LLValue*, 4> args; 134 LLSmallVector<LLValue*, 4> args;
144 args.push_back(ptr); 135 args.push_back(ptr);
145 args.push_back(dim); 136 args.push_back(dim);
146 args.push_back(val); 137 args.push_back(val);
147 138
148 // if t is a primitive type, use the corresponding runtime function 139 // determine the right runtime function to call
149 if (t == LLType::Int1Ty) { 140 const char* funcname = NULL;
141 Type* t = value->getType()->toBasetype();
142
143 // lets first optimize all zero initializations down to a memset.
144 // this simplifies codegen later on as llvm null's have no address!
145 if (isaConstant(val) && isaConstant(val)->isNullValue())
146 {
147 size_t X = getABITypeSize(val->getType());
148 LLValue* nbytes = gIR->ir->CreateMul(dim, DtoConstSize_t(X), ".nbytes");
149 DtoMemSetZero(ptr, nbytes);
150 return;
151 }
152
153 // if not a zero initializer, call the appropriate runtime function!
154 switch (t->ty)
155 {
156 case Tbool:
150 funcname = "_d_array_init_i1"; 157 funcname = "_d_array_init_i1";
151 } 158 break;
152 else if (t == LLType::Int8Ty) { 159
160 case Tvoid:
161 case Tchar:
162 case Tint8:
163 case Tuns8:
153 funcname = "_d_array_init_i8"; 164 funcname = "_d_array_init_i8";
154 } 165 break;
155 else if (t == LLType::Int16Ty) { 166
167 case Twchar:
168 case Tint16:
169 case Tuns16:
156 funcname = "_d_array_init_i16"; 170 funcname = "_d_array_init_i16";
157 } 171 break;
158 else if (t == LLType::Int32Ty) { 172
173 case Tdchar:
174 case Tint32:
175 case Tuns32:
159 funcname = "_d_array_init_i32"; 176 funcname = "_d_array_init_i32";
160 } 177 break;
161 else if (t == LLType::Int64Ty) { 178
179 case Tint64:
180 case Tuns64:
162 funcname = "_d_array_init_i64"; 181 funcname = "_d_array_init_i64";
163 } 182 break;
164 else if (t == LLType::FloatTy) { 183
184 case Tfloat32:
185 case Timaginary32:
165 funcname = "_d_array_init_float"; 186 funcname = "_d_array_init_float";
166 } 187 break;
167 else if (t == LLType::DoubleTy) { 188
189 case Tfloat64:
190 case Timaginary64:
168 funcname = "_d_array_init_double"; 191 funcname = "_d_array_init_double";
169 } 192 break;
170 else if (t == getPtrToType(LLType::Int8Ty)) { 193
194 case Tfloat80:
195 case Timaginary80:
196 funcname = "_d_array_init_real";
197 break;
198
199 case Tpointer:
200 case Tclass:
171 funcname = "_d_array_init_pointer"; 201 funcname = "_d_array_init_pointer";
172 202 args[0] = DtoBitCast(args[0], getPtrToType(getVoidPtrType()));
173 const LLType* dstty = getPtrToType(getVoidPtrType()); 203 args[2] = DtoBitCast(args[2], getVoidPtrType());
174 if (args[0]->getType() != dstty) 204 break;
175 args[0] = DtoBitCast(args[0],dstty); 205
176 206 // this currently acts as a kind of fallback for all the bastards...
177 const LLType* valty = getVoidPtrType(); 207 // FIXME: this is probably too slow.
178 if (args[2]->getType() != valty) 208 case Tstruct:
179 args[2] = DtoBitCast(args[2],valty); 209 case Tdelegate:
180 } 210 case Tarray:
181 // handle array rhs 211 case Tsarray:
182 else if (value->getType()->ty == Tarray || value->getType()->ty == Tsarray) 212 case Tcomplex32:
183 { 213 case Tcomplex64:
184 const LLArrayType* dstarrty = isaArray(pt); 214 case Tcomplex80:
185 assert(dstarrty);
186 const LLPointerType* srcty = isaPointer(t);
187 assert(dstarrty == srcty->getElementType());
188
189 funcname = "_d_array_init_mem"; 215 funcname = "_d_array_init_mem";
190 216 args[0] = DtoBitCast(args[0], getVoidPtrType());
191 args[0] = gIR->ir->CreateBitCast(ptr, getVoidPtrType(), "tmp"); 217 args[2] = DtoBitCast(args[2], getVoidPtrType());
192 args[2] = gIR->ir->CreateBitCast(val, getVoidPtrType(), "tmp"); 218 args.push_back(DtoConstSize_t(getABITypeSize(DtoType(t))));
193 219 break;
194 size_t n_inner = getABITypeSize(srcty->getElementType()); 220
195 args.push_back(DtoConstSize_t(n_inner)); 221 default:
196 } 222 error("unhandled array init: %s = %s", array->getType()->toChars(), value->getType()->toChars());
197 // handle null aggregate 223 assert(0 && "unhandled array init");
198 else if (isaStruct(t))
199 {
200 aggrsz = getABITypeSize(t);
201 LLConstant* c = isaConstant(val);
202 assert(c && c->isNullValue());
203 LLValue* nbytes;
204 if (aggrsz == 1)
205 nbytes = dim;
206 else
207 nbytes = gIR->ir->CreateMul(dim, DtoConstSize_t(aggrsz), "tmp");
208 DtoMemSetZero(ptr,nbytes);
209 return;
210 }
211 // handle general aggregate case
212 else if (DtoIsPassedByRef(valtype))
213 {
214 funcname = "_d_array_init_mem";
215
216 args[0] = gIR->ir->CreateBitCast(ptr, getVoidPtrType(), "tmp");
217 args[2] = gIR->ir->CreateBitCast(val, getVoidPtrType(), "tmp");
218
219 aggrsz = getABITypeSize(pt);
220 args.push_back(DtoConstSize_t(aggrsz));
221 }
222 else
223 {
224 Logger::cout() << *ptr->getType() << " = " << *val->getType() << '\n';
225 assert(0);
226 } 224 }
227 225
228 LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname); 226 LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname);
229 assert(fn); 227 assert(fn);
230 Logger::cout() << "calling array init function: " << *fn <<'\n'; 228 Logger::cout() << "calling array init function: " << *fn <<'\n';