comparison gen/structs.cpp @ 870:af7a6faf9406

Fix #153. Factor out common code in StructLiteralExp::to(Const)Elem.
author Christian Kamm <kamm incasoftware de>
date Tue, 30 Dec 2008 11:42:01 +0100
parents a125ada7fd95
children 39519a1ff603
comparison
equal deleted inserted replaced
869:5dbc63f83380 870:af7a6faf9406
296 return c; 296 return c;
297 } 297 }
298 298
299 ////////////////////////////////////////////////////////////////////////////////////////// 299 //////////////////////////////////////////////////////////////////////////////////////////
300 300
301 std::vector<llvm::Value*> DtoStructLiteralValues(const StructDeclaration* sd, const std::vector<llvm::Value*>& inits)
302 {
303 // get arrays
304 size_t nvars = sd->fields.dim;
305 VarDeclaration** vars = (VarDeclaration**)sd->fields.data;
306
307 assert(inits.size() == nvars);
308
309 // first locate all explicit initializers
310 std::vector<VarDeclaration*> explicitInits;
311 for (size_t i=0; i < nvars; i++)
312 {
313 if (inits[i])
314 {
315 explicitInits.push_back(vars[i]);
316 }
317 }
318
319 // vector of values to build aggregate from
320 std::vector<llvm::Value*> values;
321
322 // offset trackers
323 size_t lastoffset = 0;
324 size_t lastsize = 0;
325
326 // index of next explicit init
327 size_t exidx = 0;
328 // number of explicit inits
329 size_t nex = explicitInits.size();
330
331 // for through each field and build up the struct, padding with zeros
332 size_t i;
333 for (i=0; i<nvars; i++)
334 {
335 VarDeclaration* var = vars[i];
336
337 // get var info
338 size_t os = var->offset;
339 size_t sz = var->type->size();
340
341 // get next explicit
342 VarDeclaration* nextVar = NULL;
343 size_t nextOs = 0;
344 if (exidx < nex)
345 {
346 nextVar = explicitInits[exidx];
347 nextOs = nextVar->offset;
348 }
349 // none, rest is defaults
350 else
351 {
352 break;
353 }
354
355 // not explicit initializer, default initialize if there is room, otherwise skip
356 if (!inits[i])
357 {
358 // default init if there is room
359 // (past current offset) and (small enough to fit before next explicit)
360 if ((os >= lastoffset + lastsize) && (os+sz <= nextOs))
361 {
362 // add any 0 padding needed before this field
363 if (os > lastoffset + lastsize)
364 {
365 //printf("1added %lu zeros\n", os - lastoffset - lastsize);
366 addZeros(values, lastoffset + lastsize, os);
367 }
368
369 // get field default init
370 IrField* f = var->ir.irField;
371 assert(f);
372 if (!f->constInit)
373 f->constInit = DtoConstInitializer(var->loc, var->type, var->init);
374
375 values.push_back(f->constInit);
376
377 lastoffset = os;
378 lastsize = sz;
379 //printf("added default: %s : %lu (%lu)\n", var->toChars(), os, sz);
380 }
381 // skip
382 continue;
383 }
384
385 assert(nextVar == var);
386
387 // add any 0 padding needed before this field
388 if (os > lastoffset + lastsize)
389 {
390 //printf("added %lu zeros\n", os - lastoffset - lastsize);
391 addZeros(values, lastoffset + lastsize, os);
392 }
393
394 // add the expression value
395 values.push_back(inits[i]);
396
397 // update offsets
398 lastoffset = os;
399 lastsize = sz;
400
401 // go to next explicit init
402 exidx++;
403
404 //printf("added field: %s : %lu (%lu)\n", var->toChars(), os, sz);
405 }
406
407 // fill out rest with default initializers
408 const LLType* structtype = DtoType(sd->type);
409 size_t structsize = getABITypeSize(structtype);
410
411 // FIXME: this could probably share some code with the above
412 if (structsize > lastoffset+lastsize)
413 {
414 for (/*continue from first loop*/; i < nvars; i++)
415 {
416 VarDeclaration* var = vars[i];
417
418 // get var info
419 size_t os = var->offset;
420 size_t sz = var->type->size();
421
422 // skip?
423 if (os < lastoffset + lastsize)
424 continue;
425
426 // add any 0 padding needed before this field
427 if (os > lastoffset + lastsize)
428 {
429 //printf("2added %lu zeros\n", os - lastoffset - lastsize);
430 addZeros(values, lastoffset + lastsize, os);
431 }
432
433 // get field default init
434 IrField* f = var->ir.irField;
435 assert(f);
436 if (!f->constInit)
437 f->constInit = DtoConstInitializer(var->loc, var->type, var->init);
438
439 values.push_back(f->constInit);
440
441 lastoffset = os;
442 lastsize = sz;
443 //printf("2added default: %s : %lu (%lu)\n", var->toChars(), os, sz);
444 }
445 }
446
447 // add any 0 padding needed at the end of the literal
448 if (structsize > lastoffset+lastsize)
449 {
450 //printf("3added %lu zeros\n", structsize - lastoffset - lastsize);
451 addZeros(values, lastoffset + lastsize, structsize);
452 }
453
454 return values;
455 }
456
457 //////////////////////////////////////////////////////////////////////////////////////////
458
301 LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd) 459 LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
302 { 460 {
303 Logger::println("indexing struct field %s:", vd->toPrettyChars()); 461 Logger::println("indexing struct field %s:", vd->toPrettyChars());
304 LOG_SCOPE; 462 LOG_SCOPE;
305 463