comparison gen/toir.cpp @ 823:794c8af186ce

Fixed non-static struct initializers.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Wed, 03 Dec 2008 01:40:28 +0100
parents bb4a81e68ddb
children a70ddd449e7d
comparison
equal deleted inserted replaced
822:43178a913a28 823:794c8af186ce
2333 { 2333 {
2334 Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); 2334 Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
2335 LOG_SCOPE; 2335 LOG_SCOPE;
2336 2336
2337 // get arrays 2337 // get arrays
2338 size_t n = elements->dim; 2338 size_t nexprs = elements->dim;;
2339 Expression** exprs = (Expression**)elements->data; 2339 Expression** exprs = (Expression**)elements->data;
2340 2340
2341 assert(sd->fields.dim == n); 2341 size_t nvars = sd->fields.dim;
2342 VarDeclaration** vars = (VarDeclaration**)sd->fields.data; 2342 VarDeclaration** vars = (VarDeclaration**)sd->fields.data;
2343
2344 assert(nexprs <= nvars);
2345
2346 // first locate all explicit initializers
2347 std::vector<VarDeclaration*> explicitInits;
2348 for (size_t i=0; i < nexprs; i++)
2349 {
2350 if (exprs[i])
2351 {
2352 explicitInits.push_back(vars[i]);
2353 }
2354 }
2343 2355
2344 // vector of values to build aggregate from 2356 // vector of values to build aggregate from
2345 std::vector<llvm::Value*> values; 2357 std::vector<llvm::Value*> values;
2346 2358
2347 // trackers 2359 // offset trackers
2348 size_t lastoffset = 0; 2360 size_t lastoffset = 0;
2349 size_t lastsize = 0; 2361 size_t lastsize = 0;
2350 2362
2363 // index of next explicit init
2364 size_t exidx = 0;
2365 // number of explicit inits
2366 size_t nex = explicitInits.size();
2367
2351 // for through each field and build up the struct, padding with zeros 2368 // for through each field and build up the struct, padding with zeros
2352 for (size_t i=0; i<n; i++) 2369 size_t i;
2353 { 2370 for (i=0; i<nvars; i++)
2354 Expression* e = exprs[i]; 2371 {
2372 Expression* e = (nexprs > i) ? exprs[i] : NULL;
2355 VarDeclaration* var = vars[i]; 2373 VarDeclaration* var = vars[i];
2356 2374
2357 // field is skipped 2375 // get var info
2376 size_t os = var->offset;
2377 size_t sz = var->type->size();
2378
2379 // get next explicit
2380 VarDeclaration* nextVar = NULL;
2381 size_t nextOs = 0;
2382 if (exidx < nex)
2383 {
2384 nextVar = explicitInits[exidx];
2385 nextOs = nextVar->offset;
2386 }
2387 // none, rest is defaults
2388 else
2389 {
2390 break;
2391 }
2392
2393 // not explicit initializer, default initialize if there is room, otherwise skip
2358 if (!e) 2394 if (!e)
2395 {
2396 // default init if there is room
2397 // (past current offset) and (small enough to fit before next explicit)
2398 if ((os >= lastoffset + lastsize) && (os+sz <= nextOs))
2399 {
2400 // add any 0 padding needed before this field
2401 if (os > lastoffset + lastsize)
2402 {
2403 //printf("1added %lu zeros\n", os - lastoffset - lastsize);
2404 addZeros(values, lastoffset + lastsize, os);
2405 }
2406
2407 // get field default init
2408 IrField* f = var->ir.irField;
2409 assert(f);
2410 if (!f->constInit)
2411 f->constInit = DtoConstInitializer(var->loc, var->type, var->init);
2412
2413 values.push_back(f->constInit);
2414
2415 lastoffset = os;
2416 lastsize = sz;
2417 //printf("added default: %s : %lu (%lu)\n", var->toChars(), os, sz);
2418 }
2419 // skip
2359 continue; 2420 continue;
2421 }
2422
2423 assert(nextVar == var);
2360 2424
2361 // add any 0 padding needed before this field 2425 // add any 0 padding needed before this field
2362 if (var->offset > lastoffset + lastsize) 2426 if (os > lastoffset + lastsize)
2363 { 2427 {
2364 addZeros(values, lastoffset + lastsize, var->offset); 2428 //printf("added %lu zeros\n", os - lastoffset - lastsize);
2429 addZeros(values, lastoffset + lastsize, os);
2365 } 2430 }
2366 2431
2367 // add the expression value 2432 // add the expression value
2368 DValue* v = e->toElem(p); 2433 DValue* v = e->toElem(p);
2369 values.push_back(v->getRVal()); 2434 values.push_back(v->getRVal());
2370 2435
2371 // update offsets 2436 // update offsets
2372 lastoffset = var->offset; 2437 lastoffset = os;
2373 lastsize = var->type->size(); 2438 lastsize = sz;
2374 } 2439
2375 2440 // go to next explicit init
2376 // add any 0 padding needed at the end of the literal 2441 exidx++;
2442
2443 //printf("added field: %s : %lu (%lu)\n", var->toChars(), os, sz);
2444 }
2445
2446 // fill out rest with default initializers
2377 const LLType* structtype = DtoType(sd->type); 2447 const LLType* structtype = DtoType(sd->type);
2378 size_t structsize = getABITypeSize(structtype); 2448 size_t structsize = getABITypeSize(structtype);
2379 2449
2450 // FIXME: this could probably share some code with the above
2380 if (structsize > lastoffset+lastsize) 2451 if (structsize > lastoffset+lastsize)
2381 { 2452 {
2453 for (/*continue from first loop*/; i < nvars; i++)
2454 {
2455 VarDeclaration* var = vars[i];
2456
2457 // get var info
2458 size_t os = var->offset;
2459 size_t sz = var->type->size();
2460
2461 // skip?
2462 if (os < lastoffset + lastsize)
2463 continue;
2464
2465 // add any 0 padding needed before this field
2466 if (os > lastoffset + lastsize)
2467 {
2468 //printf("2added %lu zeros\n", os - lastoffset - lastsize);
2469 addZeros(values, lastoffset + lastsize, os);
2470 }
2471
2472 // get field default init
2473 IrField* f = var->ir.irField;
2474 assert(f);
2475 if (!f->constInit)
2476 f->constInit = DtoConstInitializer(var->loc, var->type, var->init);
2477
2478 values.push_back(f->constInit);
2479
2480 lastoffset = os;
2481 lastsize = sz;
2482 //printf("2added default: %s : %lu (%lu)\n", var->toChars(), os, sz);
2483 }
2484 }
2485
2486 // add any 0 padding needed at the end of the literal
2487 if (structsize > lastoffset+lastsize)
2488 {
2489 //printf("3added %lu zeros\n", structsize - lastoffset - lastsize);
2382 addZeros(values, lastoffset + lastsize, structsize); 2490 addZeros(values, lastoffset + lastsize, structsize);
2383 } 2491 }
2384 2492
2385 // get the struct type from the values 2493 // get the struct type from the values
2386 n = values.size(); 2494 size_t n = values.size();
2387 std::vector<const LLType*> types(n, NULL); 2495 std::vector<const LLType*> types(n, NULL);
2388 2496
2389 for (size_t i=0; i<n; i++) 2497 for (size_t i=0; i<n; i++)
2390 { 2498 {
2391 types[i] = values[i]->getType(); 2499 types[i] = values[i]->getType();