Mercurial > projects > ldc
comparison gen/toir.c @ 14:0e86428ee567 trunk
[svn r18] * Initial support for switch statements - No string switches yet.
* Moved Statement::toIR definitions into gen/statements.c - toir.c is still too big.
* Removed some BB bloat with ScopeStatements.
author | lindquist |
---|---|
date | Wed, 03 Oct 2007 02:15:12 +0200 |
parents | d3ee9efe20e2 |
children | 37a4fdab33fc |
comparison
equal
deleted
inserted
replaced
13:3d1d98329fa7 | 14:0e86428ee567 |
---|---|
2397 void | 2397 void |
2398 ClassDeclaration::toDebug() | 2398 ClassDeclaration::toDebug() |
2399 { | 2399 { |
2400 } | 2400 } |
2401 | 2401 |
2402 /* --------------------------------------------------------------------------------------- */ | 2402 ////////////////////////////////////////////////////////////////////////////// |
2403 | |
2404 void CompoundStatement::toIR(IRState* p) | |
2405 { | |
2406 static int csi = 0; | |
2407 Logger::println("CompoundStatement::toIR(%d):\n<<<\n%s>>>", csi++, toChars()); | |
2408 LOG_SCOPE; | |
2409 | |
2410 /* | |
2411 const char* labelname; | |
2412 bool insterm = false; | |
2413 | |
2414 if (!p->scopes()) { | |
2415 labelname = "bb"; | |
2416 insterm = true; | |
2417 } | |
2418 else | |
2419 labelname = "entry"; | |
2420 | |
2421 //if (!llvm::isa<llvm::TerminatorInst>(p->topfunc()->back().back())) | |
2422 // insterm = true; | |
2423 | |
2424 llvm::BasicBlock* bb = new llvm::BasicBlock(labelname, p->topfunc()); | |
2425 | |
2426 if (insterm) { | |
2427 new llvm::BranchInst(bb,p->topbb()); | |
2428 } | |
2429 | |
2430 p->bbs.push(bb); | |
2431 */ | |
2432 | |
2433 size_t n = statements->dim; | |
2434 for (size_t i=0; i<n; i++) | |
2435 { | |
2436 Statement* s = (Statement*)statements->data[i]; | |
2437 if (s) | |
2438 s->toIR(p); | |
2439 else | |
2440 Logger::println("NULL statement found in CompoundStatement !! :S"); | |
2441 } | |
2442 | |
2443 //p->bbs.pop(); | |
2444 } | |
2445 | |
2446 void ReturnStatement::toIR(IRState* p) | |
2447 { | |
2448 static int rsi = 0; | |
2449 Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars()); | |
2450 LOG_SCOPE; | |
2451 | |
2452 if (exp) | |
2453 { | |
2454 TY expty = exp->type->ty; | |
2455 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { | |
2456 assert(expty == Tstruct || expty == Tdelegate || expty == Tarray); | |
2457 | |
2458 TypeFunction* f = p->topfunctype(); | |
2459 assert(f->llvmRetInPtr && f->llvmRetArg); | |
2460 | |
2461 p->lvals.push_back(f->llvmRetArg); | |
2462 elem* e = exp->toElem(p); | |
2463 p->lvals.pop_back(); | |
2464 | |
2465 // structliterals do this themselves | |
2466 // also they dont produce any value | |
2467 if (expty == Tstruct) { | |
2468 if (!e->inplace) { | |
2469 TypeStruct* ts = (TypeStruct*)exp->type; | |
2470 assert(e->mem); | |
2471 LLVM_DtoStructCopy(ts,f->llvmRetArg,e->mem); | |
2472 } | |
2473 } | |
2474 else if (expty == Tdelegate) { | |
2475 // do nothing, handled by the DelegateExp | |
2476 LLVM_DtoDelegateCopy(f->llvmRetArg,e->mem); | |
2477 } | |
2478 else if (expty == Tarray) { | |
2479 if (e->type == elem::SLICE) { | |
2480 LLVM_DtoSetArray(f->llvmRetArg,e->arg,e->mem); | |
2481 } | |
2482 // else the return value is a variable and should already have been assigned by now | |
2483 } | |
2484 else | |
2485 assert(0); | |
2486 | |
2487 new llvm::ReturnInst(p->scopebb()); | |
2488 delete e; | |
2489 } | |
2490 else { | |
2491 elem* e = exp->toElem(p); | |
2492 llvm::Value* v = e->getValue(); | |
2493 Logger::cout() << *v << '\n'; | |
2494 new llvm::ReturnInst(v, p->scopebb()); | |
2495 delete e; | |
2496 } | |
2497 } | |
2498 else | |
2499 { | |
2500 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) | |
2501 new llvm::ReturnInst(p->scopebb()); | |
2502 else | |
2503 new llvm::UnreachableInst(p->scopebb()); | |
2504 } | |
2505 | |
2506 p->scope().returned = true; | |
2507 } | |
2508 | |
2509 void ExpStatement::toIR(IRState* p) | |
2510 { | |
2511 static int esi = 0; | |
2512 Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars()); | |
2513 LOG_SCOPE; | |
2514 | |
2515 if (exp != 0) { | |
2516 elem* e = exp->toElem(p); | |
2517 delete e; | |
2518 } | |
2519 /*elem* e = exp->toElem(p); | |
2520 p->buf.printf("%s", e->toChars()); | |
2521 delete e; | |
2522 p->buf.writenl();*/ | |
2523 } | |
2524 | |
2525 void IfStatement::toIR(IRState* p) | |
2526 { | |
2527 static int wsi = 0; | |
2528 Logger::println("IfStatement::toIR(%d): %s", wsi++, toChars()); | |
2529 LOG_SCOPE; | |
2530 | |
2531 elem* cond_e = condition->toElem(p); | |
2532 llvm::Value* cond_val = cond_e->getValue(); | |
2533 delete cond_e; | |
2534 | |
2535 llvm::BasicBlock* oldend = gIR->scopeend(); | |
2536 | |
2537 llvm::BasicBlock* ifbb = new llvm::BasicBlock("if", gIR->topfunc(), oldend); | |
2538 llvm::BasicBlock* endbb = new llvm::BasicBlock("endif", gIR->topfunc(), oldend); | |
2539 llvm::BasicBlock* elsebb = 0; | |
2540 if (elsebody) { | |
2541 elsebb = new llvm::BasicBlock("else", gIR->topfunc(), endbb); | |
2542 } | |
2543 else { | |
2544 elsebb = endbb; | |
2545 } | |
2546 | |
2547 if (cond_val->getType() != llvm::Type::Int1Ty) { | |
2548 Logger::cout() << "if conditional: " << *cond_val << '\n'; | |
2549 cond_val = LLVM_DtoBoolean(cond_val); | |
2550 } | |
2551 llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebegin()); | |
2552 | |
2553 // replace current scope | |
2554 gIR->scope() = IRScope(ifbb,elsebb); | |
2555 | |
2556 bool endifUsed = false; | |
2557 | |
2558 // do scoped statements | |
2559 ifbody->toIR(p); | |
2560 if (!gIR->scopereturned()) { | |
2561 new llvm::BranchInst(endbb,gIR->scopebegin()); | |
2562 endifUsed = true; | |
2563 } | |
2564 | |
2565 if (elsebody) { | |
2566 //assert(0); | |
2567 gIR->scope() = IRScope(elsebb,endbb); | |
2568 elsebody->toIR(p); | |
2569 if (!gIR->scopereturned()) { | |
2570 new llvm::BranchInst(endbb,gIR->scopebegin()); | |
2571 endifUsed = true; | |
2572 } | |
2573 } | |
2574 | |
2575 // rewrite the scope | |
2576 gIR->scope() = IRScope(endbb,oldend); | |
2577 } | |
2578 | |
2579 void ScopeStatement::toIR(IRState* p) | |
2580 { | |
2581 static int wsi = 0; | |
2582 Logger::println("ScopeStatement::toIR(%d): %s", wsi++, toChars()); | |
2583 LOG_SCOPE; | |
2584 | |
2585 llvm::BasicBlock* oldend = gIR->scopeend(); | |
2586 | |
2587 IRScope irs; | |
2588 // remove useless branches by clearing and reusing the current basicblock | |
2589 llvm::BasicBlock* bb = gIR->scopebegin(); | |
2590 if (bb->empty()) { | |
2591 irs.begin = bb; | |
2592 } | |
2593 else { | |
2594 irs.begin = new llvm::BasicBlock("scope", gIR->topfunc(), oldend); | |
2595 new llvm::BranchInst(irs.begin, gIR->scopebegin()); | |
2596 } | |
2597 irs.end = new llvm::BasicBlock("endscope", gIR->topfunc(), oldend); | |
2598 | |
2599 gIR->scope() = irs; | |
2600 | |
2601 statement->toIR(p); | |
2602 if (!gIR->scopereturned()) { | |
2603 new llvm::BranchInst(irs.end, gIR->scopebegin()); | |
2604 } | |
2605 | |
2606 // rewrite the scope | |
2607 gIR->scope() = IRScope(irs.end,oldend); | |
2608 } | |
2609 | |
2610 void WhileStatement::toIR(IRState* p) | |
2611 { | |
2612 static int wsi = 0; | |
2613 Logger::println("WhileStatement::toIR(%d): %s", wsi++, toChars()); | |
2614 LOG_SCOPE; | |
2615 | |
2616 // create while blocks | |
2617 llvm::BasicBlock* oldend = gIR->scopeend(); | |
2618 llvm::BasicBlock* whilebb = new llvm::BasicBlock("whilecond", gIR->topfunc(), oldend); | |
2619 llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend); | |
2620 | |
2621 // move into the while block | |
2622 new llvm::BranchInst(whilebb, gIR->scopebegin()); | |
2623 | |
2624 // replace current scope | |
2625 gIR->scope() = IRScope(whilebb,endbb); | |
2626 | |
2627 // create the condition | |
2628 elem* cond_e = condition->toElem(p); | |
2629 llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); | |
2630 delete cond_e; | |
2631 | |
2632 // while body block | |
2633 llvm::BasicBlock* whilebodybb = new llvm::BasicBlock("whilebody", gIR->topfunc(), endbb); | |
2634 | |
2635 // conditional branch | |
2636 llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, whilebb); | |
2637 | |
2638 // rewrite scope | |
2639 gIR->scope() = IRScope(whilebodybb,endbb); | |
2640 | |
2641 // do while body code | |
2642 body->toIR(p); | |
2643 | |
2644 // loop | |
2645 new llvm::BranchInst(whilebb, gIR->scopebegin()); | |
2646 | |
2647 // rewrite the scope | |
2648 gIR->scope() = IRScope(endbb,oldend); | |
2649 } | |
2650 | |
2651 void DoStatement::toIR(IRState* p) | |
2652 { | |
2653 static int wsi = 0; | |
2654 Logger::println("DoStatement::toIR(%d): %s", wsi++, toChars()); | |
2655 LOG_SCOPE; | |
2656 | |
2657 // create while blocks | |
2658 llvm::BasicBlock* oldend = gIR->scopeend(); | |
2659 llvm::BasicBlock* dowhilebb = new llvm::BasicBlock("dowhile", gIR->topfunc(), oldend); | |
2660 llvm::BasicBlock* endbb = new llvm::BasicBlock("enddowhile", gIR->topfunc(), oldend); | |
2661 | |
2662 // move into the while block | |
2663 new llvm::BranchInst(dowhilebb, gIR->scopebegin()); | |
2664 | |
2665 // replace current scope | |
2666 gIR->scope() = IRScope(dowhilebb,endbb); | |
2667 | |
2668 // do do-while body code | |
2669 body->toIR(p); | |
2670 | |
2671 // create the condition | |
2672 elem* cond_e = condition->toElem(p); | |
2673 llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); | |
2674 delete cond_e; | |
2675 | |
2676 // conditional branch | |
2677 llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebegin()); | |
2678 | |
2679 // rewrite the scope | |
2680 gIR->scope() = IRScope(endbb,oldend); | |
2681 } | |
2682 | |
2683 void ForStatement::toIR(IRState* p) | |
2684 { | |
2685 static int wsi = 0; | |
2686 Logger::println("ForStatement::toIR(%d): %s", wsi++, toChars()); | |
2687 LOG_SCOPE; | |
2688 | |
2689 // create for blocks | |
2690 llvm::BasicBlock* oldend = gIR->scopeend(); | |
2691 llvm::BasicBlock* forbb = new llvm::BasicBlock("forcond", gIR->topfunc(), oldend); | |
2692 llvm::BasicBlock* forbodybb = new llvm::BasicBlock("forbody", gIR->topfunc(), oldend); | |
2693 llvm::BasicBlock* forincbb = new llvm::BasicBlock("forinc", gIR->topfunc(), oldend); | |
2694 llvm::BasicBlock* endbb = new llvm::BasicBlock("endfor", gIR->topfunc(), oldend); | |
2695 | |
2696 // init | |
2697 if (init != 0) | |
2698 init->toIR(p); | |
2699 | |
2700 // move into the for condition block, ie. start the loop | |
2701 new llvm::BranchInst(forbb, gIR->scopebegin()); | |
2702 | |
2703 IRScope loop; | |
2704 loop.begin = forincbb; | |
2705 loop.end = endbb; | |
2706 p->loopbbs.push_back(loop); | |
2707 | |
2708 // replace current scope | |
2709 gIR->scope() = IRScope(forbb,forbodybb); | |
2710 | |
2711 // create the condition | |
2712 elem* cond_e = condition->toElem(p); | |
2713 llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); | |
2714 delete cond_e; | |
2715 | |
2716 // conditional branch | |
2717 llvm::Value* ifbreak = new llvm::BranchInst(forbodybb, endbb, cond_val, forbb); | |
2718 | |
2719 // rewrite scope | |
2720 gIR->scope() = IRScope(forbodybb,forincbb); | |
2721 | |
2722 // do for body code | |
2723 body->toIR(p); | |
2724 | |
2725 // move into the for increment block | |
2726 new llvm::BranchInst(forincbb, gIR->scopebegin()); | |
2727 gIR->scope() = IRScope(forincbb, endbb); | |
2728 | |
2729 // increment | |
2730 if (increment) { | |
2731 elem* inc = increment->toElem(p); | |
2732 delete inc; | |
2733 } | |
2734 | |
2735 // loop | |
2736 new llvm::BranchInst(forbb, gIR->scopebegin()); | |
2737 | |
2738 p->loopbbs.pop_back(); | |
2739 | |
2740 // rewrite the scope | |
2741 gIR->scope() = IRScope(endbb,oldend); | |
2742 } | |
2743 | |
2744 void BreakStatement::toIR(IRState* p) | |
2745 { | |
2746 static int wsi = 0; | |
2747 Logger::println("BreakStatement::toIR(%d): %s", wsi++, toChars()); | |
2748 LOG_SCOPE; | |
2749 | |
2750 if (ident != 0) { | |
2751 Logger::println("ident = %s", ident->toChars()); | |
2752 assert(0); | |
2753 } | |
2754 else { | |
2755 new llvm::BranchInst(gIR->loopbbs.back().end, gIR->scopebegin()); | |
2756 } | |
2757 } | |
2758 | |
2759 void ContinueStatement::toIR(IRState* p) | |
2760 { | |
2761 static int wsi = 0; | |
2762 Logger::println("ContinueStatement::toIR(%d): %s", wsi++, toChars()); | |
2763 LOG_SCOPE; | |
2764 | |
2765 if (ident != 0) { | |
2766 Logger::println("ident = %s", ident->toChars()); | |
2767 assert(0); | |
2768 } | |
2769 else { | |
2770 new llvm::BranchInst(gIR->loopbbs.back().begin, gIR->scopebegin()); | |
2771 } | |
2772 } | |
2773 | |
2774 void OnScopeStatement::toIR(IRState* p) | |
2775 { | |
2776 static int wsi = 0; | |
2777 Logger::println("OnScopeStatement::toIR(%d): %s", wsi++, toChars()); | |
2778 LOG_SCOPE; | |
2779 | |
2780 assert(statement); | |
2781 //statement->toIR(p); // this seems to be redundant | |
2782 } | |
2783 | |
2784 void TryFinallyStatement::toIR(IRState* p) | |
2785 { | |
2786 static int wsi = 0; | |
2787 Logger::println("TryFinallyStatement::toIR(%d): %s", wsi++, toChars()); | |
2788 LOG_SCOPE; | |
2789 | |
2790 llvm::BasicBlock* oldend = gIR->scopeend(); | |
2791 | |
2792 llvm::BasicBlock* trybb = new llvm::BasicBlock("try", gIR->topfunc(), oldend); | |
2793 llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", gIR->topfunc(), oldend); | |
2794 llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", gIR->topfunc(), oldend); | |
2795 | |
2796 // pass the previous BB into this | |
2797 new llvm::BranchInst(trybb, gIR->scopebegin()); | |
2798 | |
2799 gIR->scope() = IRScope(trybb,finallybb); | |
2800 | |
2801 assert(body); | |
2802 body->toIR(p); | |
2803 new llvm::BranchInst(finallybb, gIR->scopebegin()); | |
2804 | |
2805 // rewrite the scope | |
2806 gIR->scope() = IRScope(finallybb,endbb); | |
2807 | |
2808 assert(finalbody); | |
2809 finalbody->toIR(p); | |
2810 new llvm::BranchInst(endbb, gIR->scopebegin()); | |
2811 | |
2812 // rewrite the scope | |
2813 gIR->scope() = IRScope(endbb,oldend); | |
2814 } | |
2815 | |
2816 void TryCatchStatement::toIR(IRState* p) | |
2817 { | |
2818 static int wsi = 0; | |
2819 Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars()); | |
2820 LOG_SCOPE; | |
2821 | |
2822 assert(0 && "try-catch is not properly"); | |
2823 | |
2824 assert(body); | |
2825 body->toIR(p); | |
2826 | |
2827 assert(catches); | |
2828 for(size_t i=0; i<catches->dim; ++i) | |
2829 { | |
2830 Catch* c = (Catch*)catches->data[i]; | |
2831 c->handler->toIR(p); | |
2832 } | |
2833 } | |
2834 | |
2835 void ThrowStatement::toIR(IRState* p) | |
2836 { | |
2837 static int wsi = 0; | |
2838 Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars()); | |
2839 LOG_SCOPE; | |
2840 | |
2841 assert(0 && "throw is not implemented"); | |
2842 | |
2843 assert(exp); | |
2844 elem* e = exp->toElem(p); | |
2845 delete e; | |
2846 } | |
2847 | |
2848 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();} | |
2849 //STUBST(BreakStatement); | |
2850 //STUBST(ForStatement); | |
2851 STUBST(WithStatement); | |
2852 STUBST(SynchronizedStatement); | |
2853 //STUBST(ReturnStatement); | |
2854 //STUBST(ContinueStatement); | |
2855 STUBST(DefaultStatement); | |
2856 STUBST(CaseStatement); | |
2857 STUBST(SwitchStatement); | |
2858 STUBST(SwitchErrorStatement); | |
2859 STUBST(Statement); | |
2860 //STUBST(IfStatement); | |
2861 STUBST(ForeachStatement); | |
2862 //STUBST(DoStatement); | |
2863 //STUBST(WhileStatement); | |
2864 //STUBST(ExpStatement); | |
2865 //STUBST(CompoundStatement); | |
2866 //STUBST(ScopeStatement); | |
2867 STUBST(AsmStatement); | |
2868 //STUBST(TryCatchStatement); | |
2869 //STUBST(TryFinallyStatement); | |
2870 STUBST(VolatileStatement); | |
2871 STUBST(LabelStatement); | |
2872 //STUBST(ThrowStatement); | |
2873 STUBST(GotoCaseStatement); | |
2874 STUBST(GotoDefaultStatement); | |
2875 STUBST(GotoStatement); | |
2876 STUBST(UnrolledLoopStatement); | |
2877 //STUBST(OnScopeStatement); | |
2878 | |
2879 | 2403 |
2880 void | 2404 void |
2881 EnumDeclaration::toDebug() | 2405 EnumDeclaration::toDebug() |
2882 { | 2406 { |
2883 | 2407 |