Skip to content

Commit 65c5b8c

Browse files
committed
ir: extract Tools from Context
1 parent f7570fe commit 65c5b8c

File tree

4 files changed

+172
-161
lines changed

4 files changed

+172
-161
lines changed

ir/context.c2

Lines changed: 86 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,42 @@ import string;
2828
import 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+
3159
public 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

6185
public 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

8099
public 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

559573
fn 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

718731
fn 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;

ir/function_info.c2

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,21 @@ fn Type FunctionInfo.getArg(const FunctionInfo* fi, u32 idx) {
9494
return cast<Type>(value);
9595
}
9696

97+
fn Ref FunctionInfo.addPhiInstr(FunctionInfo* fi, const PhiCache* cache) {
98+
Ref out.init(RefKind.Temp, fi.instructions.getCount());
99+
100+
u32 phi_start = fi.phis.addCache(cache);
101+
Instr* ii = fi.instructions.add();
102+
ii.initPhi(phi_start, cache.getCount());
103+
104+
// mark all source blocks as phi_source
105+
const PhiClause* clauses = cache.getClauses();
106+
for (u32 i=0; i<cache.getCount(); i++) {
107+
BlockId blk_id = clauses[i].src;
108+
Block* b = fi.blocks.get(blk_id);
109+
b.phi_source = 1;
110+
}
111+
112+
return out;
113+
}
114+

ir/print.c2

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ type PrintHelper struct {
5656
}
5757

5858
fn void PrintHelper.init(PrintHelper* ph, const Context* c) {
59-
ph.out = string_buffer.create(16*1024, useColor(), 2);
59+
ph.out = string_buffer.create(64*1024, useColor(), 2);
6060

6161
// TODO print name of module
6262

@@ -120,7 +120,7 @@ fn void PrintHelper.print_func(PrintHelper* ph, const Symbol* s, const FunctionI
120120
const Context* c = ph.c;
121121

122122
if (!info) return; // external symbol
123-
//ph.c.dump_function(info, c.pool.idx2str(s.name));
123+
//dump_function(info, c.pool.idx2str(s.name));
124124

125125
ph.blocks = &info.blocks;
126126
ph.cur_info = info;
@@ -224,15 +224,15 @@ fn void PrintHelper.print_func(PrintHelper* ph, const Symbol* s, const FunctionI
224224
}
225225

226226
fn void Context.print_function(const Context* c,
227-
SymbolId id,
227+
const Symbol* symbol,
228228
const FunctionInfo* info,
229229
const char* version) @(unused) {
230230
PrintHelper ph.init(c);
231231

232232
ph.out.add("------ ");
233233
ph.out.add(version);
234234
ph.out.add(" ------\n");
235-
ph.print_func(c.symbols.get(id), info);
235+
ph.print_func(symbol, info);
236236

237237
ph.print();
238238
ph.free();
@@ -517,7 +517,7 @@ fn void PrintHelper.printRef(PrintHelper* ph, Ref r, bool print_type) {
517517
}
518518

519519

520-
fn void Context.dump_function(const Context* c, const FunctionInfo* info, const char* name) @(unused) {
520+
fn void dump_function(const FunctionInfo* info, const char* name) @(unused) {
521521
string_buffer.Buf* out = string_buffer.create(16*1024, false, 1);
522522
out.print("function %s:\n", name);
523523
dump_function_info(out, info);

0 commit comments

Comments
 (0)