Mercurial > projects > ldc
comparison gen/toir.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 | 2025c9a24efd |
children | 7f6eeb7b003e |
comparison
equal
deleted
inserted
replaced
869:5dbc63f83380 | 870:af7a6faf9406 |
---|---|
858 LLConstant* CastExp::toConstElem(IRState* p) | 858 LLConstant* CastExp::toConstElem(IRState* p) |
859 { | 859 { |
860 Logger::print("CastExp::toConstElem: %s | %s\n", toChars(), type->toChars()); | 860 Logger::print("CastExp::toConstElem: %s | %s\n", toChars(), type->toChars()); |
861 LOG_SCOPE; | 861 LOG_SCOPE; |
862 | 862 |
863 LLConstant* c = e1->toConstElem(p); | 863 LLConstant* res; |
864 const LLType* lltype = DtoType(type); | 864 const LLType* lltype = DtoType(type); |
865 | 865 Type* tb = to->toBasetype(); |
866 if(!isaPointer(c->getType()) || !isaPointer(lltype)) { | 866 |
867 error("can only cast pointers to pointers at code generation time, not %s to %s", type->toChars(), e1->type->toChars()); | 867 // string literal to dyn array: |
868 fatal(); | 868 // reinterpret the string data as an array, calculate the length |
869 } | 869 if (e1->op == TOKstring && tb->ty == Tarray) { |
870 | 870 /* StringExp *strexp = (StringExp*)e1; |
871 return llvm::ConstantExpr::getBitCast(c, lltype); | 871 size_t datalen = strexp->sz * strexp->len; |
872 Type* eltype = tb->nextOf()->toBasetype(); | |
873 if (datalen % eltype->size() != 0) { | |
874 error("the sizes don't line up"); | |
875 return e1->toConstElem(p); | |
876 } | |
877 size_t arrlen = datalen / eltype->size();*/ | |
878 error("ct cast of string to dynamic array not fully implemented"); | |
879 return e1->toConstElem(p); | |
880 } | |
881 // pointer to pointer | |
882 else if (tb->ty == Tpointer && e1->type->toBasetype()->ty == Tpointer) { | |
883 res = llvm::ConstantExpr::getBitCast(e1->toConstElem(p), lltype); | |
884 } | |
885 else { | |
886 error("can not cast %s to %s at compile time", e1->type->toChars(), type->toChars()); | |
887 return e1->toConstElem(p); | |
888 } | |
889 | |
890 return res; | |
872 } | 891 } |
873 | 892 |
874 ////////////////////////////////////////////////////////////////////////////////////////// | 893 ////////////////////////////////////////////////////////////////////////////////////////// |
875 | 894 |
876 DValue* SymOffExp::toElem(IRState* p) | 895 DValue* SymOffExp::toElem(IRState* p) |
2362 DValue* StructLiteralExp::toElem(IRState* p) | 2381 DValue* StructLiteralExp::toElem(IRState* p) |
2363 { | 2382 { |
2364 Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); | 2383 Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); |
2365 LOG_SCOPE; | 2384 LOG_SCOPE; |
2366 | 2385 |
2367 // get arrays | 2386 // get inits |
2387 std::vector<LLValue*> inits(sd->fields.dim, NULL); | |
2388 | |
2368 size_t nexprs = elements->dim;; | 2389 size_t nexprs = elements->dim;; |
2369 Expression** exprs = (Expression**)elements->data; | 2390 Expression** exprs = (Expression**)elements->data; |
2370 | 2391 |
2371 size_t nvars = sd->fields.dim; | 2392 for (size_t i = 0; i < nexprs; i++) |
2372 VarDeclaration** vars = (VarDeclaration**)sd->fields.data; | |
2373 | |
2374 assert(nexprs <= nvars); | |
2375 | |
2376 // first locate all explicit initializers | |
2377 std::vector<VarDeclaration*> explicitInits; | |
2378 for (size_t i=0; i < nexprs; i++) | |
2379 { | 2393 { |
2380 if (exprs[i]) | 2394 if (exprs[i]) |
2381 { | 2395 { |
2382 explicitInits.push_back(vars[i]); | 2396 DValue* v = exprs[i]->toElem(p); |
2397 inits[i] = v->getRVal(); | |
2383 } | 2398 } |
2384 } | 2399 } |
2385 | 2400 |
2386 // vector of values to build aggregate from | 2401 // vector of values to build aggregate from |
2387 std::vector<llvm::Value*> values; | 2402 std::vector<LLValue*> values = DtoStructLiteralValues(sd, inits); |
2388 | |
2389 // offset trackers | |
2390 size_t lastoffset = 0; | |
2391 size_t lastsize = 0; | |
2392 | |
2393 // index of next explicit init | |
2394 size_t exidx = 0; | |
2395 // number of explicit inits | |
2396 size_t nex = explicitInits.size(); | |
2397 | |
2398 // for through each field and build up the struct, padding with zeros | |
2399 size_t i; | |
2400 for (i=0; i<nvars; i++) | |
2401 { | |
2402 Expression* e = (nexprs > i) ? exprs[i] : NULL; | |
2403 VarDeclaration* var = vars[i]; | |
2404 | |
2405 // get var info | |
2406 size_t os = var->offset; | |
2407 size_t sz = var->type->size(); | |
2408 | |
2409 // get next explicit | |
2410 VarDeclaration* nextVar = NULL; | |
2411 size_t nextOs = 0; | |
2412 if (exidx < nex) | |
2413 { | |
2414 nextVar = explicitInits[exidx]; | |
2415 nextOs = nextVar->offset; | |
2416 } | |
2417 // none, rest is defaults | |
2418 else | |
2419 { | |
2420 break; | |
2421 } | |
2422 | |
2423 // not explicit initializer, default initialize if there is room, otherwise skip | |
2424 if (!e) | |
2425 { | |
2426 // default init if there is room | |
2427 // (past current offset) and (small enough to fit before next explicit) | |
2428 if ((os >= lastoffset + lastsize) && (os+sz <= nextOs)) | |
2429 { | |
2430 // add any 0 padding needed before this field | |
2431 if (os > lastoffset + lastsize) | |
2432 { | |
2433 //printf("1added %lu zeros\n", os - lastoffset - lastsize); | |
2434 addZeros(values, lastoffset + lastsize, os); | |
2435 } | |
2436 | |
2437 // get field default init | |
2438 IrField* f = var->ir.irField; | |
2439 assert(f); | |
2440 if (!f->constInit) | |
2441 f->constInit = DtoConstInitializer(var->loc, var->type, var->init); | |
2442 | |
2443 values.push_back(f->constInit); | |
2444 | |
2445 lastoffset = os; | |
2446 lastsize = sz; | |
2447 //printf("added default: %s : %lu (%lu)\n", var->toChars(), os, sz); | |
2448 } | |
2449 // skip | |
2450 continue; | |
2451 } | |
2452 | |
2453 assert(nextVar == var); | |
2454 | |
2455 // add any 0 padding needed before this field | |
2456 if (os > lastoffset + lastsize) | |
2457 { | |
2458 //printf("added %lu zeros\n", os - lastoffset - lastsize); | |
2459 addZeros(values, lastoffset + lastsize, os); | |
2460 } | |
2461 | |
2462 // add the expression value | |
2463 DValue* v = e->toElem(p); | |
2464 values.push_back(v->getRVal()); | |
2465 | |
2466 // update offsets | |
2467 lastoffset = os; | |
2468 lastsize = sz; | |
2469 | |
2470 // go to next explicit init | |
2471 exidx++; | |
2472 | |
2473 //printf("added field: %s : %lu (%lu)\n", var->toChars(), os, sz); | |
2474 } | |
2475 | |
2476 // fill out rest with default initializers | |
2477 const LLType* structtype = DtoType(sd->type); | |
2478 size_t structsize = getABITypeSize(structtype); | |
2479 | |
2480 // FIXME: this could probably share some code with the above | |
2481 if (structsize > lastoffset+lastsize) | |
2482 { | |
2483 for (/*continue from first loop*/; i < nvars; i++) | |
2484 { | |
2485 VarDeclaration* var = vars[i]; | |
2486 | |
2487 // get var info | |
2488 size_t os = var->offset; | |
2489 size_t sz = var->type->size(); | |
2490 | |
2491 // skip? | |
2492 if (os < lastoffset + lastsize) | |
2493 continue; | |
2494 | |
2495 // add any 0 padding needed before this field | |
2496 if (os > lastoffset + lastsize) | |
2497 { | |
2498 //printf("2added %lu zeros\n", os - lastoffset - lastsize); | |
2499 addZeros(values, lastoffset + lastsize, os); | |
2500 } | |
2501 | |
2502 // get field default init | |
2503 IrField* f = var->ir.irField; | |
2504 assert(f); | |
2505 if (!f->constInit) | |
2506 f->constInit = DtoConstInitializer(var->loc, var->type, var->init); | |
2507 | |
2508 values.push_back(f->constInit); | |
2509 | |
2510 lastoffset = os; | |
2511 lastsize = sz; | |
2512 //printf("2added default: %s : %lu (%lu)\n", var->toChars(), os, sz); | |
2513 } | |
2514 } | |
2515 | |
2516 // add any 0 padding needed at the end of the literal | |
2517 if (structsize > lastoffset+lastsize) | |
2518 { | |
2519 //printf("3added %lu zeros\n", structsize - lastoffset - lastsize); | |
2520 addZeros(values, lastoffset + lastsize, structsize); | |
2521 } | |
2522 | 2403 |
2523 // get the struct type from the values | 2404 // get the struct type from the values |
2524 size_t n = values.size(); | 2405 size_t n = values.size(); |
2525 std::vector<const LLType*> types(n, NULL); | 2406 std::vector<const LLType*> types(n, NULL); |
2526 | 2407 |
2540 LLValue* ptr = DtoGEPi(mem, 0, i); | 2421 LLValue* ptr = DtoGEPi(mem, 0, i); |
2541 DtoStore(values[i], ptr); | 2422 DtoStore(values[i], ptr); |
2542 } | 2423 } |
2543 | 2424 |
2544 // cast the alloca pointer to the "formal" struct type | 2425 // cast the alloca pointer to the "formal" struct type |
2426 const LLType* structtype = DtoType(sd->type); | |
2545 mem = DtoBitCast(mem, getPtrToType(structtype)); | 2427 mem = DtoBitCast(mem, getPtrToType(structtype)); |
2546 | 2428 |
2547 // return as a var | 2429 // return as a var |
2548 return new DVarValue(type, mem); | 2430 return new DVarValue(type, mem); |
2549 } | 2431 } |
2553 LLConstant* StructLiteralExp::toConstElem(IRState* p) | 2435 LLConstant* StructLiteralExp::toConstElem(IRState* p) |
2554 { | 2436 { |
2555 Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars()); | 2437 Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars()); |
2556 LOG_SCOPE; | 2438 LOG_SCOPE; |
2557 | 2439 |
2558 // get arrays | 2440 // get inits |
2559 size_t n = elements->dim; | 2441 std::vector<LLValue*> inits(sd->fields.dim, NULL); |
2442 | |
2443 size_t nexprs = elements->dim;; | |
2560 Expression** exprs = (Expression**)elements->data; | 2444 Expression** exprs = (Expression**)elements->data; |
2561 | 2445 |
2562 assert(sd->fields.dim == n); | 2446 for (size_t i = 0; i < nexprs; i++) |
2563 VarDeclaration** vars = (VarDeclaration**)sd->fields.data; | 2447 if (exprs[i]) |
2448 inits[i] = exprs[i]->toConstElem(p); | |
2564 | 2449 |
2565 // vector of values to build aggregate from | 2450 // vector of values to build aggregate from |
2566 std::vector<llvm::Constant*> values; | 2451 std::vector<LLValue*> values = DtoStructLiteralValues(sd, inits); |
2567 | 2452 |
2568 // trackers | 2453 // we know those values are constants.. cast them |
2569 size_t lastoffset = 0; | 2454 std::vector<LLConstant*> constvals(values.size(), NULL); |
2570 size_t lastsize = 0; | 2455 for (size_t i = 0; i < values.size(); ++i) |
2571 | 2456 constvals[i] = llvm::cast<LLConstant>(values[i]); |
2572 // for through each field and build up the struct, padding with zeros | |
2573 for (size_t i=0; i<n; i++) | |
2574 { | |
2575 Expression* e = exprs[i]; | |
2576 VarDeclaration* var = vars[i]; | |
2577 | |
2578 // field is skipped | |
2579 if (!e) | |
2580 continue; | |
2581 | |
2582 // add any 0 padding needed before this field | |
2583 if (var->offset > lastoffset + lastsize) | |
2584 { | |
2585 addZeros(values, lastoffset + lastsize, var->offset); | |
2586 } | |
2587 | |
2588 // add the expression value | |
2589 values.push_back(e->toConstElem(p)); | |
2590 | |
2591 // update offsets | |
2592 lastoffset = var->offset; | |
2593 lastsize = var->type->size(); | |
2594 } | |
2595 | |
2596 // add any 0 padding needed at the end of the literal | |
2597 const LLType* structtype = DtoType(sd->type); | |
2598 size_t structsize = getABITypeSize(structtype); | |
2599 | |
2600 if (structsize > lastoffset+lastsize) | |
2601 { | |
2602 addZeros(values, lastoffset + lastsize, structsize); | |
2603 } | |
2604 | 2457 |
2605 // return constant struct | 2458 // return constant struct |
2606 return LLConstantStruct::get(values, sd->ir.irStruct->packed); | 2459 return LLConstantStruct::get(constvals, sd->ir.irStruct->packed); |
2607 } | 2460 } |
2608 | 2461 |
2609 ////////////////////////////////////////////////////////////////////////////////////////// | 2462 ////////////////////////////////////////////////////////////////////////////////////////// |
2610 | 2463 |
2611 DValue* InExp::toElem(IRState* p) | 2464 DValue* InExp::toElem(IRState* p) |