comparison gen/toir.cpp @ 1255:9014d7f0433f

Rewrote runtime struct literal codegen.
author Tomas Lindquist Olsen <tomas.l.olsen gmail com>
date Wed, 22 Apr 2009 03:08:28 +0200
parents 01909bd1132c
children dd135ff697fa
comparison
equal deleted inserted replaced
1254:747fdd9245d7 1255:9014d7f0433f
35 #include "gen/dvalue.h" 35 #include "gen/dvalue.h"
36 #include "gen/aa.h" 36 #include "gen/aa.h"
37 #include "gen/functions.h" 37 #include "gen/functions.h"
38 #include "gen/todebug.h" 38 #include "gen/todebug.h"
39 #include "gen/nested.h" 39 #include "gen/nested.h"
40 #include "gen/utils.h"
40 41
41 #include "llvm/Support/ManagedStatic.h" 42 #include "llvm/Support/ManagedStatic.h"
42 43
43 ////////////////////////////////////////////////////////////////////////////////////////// 44 //////////////////////////////////////////////////////////////////////////////////////////
44 45
2402 return DtoConstSlice(DtoConstSize_t(elements->dim), globalstorePtr); 2403 return DtoConstSlice(DtoConstSize_t(elements->dim), globalstorePtr);
2403 } 2404 }
2404 2405
2405 ////////////////////////////////////////////////////////////////////////////////////////// 2406 //////////////////////////////////////////////////////////////////////////////////////////
2406 2407
2408 // building a struct literal is pretty much the same as building a default initializer.
2409
2410 extern size_t add_zeros(std::vector<llvm::Value*>& values, size_t diff);
2411 extern LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init);
2412
2407 DValue* StructLiteralExp::toElem(IRState* p) 2413 DValue* StructLiteralExp::toElem(IRState* p)
2408 { 2414 {
2409 Logger::print("StructLiteralExp::toElem: %s @ %s\n", toChars(), type->toChars()); 2415 Logger::print("StructLiteralExp::toElem: %s @ %s\n", toChars(), type->toChars());
2410 LOG_SCOPE; 2416 LOG_SCOPE;
2411 2417
2412 // make sure the struct is resolved 2418 // make sure the struct is fully resolved
2413 sd->codegen(Type::sir); 2419 sd->codegen(Type::sir);
2414 2420
2415 // get inits 2421 // final list of values to put in the struct
2416 std::vector<LLValue*> inits(sd->fields.dim, NULL); 2422 std::vector<LLValue*> initvalues;
2417 2423
2424 // offset tracker
2425 size_t offset = 0;
2426
2427 // align(1) struct S { ... }
2428 bool packed = sd->type->alignsize() == 1;
2429
2430 // ready elements data
2431 assert(elements && "struct literal has null elements");
2418 size_t nexprs = elements->dim;; 2432 size_t nexprs = elements->dim;;
2419 Expression** exprs = (Expression**)elements->data; 2433 Expression** exprs = (Expression**)elements->data;
2420 2434
2421 for (size_t i = 0; i < nexprs; i++) 2435 // go through fields
2422 { 2436 ArrayIter<VarDeclaration> it(sd->fields);
2423 if (exprs[i]) 2437 for (; !it.done(); it.next())
2424 { 2438 {
2425 DValue* v = exprs[i]->toElem(p); 2439 VarDeclaration* vd = it.get();
2426 inits[i] = v->getRVal(); 2440
2427 2441 if (vd->offset < offset)
2428 // make sure we get inner structs/staticarrays right 2442 {
2429 if (DtoIsPassedByRef(v->getType())) 2443 IF_LOG Logger::println("skipping field: %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
2430 inits[i] = DtoLoad(inits[i]); 2444 continue;
2431 } 2445 }
2432 } 2446
2433 2447 IF_LOG Logger::println("using field: %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
2434 // vector of values to build aggregate from 2448
2435 std::vector<LLValue*> values = DtoStructLiteralValues(sd, inits); 2449 // get next aligned offset for this field
2436 2450 size_t alignedoffset = offset;
2437 // get the struct type from the values 2451 if (!packed)
2438 size_t n = values.size(); 2452 {
2439 std::vector<const LLType*> types(n, NULL); 2453 size_t alignsize = vd->type->alignsize();
2440 2454 alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
2441 for (size_t i=0; i<n; i++) 2455 }
2442 { 2456
2443 types[i] = values[i]->getType(); 2457 // insert explicit padding?
2444 } 2458 if (alignedoffset < vd->offset)
2445 2459 {
2446 const LLStructType* sty = LLStructType::get(types, sd->ir.irStruct->packed); 2460 add_zeros(initvalues, vd->offset - alignedoffset);
2447 2461 }
2448 // allocate storage for the struct literal on the stack 2462
2449 LLValue* mem = DtoAlloca(sty, "tmpstructliteral"); 2463 // add initializer
2450 2464 Expression* expr = (it.index < nexprs) ? exprs[it.index] : NULL;
2451 // put all the values into the storage 2465 IF_LOG Logger::println("expr: %p", expr);
2452 for (size_t i=0; i<n; i++) 2466 if (expr)
2453 { 2467 {
2454 LLValue* ptr = DtoGEPi(mem, 0, i); 2468 IF_LOG Logger::println("expr = %s", it.index, expr->toChars());
2455 DtoStore(values[i], ptr); 2469 LLValue* v = DtoExprValue(vd->type, expr);
2456 } 2470 initvalues.push_back(v);
2457 2471 }
2458 // cast the alloca pointer to the "formal" struct type 2472 else
2459 const LLType* structtype = DtoType(sd->type); 2473 {
2460 mem = DtoBitCast(mem, getPtrToType(structtype)); 2474 IF_LOG Logger::println("using default initializer");
2475 initvalues.push_back(get_default_initializer(vd, NULL));
2476 }
2477
2478 // advance offset to right past this field
2479 offset = vd->offset + vd->type->size();
2480 }
2481
2482 // tail padding?
2483 if (offset < sd->structsize)
2484 {
2485 add_zeros(initvalues, sd->structsize - offset);
2486 }
2487
2488 // build type
2489 std::vector<const LLType*> valuetypes;
2490
2491 size_t n = initvalues.size();
2492 valuetypes.reserve(n);
2493
2494 for (size_t i = 0; i < n; i++)
2495 {
2496 valuetypes.push_back(initvalues[i]->getType());
2497 }
2498
2499 const LLType* st = llvm::StructType::get(valuetypes, packed);
2500
2501 // alloca a stack slot
2502 LLValue* mem = DtoAlloca(st, ".structliteral");
2503
2504 // fill in values
2505 for (size_t i = 0; i < n; i++)
2506 {
2507 LLValue* addr = DtoGEPi(mem, 0, i);
2508 p->ir->CreateStore(initvalues[i], addr);
2509 }
2510
2511 // cast to default struct type
2512 mem = DtoBitCast(mem, DtoType(sd->type->pointerTo()));
2461 2513
2462 // return as a var 2514 // return as a var
2463 return new DVarValue(type, mem); 2515 return new DVarValue(type, mem);
2464 } 2516 }
2465 2517