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