From 3048b0a908bacad4776c1659357787688707d68e Mon Sep 17 00:00:00 2001 From: linsyking Date: Mon, 12 Aug 2024 14:41:53 -0400 Subject: [PATCH 01/28] chore: remove redundant header files --- IR/aux/graph_coloring.c | 1 - 1 file changed, 1 deletion(-) diff --git a/IR/aux/graph_coloring.c b/IR/aux/graph_coloring.c index e81c420d..ffee9892 100644 --- a/IR/aux/graph_coloring.c +++ b/IR/aux/graph_coloring.c @@ -1,7 +1,6 @@ #include #include #include -#include #include "array.h" #include "bpf_ir.h" #include "code_gen.h" From 6a86ea0aaaeb0efa920fb51f58150c963490d0f8 Mon Sep 17 00:00:00 2001 From: linsyking Date: Mon, 12 Aug 2024 15:08:42 -0400 Subject: [PATCH 02/28] feat: flatten --- IR/aux/flatten.c | 21 +++++++++++++++++++++ IR/aux/translate.c | 0 IR/include/code_gen.h | 6 ++++++ IR/ir_code_gen.c | 24 +++++++++++++----------- 4 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 IR/aux/flatten.c create mode 100644 IR/aux/translate.c diff --git a/IR/aux/flatten.c b/IR/aux/flatten.c new file mode 100644 index 00000000..364fc0e7 --- /dev/null +++ b/IR/aux/flatten.c @@ -0,0 +1,21 @@ +// Flatten the IR to the bpf-form bytecode + +#include "code_gen.h" + +void flatten(struct ir_function *fun) { + // fun is still in IR form + struct ir_basic_block **pos; + array_for(pos, fun->reachable_bbs) { + struct ir_basic_block *bb = *pos; + struct ir_insn *insn; + list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { + struct ir_insn_cg_extra *extra = insn_cg(insn); + if (insn->op == IR_INSN_CALL) { + if (insn->users.num_elem == 0) { + // Call instructions, no destination if no users (but still execute) + extra->dst = NULL; + } + } + } + } +} \ No newline at end of file diff --git a/IR/aux/translate.c b/IR/aux/translate.c new file mode 100644 index 00000000..e69de29b diff --git a/IR/include/code_gen.h b/IR/include/code_gen.h index 34d478ab..e662e1ce 100644 --- a/IR/include/code_gen.h +++ b/IR/include/code_gen.h @@ -23,6 +23,10 @@ struct ir_insn_cg_extra { // Array of struct ir_insn* struct array adj; + // Translated pre_ir_insn + struct pre_ir_insn translated[10]; + __u8 translated_num; + __u8 allocated; // When allocating register, whether dst will be spilled @@ -54,4 +58,6 @@ void print_interference_graph(struct ir_function *fun); void graph_coloring(struct ir_function *fun); +void flatten(struct ir_function *fun); + #endif diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index d0fda16f..a4feb5db 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -21,18 +21,19 @@ void init_cg(struct ir_function *fun) { struct ir_insn *insn; list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { - struct ir_insn_cg_extra *insn_cg = __malloc(sizeof(struct ir_insn_cg_extra)); + struct ir_insn_cg_extra *extra = __malloc(sizeof(struct ir_insn_cg_extra)); // When init, the destination is itself - if (insn->users.num_elem > 0) { - insn_cg->dst = insn; - } else { - insn_cg->dst = NULL; - } - insn_cg->adj = INIT_ARRAY(struct ir_insn *); - insn_cg->allocated = 0; - insn_cg->spilled = 0; - insn_cg->alloc_reg = 0; - insn->user_data = insn_cg; + extra->dst = insn; + // if (insn->users.num_elem > 0) { + // extra->dst = insn; + // } else { + // extra->dst = NULL; + // } + extra->adj = INIT_ARRAY(struct ir_insn *); + extra->allocated = 0; + extra->spilled = 0; + extra->alloc_reg = 0; + insn->user_data = extra; } } } @@ -83,6 +84,7 @@ void code_gen(struct ir_function *fun) { // Init CG, start real code generation // No "users" available after this step init_cg(fun); + flatten(fun); remove_phi(fun); From 292c875264f8fccaa979a3aaf6674ac01fe31dcf Mon Sep 17 00:00:00 2001 From: linsyking Date: Mon, 12 Aug 2024 15:09:07 -0400 Subject: [PATCH 03/28] chore: comment --- IR/aux/flatten.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IR/aux/flatten.c b/IR/aux/flatten.c index 364fc0e7..c6005dc4 100644 --- a/IR/aux/flatten.c +++ b/IR/aux/flatten.c @@ -1,4 +1,4 @@ -// Flatten the IR to the bpf-form bytecode +// Flatten the IR to better work with RA #include "code_gen.h" From cce96136461fb67a8c5d378769e8a2282c55447a Mon Sep 17 00:00:00 2001 From: linsyking Date: Mon, 12 Aug 2024 15:14:24 -0400 Subject: [PATCH 04/28] feat: flatten --- IR/aux/flatten.c | 4 ++++ IR/aux/translate.c | 24 ++++++++++++++++++++++++ IR/ir_code_gen.c | 11 ++++++----- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/IR/aux/flatten.c b/IR/aux/flatten.c index c6005dc4..fbd1003d 100644 --- a/IR/aux/flatten.c +++ b/IR/aux/flatten.c @@ -1,6 +1,7 @@ // Flatten the IR to better work with RA #include "code_gen.h" +#include "ir_insn.h" void flatten(struct ir_function *fun) { // fun is still in IR form @@ -16,6 +17,9 @@ void flatten(struct ir_function *fun) { extra->dst = NULL; } } + if (is_void(insn)) { + extra->dst = NULL; + } } } } \ No newline at end of file diff --git a/IR/aux/translate.c b/IR/aux/translate.c index e69de29b..7a42ed8a 100644 --- a/IR/aux/translate.c +++ b/IR/aux/translate.c @@ -0,0 +1,24 @@ +#include "bpf_ir.h" +#include "code_gen.h" +#include "dbg.h" + +void translate(struct ir_function *fun) { + // fun is still in IR form + struct ir_basic_block **pos; + array_for(pos, fun->reachable_bbs) { + struct ir_basic_block *bb = *pos; + struct ir_insn *insn; + list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { + struct ir_insn_cg_extra *extra = insn_cg(insn); + + struct pre_ir_insn *translated1 = &extra->translated[0]; + struct pre_ir_insn *translated2 = &extra->translated[1]; + + if (insn->op == IR_INSN_ALLOC) { + // alloc + } else { + CRITICAL("No such instruction"); + } + } + } +} \ No newline at end of file diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index a4feb5db..e6ff7435 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -29,11 +29,12 @@ void init_cg(struct ir_function *fun) { // } else { // extra->dst = NULL; // } - extra->adj = INIT_ARRAY(struct ir_insn *); - extra->allocated = 0; - extra->spilled = 0; - extra->alloc_reg = 0; - insn->user_data = extra; + extra->adj = INIT_ARRAY(struct ir_insn *); + extra->allocated = 0; + extra->spilled = 0; + extra->alloc_reg = 0; + extra->translated_num = 0; + insn->user_data = extra; } } } From 5153d1932f2c9f048a9bc3b48b21a084d4872aea Mon Sep 17 00:00:00 2001 From: linsyking Date: Mon, 12 Aug 2024 15:51:28 -0400 Subject: [PATCH 05/28] feat: array --- IR/aux/translate.c | 19 +++++++++++++++---- IR/include/code_gen.h | 5 ++--- IR/ir_code_gen.c | 13 +++++++------ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/IR/aux/translate.c b/IR/aux/translate.c index 7a42ed8a..da987c5c 100644 --- a/IR/aux/translate.c +++ b/IR/aux/translate.c @@ -2,6 +2,15 @@ #include "code_gen.h" #include "dbg.h" +#define IU_REG0 BPF_REG_0 +#define IU_REG1 BPF_REG_1 + +void save_to_reg(struct array *to_gen, __u8 reg, struct ir_value val) { + // Save the full value to a register +} + +void save_to_stack(struct array *to_gen, size_t offset, struct ir_value val) {} + void translate(struct ir_function *fun) { // fun is still in IR form struct ir_basic_block **pos; @@ -11,11 +20,13 @@ void translate(struct ir_function *fun) { list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { struct ir_insn_cg_extra *extra = insn_cg(insn); - struct pre_ir_insn *translated1 = &extra->translated[0]; - struct pre_ir_insn *translated2 = &extra->translated[1]; - if (insn->op == IR_INSN_ALLOC) { - // alloc + // dst = alloc + // Nothing to do + } else if (insn->op == IR_INSN_ASSIGN) { + // dst = + // MOV dst val + } else { CRITICAL("No such instruction"); } diff --git a/IR/include/code_gen.h b/IR/include/code_gen.h index e662e1ce..05cb3bc8 100644 --- a/IR/include/code_gen.h +++ b/IR/include/code_gen.h @@ -23,9 +23,8 @@ struct ir_insn_cg_extra { // Array of struct ir_insn* struct array adj; - // Translated pre_ir_insn - struct pre_ir_insn translated[10]; - __u8 translated_num; + // Translated pre_ir_insn: array of struct pre_ir_insn + struct array translated; __u8 allocated; diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index e6ff7435..a187987b 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -29,12 +29,12 @@ void init_cg(struct ir_function *fun) { // } else { // extra->dst = NULL; // } - extra->adj = INIT_ARRAY(struct ir_insn *); - extra->allocated = 0; - extra->spilled = 0; - extra->alloc_reg = 0; - extra->translated_num = 0; - insn->user_data = extra; + extra->adj = INIT_ARRAY(struct ir_insn *); + extra->allocated = 0; + extra->spilled = 0; + extra->alloc_reg = 0; + extra->translated = INIT_ARRAY(struct pre_ir_insn); + insn->user_data = extra; } } } @@ -54,6 +54,7 @@ void free_cg_res(struct ir_function *fun) { list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { struct ir_insn_cg_extra *insn_cg = insn->user_data; array_free(&insn_cg->adj); + array_free(&insn_cg->translated); __free(insn_cg); insn->user_data = NULL; } From a878db8fb9cf4f38db5b0dbebd86cacc5a911b8a Mon Sep 17 00:00:00 2001 From: linsyking Date: Mon, 12 Aug 2024 16:38:50 -0400 Subject: [PATCH 06/28] fix: no translating nonsense program --- IR/aux/translate.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/IR/aux/translate.c b/IR/aux/translate.c index da987c5c..82e6a206 100644 --- a/IR/aux/translate.c +++ b/IR/aux/translate.c @@ -5,12 +5,6 @@ #define IU_REG0 BPF_REG_0 #define IU_REG1 BPF_REG_1 -void save_to_reg(struct array *to_gen, __u8 reg, struct ir_value val) { - // Save the full value to a register -} - -void save_to_stack(struct array *to_gen, size_t offset, struct ir_value val) {} - void translate(struct ir_function *fun) { // fun is still in IR form struct ir_basic_block **pos; From 09bb5b9fe868072331e53ccd70b8e51e6a691071 Mon Sep 17 00:00:00 2001 From: linsyking Date: Mon, 12 Aug 2024 21:36:57 -0400 Subject: [PATCH 07/28] fix: spill --- IR/aux/spill.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ IR/ir_code_gen.c | 1 - 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 IR/aux/spill.c diff --git a/IR/aux/spill.c b/IR/aux/spill.c new file mode 100644 index 00000000..5b717184 --- /dev/null +++ b/IR/aux/spill.c @@ -0,0 +1,54 @@ +#include "bpf_ir.h" +#include "code_gen.h" +#include "dbg.h" +enum val_type{ + REG, + CONST, + STACK +}; + +enum val_type vtype(struct ir_value val){ + if (val.type == IR_VALUE_INSN) { + struct ir_insn *insn = dst(val.data.insn_d); + struct ir_insn_cg_extra * extra = insn_cg(insn); + if(extra->spilled){ + return STACK; + }else{ + return REG; + } + }else{ + + } +} + +int check_need_spill(struct ir_function *fun){ + // Check if all instruction values are OK for translating + struct ir_basic_block **pos; + array_for(pos, fun->reachable_bbs) { + struct ir_basic_block *bb = *pos; + struct ir_insn *insn; + list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { + if (insn->op == IR_INSN_ALLOC) { + // dst = alloc + // Nothing to do + } else if (insn->op == IR_INSN_STORE) { + // store v0 v1 + // v0: reg + v1: reg, const, stack + // v0: stack + v1: reg, const + + } else if (insn->op == IR_INSN_ASSIGN) { + // dst = + // MOV dst val + + } else { + CRITICAL("No such instruction"); + } + } + } + return 0; +} + + +void spill(struct ir_function *fun){ + +} \ No newline at end of file diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index a187987b..5adf845c 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -84,7 +84,6 @@ void code_gen(struct ir_function *fun) { print_ir_prog_cg(fun); // Init CG, start real code generation - // No "users" available after this step init_cg(fun); flatten(fun); From d56dc188cba2d4f7d047577f68a1258564da9cd4 Mon Sep 17 00:00:00 2001 From: linsyking Date: Mon, 12 Aug 2024 21:41:27 -0400 Subject: [PATCH 08/28] fix: explicit reg --- IR/aux/{flatten.c => explicit_reg.c} | 19 ++++++++----------- IR/include/code_gen.h | 2 +- IR/ir_code_gen.c | 14 +++++++------- 3 files changed, 16 insertions(+), 19 deletions(-) rename IR/aux/{flatten.c => explicit_reg.c} (51%) diff --git a/IR/aux/flatten.c b/IR/aux/explicit_reg.c similarity index 51% rename from IR/aux/flatten.c rename to IR/aux/explicit_reg.c index fbd1003d..fd0c911f 100644 --- a/IR/aux/flatten.c +++ b/IR/aux/explicit_reg.c @@ -1,9 +1,12 @@ -// Flatten the IR to better work with RA +// Make register usage explicit +// Example: +// %x = add %y, %arg1 +// arg1 is r0 at the beginning of the function +// We then add a new instruction to the beginning of the function. #include "code_gen.h" -#include "ir_insn.h" -void flatten(struct ir_function *fun) { +void explicit_reg(struct ir_function *fun) { // fun is still in IR form struct ir_basic_block **pos; array_for(pos, fun->reachable_bbs) { @@ -12,14 +15,8 @@ void flatten(struct ir_function *fun) { list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { struct ir_insn_cg_extra *extra = insn_cg(insn); if (insn->op == IR_INSN_CALL) { - if (insn->users.num_elem == 0) { - // Call instructions, no destination if no users (but still execute) - extra->dst = NULL; - } - } - if (is_void(insn)) { - extra->dst = NULL; + // TODO } } } -} \ No newline at end of file +} diff --git a/IR/include/code_gen.h b/IR/include/code_gen.h index 05cb3bc8..4c3fd4b7 100644 --- a/IR/include/code_gen.h +++ b/IR/include/code_gen.h @@ -57,6 +57,6 @@ void print_interference_graph(struct ir_function *fun); void graph_coloring(struct ir_function *fun); -void flatten(struct ir_function *fun); +void explicit_reg(struct ir_function *fun); #endif diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index 5adf845c..dbbc58a2 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -3,6 +3,7 @@ #include "bpf_ir.h" #include "code_gen.h" #include "dbg.h" +#include "ir_insn.h" #include "list.h" #include "prog_check.h" #include "ir_helper.h" @@ -23,12 +24,11 @@ void init_cg(struct ir_function *fun) { list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { struct ir_insn_cg_extra *extra = __malloc(sizeof(struct ir_insn_cg_extra)); // When init, the destination is itself - extra->dst = insn; - // if (insn->users.num_elem > 0) { - // extra->dst = insn; - // } else { - // extra->dst = NULL; - // } + if (is_void(insn)) { + extra->dst = NULL; + } else { + extra->dst = insn; + } extra->adj = INIT_ARRAY(struct ir_insn *); extra->allocated = 0; extra->spilled = 0; @@ -85,7 +85,7 @@ void code_gen(struct ir_function *fun) { // Init CG, start real code generation init_cg(fun); - flatten(fun); + explicit_reg(fun); remove_phi(fun); From 4ebf4f897997cba369328897bbcb8ed4824fab40 Mon Sep 17 00:00:00 2001 From: linsyking Date: Mon, 12 Aug 2024 22:22:13 -0400 Subject: [PATCH 09/28] feat: start ra --- IR/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/IR/CMakeLists.txt b/IR/CMakeLists.txt index fac908ff..fe62baba 100644 --- a/IR/CMakeLists.txt +++ b/IR/CMakeLists.txt @@ -21,6 +21,7 @@ add_executable( aux/eliminate_ssa.c aux/conflict_analysis.c aux/graph_coloring.c + aux/explicit_reg.c ir_code_gen.c ) From b6d9b77108abfbb937e0ecc39d1da09744729bf5 Mon Sep 17 00:00:00 2001 From: linsyking Date: Mon, 12 Aug 2024 23:40:55 -0400 Subject: [PATCH 10/28] feat: live analysis on insn --- IR/aux/conflict_analysis.c | 34 +++++++------- IR/aux/live_variable.c | 91 +++++++++++++++++++++++--------------- IR/include/code_gen.h | 10 +++-- IR/include/ir_bb.h | 4 ++ IR/include/ir_helper.h | 4 +- IR/include/ir_insn.h | 2 + IR/ir_bb.c | 13 +++++- IR/ir_code_gen.c | 38 ++++++++-------- IR/ir_helper.c | 28 +++++++----- IR/ir_insn.c | 10 ++++- 10 files changed, 143 insertions(+), 91 deletions(-) diff --git a/IR/aux/conflict_analysis.c b/IR/aux/conflict_analysis.c index d69aec57..b04b5515 100644 --- a/IR/aux/conflict_analysis.c +++ b/IR/aux/conflict_analysis.c @@ -4,6 +4,7 @@ #include "code_gen.h" #include "dbg.h" #include "ir_helper.h" +#include "list.h" int is_final(struct ir_insn *v1) { return v1 == dst(v1); @@ -62,23 +63,24 @@ void conflict_analysis(struct ir_function *fun) { struct ir_basic_block **pos; // For each BB array_for(pos, fun->reachable_bbs) { - struct ir_basic_block *bb = *pos; - struct ir_bb_cg_extra *bb_cg = bb->user_data; - struct ir_insn **pos2; - array_for(pos2, bb_cg->out) { - struct ir_insn *insn_dst = dst(*pos2); - // Add the variable to the "all variable set" - array_push_unique(&fun->cg_info.all_var, &insn_dst); - } - array_for(pos2, bb_cg->kill) { - struct ir_insn *insn_dst = dst(*pos2); - array_push_unique(&fun->cg_info.all_var, &insn_dst); - struct ir_insn **pos3; - array_for(pos3, bb_cg->out) { - build_conflict(insn_dst, dst(*pos3)); + struct ir_basic_block *bb = *pos; + struct ir_insn *insn; + // For each operation + list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { + struct ir_insn **pos2; + struct ir_insn_cg_extra *insn_cg = insn->user_data; + array_for(pos2, insn_cg->out) { + struct ir_insn *insn_dst = dst(*pos2); + // Add the variable to the "all variable set" + array_push_unique(&fun->cg_info.all_var, &insn_dst); } - array_for(pos3, bb_cg->kill) { - build_conflict(insn_dst, dst(*pos3)); + array_for(pos2, insn_cg->kill) { + struct ir_insn *insn_dst = dst(*pos2); + array_push_unique(&fun->cg_info.all_var, &insn_dst); + struct ir_insn **pos3; + array_for(pos3, insn_cg->out) { + build_conflict(insn_dst, dst(*pos3)); + } } } } diff --git a/IR/aux/live_variable.c b/IR/aux/live_variable.c index e6cc6b4a..3ed4ded3 100644 --- a/IR/aux/live_variable.c +++ b/IR/aux/live_variable.c @@ -5,6 +5,7 @@ #include "bpf_ir.h" #include "code_gen.h" #include "dbg.h" +#include "ir_bb.h" #include "ir_fun.h" #include "ir_insn.h" #include "list.h" @@ -25,15 +26,14 @@ void gen_kill(struct ir_function *fun) { struct ir_basic_block **pos; // For each BB array_for(pos, fun->reachable_bbs) { - struct ir_basic_block *bb = *pos; - struct ir_bb_cg_extra *bb_cg = bb->user_data; + struct ir_basic_block *bb = *pos; struct ir_insn *pos2; - // For each operation in reverse - list_for_each_entry_reverse(pos2, &bb->ir_insn_head, list_ptr) { - struct ir_insn *insn_dst = dst(pos2); + // For each operation + list_for_each_entry(pos2, &bb->ir_insn_head, list_ptr) { + struct ir_insn *insn_dst = dst(pos2); + struct ir_insn_cg_extra *insn_cg = pos2->user_data; if (!is_void(pos2) && insn_dst) { - array_erase_elem(&bb_cg->gen, insn_dst); - array_push_unique(&bb_cg->kill, &insn_dst); + array_push_unique(&insn_cg->kill, &insn_dst); } struct array value_uses = get_operands(pos2); struct ir_value **pos3; @@ -41,8 +41,8 @@ void gen_kill(struct ir_function *fun) { struct ir_value *val = *pos3; if (val->type == IR_VALUE_INSN) { struct ir_insn *insn = dst(val->data.insn_d); - array_push_unique(&bb_cg->gen, &insn); - array_erase_elem(&bb_cg->kill, insn); + array_push_unique(&insn_cg->gen, &insn); + // array_erase_elem(&insn_cg->kill, insn); } } } @@ -100,52 +100,71 @@ void in_out(struct ir_function *fun) { change = 0; struct ir_basic_block **pos; array_for(pos, fun->reachable_bbs) { - struct ir_basic_block *bb = *pos; - struct ir_bb_cg_extra *bb_cg = bb->user_data; - struct array old_in = bb_cg->in; - struct ir_basic_block **pos2; - array_clear(&bb_cg->out); - array_for(pos2, bb->succs) { - struct ir_bb_cg_extra *bb_cg2 = (*pos2)->user_data; - merge_array(&bb_cg->out, &bb_cg2->in); - } - struct array out_kill_delta = array_delta(&bb_cg->out, &bb_cg->kill); - bb_cg->in = array_clone(&bb_cg->gen); - merge_array(&bb_cg->in, &out_kill_delta); - // Check for change - if (!equal_set(&bb_cg->in, &old_in)) { - change = 1; + struct ir_basic_block *bb = *pos; + struct ir_insn *insn; + + list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { + struct ir_insn_cg_extra *insn_cg = insn->user_data; + struct array old_in = insn_cg->in; + array_clear(&insn_cg->out); + + if (get_last_insn(bb) == insn) { + // Last instruction + struct ir_basic_block **pos2; + array_for(pos2, bb->succs) { + struct ir_basic_block *bb2 = *pos2; + if (bb_empty(bb2)) { + CRITICAL("Found empty BB"); + } + struct ir_insn *first = get_first_insn(bb2); + struct ir_insn_cg_extra *insn2_cg = first->user_data; + merge_array(&insn_cg->out, &insn2_cg->in); + } + } else { + // Not last instruction + struct ir_insn *next_insn = + list_entry(insn->list_ptr.next, struct ir_insn, list_ptr); + struct ir_insn_cg_extra *next_insn_cg = next_insn->user_data; + merge_array(&insn_cg->out, &next_insn_cg->in); + } + struct array out_kill_delta = array_delta(&insn_cg->out, &insn_cg->kill); + insn_cg->in = array_clone(&insn_cg->gen); + merge_array(&insn_cg->in, &out_kill_delta); + // Check for change + if (!equal_set(&insn_cg->in, &old_in)) { + change = 1; + } + // Collect grabage + array_free(&out_kill_delta); + array_free(&old_in); } - // Collect grabage - array_free(&out_kill_delta); - array_free(&old_in); } } } -void print_bb_extra(struct ir_basic_block *bb) { - struct ir_bb_cg_extra *bb_cg = bb->user_data; - if (bb->user_data == NULL) { +void print_insn_extra(struct ir_insn *insn) { + struct ir_insn_cg_extra *insn_cg = insn->user_data; + if (insn_cg == NULL) { CRITICAL("NULL user data"); } printf("--\nGen:"); struct ir_insn **pos; - array_for(pos, bb_cg->gen) { + array_for(pos, insn_cg->gen) { struct ir_insn *insn = *pos; printf(" %%%zu", insn->_insn_id); } printf("\nKill:"); - array_for(pos, bb_cg->kill) { + array_for(pos, insn_cg->kill) { struct ir_insn *insn = *pos; printf(" %%%zu", insn->_insn_id); } printf("\nIn:"); - array_for(pos, bb_cg->in) { + array_for(pos, insn_cg->in) { struct ir_insn *insn = *pos; printf(" %%%zu", insn->_insn_id); } printf("\nOut:"); - array_for(pos, bb_cg->out) { + array_for(pos, insn_cg->out) { struct ir_insn *insn = *pos; printf(" %%%zu", insn->_insn_id); } @@ -157,6 +176,6 @@ void liveness_analysis(struct ir_function *fun) { gen_kill(fun); in_out(fun); printf("--------------\n"); - print_ir_prog_advanced(fun, print_bb_extra, print_ir_dst); - print_ir_prog_advanced(fun, NULL, print_ir_dst); + print_ir_prog_advanced(fun, NULL, print_insn_extra, print_ir_dst); + print_ir_prog_advanced(fun, NULL, NULL, print_ir_dst); } diff --git a/IR/include/code_gen.h b/IR/include/code_gen.h index 4c3fd4b7..077f5755 100644 --- a/IR/include/code_gen.h +++ b/IR/include/code_gen.h @@ -9,16 +9,18 @@ void code_gen(struct ir_function *fun); // Extra information needed for code gen struct ir_bb_cg_extra { // Liveness analysis - struct array in; - struct array out; - struct array gen; - struct array kill; }; struct ir_insn_cg_extra { // Destination (Not in SSA form anymore) struct ir_insn *dst; + // Liveness analysis + struct array in; + struct array out; + struct array gen; + struct array kill; + // Adj list in interference graph // Array of struct ir_insn* struct array adj; diff --git a/IR/include/ir_bb.h b/IR/include/ir_bb.h index d526a73f..e6cf6bc1 100644 --- a/IR/include/ir_bb.h +++ b/IR/include/ir_bb.h @@ -18,4 +18,8 @@ struct ir_basic_block *split_bb(struct ir_function *fun, struct ir_insn *insn); struct ir_insn *get_last_insn(struct ir_basic_block *bb); +struct ir_insn *get_first_insn(struct ir_basic_block *bb); + +int bb_empty(struct ir_basic_block *bb); + #endif diff --git a/IR/include/ir_helper.h b/IR/include/ir_helper.h index 5e7b435c..a91cf6e4 100644 --- a/IR/include/ir_helper.h +++ b/IR/include/ir_helper.h @@ -7,8 +7,8 @@ void clean_env_all(struct ir_function *fun); void print_ir_prog(struct ir_function *); -void print_ir_prog_advanced(struct ir_function *fun, void (*post_fun)(struct ir_basic_block *), - void (*print_ir)(struct ir_insn *)); +void print_ir_prog_advanced(struct ir_function *, void (*)(struct ir_basic_block *), + void (*)(struct ir_insn *), void (*)(struct ir_insn *)); void print_ir_dst(struct ir_insn *insn); diff --git a/IR/include/ir_insn.h b/IR/include/ir_insn.h index d1924f1b..3217598f 100644 --- a/IR/include/ir_insn.h +++ b/IR/include/ir_insn.h @@ -24,6 +24,8 @@ int is_jmp(struct ir_insn *insn); struct ir_insn *prev_insn(struct ir_insn *insn); +struct ir_insn *next_insn(struct ir_insn *insn); + struct ir_insn *create_alloc_insn(struct ir_insn *insn, enum ir_vr_type type, enum insert_position pos); diff --git a/IR/ir_bb.c b/IR/ir_bb.c index f1d4615f..93ca2c4c 100644 --- a/IR/ir_bb.c +++ b/IR/ir_bb.c @@ -11,6 +11,10 @@ size_t bb_len(struct ir_basic_block *bb) { return len; } +int bb_empty(struct ir_basic_block *bb) { + return list_empty(&bb->ir_insn_head); +} + struct ir_basic_block *create_bb(struct ir_function *fun) { struct ir_basic_block *new_bb = init_ir_bb_raw(); array_push(&fun->all_bbs, &new_bb); @@ -56,8 +60,15 @@ struct ir_basic_block *split_bb(struct ir_function *fun, struct ir_insn *insn) { } struct ir_insn *get_last_insn(struct ir_basic_block *bb) { - if (list_empty(&bb->ir_insn_head)) { + if (bb_empty(bb)) { return NULL; } return list_entry(bb->ir_insn_head.prev, struct ir_insn, list_ptr); } + +struct ir_insn *get_first_insn(struct ir_basic_block *bb) { + if (bb_empty(bb)) { + return NULL; + } + return list_entry(bb->ir_insn_head.next, struct ir_insn, list_ptr); +} diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index dbbc58a2..137dd087 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -13,11 +13,7 @@ void init_cg(struct ir_function *fun) { array_for(pos, fun->reachable_bbs) { struct ir_basic_block *bb = *pos; struct ir_bb_cg_extra *bb_cg = __malloc(sizeof(struct ir_bb_cg_extra)); - bb_cg->gen = INIT_ARRAY(struct ir_insn *); - bb_cg->kill = INIT_ARRAY(struct ir_insn *); - bb_cg->in = INIT_ARRAY(struct ir_insn *); - bb_cg->out = INIT_ARRAY(struct ir_insn *); - + // Empty bb cg bb->user_data = bb_cg; struct ir_insn *insn; @@ -34,6 +30,10 @@ void init_cg(struct ir_function *fun) { extra->spilled = 0; extra->alloc_reg = 0; extra->translated = INIT_ARRAY(struct pre_ir_insn); + extra->gen = INIT_ARRAY(struct ir_insn *); + extra->kill = INIT_ARRAY(struct ir_insn *); + extra->in = INIT_ARRAY(struct ir_insn *); + extra->out = INIT_ARRAY(struct ir_insn *); insn->user_data = extra; } } @@ -44,17 +44,17 @@ void free_cg_res(struct ir_function *fun) { array_for(pos, fun->reachable_bbs) { struct ir_basic_block *bb = *pos; struct ir_bb_cg_extra *bb_cg = bb->user_data; - array_free(&bb_cg->gen); - array_free(&bb_cg->kill); - array_free(&bb_cg->in); - array_free(&bb_cg->out); - __free(bb->user_data); + __free(bb_cg); bb->user_data = NULL; struct ir_insn *insn; list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { struct ir_insn_cg_extra *insn_cg = insn->user_data; array_free(&insn_cg->adj); array_free(&insn_cg->translated); + array_free(&insn_cg->gen); + array_free(&insn_cg->kill); + array_free(&insn_cg->in); + array_free(&insn_cg->out); __free(insn_cg); insn->user_data = NULL; } @@ -71,7 +71,7 @@ struct ir_insn *dst(struct ir_insn *insn) { void print_ir_prog_cg(struct ir_function *fun) { printf("-----------------\n"); - print_ir_prog_advanced(fun, NULL, NULL); + print_ir_prog_advanced(fun, NULL, NULL, NULL); } void code_gen(struct ir_function *fun) { @@ -93,14 +93,14 @@ void code_gen(struct ir_function *fun) { liveness_analysis(fun); // Step 4: Conflict Analysis - conflict_analysis(fun); - print_interference_graph(fun); - printf("-------------\n"); - - // Step 5: Graph coloring - graph_coloring(fun); - print_interference_graph(fun); - print_ir_prog_advanced(fun, NULL, print_ir_alloc); + // conflict_analysis(fun); + // print_interference_graph(fun); + // printf("-------------\n"); + + // // Step 5: Graph coloring + // graph_coloring(fun); + // print_interference_graph(fun); + // print_ir_prog_advanced(fun, NULL, NULL, print_ir_alloc); // Register allocation finished diff --git a/IR/ir_helper.c b/IR/ir_helper.c index 3a0f9ae4..39fa15c5 100644 --- a/IR/ir_helper.c +++ b/IR/ir_helper.c @@ -366,8 +366,8 @@ void print_raw_ir_insn(struct ir_insn *insn) { print_raw_ir_insn_full(insn, 0); } -void print_ir_bb(struct ir_basic_block *bb, void (*post_fun)(struct ir_basic_block *), - void (*print_ir)(struct ir_insn *)) { +void print_ir_bb(struct ir_basic_block *bb, void (*post_bb)(struct ir_basic_block *), + void (*post_insn)(struct ir_insn *), void (*print_insn_name)(struct ir_insn *)) { if (bb->_visited) { return; } @@ -380,23 +380,26 @@ void print_ir_bb(struct ir_basic_block *bb, void (*post_fun)(struct ir_basic_blo printf(" "); } else { printf(" "); - if (print_ir) { - print_ir(insn); + if (print_insn_name) { + print_insn_name(insn); } else { printf("%%%zu", insn->_insn_id); } printf(" = "); } - print_ir_insn_full(insn, print_ir); + print_ir_insn_full(insn, print_insn_name); printf("\n"); + if (post_insn) { + post_insn(insn); + } } - if (post_fun) { - post_fun(bb); + if (post_bb) { + post_bb(bb); } for (size_t i = 0; i < bb->succs.num_elem; ++i) { struct ir_basic_block *next = ((struct ir_basic_block **)(bb->succs.data))[i]; - print_ir_bb(next, post_fun, print_ir); + print_ir_bb(next, post_bb, post_insn, print_insn_name); } } @@ -443,7 +446,7 @@ void tag_ir(struct ir_function *fun) { void print_ir_prog(struct ir_function *fun) { tag_ir(fun); - print_ir_bb(fun->entry, NULL, 0); + print_ir_bb(fun->entry, NULL, NULL, NULL); clean_tag(fun); } @@ -478,9 +481,10 @@ void print_ir_alloc(struct ir_insn *insn) { } } -void print_ir_prog_advanced(struct ir_function *fun, void (*post_fun)(struct ir_basic_block *), - void (*print_ir)(struct ir_insn *)) { +void print_ir_prog_advanced(struct ir_function *fun, void (*post_bb)(struct ir_basic_block *), + void (*post_insn)(struct ir_insn *), + void (*print_insn_name)(struct ir_insn *)) { tag_ir(fun); - print_ir_bb(fun->entry, post_fun, print_ir); + print_ir_bb(fun->entry, post_bb, post_insn, print_insn_name); clean_tag(fun); } diff --git a/IR/ir_insn.c b/IR/ir_insn.c index 7de70807..9a30bb73 100644 --- a/IR/ir_insn.c +++ b/IR/ir_insn.c @@ -228,12 +228,20 @@ struct ir_insn *create_bin_insn_bb(struct ir_basic_block *bb, struct ir_value va struct ir_insn *prev_insn(struct ir_insn *insn) { struct list_head *prev = insn->list_ptr.prev; - if (list_empty(prev)) { + if (prev == &insn->parent_bb->ir_insn_head) { return NULL; } return list_entry(prev, struct ir_insn, list_ptr); } +struct ir_insn *next_insn(struct ir_insn *insn) { + struct list_head *next = insn->list_ptr.next; + if (next == &insn->parent_bb->ir_insn_head) { + return NULL; + } + return list_entry(next, struct ir_insn, list_ptr); +} + struct ir_insn *create_ja_insn_base(struct ir_basic_block *bb, struct ir_basic_block *to_bb) { struct ir_insn *new_insn = create_insn_base(bb); new_insn->op = IR_INSN_JA; From 3d8df0c25f91c98118108764311ab2cfe6ac9e83 Mon Sep 17 00:00:00 2001 From: linsyking Date: Mon, 12 Aug 2024 23:48:31 -0400 Subject: [PATCH 11/28] feat: insn level RA --- IR/aux/conflict_analysis.c | 5 ----- IR/ir_code_gen.c | 16 ++++++++-------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/IR/aux/conflict_analysis.c b/IR/aux/conflict_analysis.c index b04b5515..a056c8a2 100644 --- a/IR/aux/conflict_analysis.c +++ b/IR/aux/conflict_analysis.c @@ -69,11 +69,6 @@ void conflict_analysis(struct ir_function *fun) { list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { struct ir_insn **pos2; struct ir_insn_cg_extra *insn_cg = insn->user_data; - array_for(pos2, insn_cg->out) { - struct ir_insn *insn_dst = dst(*pos2); - // Add the variable to the "all variable set" - array_push_unique(&fun->cg_info.all_var, &insn_dst); - } array_for(pos2, insn_cg->kill) { struct ir_insn *insn_dst = dst(*pos2); array_push_unique(&fun->cg_info.all_var, &insn_dst); diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index 137dd087..f9b2cb26 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -93,14 +93,14 @@ void code_gen(struct ir_function *fun) { liveness_analysis(fun); // Step 4: Conflict Analysis - // conflict_analysis(fun); - // print_interference_graph(fun); - // printf("-------------\n"); - - // // Step 5: Graph coloring - // graph_coloring(fun); - // print_interference_graph(fun); - // print_ir_prog_advanced(fun, NULL, NULL, print_ir_alloc); + conflict_analysis(fun); + print_interference_graph(fun); + printf("-------------\n"); + + // Step 5: Graph coloring + graph_coloring(fun); + print_interference_graph(fun); + print_ir_prog_advanced(fun, NULL, NULL, print_ir_alloc); // Register allocation finished From 8606749ce3b1df1af789393ef182b01c0efdf7cb Mon Sep 17 00:00:00 2001 From: linsyking Date: Tue, 13 Aug 2024 00:00:10 -0400 Subject: [PATCH 12/28] fix: free get_operands --- IR/aux/live_variable.c | 1 + IR/ir_code_gen.c | 11 +++++++++++ IR/ir_insn.c | 1 + 3 files changed, 13 insertions(+) diff --git a/IR/aux/live_variable.c b/IR/aux/live_variable.c index 3ed4ded3..19de03ea 100644 --- a/IR/aux/live_variable.c +++ b/IR/aux/live_variable.c @@ -45,6 +45,7 @@ void gen_kill(struct ir_function *fun) { // array_erase_elem(&insn_cg->kill, insn); } } + array_free(&value_uses); } } } diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index f9b2cb26..81a48013 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -35,6 +35,17 @@ void init_cg(struct ir_function *fun) { extra->in = INIT_ARRAY(struct ir_insn *); extra->out = INIT_ARRAY(struct ir_insn *); insn->user_data = extra; + + // Change all operands to dst(*) + struct array value_uses = get_operands(insn); + struct ir_value **pos2; + array_for(pos2, value_uses) { + struct ir_value *val = *pos2; + if (val->type == IR_VALUE_INSN) { + val->data.insn_d = dst(val->data.insn_d); + } + } + array_free(&value_uses); } } } diff --git a/IR/ir_insn.c b/IR/ir_insn.c index 9a30bb73..27da8c9b 100644 --- a/IR/ir_insn.c +++ b/IR/ir_insn.c @@ -26,6 +26,7 @@ void replace_all_usage(struct ir_insn *insn, struct ir_value rep) { **pos2 = rep; } } + array_free(&operands); } } From c6db1f88cd271e3ed71012f7d44a9842a33cbf07 Mon Sep 17 00:00:00 2001 From: linsyking Date: Tue, 13 Aug 2024 00:05:42 -0400 Subject: [PATCH 13/28] feat: dst --- IR/aux/conflict_analysis.c | 6 ++++-- IR/aux/live_variable.c | 3 ++- IR/include/dbg.h | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/IR/aux/conflict_analysis.c b/IR/aux/conflict_analysis.c index a056c8a2..4e327c13 100644 --- a/IR/aux/conflict_analysis.c +++ b/IR/aux/conflict_analysis.c @@ -70,11 +70,13 @@ void conflict_analysis(struct ir_function *fun) { struct ir_insn **pos2; struct ir_insn_cg_extra *insn_cg = insn->user_data; array_for(pos2, insn_cg->kill) { - struct ir_insn *insn_dst = dst(*pos2); + struct ir_insn *insn_dst = *pos2; + DBGASSERT(insn_dst == dst(insn_dst)); array_push_unique(&fun->cg_info.all_var, &insn_dst); struct ir_insn **pos3; array_for(pos3, insn_cg->out) { - build_conflict(insn_dst, dst(*pos3)); + DBGASSERT(*pos3 == dst(*pos3)); + build_conflict(insn_dst, *pos3); } } } diff --git a/IR/aux/live_variable.c b/IR/aux/live_variable.c index 19de03ea..d69968d5 100644 --- a/IR/aux/live_variable.c +++ b/IR/aux/live_variable.c @@ -40,7 +40,8 @@ void gen_kill(struct ir_function *fun) { array_for(pos3, value_uses) { struct ir_value *val = *pos3; if (val->type == IR_VALUE_INSN) { - struct ir_insn *insn = dst(val->data.insn_d); + struct ir_insn *insn = val->data.insn_d; + DBGASSERT(insn == dst(insn)); array_push_unique(&insn_cg->gen, &insn); // array_erase_elem(&insn_cg->kill, insn); } diff --git a/IR/include/dbg.h b/IR/include/dbg.h index e38d1999..ecd5a83f 100644 --- a/IR/include/dbg.h +++ b/IR/include/dbg.h @@ -3,6 +3,7 @@ #include #include +#include #define CRITICAL(str) \ { \ @@ -10,4 +11,6 @@ exit(1); \ } +#define DBGASSERT(cond) assert(cond) + #endif From 63b7a0a052c51acc96e79a0ab3edf4877971c44a Mon Sep 17 00:00:00 2001 From: linsyking Date: Tue, 13 Aug 2024 00:30:57 -0400 Subject: [PATCH 14/28] feat: ensure dst property --- IR/aux/eliminate_ssa.c | 2 ++ IR/ir_code_gen.c | 12 +----------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/IR/aux/eliminate_ssa.c b/IR/aux/eliminate_ssa.c index bdfcdba1..9bc1bccd 100644 --- a/IR/aux/eliminate_ssa.c +++ b/IR/aux/eliminate_ssa.c @@ -82,6 +82,8 @@ void remove_phi(struct ir_function *fun) { CRITICAL("Empty Phi not removed!"); } + DBGASSERT(repr == dst(repr)); + replace_all_usage(insn, ir_value_insn(repr)); erase_insn(insn); } diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index 81a48013..f092f8c2 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -17,6 +17,7 @@ void init_cg(struct ir_function *fun) { bb->user_data = bb_cg; struct ir_insn *insn; + printf("BB\n"); list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { struct ir_insn_cg_extra *extra = __malloc(sizeof(struct ir_insn_cg_extra)); // When init, the destination is itself @@ -35,17 +36,6 @@ void init_cg(struct ir_function *fun) { extra->in = INIT_ARRAY(struct ir_insn *); extra->out = INIT_ARRAY(struct ir_insn *); insn->user_data = extra; - - // Change all operands to dst(*) - struct array value_uses = get_operands(insn); - struct ir_value **pos2; - array_for(pos2, value_uses) { - struct ir_value *val = *pos2; - if (val->type == IR_VALUE_INSN) { - val->data.insn_d = dst(val->data.insn_d); - } - } - array_free(&value_uses); } } } From 80778cc39bb621bcd6fa3a59496f880eaee5a5da Mon Sep 17 00:00:00 2001 From: linsyking Date: Tue, 13 Aug 2024 01:12:06 -0400 Subject: [PATCH 15/28] feat: REG instruction --- IR/bpf_ir.c | 12 ++++++++++++ IR/include/bpf_ir.h | 8 +++----- IR/include/ir_fun.h | 3 +++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/IR/bpf_ir.c b/IR/bpf_ir.c index 46010eec..439f572f 100644 --- a/IR/bpf_ir.c +++ b/IR/bpf_ir.c @@ -802,6 +802,10 @@ void free_function(struct ir_function *fun) { } free(bb); } + + for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { + __free(fun->cg_info.regs[i].user_data); + } } struct ir_function gen_function(struct ssa_transform_env *env) { @@ -812,6 +816,14 @@ struct ir_function gen_function(struct ssa_transform_env *env) { fun.all_bbs = INIT_ARRAY(struct ir_basic_block *); fun.reachable_bbs = INIT_ARRAY(struct ir_basic_block *); fun.cg_info.all_var = INIT_ARRAY(struct ir_insn *); + for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { + fun.cg_info.regs[i].op = IR_INSN_REG; + struct ir_insn_cg_extra *extra = __malloc(sizeof(struct ir_insn_cg_extra)); + extra->spilled = 0; + extra->dst = &fun.cg_info.regs[i]; + extra->alloc_reg = i; + fun.cg_info.regs[i].user_data = extra; + } for (size_t i = 0; i < MAX_BPF_REG; ++i) { struct array *currentDef = &env->currentDef[i]; array_free(currentDef); diff --git a/IR/include/bpf_ir.h b/IR/include/bpf_ir.h index fdcee64c..134e9e74 100644 --- a/IR/include/bpf_ir.h +++ b/IR/include/bpf_ir.h @@ -129,7 +129,8 @@ enum ir_insn_type { // PHI IR_INSN_PHI, // Code-gen instructions - IR_INSN_ASSIGN + IR_INSN_ASSIGN, + IR_INSN_REG, }; /** @@ -156,6 +157,7 @@ enum ir_insn_type { | PHI (For code gen usage) | ASSIGN + | REG Note. must be the next basic block. */ @@ -190,10 +192,6 @@ struct ir_insn { // Users struct array users; - // Might be useful? - // Too difficult, need BTF - // enum ir_vr_type type; - // Used when generating the real code size_t _insn_id; void *user_data; diff --git a/IR/include/ir_fun.h b/IR/include/ir_fun.h index 9ade35de..fdc1ac16 100644 --- a/IR/include/ir_fun.h +++ b/IR/include/ir_fun.h @@ -7,6 +7,9 @@ struct code_gen_info { // All vertex in interference graph // Array of struct ir_insn* struct array all_var; + + // BPF Register Virtual Instruction (used as dst) + struct ir_insn regs[__MAX_BPF_REG]; }; struct ir_function { From a6ceaf9659bea4d64944df1d45fc8b9e2e98791a Mon Sep 17 00:00:00 2001 From: linsyking Date: Tue, 13 Aug 2024 10:46:35 -0400 Subject: [PATCH 16/28] fix: memory leak --- IR/bpf_ir.c | 15 ++-------- IR/ir_code_gen.c | 72 +++++++++++++++++++++++++++++++----------------- 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/IR/bpf_ir.c b/IR/bpf_ir.c index 439f572f..e0828173 100644 --- a/IR/bpf_ir.c +++ b/IR/bpf_ir.c @@ -802,10 +802,9 @@ void free_function(struct ir_function *fun) { } free(bb); } - - for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { - __free(fun->cg_info.regs[i].user_data); - } + array_free(&fun->all_bbs); + array_free(&fun->reachable_bbs); + array_free(&fun->cg_info.all_var); } struct ir_function gen_function(struct ssa_transform_env *env) { @@ -816,14 +815,6 @@ struct ir_function gen_function(struct ssa_transform_env *env) { fun.all_bbs = INIT_ARRAY(struct ir_basic_block *); fun.reachable_bbs = INIT_ARRAY(struct ir_basic_block *); fun.cg_info.all_var = INIT_ARRAY(struct ir_insn *); - for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { - fun.cg_info.regs[i].op = IR_INSN_REG; - struct ir_insn_cg_extra *extra = __malloc(sizeof(struct ir_insn_cg_extra)); - extra->spilled = 0; - extra->dst = &fun.cg_info.regs[i]; - extra->alloc_reg = i; - fun.cg_info.regs[i].user_data = extra; - } for (size_t i = 0; i < MAX_BPF_REG; ++i) { struct array *currentDef = &env->currentDef[i]; array_free(currentDef); diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index f092f8c2..88729026 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -8,6 +8,27 @@ #include "prog_check.h" #include "ir_helper.h" +struct ir_insn_cg_extra *init_insn_cg(struct ir_insn *insn) { + struct ir_insn_cg_extra *extra = __malloc(sizeof(struct ir_insn_cg_extra)); + // When init, the destination is itself + if (is_void(insn)) { + extra->dst = NULL; + } else { + extra->dst = insn; + } + extra->adj = INIT_ARRAY(struct ir_insn *); + extra->allocated = 0; + extra->spilled = 0; + extra->alloc_reg = 0; + extra->translated = INIT_ARRAY(struct pre_ir_insn); + extra->gen = INIT_ARRAY(struct ir_insn *); + extra->kill = INIT_ARRAY(struct ir_insn *); + extra->in = INIT_ARRAY(struct ir_insn *); + extra->out = INIT_ARRAY(struct ir_insn *); + insn->user_data = extra; + return extra; +} + void init_cg(struct ir_function *fun) { struct ir_basic_block **pos; array_for(pos, fun->reachable_bbs) { @@ -19,25 +40,27 @@ void init_cg(struct ir_function *fun) { struct ir_insn *insn; printf("BB\n"); list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { - struct ir_insn_cg_extra *extra = __malloc(sizeof(struct ir_insn_cg_extra)); - // When init, the destination is itself - if (is_void(insn)) { - extra->dst = NULL; - } else { - extra->dst = insn; - } - extra->adj = INIT_ARRAY(struct ir_insn *); - extra->allocated = 0; - extra->spilled = 0; - extra->alloc_reg = 0; - extra->translated = INIT_ARRAY(struct pre_ir_insn); - extra->gen = INIT_ARRAY(struct ir_insn *); - extra->kill = INIT_ARRAY(struct ir_insn *); - extra->in = INIT_ARRAY(struct ir_insn *); - extra->out = INIT_ARRAY(struct ir_insn *); - insn->user_data = extra; + init_insn_cg(insn); } } + + for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { + struct ir_insn *insn = &fun->cg_info.regs[i]; + insn->op = IR_INSN_REG; + init_insn_cg(insn)->alloc_reg = i; + } +} + +void free_insn_cg(struct ir_insn *insn) { + struct ir_insn_cg_extra *extra = insn_cg(insn); + array_free(&extra->adj); + array_free(&extra->translated); + array_free(&extra->gen); + array_free(&extra->kill); + array_free(&extra->in); + array_free(&extra->out); + __free(extra); + insn->user_data = NULL; } void free_cg_res(struct ir_function *fun) { @@ -49,17 +72,14 @@ void free_cg_res(struct ir_function *fun) { bb->user_data = NULL; struct ir_insn *insn; list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { - struct ir_insn_cg_extra *insn_cg = insn->user_data; - array_free(&insn_cg->adj); - array_free(&insn_cg->translated); - array_free(&insn_cg->gen); - array_free(&insn_cg->kill); - array_free(&insn_cg->in); - array_free(&insn_cg->out); - __free(insn_cg); - insn->user_data = NULL; + free_insn_cg(insn); } } + + for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { + struct ir_insn *insn = &fun->cg_info.regs[i]; + free_insn_cg(insn); + } } struct ir_insn_cg_extra *insn_cg(struct ir_insn *insn) { From 22dbbf39e7173e8390443624cd5800174c845df8 Mon Sep 17 00:00:00 2001 From: linsyking Date: Tue, 13 Aug 2024 16:58:05 -0400 Subject: [PATCH 17/28] feat: start adding func arg --- IR/aux/explicit_reg.c | 18 ++++++++++++++++-- IR/aux/graph_coloring.c | 4 ++-- IR/bpf_ir.c | 38 +++++++++++++++++++++++++------------- IR/include/bpf_ir.h | 12 +++++++----- IR/include/ir_fun.h | 5 ++++- IR/ir_code_gen.c | 34 ++++++++++++++++++++-------------- IR/ir_helper.c | 11 ++++++++--- 7 files changed, 82 insertions(+), 40 deletions(-) diff --git a/IR/aux/explicit_reg.c b/IR/aux/explicit_reg.c index fd0c911f..239a1751 100644 --- a/IR/aux/explicit_reg.c +++ b/IR/aux/explicit_reg.c @@ -4,18 +4,32 @@ // arg1 is r0 at the beginning of the function // We then add a new instruction to the beginning of the function. +#include "array.h" +#include "bpf_ir.h" #include "code_gen.h" +#include "dbg.h" +#include "ir_insn.h" void explicit_reg(struct ir_function *fun) { // fun is still in IR form struct ir_basic_block **pos; + // Maximum number of functions: MAX_FUNC_ARG + __u8 function_arg[MAX_FUNC_ARG] = {0}; + struct array call_insns = INIT_ARRAY(struct ir_insn *); array_for(pos, fun->reachable_bbs) { struct ir_basic_block *bb = *pos; struct ir_insn *insn; list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { - struct ir_insn_cg_extra *extra = insn_cg(insn); + // struct ir_insn_cg_extra *extra = insn_cg(insn); if (insn->op == IR_INSN_CALL) { - // TODO + // Change the return value to NULL + // The result is in r0 + // extra->dst = NULL; + // struct ir_value val; + // val.type = IR_VALUE_INSN; + // val.data.insn_d = &fun->cg_info.regs[0]; + // create_assign_insn(insn, val, INSERT_BACK); + array_push(&call_insns, &insn); } } } diff --git a/IR/aux/graph_coloring.c b/IR/aux/graph_coloring.c index ffee9892..84a998a7 100644 --- a/IR/aux/graph_coloring.c +++ b/IR/aux/graph_coloring.c @@ -27,7 +27,7 @@ void graph_coloring(struct ir_function *fun) { struct ir_insn_cg_extra *extra = insn_cg(insn); struct ir_insn **pos2; - int used_reg[__MAX_BPF_REG] = {0}; + int used_reg[MAX_BPF_REG] = {0}; struct array used_spill = INIT_ARRAY(size_t); array_for(pos2, extra->adj) { struct ir_insn *insn2 = *pos2; // Adj instruction @@ -41,7 +41,7 @@ void graph_coloring(struct ir_function *fun) { } } __u8 need_spill = 1; - for (__u8 i = 0; i < __MAX_BPF_REG; i++) { + for (__u8 i = 0; i < MAX_BPF_REG; i++) { if (!used_reg[i]) { extra->allocated = 1; printf("Allocate r%u for %zu\n", i, insn->_insn_id); diff --git a/IR/bpf_ir.c b/IR/bpf_ir.c index e0828173..807cbc33 100644 --- a/IR/bpf_ir.c +++ b/IR/bpf_ir.c @@ -267,16 +267,24 @@ void print_pre_ir_cfg(struct pre_ir_basic_block *bb) { struct ssa_transform_env init_env(struct bb_info info) { struct ssa_transform_env env; for (size_t i = 0; i < MAX_BPF_REG; ++i) { - env.currentDef[i] = array_init(sizeof(struct bb_val)); + env.currentDef[i] = INIT_ARRAY(struct bb_val); } env.info = info; - env.sp_users = array_init(sizeof(struct ir_insn *)); + env.sp_users = INIT_ARRAY(struct ir_insn *); // Initialize function argument - // TODO: more than one arg - struct ir_value val; - val.type = IR_VALUE_FUNCTIONARG; - val.data.arg_id = 0; - write_variable(&env, BPF_REG_1, info.entry, val); + for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { + env.function_arg[i] = __malloc(sizeof(struct ir_insn)); + + env.function_arg[i]->users = INIT_ARRAY(struct ir_insn *); + env.function_arg[i]->op = IR_INSN_FUNCTIONARG; + env.function_arg[i]->fid = i; + env.function_arg[i]->value_num = 0; + env.function_arg[i]->user_data = NULL; + struct ir_value val; + val.type = IR_VALUE_INSN; + val.data.insn_d = env.function_arg[i]; + write_variable(&env, BPF_REG_1 + i, info.entry, val); + } return env; } @@ -802,6 +810,10 @@ void free_function(struct ir_function *fun) { } free(bb); } + for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { + array_free(&fun->function_arg[i]->users); + __free(fun->function_arg[i]); + } array_free(&fun->all_bbs); array_free(&fun->reachable_bbs); array_free(&fun->cg_info.all_var); @@ -809,9 +821,12 @@ void free_function(struct ir_function *fun) { struct ir_function gen_function(struct ssa_transform_env *env) { struct ir_function fun; - fun.arg_num = 1; - fun.entry = env->info.entry->ir_bb; - fun.sp_users = env->sp_users; + fun.arg_num = 1; + fun.entry = env->info.entry->ir_bb; + fun.sp_users = env->sp_users; + for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { + fun.function_arg[i] = env->function_arg[i]; + } fun.all_bbs = INIT_ARRAY(struct ir_basic_block *); fun.reachable_bbs = INIT_ARRAY(struct ir_basic_block *); fun.cg_info.all_var = INIT_ARRAY(struct ir_insn *); @@ -838,9 +853,6 @@ __u8 ir_value_equal(struct ir_value a, struct ir_value b) { if (a.type == IR_VALUE_CONSTANT) { return a.data.constant_d.data.s32_d == b.data.constant_d.data.s32_d; } - if (a.type == IR_VALUE_FUNCTIONARG) { - return a.data.arg_id == b.data.arg_id; - } if (a.type == IR_VALUE_INSN) { return a.data.insn_d == b.data.insn_d; } diff --git a/IR/include/bpf_ir.h b/IR/include/bpf_ir.h index 134e9e74..ff1f5429 100644 --- a/IR/include/bpf_ir.h +++ b/IR/include/bpf_ir.h @@ -49,14 +49,13 @@ struct ir_constant { enum ir_value_type { IR_VALUE_CONSTANT, - IR_VALUE_FUNCTIONARG, IR_VALUE_INSN, IR_VALUE_STACK_PTR, IR_VALUE_UNDEF, }; /** - VALUE = CONSTANT | INSN | FUNCTIONARG + VALUE = CONSTANT | INSN "r1 = constant" pattern will use `CONSTANT` which will not be added to BB. */ @@ -64,7 +63,6 @@ struct ir_value { union { struct ir_constant constant_d; struct ir_insn *insn_d; - __u8 arg_id; } data; enum ir_value_type type; }; @@ -109,6 +107,7 @@ enum ir_insn_type { IR_INSN_LOAD, IR_INSN_STORERAW, IR_INSN_LOADRAW, + IR_INSN_FUNCTIONARG, // The function argument store // ALU IR_INSN_ADD, IR_INSN_SUB, @@ -140,6 +139,8 @@ enum ir_insn_type { | LOAD | STORERAW , | LOADRAW + | FUNCTIONARG + | ADD , | SUB , | MUL , @@ -178,8 +179,7 @@ struct ir_insn { // Array of phi_value struct array phi; - __s32 fid; - // __u32 f_arg_num; + __s32 fid; enum ir_insn_type op; // Linked list @@ -286,6 +286,8 @@ struct ssa_transform_env { // Stack pointer (r10) users struct array sp_users; + // Function argument + struct ir_insn *function_arg[MAX_FUNC_ARG]; }; // helper functions diff --git a/IR/include/ir_fun.h b/IR/include/ir_fun.h index fdc1ac16..ccb0983d 100644 --- a/IR/include/ir_fun.h +++ b/IR/include/ir_fun.h @@ -9,7 +9,7 @@ struct code_gen_info { struct array all_var; // BPF Register Virtual Instruction (used as dst) - struct ir_insn regs[__MAX_BPF_REG]; + struct ir_insn *regs[MAX_BPF_REG]; }; struct ir_function { @@ -27,6 +27,9 @@ struct ir_function { // Stack pointer (r10) users. Should be readonly. No more manual stack access should be allowed. struct array sp_users; + // Function argument + struct ir_insn *function_arg[MAX_FUNC_ARG]; + // Array of struct ir_constraint. Value constraints. struct array value_constraints; diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index 88729026..24b1b080 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -38,15 +38,18 @@ void init_cg(struct ir_function *fun) { bb->user_data = bb_cg; struct ir_insn *insn; - printf("BB\n"); list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { init_insn_cg(insn); } } for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { - struct ir_insn *insn = &fun->cg_info.regs[i]; + fun->cg_info.regs[i] = __malloc(sizeof(struct ir_insn)); + struct ir_insn *insn = fun->cg_info.regs[i]; insn->op = IR_INSN_REG; + insn->parent_bb = NULL; + insn->users = INIT_ARRAY(struct ir_insn *); + insn->value_num = 0; init_insn_cg(insn)->alloc_reg = i; } } @@ -77,8 +80,10 @@ void free_cg_res(struct ir_function *fun) { } for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { - struct ir_insn *insn = &fun->cg_info.regs[i]; + struct ir_insn *insn = fun->cg_info.regs[i]; + array_free(&insn->users); free_insn_cg(insn); + __free(insn); } } @@ -107,21 +112,22 @@ void code_gen(struct ir_function *fun) { // Init CG, start real code generation init_cg(fun); explicit_reg(fun); + print_ir_prog_cg(fun); - remove_phi(fun); + // remove_phi(fun); - // Step 3: Liveness Analysis - liveness_analysis(fun); + // // Step 3: Liveness Analysis + // liveness_analysis(fun); - // Step 4: Conflict Analysis - conflict_analysis(fun); - print_interference_graph(fun); - printf("-------------\n"); + // // Step 4: Conflict Analysis + // conflict_analysis(fun); + // print_interference_graph(fun); + // printf("-------------\n"); - // Step 5: Graph coloring - graph_coloring(fun); - print_interference_graph(fun); - print_ir_prog_advanced(fun, NULL, NULL, print_ir_alloc); + // // Step 5: Graph coloring + // graph_coloring(fun); + // print_interference_graph(fun); + // print_ir_prog_advanced(fun, NULL, NULL, print_ir_alloc); // Register allocation finished diff --git a/IR/ir_helper.c b/IR/ir_helper.c index 39fa15c5..68069d93 100644 --- a/IR/ir_helper.c +++ b/IR/ir_helper.c @@ -89,6 +89,14 @@ void print_insn_ptr(struct ir_insn *insn, void (*print_ir)(struct ir_insn *)) { if (print_ir) { print_ir(insn); } else { + if (insn->op == IR_INSN_REG) { + printf("R%u", insn_cg(insn)->alloc_reg); + return; + } + if (insn->op == IR_INSN_FUNCTIONARG) { + printf("arg%u", insn->fid); + return; + } if (insn->_insn_id == SIZE_MAX) { printf("%p", insn); return; @@ -116,9 +124,6 @@ void print_ir_value_full(struct ir_value v, void (*print_ir)(struct ir_insn *)) case IR_VALUE_CONSTANT: print_constant(v.data.constant_d); break; - case IR_VALUE_FUNCTIONARG: - printf("arg%d", v.data.arg_id); - break; case IR_VALUE_UNDEF: printf("undef"); break; From 58b56bda40b35eba7c349549e9f7dcfd79b3736c Mon Sep 17 00:00:00 2001 From: linsyking Date: Tue, 13 Aug 2024 17:02:33 -0400 Subject: [PATCH 18/28] feat: loop1 update --- IR/ir_code_gen.c | 2 ++ IR/tests/loop1.c | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index 24b1b080..59e950e1 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -114,6 +114,8 @@ void code_gen(struct ir_function *fun) { explicit_reg(fun); print_ir_prog_cg(fun); + // SSA Destruction + // remove_phi(fun); // // Step 3: Liveness Analysis diff --git a/IR/tests/loop1.c b/IR/tests/loop1.c index b0a0d0a1..45370b9f 100644 --- a/IR/tests/loop1.c +++ b/IR/tests/loop1.c @@ -8,8 +8,9 @@ SEC("xdp") int prog(void *ctx) { __u64 t = bpf_ktime_get_ns(); - for (int i = 0; i < t; ++i) { - bpf_trace_printk("s", 1); + bpf_trace_printk(ctx, t); + for (__u64 i = 0; i < t; ++i) { + bpf_trace_printk("s", i); } return 0; } From bdd362967794cb76d1c1b9572bcc1bdd1fc6e117 Mon Sep 17 00:00:00 2001 From: linsyking Date: Tue, 13 Aug 2024 17:51:34 -0400 Subject: [PATCH 19/28] fix: replace all users --- IR/aux/explicit_reg.c | 14 ++++++++++-- IR/include/code_gen.h | 2 ++ IR/include/ir_insn.h | 8 +++++++ IR/ir_insn.c | 50 ++++++++++++++++++++++++++++++++++++++++++- IR/tests/loop1.c | 1 + 5 files changed, 72 insertions(+), 3 deletions(-) diff --git a/IR/aux/explicit_reg.c b/IR/aux/explicit_reg.c index 239a1751..3e3d4c4e 100644 --- a/IR/aux/explicit_reg.c +++ b/IR/aux/explicit_reg.c @@ -4,6 +4,7 @@ // arg1 is r0 at the beginning of the function // We then add a new instruction to the beginning of the function. +#include #include "array.h" #include "bpf_ir.h" #include "code_gen.h" @@ -14,8 +15,7 @@ void explicit_reg(struct ir_function *fun) { // fun is still in IR form struct ir_basic_block **pos; // Maximum number of functions: MAX_FUNC_ARG - __u8 function_arg[MAX_FUNC_ARG] = {0}; - struct array call_insns = INIT_ARRAY(struct ir_insn *); + struct array call_insns = INIT_ARRAY(struct ir_insn *); array_for(pos, fun->reachable_bbs) { struct ir_basic_block *bb = *pos; struct ir_insn *insn; @@ -33,4 +33,14 @@ void explicit_reg(struct ir_function *fun) { } } } + for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { + if (fun->function_arg[i]->users.num_elem > 0) { + // Insert ASSIGN arg[i] at the beginning of the function + struct ir_value val; + val.type = IR_VALUE_UNDEF; + struct ir_insn *new_insn = create_assign_insn_bb_cg(fun->entry, val, INSERT_FRONT_AFTER_PHI); + replace_all_usage(fun->function_arg[i], ir_value_insn(new_insn)); + } + } + array_free(&call_insns); } diff --git a/IR/include/code_gen.h b/IR/include/code_gen.h index 077f5755..af03a544 100644 --- a/IR/include/code_gen.h +++ b/IR/include/code_gen.h @@ -43,6 +43,8 @@ struct ir_insn_cg_extra { struct ir_insn_cg_extra *insn_cg(struct ir_insn *insn); +struct ir_insn_cg_extra *init_insn_cg(struct ir_insn *insn); + struct ir_insn *dst(struct ir_insn *insn); void to_cssa(struct ir_function *fun); diff --git a/IR/include/ir_insn.h b/IR/include/ir_insn.h index 3217598f..3e950446 100644 --- a/IR/include/ir_insn.h +++ b/IR/include/ir_insn.h @@ -88,4 +88,12 @@ void val_add_user(struct ir_value val, struct ir_insn *user); void val_remove_user(struct ir_value val, struct ir_insn *user); +struct ir_insn *create_assign_insn_cg(struct ir_insn *insn, struct ir_value val, + enum insert_position pos); + +struct ir_insn *create_assign_insn_bb_cg(struct ir_basic_block *bb, struct ir_value val, + enum insert_position pos); + +void replace_operand(struct ir_insn *insn, struct ir_value v1, struct ir_value v2); + #endif diff --git a/IR/ir_insn.c b/IR/ir_insn.c index 27da8c9b..5a9c0f52 100644 --- a/IR/ir_insn.c +++ b/IR/ir_insn.c @@ -2,6 +2,7 @@ #include #include "array.h" #include "bpf_ir.h" +#include "code_gen.h" #include "dbg.h" #include "ir_bb.h" #include "list.h" @@ -14,20 +15,44 @@ struct ir_insn *create_insn_base(struct ir_basic_block *bb) { return new_insn; } +struct ir_insn *create_insn_base_cg(struct ir_basic_block *bb) { + struct ir_insn *new_insn = create_insn_base(bb); + init_insn_cg(new_insn); + insn_cg(new_insn)->dst = new_insn; + return new_insn; +} + +void replace_operand(struct ir_insn *insn, struct ir_value v1, struct ir_value v2) { + // Replace v1 with v2 in insn + if (v1.type == IR_VALUE_INSN) { + // Remove user from v1 + val_remove_user(v1, insn); + } + if (v2.type == IR_VALUE_INSN) { + val_add_user(v2, insn); + } +} + void replace_all_usage(struct ir_insn *insn, struct ir_value rep) { struct ir_insn **pos; - array_for(pos, insn->users) { + struct array users = insn->users; + insn->users = INIT_ARRAY(struct ir_insn*); + array_for(pos, users) { + printf("Found user\n"); struct ir_insn *user = *pos; struct array operands = get_operands(user); struct ir_value **pos2; array_for(pos2, operands) { if ((*pos2)->type == IR_VALUE_INSN && (*pos2)->data.insn_d == insn) { // Match, replace + printf("Match~\n"); **pos2 = rep; + val_add_user(rep, user); } } array_free(&operands); } + array_free(&users); } struct array get_operands(struct ir_insn *insn) { @@ -354,6 +379,29 @@ struct ir_insn *create_assign_insn_bb(struct ir_basic_block *bb, struct ir_value return new_insn; } +struct ir_insn *create_assign_insn_base_cg(struct ir_basic_block *bb, struct ir_value val) { + struct ir_insn *new_insn = create_insn_base_cg(bb); + new_insn->op = IR_INSN_ASSIGN; + new_insn->values[0] = val; + new_insn->value_num = 1; + val_add_user(val, new_insn); + return new_insn; +} + +struct ir_insn *create_assign_insn_cg(struct ir_insn *insn, struct ir_value val, + enum insert_position pos) { + struct ir_insn *new_insn = create_assign_insn_base_cg(insn->parent_bb, val); + insert_at(new_insn, insn, pos); + return new_insn; +} + +struct ir_insn *create_assign_insn_bb_cg(struct ir_basic_block *bb, struct ir_value val, + enum insert_position pos) { + struct ir_insn *new_insn = create_assign_insn_base_cg(bb, val); + insert_at_bb(new_insn, bb, pos); + return new_insn; +} + struct ir_insn *create_phi_insn_base(struct ir_basic_block *bb) { struct ir_insn *new_insn = create_insn_base(bb); new_insn->op = IR_INSN_PHI; diff --git a/IR/tests/loop1.c b/IR/tests/loop1.c index 45370b9f..a2cbe6e6 100644 --- a/IR/tests/loop1.c +++ b/IR/tests/loop1.c @@ -11,6 +11,7 @@ int prog(void *ctx) { bpf_trace_printk(ctx, t); for (__u64 i = 0; i < t; ++i) { bpf_trace_printk("s", i); + bpf_trace_printk(ctx, 2); } return 0; } From e1c513a9d5c8850ee4abbc0231ea09676d641976 Mon Sep 17 00:00:00 2001 From: linsyking Date: Tue, 13 Aug 2024 18:16:38 -0400 Subject: [PATCH 20/28] bug: not deleting instructions properly --- IR/aux/explicit_reg.c | 24 ++++++++++++++++++++---- IR/ir_code_gen.c | 2 +- IR/ir_insn.c | 31 ++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/IR/aux/explicit_reg.c b/IR/aux/explicit_reg.c index 3e3d4c4e..87f547ae 100644 --- a/IR/aux/explicit_reg.c +++ b/IR/aux/explicit_reg.c @@ -10,6 +10,15 @@ #include "code_gen.h" #include "dbg.h" #include "ir_insn.h" +#include "ir_helper.h" + +void print_raw(struct ir_function *fun){ + + struct ir_basic_block **pos; + array_for(pos, fun->reachable_bbs) { + print_raw_ir_bb(*pos); + } +} void explicit_reg(struct ir_function *fun) { // fun is still in IR form @@ -34,13 +43,20 @@ void explicit_reg(struct ir_function *fun) { } } for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { + struct ir_insn **pos2; + array_for(pos2, fun->function_arg[i]->users){ + print_raw_ir_insn(*pos2); + } if (fun->function_arg[i]->users.num_elem > 0) { // Insert ASSIGN arg[i] at the beginning of the function - struct ir_value val; - val.type = IR_VALUE_UNDEF; - struct ir_insn *new_insn = create_assign_insn_bb_cg(fun->entry, val, INSERT_FRONT_AFTER_PHI); - replace_all_usage(fun->function_arg[i], ir_value_insn(new_insn)); + // struct ir_value val; + // val.type = IR_VALUE_UNDEF; + // struct ir_insn *new_insn = create_assign_insn_bb_cg(fun->entry, val, INSERT_FRONT_AFTER_PHI); + + // replace_all_usage(fun->function_arg[i], ir_value_insn(new_insn)); } } + print_raw(fun); array_free(&call_insns); } + diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index 59e950e1..e6b51407 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -106,7 +106,7 @@ void code_gen(struct ir_function *fun) { // Step 1: Check program prog_check(fun); // Step 2: Eliminate SSA - to_cssa(fun); + // to_cssa(fun); print_ir_prog_cg(fun); // Init CG, start real code generation diff --git a/IR/ir_insn.c b/IR/ir_insn.c index 5a9c0f52..7fb9bd7f 100644 --- a/IR/ir_insn.c +++ b/IR/ir_insn.c @@ -6,6 +6,7 @@ #include "dbg.h" #include "ir_bb.h" #include "list.h" +#include "ir_helper.h" struct ir_insn *create_insn_base(struct ir_basic_block *bb) { struct ir_insn *new_insn = __malloc(sizeof(struct ir_insn)); @@ -35,22 +36,30 @@ void replace_operand(struct ir_insn *insn, struct ir_value v1, struct ir_value v void replace_all_usage(struct ir_insn *insn, struct ir_value rep) { struct ir_insn **pos; - struct array users = insn->users; - insn->users = INIT_ARRAY(struct ir_insn*); + struct array users = insn->users; + insn->users = INIT_ARRAY(struct ir_insn *); array_for(pos, users) { printf("Found user\n"); - struct ir_insn *user = *pos; - struct array operands = get_operands(user); - struct ir_value **pos2; - array_for(pos2, operands) { - if ((*pos2)->type == IR_VALUE_INSN && (*pos2)->data.insn_d == insn) { - // Match, replace - printf("Match~\n"); - **pos2 = rep; + struct ir_insn *user = *pos; + print_raw_ir_insn(user); + for (__u8 j = 0; j < user->value_num; ++j) { + if (user->values[j].type == IR_VALUE_INSN && user->values[j].data.insn_d == insn) { + printf("Match~\n"); + user->values[j] = rep; val_add_user(rep, user); } } - array_free(&operands); + // struct array operands = get_operands(user); + // struct ir_value **pos2; + // array_for(pos2, operands) { + // if ((*pos2)->type == IR_VALUE_INSN && (*pos2)->data.insn_d == insn) { + // // Match, replace + // printf("Match~\n"); + // **pos2 = rep; + // val_add_user(rep, user); + // } + // } + // array_free(&operands); } array_free(&users); } From 0e18fe9383f5c88d4078166ac42b8520ecdedad4 Mon Sep 17 00:00:00 2001 From: linsyking Date: Wed, 14 Aug 2024 01:21:51 -0400 Subject: [PATCH 21/28] fix: users --- IR/aux/explicit_reg.c | 17 ++++--------- IR/aux/prog_check.c | 5 ++++ IR/include/ir_insn.h | 2 ++ IR/ir_insn.c | 55 ++++++++++++++++++++++++++++++------------- IR/passes/phi_pass.c | 2 ++ 5 files changed, 51 insertions(+), 30 deletions(-) diff --git a/IR/aux/explicit_reg.c b/IR/aux/explicit_reg.c index 87f547ae..289d8e0c 100644 --- a/IR/aux/explicit_reg.c +++ b/IR/aux/explicit_reg.c @@ -12,14 +12,6 @@ #include "ir_insn.h" #include "ir_helper.h" -void print_raw(struct ir_function *fun){ - - struct ir_basic_block **pos; - array_for(pos, fun->reachable_bbs) { - print_raw_ir_bb(*pos); - } -} - void explicit_reg(struct ir_function *fun) { // fun is still in IR form struct ir_basic_block **pos; @@ -49,14 +41,13 @@ void explicit_reg(struct ir_function *fun) { } if (fun->function_arg[i]->users.num_elem > 0) { // Insert ASSIGN arg[i] at the beginning of the function - // struct ir_value val; - // val.type = IR_VALUE_UNDEF; - // struct ir_insn *new_insn = create_assign_insn_bb_cg(fun->entry, val, INSERT_FRONT_AFTER_PHI); + struct ir_value val; + val.type = IR_VALUE_UNDEF; + struct ir_insn *new_insn = create_assign_insn_bb_cg(fun->entry, val, INSERT_FRONT_AFTER_PHI); - // replace_all_usage(fun->function_arg[i], ir_value_insn(new_insn)); + replace_all_usage(fun->function_arg[i], ir_value_insn(new_insn)); } } - print_raw(fun); array_free(&call_insns); } diff --git a/IR/aux/prog_check.c b/IR/aux/prog_check.c index 87925ede..6a455f49 100644 --- a/IR/aux/prog_check.c +++ b/IR/aux/prog_check.c @@ -4,6 +4,11 @@ #include "dbg.h" #include "list.h" +// Check if the users are correct +void check_users(struct ir_function *fun){ + // TODO +} + // Check if the PHI nodes are at the beginning of the BB void check_phi(struct ir_function *fun) { struct ir_basic_block **pos; diff --git a/IR/include/ir_insn.h b/IR/include/ir_insn.h index 3e950446..21eea069 100644 --- a/IR/include/ir_insn.h +++ b/IR/include/ir_insn.h @@ -16,6 +16,8 @@ struct array get_operands(struct ir_insn *insn); void replace_all_usage(struct ir_insn *insn, struct ir_value rep); +void replace_all_usage_except(struct ir_insn *insn, struct ir_value rep, struct ir_insn *except); + void erase_insn(struct ir_insn *insn); int is_void(struct ir_insn *insn); diff --git a/IR/ir_insn.c b/IR/ir_insn.c index 7fb9bd7f..d3b0d096 100644 --- a/IR/ir_insn.c +++ b/IR/ir_insn.c @@ -39,27 +39,41 @@ void replace_all_usage(struct ir_insn *insn, struct ir_value rep) { struct array users = insn->users; insn->users = INIT_ARRAY(struct ir_insn *); array_for(pos, users) { - printf("Found user\n"); struct ir_insn *user = *pos; - print_raw_ir_insn(user); - for (__u8 j = 0; j < user->value_num; ++j) { - if (user->values[j].type == IR_VALUE_INSN && user->values[j].data.insn_d == insn) { - printf("Match~\n"); - user->values[j] = rep; + struct array operands = get_operands(user); + struct ir_value **pos2; + array_for(pos2, operands) { + if ((*pos2)->type == IR_VALUE_INSN && (*pos2)->data.insn_d == insn) { + // Match, replace + **pos2 = rep; val_add_user(rep, user); } } - // struct array operands = get_operands(user); - // struct ir_value **pos2; - // array_for(pos2, operands) { - // if ((*pos2)->type == IR_VALUE_INSN && (*pos2)->data.insn_d == insn) { - // // Match, replace - // printf("Match~\n"); - // **pos2 = rep; - // val_add_user(rep, user); - // } - // } - // array_free(&operands); + array_free(&operands); + } + array_free(&users); +} + +void replace_all_usage_except(struct ir_insn *insn, struct ir_value rep, struct ir_insn *except) { + struct ir_insn **pos; + struct array users = insn->users; + insn->users = INIT_ARRAY(struct ir_insn *); + array_for(pos, users) { + struct ir_insn *user = *pos; + if (user == except) { + array_push(&insn->users, &user); + continue; + } + struct array operands = get_operands(user); + struct ir_value **pos2; + array_for(pos2, operands) { + if ((*pos2)->type == IR_VALUE_INSN && (*pos2)->data.insn_d == insn) { + // Match, replace + **pos2 = rep; + val_add_user(rep, user); + } + } + array_free(&operands); } array_free(&users); } @@ -87,6 +101,13 @@ __u8 is_last_insn(struct ir_insn *insn) { } void erase_insn(struct ir_insn *insn) { + // TODO: remove users + struct array operands = get_operands(insn); + struct ir_value **pos2; + array_for(pos2, operands) { + val_remove_user((**pos2), insn); + } + array_free(&operands); list_del(&insn->list_ptr); __free(insn); } diff --git a/IR/passes/phi_pass.c b/IR/passes/phi_pass.c index e13bb674..f36c7342 100644 --- a/IR/passes/phi_pass.c +++ b/IR/passes/phi_pass.c @@ -2,6 +2,7 @@ #include #include "array.h" #include "bpf_ir.h" +#include "dbg.h" #include "ir_insn.h" #include "list.h" @@ -54,6 +55,7 @@ void try_remove_trivial_phi(struct ir_insn *phi) { } void remove_trivial_phi(struct ir_function *fun) { + printf("PHI removal\n"); for (size_t i = 0; i < fun->reachable_bbs.num_elem; ++i) { struct ir_basic_block *bb = ((struct ir_basic_block **)(fun->reachable_bbs.data))[i]; struct ir_insn *pos, *n; From ecbbc9bb58987f3bd01888e9f8884937837bfad1 Mon Sep 17 00:00:00 2001 From: linsyking Date: Wed, 14 Aug 2024 01:24:32 -0400 Subject: [PATCH 22/28] fix: phi pass --- IR/passes/phi_pass.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/IR/passes/phi_pass.c b/IR/passes/phi_pass.c index f36c7342..b5f1eaf6 100644 --- a/IR/passes/phi_pass.c +++ b/IR/passes/phi_pass.c @@ -32,25 +32,8 @@ void try_remove_trivial_phi(struct ir_insn *phi) { if (!same_has_value) { same.type = IR_VALUE_UNDEF; } - struct ir_value phi_val; - phi_val.type = IR_VALUE_INSN; - phi_val.data.insn_d = phi; - struct ir_insn **pos; - array_for(pos, phi->users) { - struct ir_insn *user = *pos; - if (user == phi) { - continue; - } + replace_all_usage_except(phi, same, phi); - struct array value_uses = get_operands(user); - struct ir_value **pos2; - array_for(pos2, value_uses) { - if (ir_value_equal(**pos2, phi_val)) { - **pos2 = same; - } - } - array_free(&value_uses); - } erase_insn(phi); } From ca2e0220eb9dee12329b7db6f26d1c59f18e5710 Mon Sep 17 00:00:00 2001 From: linsyking Date: Wed, 14 Aug 2024 01:45:04 -0400 Subject: [PATCH 23/28] feat: check users --- IR/aux/explicit_reg.c | 7 ++---- IR/aux/prog_check.c | 54 +++++++++++++++++++++++++++++++++++++++++ IR/bpf_ir.c | 3 +++ IR/include/prog_check.h | 2 ++ IR/ir_code_gen.c | 3 ++- 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/IR/aux/explicit_reg.c b/IR/aux/explicit_reg.c index 289d8e0c..aa5410d1 100644 --- a/IR/aux/explicit_reg.c +++ b/IR/aux/explicit_reg.c @@ -35,14 +35,11 @@ void explicit_reg(struct ir_function *fun) { } } for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { - struct ir_insn **pos2; - array_for(pos2, fun->function_arg[i]->users){ - print_raw_ir_insn(*pos2); - } if (fun->function_arg[i]->users.num_elem > 0) { // Insert ASSIGN arg[i] at the beginning of the function struct ir_value val; - val.type = IR_VALUE_UNDEF; + val.type = IR_VALUE_INSN; + val.data.insn_d = fun->cg_info.regs[i + 1]; struct ir_insn *new_insn = create_assign_insn_bb_cg(fun->entry, val, INSERT_FRONT_AFTER_PHI); replace_all_usage(fun->function_arg[i], ir_value_insn(new_insn)); diff --git a/IR/aux/prog_check.c b/IR/aux/prog_check.c index 6a455f49..a0191ba8 100644 --- a/IR/aux/prog_check.c +++ b/IR/aux/prog_check.c @@ -2,11 +2,65 @@ #include "array.h" #include "bpf_ir.h" #include "dbg.h" +#include "ir_insn.h" #include "list.h" // Check if the users are correct void check_users(struct ir_function *fun){ // TODO + struct ir_basic_block **pos; + array_for(pos, fun->reachable_bbs) { + struct ir_basic_block *bb = *pos; + struct ir_insn *insn; + list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { + // Check users of this instruction + struct ir_insn **pos2; + array_for (pos2, insn->users) { + struct ir_insn *user = *pos2; + // Check if the user actually uses this instruction + struct array operands = get_operands(user); + struct ir_value **val; + int found = 0; + array_for(val, operands) { + struct ir_value *v = *val; + if (v->type == IR_VALUE_INSN && v->data.insn_d == insn) { + // Found the user + found = 1; + break; + } + } + array_free(&operands); + if (!found) { + // Error! + CRITICAL("User does not use the instruction"); + } + } + // Check operands of this instruction + struct array operands = get_operands(insn); + struct ir_value **val; + array_for(val, operands) { + struct ir_value *v = *val; + if (v->type == IR_VALUE_INSN) { + // Check if the operand actually is used by this instruction + struct ir_insn **pos2; + int found = 0; + array_for(pos2, v->data.insn_d->users) { + struct ir_insn *user = *pos2; + if (user == insn) { + // Found the user + found = 1; + break; + } + } + if (!found) { + // Error! + CRITICAL("Operand is not used by the instruction"); + } + } + } + array_free(&operands); + } + } } // Check if the PHI nodes are at the beginning of the BB diff --git a/IR/bpf_ir.c b/IR/bpf_ir.c index 807cbc33..39ef5b11 100644 --- a/IR/bpf_ir.c +++ b/IR/bpf_ir.c @@ -12,6 +12,7 @@ #include "list.h" #include "dbg.h" #include "passes.h" +#include "prog_check.h" #include "reachable_bb.h" #include "read.h" @@ -868,6 +869,8 @@ void run_passes(struct ir_function *fun) { gen_reachable_bbs(fun); passes[i](fun); printf("--------------------\n"); + // Validate the IR + check_users(fun); print_ir_prog(fun); } } diff --git a/IR/include/prog_check.h b/IR/include/prog_check.h index 07fe631e..aa54d498 100644 --- a/IR/include/prog_check.h +++ b/IR/include/prog_check.h @@ -5,4 +5,6 @@ void prog_check(struct ir_function *fun); +void check_users(struct ir_function *fun); + #endif diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index e6b51407..9f02eaba 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -106,7 +106,8 @@ void code_gen(struct ir_function *fun) { // Step 1: Check program prog_check(fun); // Step 2: Eliminate SSA - // to_cssa(fun); + to_cssa(fun); + check_users(fun); print_ir_prog_cg(fun); // Init CG, start real code generation From db6e349e18f7f806f0ca7243810a6e3f9e6726eb Mon Sep 17 00:00:00 2001 From: linsyking Date: Wed, 14 Aug 2024 12:06:23 -0400 Subject: [PATCH 24/28] feat: explicit reg --- IR/aux/explicit_reg.c | 34 ++++++++++++++++++------ IR/aux/prog_check.c | 60 +++++++++++++++++++++++++------------------ IR/include/bpf_ir.h | 5 ++++ IR/ir_code_gen.c | 18 ++++++++----- IR/ir_helper.c | 36 +++++++++++++------------- 5 files changed, 95 insertions(+), 58 deletions(-) diff --git a/IR/aux/explicit_reg.c b/IR/aux/explicit_reg.c index aa5410d1..73301176 100644 --- a/IR/aux/explicit_reg.c +++ b/IR/aux/explicit_reg.c @@ -16,7 +16,7 @@ void explicit_reg(struct ir_function *fun) { // fun is still in IR form struct ir_basic_block **pos; // Maximum number of functions: MAX_FUNC_ARG - struct array call_insns = INIT_ARRAY(struct ir_insn *); + struct array call_insns = INIT_ARRAY(struct ir_insn *); array_for(pos, fun->reachable_bbs) { struct ir_basic_block *bb = *pos; struct ir_insn *insn; @@ -34,17 +34,35 @@ void explicit_reg(struct ir_function *fun) { } } } + // Functions that are called + struct ir_insn **pos2; + array_for(pos2, call_insns) { + struct ir_insn *insn = *pos2; + for (__u8 i = 0; i < insn->value_num; ++i) { + struct ir_value val = insn->values[i]; + struct ir_insn *new_insn = + create_assign_insn_cg(insn, val, INSERT_FRONT); + insn_cg(new_insn)->dst = fun->cg_info.regs[i + 1]; + val_remove_user(val, insn); + } + insn->value_num = 0; + struct ir_insn_cg_extra *extra = insn_cg(insn); + extra->dst = NULL; + if (insn->users.num_elem == 0) { + continue; + } + struct ir_insn *new_insn = + create_assign_insn_cg(insn, ir_value_insn(fun->cg_info.regs[0]), INSERT_BACK); + replace_all_usage(insn, ir_value_insn(new_insn)); + } + array_free(&call_insns); + // Arg for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { if (fun->function_arg[i]->users.num_elem > 0) { // Insert ASSIGN arg[i] at the beginning of the function - struct ir_value val; - val.type = IR_VALUE_INSN; - val.data.insn_d = fun->cg_info.regs[i + 1]; - struct ir_insn *new_insn = create_assign_insn_bb_cg(fun->entry, val, INSERT_FRONT_AFTER_PHI); - + struct ir_insn *new_insn = create_assign_insn_bb_cg( + fun->entry, ir_value_insn(fun->cg_info.regs[i + 1]), INSERT_FRONT_AFTER_PHI); replace_all_usage(fun->function_arg[i], ir_value_insn(new_insn)); } } - array_free(&call_insns); } - diff --git a/IR/aux/prog_check.c b/IR/aux/prog_check.c index a0191ba8..c38ae5d6 100644 --- a/IR/aux/prog_check.c +++ b/IR/aux/prog_check.c @@ -5,38 +5,46 @@ #include "ir_insn.h" #include "list.h" +void check_insn_users_use_insn(struct ir_insn *insn) { + struct ir_insn **pos; + array_for(pos, insn->users) { + struct ir_insn *user = *pos; + // Check if the user actually uses this instruction + struct array operands = get_operands(user); + struct ir_value **val; + int found = 0; + array_for(val, operands) { + struct ir_value *v = *val; + if (v->type == IR_VALUE_INSN && v->data.insn_d == insn) { + // Found the user + found = 1; + break; + } + } + array_free(&operands); + if (!found) { + // Error! + CRITICAL("User does not use the instruction"); + } + } +} + // Check if the users are correct -void check_users(struct ir_function *fun){ - // TODO +void check_users(struct ir_function *fun) { + // Check FunctionCallArgument Instructions + for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { + struct ir_insn *insn = fun->function_arg[i]; + check_insn_users_use_insn(insn); + } struct ir_basic_block **pos; array_for(pos, fun->reachable_bbs) { - struct ir_basic_block *bb = *pos; + struct ir_basic_block *bb = *pos; struct ir_insn *insn; list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { // Check users of this instruction - struct ir_insn **pos2; - array_for (pos2, insn->users) { - struct ir_insn *user = *pos2; - // Check if the user actually uses this instruction - struct array operands = get_operands(user); - struct ir_value **val; - int found = 0; - array_for(val, operands) { - struct ir_value *v = *val; - if (v->type == IR_VALUE_INSN && v->data.insn_d == insn) { - // Found the user - found = 1; - break; - } - } - array_free(&operands); - if (!found) { - // Error! - CRITICAL("User does not use the instruction"); - } - } + check_insn_users_use_insn(insn); // Check operands of this instruction - struct array operands = get_operands(insn); + struct array operands = get_operands(insn); struct ir_value **val; array_for(val, operands) { struct ir_value *v = *val; @@ -63,6 +71,8 @@ void check_users(struct ir_function *fun){ } } +void check_jumping(struct ir_function *fun) {} + // Check if the PHI nodes are at the beginning of the BB void check_phi(struct ir_function *fun) { struct ir_basic_block **pos; diff --git a/IR/include/bpf_ir.h b/IR/include/bpf_ir.h index ff1f5429..462144e3 100644 --- a/IR/include/bpf_ir.h +++ b/IR/include/bpf_ir.h @@ -290,6 +290,11 @@ struct ssa_transform_env { struct ir_insn *function_arg[MAX_FUNC_ARG]; }; +struct error { + __u8 is_kernel_err : 1; + unsigned int errorno : 31; +}; + // helper functions void write_variable(struct ssa_transform_env *env, __u8 reg, struct pre_ir_basic_block *bb, diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index 9f02eaba..919b782f 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -44,13 +44,15 @@ void init_cg(struct ir_function *fun) { } for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { - fun->cg_info.regs[i] = __malloc(sizeof(struct ir_insn)); - struct ir_insn *insn = fun->cg_info.regs[i]; - insn->op = IR_INSN_REG; - insn->parent_bb = NULL; - insn->users = INIT_ARRAY(struct ir_insn *); - insn->value_num = 0; - init_insn_cg(insn)->alloc_reg = i; + fun->cg_info.regs[i] = __malloc(sizeof(struct ir_insn)); + struct ir_insn *insn = fun->cg_info.regs[i]; + insn->op = IR_INSN_REG; + insn->parent_bb = NULL; + insn->users = INIT_ARRAY(struct ir_insn *); + insn->value_num = 0; + struct ir_insn_cg_extra *extra = init_insn_cg(insn); + extra->alloc_reg = i; + extra->dst = insn; } } @@ -114,6 +116,8 @@ void code_gen(struct ir_function *fun) { init_cg(fun); explicit_reg(fun); print_ir_prog_cg(fun); + printf("-----------------\n"); + print_ir_prog_advanced(fun, NULL, NULL, print_ir_dst); // SSA Destruction diff --git a/IR/ir_helper.c b/IR/ir_helper.c index 68069d93..5171d79d 100644 --- a/IR/ir_helper.c +++ b/IR/ir_helper.c @@ -85,23 +85,27 @@ void print_constant(struct ir_constant d) { } } +void print_insn_ptr_base(struct ir_insn *insn) { + if (insn->op == IR_INSN_REG) { + printf("R%u", insn_cg(insn)->alloc_reg); + return; + } + if (insn->op == IR_INSN_FUNCTIONARG) { + printf("arg%u", insn->fid); + return; + } + if (insn->_insn_id == SIZE_MAX) { + printf("%p", insn); + return; + } + printf("%%%zu", insn->_insn_id); +} + void print_insn_ptr(struct ir_insn *insn, void (*print_ir)(struct ir_insn *)) { if (print_ir) { print_ir(insn); } else { - if (insn->op == IR_INSN_REG) { - printf("R%u", insn_cg(insn)->alloc_reg); - return; - } - if (insn->op == IR_INSN_FUNCTIONARG) { - printf("arg%u", insn->fid); - return; - } - if (insn->_insn_id == SIZE_MAX) { - printf("%p", insn); - return; - } - printf("%%%zu", insn->_insn_id); + print_insn_ptr_base(insn); } } @@ -458,11 +462,7 @@ void print_ir_prog(struct ir_function *fun) { void print_ir_dst(struct ir_insn *insn) { insn = dst(insn); if (insn) { - if (insn->_insn_id == SIZE_MAX) { - printf("%p", insn); - return; - } - printf("%%%zu", insn->_insn_id); + print_insn_ptr_base(insn); } else { printf("(NULL)"); } From f404f539ee2e6af2a370990e8a958152b5346bd0 Mon Sep 17 00:00:00 2001 From: linsyking Date: Wed, 14 Aug 2024 12:09:26 -0400 Subject: [PATCH 25/28] chore: separate functions --- IR/aux/prog_check.c | 52 ++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/IR/aux/prog_check.c b/IR/aux/prog_check.c index c38ae5d6..02ae3e67 100644 --- a/IR/aux/prog_check.c +++ b/IR/aux/prog_check.c @@ -29,7 +29,33 @@ void check_insn_users_use_insn(struct ir_insn *insn) { } } -// Check if the users are correct +void check_insn_operand(struct ir_insn *insn) { + struct array operands = get_operands(insn); + struct ir_value **val; + array_for(val, operands) { + struct ir_value *v = *val; + if (v->type == IR_VALUE_INSN) { + // Check if the operand actually is used by this instruction + struct ir_insn **pos2; + int found = 0; + array_for(pos2, v->data.insn_d->users) { + struct ir_insn *user = *pos2; + if (user == insn) { + // Found the user + found = 1; + break; + } + } + if (!found) { + // Error! + CRITICAL("Operand is not used by the instruction"); + } + } + } + array_free(&operands); +} + +// Check if the users are correct (only applicable to SSA IR form) void check_users(struct ir_function *fun) { // Check FunctionCallArgument Instructions for (__u8 i = 0; i < MAX_FUNC_ARG; ++i) { @@ -44,29 +70,7 @@ void check_users(struct ir_function *fun) { // Check users of this instruction check_insn_users_use_insn(insn); // Check operands of this instruction - struct array operands = get_operands(insn); - struct ir_value **val; - array_for(val, operands) { - struct ir_value *v = *val; - if (v->type == IR_VALUE_INSN) { - // Check if the operand actually is used by this instruction - struct ir_insn **pos2; - int found = 0; - array_for(pos2, v->data.insn_d->users) { - struct ir_insn *user = *pos2; - if (user == insn) { - // Found the user - found = 1; - break; - } - } - if (!found) { - // Error! - CRITICAL("Operand is not used by the instruction"); - } - } - } - array_free(&operands); + check_insn_operand(insn); } } } From e941f79a1c778654ee6b82b5b7970b2d890041fb Mon Sep 17 00:00:00 2001 From: linsyking Date: Wed, 14 Aug 2024 12:17:29 -0400 Subject: [PATCH 26/28] fix: users --- IR/aux/explicit_reg.c | 17 ++++------------- IR/ir_code_gen.c | 3 ++- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/IR/aux/explicit_reg.c b/IR/aux/explicit_reg.c index 73301176..2313ff98 100644 --- a/IR/aux/explicit_reg.c +++ b/IR/aux/explicit_reg.c @@ -21,15 +21,7 @@ void explicit_reg(struct ir_function *fun) { struct ir_basic_block *bb = *pos; struct ir_insn *insn; list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { - // struct ir_insn_cg_extra *extra = insn_cg(insn); if (insn->op == IR_INSN_CALL) { - // Change the return value to NULL - // The result is in r0 - // extra->dst = NULL; - // struct ir_value val; - // val.type = IR_VALUE_INSN; - // val.data.insn_d = &fun->cg_info.regs[0]; - // create_assign_insn(insn, val, INSERT_BACK); array_push(&call_insns, &insn); } } @@ -39,13 +31,12 @@ void explicit_reg(struct ir_function *fun) { array_for(pos2, call_insns) { struct ir_insn *insn = *pos2; for (__u8 i = 0; i < insn->value_num; ++i) { - struct ir_value val = insn->values[i]; - struct ir_insn *new_insn = - create_assign_insn_cg(insn, val, INSERT_FRONT); - insn_cg(new_insn)->dst = fun->cg_info.regs[i + 1]; + struct ir_value val = insn->values[i]; + struct ir_insn *new_insn = create_assign_insn_cg(insn, val, INSERT_FRONT); + insn_cg(new_insn)->dst = fun->cg_info.regs[i + 1]; val_remove_user(val, insn); } - insn->value_num = 0; + insn->value_num = 0; // Remove all operands struct ir_insn_cg_extra *extra = insn_cg(insn); extra->dst = NULL; if (insn->users.num_elem == 0) { diff --git a/IR/ir_code_gen.c b/IR/ir_code_gen.c index 919b782f..542520b0 100644 --- a/IR/ir_code_gen.c +++ b/IR/ir_code_gen.c @@ -114,12 +114,13 @@ void code_gen(struct ir_function *fun) { // Init CG, start real code generation init_cg(fun); - explicit_reg(fun); + explicit_reg(fun); // Still in SSA form, users are available print_ir_prog_cg(fun); printf("-----------------\n"); print_ir_prog_advanced(fun, NULL, NULL, print_ir_dst); // SSA Destruction + // users not available from now on // remove_phi(fun); From 8056cb9485f208e3efdd06ebdb674f3e842d21f0 Mon Sep 17 00:00:00 2001 From: linsyking Date: Wed, 14 Aug 2024 12:23:54 -0400 Subject: [PATCH 27/28] docs: comments --- IR/aux/explicit_reg.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/IR/aux/explicit_reg.c b/IR/aux/explicit_reg.c index 2313ff98..9ed014bc 100644 --- a/IR/aux/explicit_reg.c +++ b/IR/aux/explicit_reg.c @@ -14,6 +14,12 @@ void explicit_reg(struct ir_function *fun) { // fun is still in IR form + // Before this step, users are correct + // In this step we change some dsts + // We need carefully handle the users + // dsts are NOT users + // Invariant: All operands are final values + // Final value: v == dst(v) struct ir_basic_block **pos; // Maximum number of functions: MAX_FUNC_ARG struct array call_insns = INIT_ARRAY(struct ir_insn *); From 0f31c106f70442fe609ffd388fbaee3f5261e71f Mon Sep 17 00:00:00 2001 From: linsyking Date: Wed, 14 Aug 2024 12:25:37 -0400 Subject: [PATCH 28/28] chore: format --- IR/aux/conflict_analysis.c | 2 +- IR/aux/graph_coloring.c | 2 +- IR/aux/spill.c | 28 ++++++++++++---------------- IR/ir_insn.c | 2 +- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/IR/aux/conflict_analysis.c b/IR/aux/conflict_analysis.c index 4e327c13..3a7727f3 100644 --- a/IR/aux/conflict_analysis.c +++ b/IR/aux/conflict_analysis.c @@ -67,7 +67,7 @@ void conflict_analysis(struct ir_function *fun) { struct ir_insn *insn; // For each operation list_for_each_entry(insn, &bb->ir_insn_head, list_ptr) { - struct ir_insn **pos2; + struct ir_insn **pos2; struct ir_insn_cg_extra *insn_cg = insn->user_data; array_for(pos2, insn_cg->kill) { struct ir_insn *insn_dst = *pos2; diff --git a/IR/aux/graph_coloring.c b/IR/aux/graph_coloring.c index 84a998a7..5ebe51a4 100644 --- a/IR/aux/graph_coloring.c +++ b/IR/aux/graph_coloring.c @@ -28,7 +28,7 @@ void graph_coloring(struct ir_function *fun) { struct ir_insn **pos2; int used_reg[MAX_BPF_REG] = {0}; - struct array used_spill = INIT_ARRAY(size_t); + struct array used_spill = INIT_ARRAY(size_t); array_for(pos2, extra->adj) { struct ir_insn *insn2 = *pos2; // Adj instruction struct ir_insn_cg_extra *extra2 = insn_cg(insn2); diff --git a/IR/aux/spill.c b/IR/aux/spill.c index 5b717184..0b7ff28f 100644 --- a/IR/aux/spill.c +++ b/IR/aux/spill.c @@ -1,27 +1,26 @@ #include "bpf_ir.h" #include "code_gen.h" #include "dbg.h" -enum val_type{ +enum val_type { REG, CONST, STACK }; -enum val_type vtype(struct ir_value val){ +enum val_type vtype(struct ir_value val) { if (val.type == IR_VALUE_INSN) { - struct ir_insn *insn = dst(val.data.insn_d); - struct ir_insn_cg_extra * extra = insn_cg(insn); - if(extra->spilled){ - return STACK; - }else{ - return REG; - } - }else{ - + struct ir_insn *insn = dst(val.data.insn_d); + struct ir_insn_cg_extra *extra = insn_cg(insn); + if (extra->spilled) { + return STACK; + } else { + return REG; + } + } else { } } -int check_need_spill(struct ir_function *fun){ +int check_need_spill(struct ir_function *fun) { // Check if all instruction values are OK for translating struct ir_basic_block **pos; array_for(pos, fun->reachable_bbs) { @@ -48,7 +47,4 @@ int check_need_spill(struct ir_function *fun){ return 0; } - -void spill(struct ir_function *fun){ - -} \ No newline at end of file +void spill(struct ir_function *fun) {} \ No newline at end of file diff --git a/IR/ir_insn.c b/IR/ir_insn.c index d3b0d096..32df4cf0 100644 --- a/IR/ir_insn.c +++ b/IR/ir_insn.c @@ -39,7 +39,7 @@ void replace_all_usage(struct ir_insn *insn, struct ir_value rep) { struct array users = insn->users; insn->users = INIT_ARRAY(struct ir_insn *); array_for(pos, users) { - struct ir_insn *user = *pos; + struct ir_insn *user = *pos; struct array operands = get_operands(user); struct ir_value **pos2; array_for(pos2, operands) {