@@ -28,13 +28,42 @@ import string;
2828import stdio;
2929#endif
3030
31+ type Tools struct {
32+ lookup_table.Table conversion;
33+ SlotCollector collector;
34+ RevList revlist;
35+ instr_inserter.InstrInserter inserter;
36+ bit_array.BitArray active_blocks;
37+ CopyList copies;
38+ usage_counter.Counter usage;
39+ }
40+
41+ fn void Tools.init(Tools* t) {
42+ t.conversion.init(64);
43+ t.collector.create();
44+ t.revlist.create(256);
45+ t.inserter.create();
46+ t.copies.init(1024);
47+ t.usage.init(1024);
48+ }
49+
50+ fn void Tools.free(Tools* t) {
51+ t.usage.free();
52+ t.copies.free();
53+ t.inserter.free();
54+ t.revlist.free();
55+ t.collector.free();
56+ t.conversion.free();
57+ }
58+
3159public type Context struct @(opaque) {
3260 // context stuff
3361 string_pool.Pool* pool;
3462 ConstantList constants;
3563 SymbolList symbols;
3664 InitValueList init_values;
3765
66+ // TODO extract to Builder builder
3867 // builder stuff, used during function generation (extract to builder?)
3968 bool in_block;
4069 u32 slot_idx;
@@ -45,17 +74,12 @@ public type Context struct @(opaque) {
4574 u32 blk_start_instr; // used to note starting instruction
4675 bool block_terminated;
4776
48- // only used during function generation / optimization
77+ // used during both function generation and optimization
4978 index_list.List block_order;
50- lookup_table.Table conversion;
5179 FunctionInfo* tmp_info;
5280
53- SlotCollector collector;
54- RevList revlist;
55- instr_inserter.InstrInserter inserter;
56- bit_array.BitArray active_blocks;
57- CopyList copies;
58- usage_counter.Counter usage;
81+ // only used during optimization
82+ Tools tools;
5983}
6084
6185public fn Context* create() {
@@ -66,31 +90,21 @@ public fn Context* create() {
6690 c.init_values.init(128);
6791
6892 c.block_order.init(64);
69- c.conversion.init(64);
70-
7193 c.tmp_info = FunctionInfo.create(32, 64, 32);
72- c.collector.create();
73- c.revlist.create(256);
74- c.inserter.create();
75- c.copies.init(1024);
76- c.usage.init(1024);
94+
95+ c.tools.init();
7796 return c;
7897}
7998
8099public fn void Context.free(Context* c) {
81- c.usage.free();
82- c.copies.free();
83- c.inserter.free();
84- c.revlist.free();
85- c.collector.free();
100+ c.tools.free();
86101 for (u32 i=1; i<c.symbols.getCount(); i++) {
87102 const Symbol* s = c.symbols.get(i);
88103 if (s.is_function && s.f.info) {
89104 s.f.info.free();
90105 }
91106 }
92107 c.tmp_info.free();
93- c.conversion.free();
94108 c.block_order.free();
95109
96110 c.init_values.free();
@@ -558,25 +572,24 @@ public fn void Context.setCase(Context* c, CaseId case_id, u32 value, BlockId bl
558572
559573fn void Context.finalizeFunction(Context* c, SymbolId id) {
560574 // prune unused blocks and flatten blocks with only a jmp instruction
561- Symbol* s = c.symbols.get(id);
562- //Function* f = c.functions.get(id);
575+ Tools* t = &c.tools;
576+ Symbol* symbol = c.symbols.get(id);
577+
563578 u32 num_blocks = c.tmp_info.blocks.getCount();
564579 c.tmp_info.num_slots = cast<u16>(c.slot_idx);
565580
566- const char* name = c.pool.idx2str(s .name);
581+ const char* name = c.pool.idx2str(symbol .name);
567582 bool print = false;
568583 //print = true;
569584
570- //c.dump_function(c.tmp_info, name);
571- // causes crash
572- if (print) c.print_function(id, c.tmp_info, "after generation");
585+ //dump_function(c.tmp_info, name);
586+ if (print) c.print_function(symbol, c.tmp_info, "after generation");
573587
574588 // prune unused and empty blocks, possible convert jmp_if to jmp
575- c. checkDest(0);
589+ checkDest(c.tmp_info, 0);
576590
577- //c.dump_function(c.tmp_info, name);
578- // causes crash
579- if (print) c.print_function(id, c.tmp_info, "after check dest");
591+ //dump_function(c.tmp_info, name);
592+ if (print) c.print_function(symbol, c.tmp_info, "after check dest");
580593
581594 // move used blocks to new list, drop unused blocks
582595
@@ -590,47 +603,47 @@ fn void Context.finalizeFunction(Context* c, SymbolId id) {
590603 const u32* order = c.block_order.getFrom(0);
591604 assert(num_blocks == c.block_order.getCount());
592605 u32 blk_count = 0;
593- c .conversion.clear(num_blocks); // NOTE: potentially large memset
606+ t .conversion.clear(num_blocks); // NOTE: potentially large memset
594607 for (u32 i=0; i<num_blocks; i++) {
595608 BlockId bid = order[i];
596609 const Block* b = c.tmp_info.blocks.get(bid);
597610 if (!b.used) continue;
598611 fi2.blocks.copy(b);
599- c .conversion.set(bid, blk_count);
612+ t .conversion.set(bid, blk_count);
600613 //stdio.printf("BLOCK MOVE %d -> %d\n", bid, blk_count);
601614 blk_count++;
602615 }
603616
604617 // convert block dests (old -> new)
605618 Block* new_blks = fi2.blocks.get(0);
606619#if 0
607- if (c .conversion.get(0) != 0) {
608- c. dump_function(c.tmp_info, name);
609- c .conversion.dump();
620+ if (t .conversion.get(0) != 0) {
621+ dump_function(c.tmp_info, name);
622+ t .conversion.dump();
610623 }
611624#endif
612- assert(c .conversion.get(0) == 0); // block 0 should never move
625+ assert(t .conversion.get(0) == 0); // block 0 should never move
613626 for (u32 i=0; i<blk_count; i++) {
614627 Block* b = &new_blks[i];
615628 if (b.end_with_switch) {
616629 CaseId case_id = b.dests[0];
617630 u32 num_cases = b.dests[1];
618631 for (u32 j=0; j<num_cases; j++) {
619632 Case* cs = c.tmp_info.cases.get(case_id+j);
620- cs.block = c .conversion.get(cs.block);
633+ cs.block = t .conversion.get(cs.block);
621634 }
622635 } else {
623- b.dests[0] = c .conversion.get(b.dests[0]);
624- b.dests[1] = c .conversion.get(b.dests[1]);
636+ b.dests[0] = t .conversion.get(b.dests[0]);
637+ b.dests[1] = t .conversion.get(b.dests[1]);
625638 }
626639 }
627640 // also update block ids in phi clauses
628641 for (u32 i=0; i<c.tmp_info.phis.getCount(); i++) {
629642 PhiClause* pc = c.tmp_info.phis.get(i);
630- pc.src = c .conversion.get(pc.src);
643+ pc.src = t .conversion.get(pc.src);
631644 }
632645
633- //c. dump_function(c.tmp_info, name);
646+ //dump_function(c.tmp_info, name);
634647
635648 // Note: for now just copy all refs
636649 // TODO remove unused refs
@@ -647,7 +660,7 @@ fn void Context.finalizeFunction(Context* c, SymbolId id) {
647660 // convert Ref.Temp to new index since intermediate blocks/instructions could have been removed
648661 const Instr* i_old = c.tmp_info.instructions.get(0);
649662 //stdio.printf("INSTR COUNT %d\n", c.tmp_info.instructions.getCount());
650- c .conversion.clear(c.tmp_info.instructions.getCount());
663+ t .conversion.clear(c.tmp_info.instructions.getCount());
651664 u32 i_index = 0;
652665 for (u32 i=0; i<blk_count; i++) {
653666 Block* b = &new_blks[i];
@@ -658,17 +671,17 @@ fn void Context.finalizeFunction(Context* c, SymbolId id) {
658671 for (u32 j=i_start; j<i_start+i_count; j++) {
659672 Instr* is = fi2.instructions.add();
660673 is.copy(&i_old[j]);
661- c .conversion.set(j, i_index);
674+ t .conversion.set(j, i_index);
662675 Ref* r = &is.args[0];
663- if (r.isTemp()) r.value = c .conversion.get(r.value);
676+ if (r.isTemp()) r.value = t .conversion.get(r.value);
664677 r = &is.args[1];
665- if (r.isTemp()) r.value = c .conversion.get(r.value);
678+ if (r.isTemp()) r.value = t .conversion.get(r.value);
666679 else if (r.isRefList()) { // can only occur on args[1]
667680 Ref* refs = fi2.refs.get(r.value);
668681 u32 idx = 0;
669682 while (1) {
670683 Ref* r2 = &refs[idx];
671- if (r2.isTemp()) r2.value = c .conversion.get(r2.value);
684+ if (r2.isTemp()) r2.value = t .conversion.get(r2.value);
672685 if (!r2.isValid()) break;
673686 idx++;
674687 }
@@ -680,39 +693,39 @@ fn void Context.finalizeFunction(Context* c, SymbolId id) {
680693 // update refs used inside Phi instructions
681694 for (u32 i=0; i<fi2.phis.getCount(); i++) {
682695 PhiClause* pc = fi2.phis.get(i);
683- if (pc.ref.isTemp()) pc.ref.value = c .conversion.get(pc.ref.value);
696+ if (pc.ref.isTemp()) pc.ref.value = t .conversion.get(pc.ref.value);
684697 }
685698
686- s .f.info = fi2;
699+ symbol .f.info = fi2;
687700 c.tmp_info.clear();
688701 c.block_order.clear();
689702
690- //c. dump_function(fi2, name);
703+ //dump_function(fi2, name);
691704 //c.generate_graphviz(fi2, name);
692- if (print) c.print_function(id , fi2, "after reorder");
705+ if (print) c.print_function(symbol , fi2, "after reorder");
693706
694- c.create_ssa(id , fi2, name, print);
707+ c.create_ssa(symbol , fi2, name, print);
695708
696- if (print) c.print_function(id , fi2, "after create SSA");
709+ if (print) c.print_function(symbol , fi2, "after create SSA");
697710
698- if (c .inserter.needsFixup()) {
699- c.fixup_function(fi2);
700- if (print) c.print_function(id , fi2, "after fixup");
711+ if (t .inserter.needsFixup()) {
712+ c.tools. fixup_function(fi2);
713+ if (print) c.print_function(symbol , fi2, "after fixup");
701714 }
702715
703- c .eliminateCopies(fi2);
704- //c. dump_function(fi2, name);
705- if (print) c.print_function(id , fi2, "after eliminate copies");
716+ t .eliminateCopies(fi2);
717+ //dump_function(fi2, name);
718+ if (print) c.print_function(symbol , fi2, "after eliminate copies");
706719
707720
708721 //c.propagateConstants(fi2);
709- //if (print) c.print_function(id , fi2, "after propagate constants");
710- c .fillUsage(fi2);
711- //if (print) c.print_function(id , fi2, "after fill usage");
722+ //if (print) c.print_function(symbol , fi2, "after propagate constants");
723+ t .fillUsage(fi2);
724+ //if (print) c.print_function(symbol , fi2, "after fill usage");
712725
713726
714- c .removeNone(fi2);
715- if (print) c.print_function(id , fi2, "after remove none");
727+ t .removeNone(fi2);
728+ if (print) c.print_function(symbol , fi2, "after remove none");
716729}
717730
718731fn bool empty_block(const Block* b, const InstrList* instructions) {
@@ -729,8 +742,8 @@ fn bool empty_block(const Block* b, const InstrList* instructions) {
729742}
730743
731744// uses tmp_info! TODO could also just use cur_info (points to current)
732- fn BlockId Context. checkDest(Context* c , BlockId id) {
733- Block* b = c.tmp_info .blocks.get(id);
745+ fn BlockId checkDest(FunctionInfo* fi , BlockId id) {
746+ Block* b = fi .blocks.get(id);
734747
735748 if (b.checked) {
736749 if (b.used) return id; // avoid circular loops
@@ -744,8 +757,8 @@ fn BlockId Context.checkDest(Context* c, BlockId id) {
744757 CaseId case_id = b.dests[0];
745758 u32 num_cases = b.dests[1];
746759 for (u32 i=0; i<num_cases; i++) {
747- Case* cs = c.tmp_info .cases.get(case_id+i);
748- BlockId new_blk = c. checkDest(cs.block);
760+ Case* cs = fi .cases.get(case_id+i);
761+ BlockId new_blk = checkDest(fi, cs.block);
749762 if (cs.block != new_blk) cs.block = new_blk;
750763 }
751764 return id;
@@ -756,8 +769,8 @@ fn BlockId Context.checkDest(Context* c, BlockId id) {
756769 return id;
757770 }
758771
759- if (!b.phi_source && id != 0 && empty_block(b, &c.tmp_info .instructions)) {
760- BlockId new_blk = c. checkDest(b.dests[0]);
772+ if (!b.phi_source && id != 0 && empty_block(b, &fi .instructions)) {
773+ BlockId new_blk = checkDest(fi, b.dests[0]);
761774 if (new_blk == id) {
762775 b.used = true;
763776 b.dests[0] = id; // create circular loop
@@ -770,15 +783,15 @@ fn BlockId Context.checkDest(Context* c, BlockId id) {
770783
771784 b.used = true;
772785 if (b.dests[0]) {
773- b.dests[0] = c. checkDest(b.dests[0]);
786+ b.dests[0] = checkDest(fi, b.dests[0]);
774787 }
775788 if (b.dests[1]) {
776- b.dests[1] = c. checkDest(b.dests[1]);
789+ b.dests[1] = checkDest(fi, b.dests[1]);
777790 }
778791
779792 if (b.dests[0] == b.dests[1]) {
780793 // both jumps go to same dest, convert cmp + jmp_if -> jmp
781- Instr* last = c.tmp_info .instructions.get(b.instr.start + b.instr.count -1);
794+ Instr* last = fi .instructions.get(b.instr.start + b.instr.count -1);
782795 Ref ref.init(RefKind.JmpDest, id);
783796 last.init1(InstrKind.Jmp, ref);
784797 b.dests[1] = 0;
0 commit comments