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