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)