Mercurial > projects > ldc
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(); |