comparison gen/structs.cpp @ 797:340acf1535d0

Removed KDevelop3 project files, CMake can generate them just fine! Fixed function literals in static initializers. Changed alignment of delegates from 2*PTRSIZE to just PTRSIZE. Changed errors to go to stderr instead of stdout. Fairly major rewriting of struct/union/class handling, STILL A BIT BUGGY !!!
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sat, 29 Nov 2008 21:25:43 +0100
parents 6e7a4c3b64d2
children d14e4594c7d7
comparison
equal deleted inserted replaced
796:6e7a4c3b64d2 797:340acf1535d0
16 #include "gen/dvalue.h" 16 #include "gen/dvalue.h"
17 17
18 #include "ir/irstruct.h" 18 #include "ir/irstruct.h"
19 19
20 ////////////////////////////////////////////////////////////////////////////////////////// 20 //////////////////////////////////////////////////////////////////////////////////////////
21 void addZeros(std::vector<llvm::Constant*>& inits, unsigned pos, unsigned offset); // defined in irstruct.cpp
22
23 // pair of var and its init
24 typedef std::pair<VarDeclaration*,Initializer*> VarInitPair;
25
26 // comparison func for qsort
27 static int varinit_offset_cmp_func(const void* p1, const void* p2)
28 {
29 VarDeclaration* v1 = ((VarInitPair*)p1)->first;
30 VarDeclaration* v2 = ((VarInitPair*)p2)->first;
31 if (v1->offset < v2->offset)
32 return -1;
33 else if (v1->offset > v2->offset)
34 return 1;
35 else
36 return 0;
37 }
38
39 /*
40 this uses a simple algorithm to build the correct constant
41
42 (1) first sort the explicit initializers by offset... well, DMD doesn't :)
43
44 (2) if there is NO space before the next explicit initializeer, goto (9)
45 (3) find the next default initializer that fits before it, if NOT found goto (7)
46 (4) insert zero padding up to the next default initializer
47 (5) insert the next default initializer
48 (6) goto (2)
49
50 (7) insert zero padding up to the next explicit initializer
51
52 (9) insert the next explicit initializer
53 (10) goto (2)
54
55 (11) done
56
57 (next can be the end too)
58
59 */
60
61 // return the next default initializer to use or null
62 static VarDeclaration* nextDefault(IrStruct* irstruct, size_t& idx, size_t pos, size_t offset)
63 {
64 IrStruct::VarDeclVector& defaults = irstruct->defVars;
65 size_t ndefaults = defaults.size();
66
67 // for each valid index
68 while(idx < ndefaults)
69 {
70 VarDeclaration* v = defaults[idx];
71
72 // skip defaults before pos
73 if (v->offset < pos)
74 {
75 idx++;
76 continue;
77 }
78
79 // this var default fits
80 if (v->offset >= pos && v->offset + v->type->size() <= offset)
81 return v;
82
83 // not usable
84 break;
85 }
86
87 // not usable
88 return NULL;
89 }
90
21 LLConstant* DtoConstStructInitializer(StructInitializer* si) 91 LLConstant* DtoConstStructInitializer(StructInitializer* si)
22 { 92 {
23 Logger::println("DtoConstStructInitializer: %s", si->toChars()); 93 Logger::println("DtoConstStructInitializer: %s", si->toChars());
24 LOG_SCOPE; 94 LOG_SCOPE;
25 95
96 // get TypeStruct
26 assert(si->ad); 97 assert(si->ad);
27 TypeStruct* ts = (TypeStruct*)si->ad->type; 98 TypeStruct* ts = (TypeStruct*)si->ad->type;
28 99
29 DtoResolveDsymbol(si->ad); 100 // force constant initialization of the symbol
30 101 DtoForceConstInitDsymbol(si->ad);
102
103 // get formal type
31 const llvm::StructType* structtype = isaStruct(ts->ir.type->get()); 104 const llvm::StructType* structtype = isaStruct(ts->ir.type->get());
32 105
106 // log it
33 if (Logger::enabled()) 107 if (Logger::enabled())
34 Logger::cout() << "llvm struct type: " << *structtype << '\n'; 108 Logger::cout() << "llvm struct type: " << *structtype << '\n';
35 109
110 // sanity check
111 assert(si->value.dim > 0);
36 assert(si->value.dim == si->vars.dim); 112 assert(si->value.dim == si->vars.dim);
37 113
38 std::vector<DUnionIdx> inits; 114 // vector of final initializer constants
39 for (int i = 0; i < si->value.dim; ++i) 115 std::vector<LLConstant*> inits;
40 { 116
117 // get the ir struct
118 IrStruct* irstruct = si->ad->ir.irStruct;
119
120 // get default fields
121 IrStruct::VarDeclVector& defaults = irstruct->defVars;
122 size_t ndefaults = defaults.size();
123
124 // make sure si->vars is sorted by offset
125 std::vector<VarInitPair> vars;
126 size_t nvars = si->vars.dim;
127 vars.resize(nvars);
128
129 // fill pair vector
130 for (size_t i = 0; i < nvars; i++)
131 {
132 VarDeclaration* var = (VarDeclaration*)si->vars.data[i];
41 Initializer* ini = (Initializer*)si->value.data[i]; 133 Initializer* ini = (Initializer*)si->value.data[i];
134 assert(var);
42 assert(ini); 135 assert(ini);
43 VarDeclaration* vd = (VarDeclaration*)si->vars.data[i]; 136 vars[i] = std::make_pair(var, ini);
44 assert(vd); 137 }
45 LLConstant* v = DtoConstInitializer(vd->loc, vd->type, ini); 138 // sort it
46 inits.push_back(DUnionIdx(vd->ir.irField->index, vd->ir.irField->indexOffset, v)); 139 qsort(&vars[0], nvars, sizeof(VarInitPair), &varinit_offset_cmp_func);
47 } 140
48 141 // check integrity
49 DtoConstInitStruct((StructDeclaration*)si->ad); 142 // and do error checking, since the frontend does verify static struct initializers
50 return si->ad->ir.irStruct->dunion->getConst(inits); 143 size_t lastoffset = 0;
144 size_t lastsize = 0;
145 bool overlap = false;
146 for (size_t i=0; i < nvars; i++)
147 {
148 // next explicit init var
149 VarDeclaration* var = vars[i].first;
150 Logger::println("var = %s : +%u", var->toChars(), var->offset);
151
152 // I would have thought this to be a frontend check
153 for (size_t j=i+1; j<nvars; j++)
154 {
155 if (j == i)
156 continue;
157 VarDeclaration* var2 = vars[j].first;
158 if (var2->offset >= var->offset && var2->offset < var->offset + var->type->size())
159 {
160 fprintf(stdmsg, "Error: %s: initializer '%s' overlaps with '%s'\n", si->loc.toChars(), var->toChars(), var2->toChars());
161 overlap = true;
162 }
163 }
164
165 // update offsets
166 lastoffset = var->offset;
167 lastsize = var->type->size();
168 }
169
170 // error handling, report all overlaps before aborting
171 if (overlap)
172 {
173 error("%s: overlapping union initializers", si->loc.toChars());
174 }
175
176 // go through each explicit initalizer, falling back to defaults or zeros when necessary
177 lastoffset = 0;
178 lastsize = 0;
179
180 size_t j=0; // defaults
181
182 for (size_t i=0; i < nvars; i++)
183 {
184 // get var and init
185 VarDeclaration* var = vars[i].first;
186 Initializer* ini = vars[i].second;
187
188 size_t offset = var->offset;
189 size_t size = var->type->size();
190
191 // if there is space before the next explicit initializer
192 Lpadding:
193 size_t pos = lastoffset+lastsize;
194 if (offset > pos)
195 {
196 // find the the next default initializer that fits in this space
197 VarDeclaration* nextdef = nextDefault(irstruct, j, lastoffset+lastsize, offset);
198
199 // found
200 if (nextdef)
201 {
202 // need zeros before the default
203 if (nextdef->offset > pos)
204 {
205 Logger::println("inserting %lu byte padding at %lu", nextdef->offset - pos, pos);
206 addZeros(inits, pos, nextdef->offset);
207 }
208
209 // do the default
210 Logger::println("adding default field: %s : +%u", nextdef->toChars(), nextdef->offset);
211 LLConstant* c = nextdef->ir.irField->constInit;
212 inits.push_back(c);
213
214 // update offsets
215 lastoffset = nextdef->offset;
216 lastsize = nextdef->type->size();
217
218 // check if more defaults would fit
219 goto Lpadding;
220 }
221 // not found, pad with zeros
222 else
223 {
224 Logger::println("inserting %lu byte padding at %lu", offset - pos, pos);
225 addZeros(inits, pos, offset);
226 // offsets are updated by the explicit initializer
227 }
228 }
229
230 // insert next explicit
231 Logger::println("adding explicit field: %s : +%lu", var->toChars(), offset);
232 LOG_SCOPE;
233 LLConstant* c = DtoConstInitializer(var->loc, var->type, ini);
234 inits.push_back(c);
235
236 lastoffset = offset;
237 lastsize = size;
238 }
239
240 // there might still be padding after the last one, make sure that is defaulted/zeroed as well
241 size_t structsize = getABITypeSize(structtype);
242
243 // if there is space before the next explicit initializer
244 // FIXME: this should be handled in the loop above as well
245 Lpadding2:
246 size_t pos = lastoffset+lastsize;
247 if (structsize > pos)
248 {
249 // find the the next default initializer that fits in this space
250 VarDeclaration* nextdef = nextDefault(irstruct, j, lastoffset+lastsize, structsize);
251
252 // found
253 if (nextdef)
254 {
255 // need zeros before the default
256 if (nextdef->offset > pos)
257 {
258 Logger::println("inserting %lu byte padding at %lu", nextdef->offset - pos, pos);
259 addZeros(inits, pos, nextdef->offset);
260 }
261
262 // do the default
263 Logger::println("adding default field: %s : +%u", nextdef->toChars(), nextdef->offset);
264 LLConstant* c = nextdef->ir.irField->constInit;
265 inits.push_back(c);
266
267 // update offsets
268 lastoffset = nextdef->offset;
269 lastsize = nextdef->type->size();
270
271 // check if more defaults would fit
272 goto Lpadding2;
273 }
274 // not found, pad with zeros
275 else
276 {
277 Logger::println("inserting %lu byte padding at %lu", structsize - pos, pos);
278 addZeros(inits, pos, structsize);
279 lastoffset = pos;
280 lastsize = structsize - pos;
281 }
282 }
283
284 assert(lastoffset+lastsize == structsize);
285
286 // make the constant struct
287 LLConstant* c = LLConstantStruct::get(inits, si->ad->ir.irStruct->packed);
288 if (Logger::enabled())
289 {
290 Logger::cout() << "constant struct initializer: " << *c << '\n';
291 }
292 assert(getABITypeSize(c->getType()) == structsize);
293 return c;
51 } 294 }
52 295
53 ////////////////////////////////////////////////////////////////////////////////////////// 296 //////////////////////////////////////////////////////////////////////////////////////////
54 297
55 LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd) 298 LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
59 302
60 // vd must be a field 303 // vd must be a field
61 IrField* field = vd->ir.irField; 304 IrField* field = vd->ir.irField;
62 assert(field); 305 assert(field);
63 306
64 unsigned idx = field->index; 307 // get the start pointer
65 unsigned off = field->indexOffset;
66
67 const LLType* st = getPtrToType(DtoType(sd->type)); 308 const LLType* st = getPtrToType(DtoType(sd->type));
309
310 // cast to the formal struct type
68 src = DtoBitCast(src, st); 311 src = DtoBitCast(src, st);
69 312
70 LLValue* val = DtoGEPi(src, 0,idx); 313 // gep to the index
314 LLValue* val = DtoGEPi(src, 0, field->index);
315
316 // do we need to offset further? (union area)
317 if (field->unionOffset)
318 {
319 // cast to void*
320 val = DtoBitCast(val, getVoidPtrType());
321 // offset
322 val = DtoGEPi1(val, field->unionOffset);
323 }
324
325 // cast it to the right type
71 val = DtoBitCast(val, getPtrToType(DtoType(vd->type))); 326 val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
72
73 if (off)
74 val = DtoGEPi1(val, off);
75 327
76 if (Logger::enabled()) 328 if (Logger::enabled())
77 Logger::cout() << "value: " << *val << '\n'; 329 Logger::cout() << "value: " << *val << '\n';
78 330
79 return val; 331 return val;
80 } 332 }
81 333
82 //////////////////////////////////////////////////////////////////////////////////////////
83
84 void DtoResolveStruct(StructDeclaration* sd) 334 void DtoResolveStruct(StructDeclaration* sd)
85 { 335 {
336 // don't do anything if already been here
86 if (sd->ir.resolved) return; 337 if (sd->ir.resolved) return;
338 // make sure above works :P
87 sd->ir.resolved = true; 339 sd->ir.resolved = true;
88 340
89 Logger::println("DtoResolveStruct(%s): %s", sd->toChars(), sd->loc.toChars()); 341 // log what we're doing
342 Logger::println("Resolving struct type: %s (%s)", sd->toChars(), sd->locToChars());
90 LOG_SCOPE; 343 LOG_SCOPE;
91 344
92 TypeStruct* ts = (TypeStruct*)sd->type->toBasetype(); 345 // get the DMD TypeStruct
93 346 TypeStruct* ts = (TypeStruct*)sd->type;
94 // this struct is a forward declaration 347
348 // create the IrStruct
349 IrStruct* irstruct = new IrStruct(sd);
350 sd->ir.irStruct = irstruct;
351
352 // create the type
353 ts->ir.type = new LLPATypeHolder(llvm::OpaqueType::get());
354
355 // handle forward declaration structs (opaques)
95 // didn't even know D had those ... 356 // didn't even know D had those ...
96 if (sd->sizeok != 1) 357 if (sd->sizeok != 1)
97 { 358 {
98 sd->ir.irStruct = new IrStruct(ts); 359 // nothing more to do
99 ts->ir.type = new llvm::PATypeHolder(llvm::OpaqueType::get());
100 return; 360 return;
101 } 361 }
102 362
363 // make this struct current
364 gIR->structs.push_back(irstruct);
365
366 // get some info
103 bool ispacked = (ts->alignsize() == 1); 367 bool ispacked = (ts->alignsize() == 1);
104 368 bool isunion = sd->isUnionDeclaration();
105 // create the IrStruct 369
106 IrStruct* irstruct = new IrStruct(ts); 370 // set irstruct info
107 sd->ir.irStruct = irstruct;
108 gIR->structs.push_back(irstruct);
109
110 // add fields
111 Array* fields = &sd->fields;
112 for (int k=0; k < fields->dim; k++)
113 {
114 VarDeclaration* v = (VarDeclaration*)fields->data[k];
115 Logger::println("Adding field: %s %s", v->type->toChars(), v->toChars());
116 // init fields, used to happen in VarDeclaration::toObjFile
117 irstruct->addField(v);
118 }
119
120 irstruct->packed = ispacked; 371 irstruct->packed = ispacked;
121 372
373 // defined in this module?
122 bool thisModule = false; 374 bool thisModule = false;
123 if (sd->getModule() == gIR->dmodule) 375 if (sd->getModule() == gIR->dmodule)
124 thisModule = true; 376 thisModule = true;
125 377
126 // methods, fields 378 // methods, fields
127 Array* arr = sd->members; 379 Array* arr = sd->members;
128 for (int k=0; k < arr->dim; k++) { 380 for (int k=0; k < arr->dim; k++) {
129 Dsymbol* s = (Dsymbol*)arr->data[k]; 381 Dsymbol* s = (Dsymbol*)arr->data[k];
130 if (FuncDeclaration* fd = s->isFuncDeclaration()) { 382 s->toObjFile(0);
131 if (thisModule || (fd->prot() != PROTprivate)) { 383 }
132 fd->toObjFile(0); // TODO: multiobj 384
133 } 385 const LLType* ST = irstruct->build();
134 } 386
135 else if (s->isAttribDeclaration() || 387 #if 0
136 s->isVarDeclaration() || 388 std::cout << sd->kind() << ' ' << sd->toPrettyChars() << " type: " << *ST << '\n';
137 s->isTemplateMixin()) { 389
138 s->toObjFile(0); // TODO: multiobj 390 // add fields
139 } 391 for (int k=0; k < fields->dim; k++)
140 else { 392 {
141 Logger::println("Ignoring dsymbol '%s' in this->members of kind '%s'", s->toPrettyChars(), s->kind()); 393 VarDeclaration* v = (VarDeclaration*)fields->data[k];
142 } 394 printf(" field: %s %s\n", v->type->toChars(), v->toChars());
143 } 395 printf(" index: %u offset: %u\n", v->ir.irField->index, v->ir.irField->unionOffset);
396 }
397
398 unsigned llvmSize = (unsigned)getABITypeSize(ST);
399 unsigned dmdSize = (unsigned)sd->type->size();
400 printf(" llvm size: %u dmd size: %u\n", llvmSize, dmdSize);
401 assert(llvmSize == dmdSize);
402
403 #endif
144 404
145 /*for (int k=0; k < sd->members->dim; k++) { 405 /*for (int k=0; k < sd->members->dim; k++) {
146 Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]); 406 Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]);
147 dsym->toObjFile(); 407 dsym->toObjFile();
148 }*/ 408 }*/
149 409
150 Logger::println("doing struct fields"); 410 Logger::println("doing struct fields");
151 411
152 const llvm::StructType* structtype = 0;
153 std::vector<const LLType*> fieldtypes;
154
155 if (irstruct->offsets.empty())
156 {
157 Logger::println("has no fields");
158 fieldtypes.push_back(LLType::Int8Ty);
159 structtype = llvm::StructType::get(fieldtypes, ispacked);
160 }
161 else
162 {
163 Logger::println("has fields");
164 unsigned prevsize = (unsigned)-1;
165 unsigned lastoffset = (unsigned)-1;
166 const LLType* fieldtype = NULL;
167 VarDeclaration* fieldinit = NULL;
168 size_t fieldpad = 0;
169 int idx = 0;
170 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
171 // first iteration
172 if (lastoffset == (unsigned)-1) {
173 lastoffset = i->first;
174 assert(lastoffset == 0);
175 fieldtype = i->second.type;
176 fieldinit = i->second.var;
177 prevsize = fieldinit->type->size();
178 i->second.var->ir.irField->index = idx;
179 }
180 // colliding offset?
181 else if (lastoffset == i->first) {
182 size_t s = i->second.var->type->size();
183 if (s > prevsize) {
184 fieldpad += s - prevsize;
185 prevsize = s;
186 }
187 sd->ir.irStruct->hasUnions = true;
188 i->second.var->ir.irField->index = idx;
189 }
190 // intersecting offset?
191 else if (i->first < (lastoffset + prevsize)) {
192 size_t s = i->second.var->type->size();
193 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
194 sd->ir.irStruct->hasUnions = true;
195 i->second.var->ir.irField->index = idx;
196 i->second.var->ir.irField->indexOffset = (i->first - lastoffset) / s;
197 }
198 // fresh offset
199 else {
200 // commit the field
201 fieldtypes.push_back(fieldtype);
202 irstruct->defaultFields.push_back(fieldinit);
203 if (fieldpad) {
204 fieldtypes.push_back(llvm::ArrayType::get(LLType::Int8Ty, fieldpad));
205 irstruct->defaultFields.push_back(NULL);
206 idx++;
207 }
208
209 idx++;
210
211 // start new
212 lastoffset = i->first;
213 fieldtype = i->second.type;
214 fieldinit = i->second.var;
215 prevsize = fieldinit->type->size();
216 i->second.var->ir.irField->index = idx;
217 fieldpad = 0;
218 }
219 }
220 fieldtypes.push_back(fieldtype);
221 irstruct->defaultFields.push_back(fieldinit);
222 if (fieldpad) {
223 fieldtypes.push_back(llvm::ArrayType::get(LLType::Int8Ty, fieldpad));
224 irstruct->defaultFields.push_back(NULL);
225 }
226
227 Logger::println("creating struct type");
228 structtype = llvm::StructType::get(fieldtypes, ispacked);
229 }
230
231 // refine abstract types for stuff like: struct S{S* next;} 412 // refine abstract types for stuff like: struct S{S* next;}
232 if (irstruct->recty != 0) 413 llvm::cast<llvm::OpaqueType>(ts->ir.type->get())->refineAbstractTypeTo(ST);
233 { 414 ST = ts->ir.type->get();
234 llvm::PATypeHolder& pa = irstruct->recty; 415
235 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype); 416 // name type
236 structtype = isaStruct(pa.get());
237 }
238
239 assert(ts->ir.type == 0);
240 ts->ir.type = new llvm::PATypeHolder(structtype);
241
242 if (sd->parent->isModule()) { 417 if (sd->parent->isModule()) {
243 gIR->module->addTypeName(sd->mangle(),structtype); 418 gIR->module->addTypeName(sd->mangle(),ST);
244 } 419 }
245 420
246 gIR->structs.pop_back(); 421 gIR->structs.pop_back();
247 422
248 gIR->declareList.push_back(sd); 423 gIR->declareList.push_back(sd);
263 std::string initname("_D"); 438 std::string initname("_D");
264 initname.append(sd->mangle()); 439 initname.append(sd->mangle());
265 initname.append("6__initZ"); 440 initname.append("6__initZ");
266 441
267 llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(sd); 442 llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(sd);
268 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->ir.type->get(), true, _linkage, NULL, initname, gIR->module); 443 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(sd->ir.irStruct->initOpaque.get(), true, _linkage, NULL, initname, gIR->module);
269 sd->ir.irStruct->init = initvar; 444 sd->ir.irStruct->init = initvar;
270 445
271 gIR->constInitList.push_back(sd); 446 gIR->constInitList.push_back(sd);
272 if (DtoIsTemplateInstance(sd) || sd->getModule() == gIR->dmodule) 447 if (DtoIsTemplateInstance(sd) || sd->getModule() == gIR->dmodule)
273 gIR->defineList.push_back(sd); 448 gIR->defineList.push_back(sd);
284 LOG_SCOPE; 459 LOG_SCOPE;
285 460
286 IrStruct* irstruct = sd->ir.irStruct; 461 IrStruct* irstruct = sd->ir.irStruct;
287 gIR->structs.push_back(irstruct); 462 gIR->structs.push_back(irstruct);
288 463
464 const llvm::StructType* structtype = isaStruct(sd->type->ir.type->get());
465
289 // make sure each offset knows its default initializer 466 // make sure each offset knows its default initializer
290 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) 467 Array* fields = &sd->fields;
291 { 468 for (int k=0; k < fields->dim; k++)
292 IrStruct::Offset* so = &i->second; 469 {
293 LLConstant* finit = DtoConstFieldInitializer(so->var->loc, so->var->type, so->var->init); 470 VarDeclaration* v = (VarDeclaration*)fields->data[k];
294 so->init = finit; 471 LLConstant* finit = DtoConstFieldInitializer(v->loc, v->type, v->init);
295 so->var->ir.irField->constInit = finit; 472 v->ir.irField->constInit = finit;
296 } 473 }
297
298 const llvm::StructType* structtype = isaStruct(sd->type->ir.type->get());
299
300 // go through the field inits and build the default initializer
301 std::vector<LLConstant*> fieldinits_ll;
302 size_t nfi = irstruct->defaultFields.size();
303 for (size_t i=0; i<nfi; ++i) {
304 LLConstant* c;
305 if (irstruct->defaultFields[i] != NULL) {
306 c = irstruct->defaultFields[i]->ir.irField->constInit;
307 assert(c);
308 }
309 else {
310 const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i));
311 std::vector<LLConstant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(LLType::Int8Ty, 0, false));
312 c = llvm::ConstantArray::get(arrty, vals);
313 }
314 fieldinits_ll.push_back(c);
315 }
316
317 // generate the union mapper
318 sd->ir.irStruct->dunion = new DUnion(); // uses gIR->topstruct()
319 474
320 // always generate the constant initalizer 475 // always generate the constant initalizer
321 if (!sd->zeroInit) { 476 if (sd->zeroInit)
477 {
478 Logger::println("Zero initialized");
479 irstruct->constInit = llvm::ConstantAggregateZero::get(structtype);
480 }
481 else
482 {
322 Logger::println("Not zero initialized"); 483 Logger::println("Not zero initialized");
323 #if 0 484
324 //assert(tk == gIR->gIR->topstruct()().size()); 485 LLConstant* c = irstruct->buildDefaultConstInit();
325 #ifndef LLVMD_NO_LOGGER 486 irstruct->constInit = c;
326 Logger::cout() << "struct type: " << *structtype << '\n'; 487 }
327 for (size_t k=0; k<fieldinits_ll.size(); ++k) { 488
328 Logger::cout() << "Type:" << '\n'; 489 // refine __initZ global type to the one of the initializer
329 Logger::cout() << *fieldinits_ll[k]->getType() << '\n'; 490 llvm::cast<llvm::OpaqueType>(irstruct->initOpaque.get())->refineAbstractTypeTo(irstruct->constInit->getType());
330 Logger::cout() << "Value:" << '\n';
331 Logger::cout() << *fieldinits_ll[k] << '\n';
332 }
333 Logger::cout() << "Initializer printed" << '\n';
334 #endif
335 #endif
336 sd->ir.irStruct->constInit = llvm::ConstantStruct::get(structtype,fieldinits_ll);
337 }
338 else {
339 Logger::println("Zero initialized");
340 sd->ir.irStruct->constInit = llvm::ConstantAggregateZero::get(structtype);
341 }
342 491
343 gIR->structs.pop_back(); 492 gIR->structs.pop_back();
344 493
345 // emit typeinfo 494 // emit typeinfo
346 if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMno_typeinfo) 495 if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMno_typeinfo)
383 // call memcmp 532 // call memcmp
384 size_t sz = getABITypeSize(DtoType(t)); 533 size_t sz = getABITypeSize(DtoType(t));
385 LLValue* val = DtoMemCmp(lhs->getRVal(), rhs->getRVal(), DtoConstSize_t(sz)); 534 LLValue* val = DtoMemCmp(lhs->getRVal(), rhs->getRVal(), DtoConstSize_t(sz));
386 return gIR->ir->CreateICmp(cmpop, val, LLConstantInt::get(val->getType(), 0, false), "tmp"); 535 return gIR->ir->CreateICmp(cmpop, val, LLConstantInt::get(val->getType(), 0, false), "tmp");
387 } 536 }
388
389 //////////////////////////////////////////////////////////////////////////////////////////
390 //////////////////////////// D UNION HELPER CLASS ////////////////////////////////////
391 //////////////////////////////////////////////////////////////////////////////////////////
392
393 DUnion::DUnion()
394 {
395 DUnionField* f = NULL;
396 IrStruct* topstruct = gIR->topstruct();
397 bool unions = false;
398 for (IrStruct::OffsetMap::iterator i=topstruct->offsets.begin(); i!=topstruct->offsets.end(); ++i)
399 {
400 unsigned o = i->first;
401 IrStruct::Offset* so = &i->second;
402 const LLType* ft = so->init->getType();
403 size_t sz = getABITypeSize(ft);
404 if (f == NULL) { // new field
405 fields.push_back(DUnionField());
406 f = &fields.back();
407 f->size = sz;
408 f->offset = o;
409 f->init = so->init;
410 f->initsize = sz;
411 f->types.push_back(ft);
412 }
413 else if (o == f->offset) { // same offset
414 if (sz > f->size)
415 f->size = sz;
416 f->types.push_back(ft);
417 unions = true;
418 }
419 else if (o < f->offset+f->size) {
420 assert((o+sz) <= (f->offset+f->size));
421 unions = true;
422 }
423 else {
424 fields.push_back(DUnionField());
425 f = &fields.back();
426 f->size = sz;
427 f->offset = o;
428 f->init = so->init;
429 f->initsize = sz;
430 f->types.push_back(ft);
431 }
432 }
433
434 ispacked = topstruct->packed;
435
436 /*{
437 LOG_SCOPE;
438 Logger::println("******** DUnion BEGIN");
439 size_t n = fields.size();
440 for (size_t i=0; i<n; ++i) {
441 Logger::cout()<<"field #"<<i<<" offset: "<<fields[i].offset<<" size: "<<fields[i].size<<'('<<fields[i].initsize<<")\n";
442 LOG_SCOPE;
443 size_t nt = fields[i].types.size();
444 for (size_t j=0; j<nt; ++j) {
445 Logger::cout()<<*fields[i].types[j]<<'\n';
446 }
447 }
448 Logger::println("******** DUnion END");
449 }*/
450 }
451
452 static void push_nulls(size_t nbytes, std::vector<LLConstant*>& out)
453 {
454 assert(nbytes > 0);
455 std::vector<LLConstant*> i(nbytes, llvm::ConstantInt::get(LLType::Int8Ty, 0, false));
456 out.push_back(llvm::ConstantArray::get(llvm::ArrayType::get(LLType::Int8Ty, nbytes), i));
457 }
458
459 LLConstant* DUnion::getConst(std::vector<DUnionIdx>& in)
460 {
461 std::sort(in.begin(), in.end());
462 std::vector<LLConstant*> out;
463
464 size_t nin = in.size();
465 size_t nfields = fields.size();
466
467 size_t fi = 0;
468 size_t last = 0;
469 size_t ii = 0;
470 size_t os = 0;
471
472 for(;;)
473 {
474 if (fi == nfields) break;
475
476 bool nextSame = (ii+1 < nin) && (in[ii+1].idx == fi);
477
478 if (ii < nin && fi == in[ii].idx)
479 {
480 size_t s = getABITypeSize(in[ii].c->getType());
481 if (in[ii].idx == last)
482 {
483 size_t nos = in[ii].idxos * s;
484 if (nos && nos-os) {
485 assert(nos >= os);
486 push_nulls(nos-os, out);
487 }
488 os = nos + s;
489 }
490 else
491 {
492 os = s;
493 }
494 out.push_back(in[ii].c);
495 ii++;
496 if (!nextSame)
497 {
498 if (os < fields[fi].size)
499 push_nulls(fields[fi].size - os, out);
500 os = 0;
501 last = fi++;
502 }
503 continue;
504 }
505
506 // default initialize if necessary
507 if (ii == nin || fi < in[ii].idx)
508 {
509 DUnionField& f = fields[fi];
510 out.push_back(f.init);
511 if (f.initsize < f.size)
512 push_nulls(f.size - f.initsize, out);
513 last = fi++;
514 os = 0;
515 continue;
516 }
517 }
518
519 std::vector<const LLType*> tys;
520 size_t nout = out.size();
521 for (size_t i=0; i<nout; ++i)
522 tys.push_back(out[i]->getType());
523
524 const llvm::StructType* st = llvm::StructType::get(tys, ispacked);
525 return llvm::ConstantStruct::get(st, out);
526 }
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547