os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

commit eecbe645ffee51c58fc1be60dc935c7de3a0e58b
parent 54a775e2819f31d961757550e5a24804a8caac29
Author: erai <erai@omiltem.net>
Date:   Mon, 27 Jan 2025 22:47:59 +0000

ir calling convention

Diffstat:
Mcc0.c | 269++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mir.om | 256+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
2 files changed, 350 insertions(+), 175 deletions(-)

diff --git a/cc0.c b/cc0.c @@ -12,7 +12,7 @@ struct my_decl; struct my_file; struct my_fixup; struct my_irblock; -struct my_ircomp; +struct my_irfunc; struct my_irlabel; struct my_irloopctx; struct my_irop; @@ -126,15 +126,18 @@ struct my_irblock { struct my_irblock* my_alt; unsigned long my_mark; }; -struct my_ircomp { +struct my_irfunc { struct my_compiler* my_c; struct my_alloc* my_a; + unsigned char* my_name; struct my_irloopctx* my_loopctx; struct my_irblock* my_top; struct my_irblock* my_cur; - struct my_irlabel* my_labels; - struct my_irvar* my_vars; - unsigned long my_numvars; + struct my_irlabel* my_labels_tree; + struct my_irvar* my_vars_tree; + struct my_irvar** my_vars; + unsigned long my_vars_len; + unsigned long my_vars_cap; }; struct my_irlabel { unsigned char* my_name; @@ -154,6 +157,9 @@ struct my_irop { unsigned long my_n; unsigned char* my_s; struct my_type* my_t; + unsigned char* my_filename; + unsigned long my_lineno; + unsigned long my_colno; }; struct my_irvar { unsigned char* my_name; @@ -300,36 +306,37 @@ enum { my_EINTR = 4, my_EPIPE = 32, my_EXACTLY_ONE = 1, - my_IOP_ADD = 10, - my_IOP_AND = 11, - my_IOP_ARG = 6, - my_IOP_BRANCH = 28, - my_IOP_CALL = 26, + my_IOP_ADD = 11, + my_IOP_AND = 12, + my_IOP_ARG = 8, + my_IOP_BRANCH = 29, + my_IOP_CALL = 27, my_IOP_CONST = 2, - my_IOP_DIV = 14, - my_IOP_EQ = 20, + my_IOP_DIV = 15, + my_IOP_EQ = 21, my_IOP_FUNC = 1, - my_IOP_GE = 23, - my_IOP_GT = 22, - my_IOP_JUMP = 27, - my_IOP_LE = 25, + my_IOP_GE = 24, + my_IOP_GT = 23, + my_IOP_JUMP = 28, + my_IOP_LE = 26, my_IOP_LOAD = 4, - my_IOP_LSH = 16, - my_IOP_LT = 24, - my_IOP_MOD = 15, - my_IOP_MUL = 18, - my_IOP_NE = 21, - my_IOP_NEG = 8, - my_IOP_NOT = 9, - my_IOP_OR = 12, - my_IOP_REF = 7, - my_IOP_RETURN = 29, - my_IOP_RSH = 17, + my_IOP_LSH = 17, + my_IOP_LT = 25, + my_IOP_MOD = 16, + my_IOP_MUL = 19, + my_IOP_NE = 22, + my_IOP_NEG = 9, + my_IOP_NOT = 10, + my_IOP_OR = 13, + my_IOP_REF = 6, + my_IOP_RETURN = 30, + my_IOP_RETVAL = 7, + my_IOP_RSH = 18, my_IOP_STORE = 5, my_IOP_STR = 3, - my_IOP_SUB = 19, + my_IOP_SUB = 20, my_IOP_VAR = 0, - my_IOP_XOR = 13, + my_IOP_XOR = 14, my_LOOK_AND = 2, my_LOOK_NORMAL = 0, my_LOOK_NOT = 1, @@ -645,7 +652,7 @@ void( my_add_symbol)(struct my_assembler* my_c,unsigned char* my_name,struct my_ void( my_addfixup)(struct my_assembler* my_c,struct my_label* my_l); unsigned char*( my_alloc)(struct my_alloc* my_c,unsigned long my_size); unsigned long( my_any)(struct my_peg* my_c); -void( my_args_to_ir)(struct my_ircomp* my_ic,struct my_node* my_n); +void( my_args_to_ir)(struct my_irfunc* my_ic,struct my_node* my_n); void( my_as_emit)(struct my_assembler* my_a,unsigned long my_b); void( my_as_jmp)(struct my_assembler* my_a,unsigned long my_op,struct my_label* my_l); void( my_as_modm)(struct my_assembler* my_a,unsigned long my_op,unsigned long my_b,unsigned long my_i,unsigned long my_s,unsigned long my_d); @@ -743,7 +750,7 @@ void( my_emit_ud)(struct my_assembler* my_c); void( my_emit_xor)(struct my_assembler* my_c); void( my_enter)(struct my_peg* my_c,unsigned long my_tag); void( my_exit)(unsigned long my_n); -struct my_irop*( my_expr_to_ir)(struct my_ircomp* my_ic,struct my_node* my_n); +struct my_irop*( my_expr_to_ir)(struct my_irfunc* my_ic,struct my_node* my_n); void( my_fail)(struct my_peg* my_c); void( my_fclose)(struct my_file* my_f); void( my_fdputc)(unsigned long my_fd,unsigned long my_ch); @@ -767,37 +774,38 @@ void( my_fputh)(struct my_file* my_out,unsigned long my_n); void( my_fputs)(struct my_file* my_f,unsigned char* my_s); unsigned char*( my_freadall)(struct my_file* my_f,unsigned long* my_size); void( my_free)(struct my_alloc* my_a,unsigned char* my_p); -void( my_func_to_ir)(struct my_compiler* my_c,struct my_node* my_n); +struct my_irfunc*( my_func_to_ir)(struct my_compiler* my_c,struct my_node* my_n); unsigned long( my_get)(struct my_peg* my_c); unsigned long( my_hex2int)(unsigned char* my_s,unsigned long my_len,unsigned long* my_ok); unsigned long( my_hexdig)(unsigned long my_ch,unsigned long* my_ok); unsigned long( my_hoist_locals)(struct my_compiler* my_c,struct my_decl* my_d,struct my_node* my_n,unsigned long my_offset); -void( my_iraddarg)(struct my_ircomp* my_ic,unsigned char* my_name,struct my_type* my_t); -void( my_iraddop)(struct my_ircomp* my_ic,struct my_irop* my_o); -void( my_iraddvar)(struct my_ircomp* my_ic,unsigned char* my_name,struct my_type* my_t); -void( my_irbranch)(struct my_ircomp* my_ic,struct my_irop* my_cond,struct my_irblock* my_alt,struct my_irblock* my_next); -struct my_irop*( my_ircall)(struct my_ircomp* my_ic,struct my_node* my_n); -struct my_irblock*( my_irfind_block)(struct my_ircomp* my_ic,unsigned char* my_name,unsigned long my_make); -struct my_irvar*( my_irfind_var)(struct my_ircomp* my_ic,unsigned char* my_name,unsigned long my_make); -void( my_irjump)(struct my_ircomp* my_ic,struct my_irblock* my_to,struct my_irblock* my_next); -void( my_irreturn)(struct my_ircomp* my_ic,struct my_irop* my_value); -void( my_labels_to_ir)(struct my_ircomp* my_ic,struct my_node* my_n); +void( my_iraddarg)(struct my_irfunc* my_ic,unsigned char* my_name,struct my_type* my_t); +void( my_iraddop)(struct my_irfunc* my_ic,struct my_irop* my_o); +void( my_iraddvar)(struct my_irfunc* my_ic,unsigned char* my_name,struct my_type* my_t); +void( my_irbranch)(struct my_irfunc* my_ic,struct my_irop* my_cond,struct my_irblock* my_alt,struct my_irblock* my_next); +struct my_irop*( my_ircall)(struct my_irfunc* my_ic,struct my_node* my_n); +struct my_irblock*( my_irfind_block)(struct my_irfunc* my_ic,unsigned char* my_name,unsigned long my_make); +struct my_irvar*( my_irfind_var)(struct my_irfunc* my_ic,unsigned char* my_name,unsigned long my_make); +void( my_irjump)(struct my_irfunc* my_ic,struct my_irblock* my_to,struct my_irblock* my_next); +void( my_irreturn)(struct my_irfunc* my_ic,struct my_irop* my_value); +void( my_labels_to_ir)(struct my_irfunc* my_ic,struct my_node* my_n); void( my_layout_struct)(struct my_compiler* my_c,struct my_decl* my_d); void( my_layout_union)(struct my_compiler* my_c,struct my_decl* my_d); void( my_leave)(struct my_peg* my_c,unsigned long my_tag); unsigned long( my_literal)(struct my_peg* my_c,unsigned char* my_s); -void( my_locals_to_ir)(struct my_ircomp* my_ic,struct my_node* my_n); +void( my_locals_to_ir)(struct my_irfunc* my_ic,struct my_node* my_n); void( my_main)(unsigned long my_argc,unsigned char** my_argv,unsigned char** my_envp); void( my_mark_expr_used)(struct my_compiler* my_c,struct my_decl* my_d,struct my_node* my_n); void( my_mark_func_used)(struct my_compiler* my_c,struct my_decl* my_d); void( my_mark_stmt_used)(struct my_compiler* my_c,struct my_decl* my_d,struct my_node* my_n); void( my_memcpy)(unsigned char* my_dest,unsigned char* my_src,unsigned long my_size); void( my_memset)(unsigned char* my_dest,unsigned long my_c,unsigned long my_size); -struct my_irblock*( my_mkirblock)(struct my_ircomp* my_ic); -struct my_irop*( my_mkirconst)(struct my_ircomp* my_ic,unsigned long my_n); -struct my_irop*( my_mkirop)(struct my_ircomp* my_ic,unsigned long my_kind,struct my_irop* my_a,struct my_irop* my_b); -struct my_irop*( my_mkirstr)(struct my_ircomp* my_ic,unsigned char* my_s); -struct my_irop*( my_mkirtmp)(struct my_ircomp* my_ic); +struct my_irblock*( my_mkirblock)(struct my_irfunc* my_ic); +struct my_irop*( my_mkirconst)(struct my_irfunc* my_ic,unsigned long my_n); +struct my_irop*( my_mkirop)(struct my_irfunc* my_ic,unsigned long my_kind,struct my_irop* my_a,struct my_irop* my_b); +struct my_irop*( my_mkirstr)(struct my_irfunc* my_ic,unsigned char* my_s); +struct my_irop*( my_mkirtmp)(struct my_irfunc* my_ic); +struct my_irvar*( my_mkirvar)(struct my_irfunc* my_ic); struct my_label*( my_mklabel)(struct my_assembler* my_c); struct my_node*( my_mknode)(struct my_parser* my_c,unsigned long my_kind,struct my_node* my_a,struct my_node* my_b); struct my_node*( my_mknode0)(struct my_parser* my_c,unsigned long my_kind); @@ -978,7 +986,7 @@ struct my_assembler*( my_setup_assembler)(struct my_alloc* my_a); struct my_parser*( my_setup_parser)(struct my_alloc* my_a); struct my_peg_compiler*( my_setup_peg)(struct my_alloc* my_a,unsigned char* my_prefix); void( my_show_node)(struct my_file* my_out,struct my_node* my_n); -void( my_stmt_to_ir)(struct my_ircomp* my_ic,struct my_node* my_n); +void( my_stmt_to_ir)(struct my_irfunc* my_ic,struct my_node* my_n); unsigned long( my_strcmp)(unsigned char* my_a,unsigned char* my_b); unsigned long( my_strlen)(unsigned char* my_s); unsigned long( my_syscall)(unsigned long my_n,unsigned long my_a1,unsigned long my_a2,unsigned long my_a3,unsigned long my_a4,unsigned long my_a5,unsigned long my_a6); @@ -1427,7 +1435,7 @@ unsigned long( my_any)(struct my_peg* my_c){ } return 1UL; } -void( my_args_to_ir)(struct my_ircomp* my_ic,struct my_node* my_n){ +void( my_args_to_ir)(struct my_irfunc* my_ic,struct my_node* my_n){ unsigned char* my_name = 0; struct my_type* my_t = 0; while (1) { @@ -2829,6 +2837,9 @@ void( my_ctranslate_zero)(struct my_compiler* my_c,struct my_type* my_ty){ (my_v)=((my_find)((my_c),(((my_ty)->my_st)->my_name),((((my_n)->my_a)->my_a)->my_s),(0UL))); (my_ctranslate_zero)((my_c),((my_v)->my_member_type)); (my_n)=((my_n)->my_b); + if (my_n) { + (my_fputs)(((my_c)->my_cout),((unsigned char *)", ")); + } } (my_fputs)(((my_c)->my_cout),((unsigned char *)"}")); } else if ((unsigned long)(((long)((my_ty)->my_kind))==((long)(my_TY_UNION)))) { @@ -4380,7 +4391,7 @@ void( my_enter)(struct my_peg* my_c,unsigned long my_tag){ void( my_exit)(unsigned long my_n){ (my_syscall)((60UL),(my_n),(0UL),(0UL),(0UL),(0UL),(0UL)); } -struct my_irop*( my_expr_to_ir)(struct my_ircomp* my_ic,struct my_node* my_n){ +struct my_irop*( my_expr_to_ir)(struct my_irfunc* my_ic,struct my_node* my_n){ struct my_irop* my_a = 0; struct my_irop* my_b = 0; struct my_irop* my_c = 0; @@ -4987,26 +4998,29 @@ unsigned char*( my_freadall)(struct my_file* my_f,unsigned long* my_size){ } void( my_free)(struct my_alloc* my_a,unsigned char* my_p){ } -void( my_func_to_ir)(struct my_compiler* my_c,struct my_node* my_n){ - struct my_ircomp my_ic = {00000000}; +struct my_irfunc*( my_func_to_ir)(struct my_compiler* my_c,struct my_node* my_n){ + struct my_irfunc* my_ic = 0; struct my_irop* my_value = 0; struct my_type* my_t = 0; if ((unsigned long)(!(my_n))) { - return; + return (void *)0; } - ((my_ic).my_c)=(my_c); - ((my_ic).my_a)=((my_c)->my_a); - ((my_ic).my_top)=((my_mkirblock)((&(my_ic)))); - ((my_ic).my_cur)=((my_ic).my_top); - (my_args_to_ir)((&(my_ic)),((((my_n)->my_a)->my_b)->my_a)); - (my_locals_to_ir)((&(my_ic)),((my_n)->my_b)); - (my_labels_to_ir)((&(my_ic)),((my_n)->my_b)); - (my_stmt_to_ir)((&(my_ic)),((my_n)->my_b)); + (my_ic)=((struct my_irfunc*)(my_alloc)(((my_c)->my_a),(88UL))); + ((my_ic)->my_c)=(my_c); + ((my_ic)->my_a)=((my_c)->my_a); + ((my_ic)->my_top)=((my_mkirblock)((my_ic))); + ((my_ic)->my_cur)=((my_ic)->my_top); + ((my_ic)->my_name)=((((my_n)->my_a)->my_a)->my_s); + (my_args_to_ir)((my_ic),((((my_n)->my_a)->my_b)->my_a)); + (my_locals_to_ir)((my_ic),((my_n)->my_b)); + (my_labels_to_ir)((my_ic),((my_n)->my_b)); + (my_stmt_to_ir)((my_ic),((my_n)->my_b)); (my_t)=((my_prototype)((my_c),(((my_n)->my_a)->my_b))); if ((unsigned long)(((long)(((my_t)->my_val)->my_kind))==((long)(my_TY_VOID)))) { - (my_value)=((my_mkirconst)((&(my_ic)),(0UL))); - (my_irreturn)((&(my_ic)),(my_value)); + (my_value)=((my_mkirconst)((my_ic),(0UL))); + (my_irreturn)((my_ic),(my_value)); } + return my_ic; } unsigned long( my_get)(struct my_peg* my_c){ unsigned long my_ch = 0; @@ -5130,10 +5144,10 @@ unsigned long( my_hoist_locals)(struct my_compiler* my_c,struct my_decl* my_d,st ((my_v)->my_var_offset)=((unsigned long)(-(unsigned long)(my_offset))); return my_offset; } -void( my_iraddarg)(struct my_ircomp* my_ic,unsigned char* my_name,struct my_type* my_t){ +void( my_iraddarg)(struct my_irfunc* my_ic,unsigned char* my_name,struct my_type* my_t){ (my_irfind_var)((my_ic),(my_name),(1UL)); } -void( my_iraddop)(struct my_ircomp* my_ic,struct my_irop* my_o){ +void( my_iraddop)(struct my_irfunc* my_ic,struct my_irop* my_o){ struct my_irblock* my_cur = 0; struct my_irop** my_ops = 0; unsigned long my_i = 0; @@ -5159,10 +5173,10 @@ void( my_iraddop)(struct my_ircomp* my_ic,struct my_irop* my_o){ (((my_cur)->my_ops)[(my_cur)->my_ops_len])=(my_o); ((my_cur)->my_ops_len)=((unsigned long)(((unsigned long)((my_cur)->my_ops_len))+((unsigned long)(1UL)))); } -void( my_iraddvar)(struct my_ircomp* my_ic,unsigned char* my_name,struct my_type* my_t){ +void( my_iraddvar)(struct my_irfunc* my_ic,unsigned char* my_name,struct my_type* my_t){ (my_irfind_var)((my_ic),(my_name),(1UL)); } -void( my_irbranch)(struct my_ircomp* my_ic,struct my_irop* my_cond,struct my_irblock* my_alt,struct my_irblock* my_next){ +void( my_irbranch)(struct my_irfunc* my_ic,struct my_irop* my_cond,struct my_irblock* my_alt,struct my_irblock* my_next){ struct my_irblock* my_cur = 0; struct my_irop* my_o = 0; (my_o)=((my_mkirop)((my_ic),(my_IOP_BRANCH),(my_cond),((void *)0))); @@ -5178,7 +5192,7 @@ void( my_irbranch)(struct my_ircomp* my_ic,struct my_irop* my_cond,struct my_irb } ((my_ic)->my_cur)=(my_next); } -struct my_irop*( my_ircall)(struct my_ircomp* my_ic,struct my_node* my_n){ +struct my_irop*( my_ircall)(struct my_irfunc* my_ic,struct my_node* my_n){ struct my_irop* my_o = 0; struct my_irop* my_a = 0; struct my_irop* my_b = 0; @@ -5186,25 +5200,62 @@ struct my_irop*( my_ircall)(struct my_ircomp* my_ic,struct my_node* my_n){ struct my_irblock* my_next = 0; struct my_irblock* my_cur = 0; struct my_node* my_arg = 0; + struct my_irop** my_tmp = 0; + struct my_irop* my_fp = 0; unsigned long my_i = 0; + unsigned long my_count = 0; + (my_fp)=((my_mkirtmp)((my_ic))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_a)=((my_mkirop)((my_ic),(my_IOP_REF),(my_fp),((void *)0))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_STORE),(my_a),(my_b))); + ((my_o)->my_t)=(((my_n)->my_a)->my_t); + (my_iraddop)((my_ic),(my_o)); + (my_arg)=((my_n)->my_b); + (my_count)=(0UL); + while (1) { + if ((unsigned long)(!(my_arg))) { + break; + } + (my_count)=((unsigned long)(((unsigned long)(my_count))+((unsigned long)(1UL)))); + (my_arg)=((my_arg)->my_b); + } + (my_tmp)=((struct my_irop**)(my_alloc)(((my_ic)->my_a),((unsigned long)(((long)(8UL))*((long)(my_count)))))); (my_arg)=((my_n)->my_b); (my_i)=(0UL); while (1) { if ((unsigned long)(!(my_arg))) { break; } - (my_a)=((my_expr_to_ir)((my_ic),((my_arg)->my_a))); - (my_o)=((my_mkirop)((my_ic),(my_IOP_ARG),(my_a),((void *)0))); + ((my_tmp)[my_i])=((my_mkirtmp)((my_ic))); + (my_b)=((my_expr_to_ir)((my_ic),((my_arg)->my_a))); + (my_a)=((my_mkirop)((my_ic),(my_IOP_REF),((my_tmp)[my_i]),((void *)0))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_STORE),(my_a),(my_b))); + ((my_o)->my_t)=(((my_arg)->my_a)->my_t); + (my_iraddop)((my_ic),(my_o)); + (my_arg)=((my_arg)->my_b); + (my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL)))); + } + (my_arg)=((my_n)->my_b); + (my_i)=(0UL); + while (1) { + if ((unsigned long)(((long)(my_i))==((long)(my_count)))) { + break; + } + (my_o)=((my_mkirop)((my_ic),(my_IOP_ARG),((my_tmp)[my_i]),((void *)0))); ((my_o)->my_n)=(my_i); ((my_o)->my_t)=(((my_arg)->my_a)->my_t); (my_iraddop)((my_ic),(my_o)); (my_arg)=((my_arg)->my_b); (my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL)))); } - (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_free)(((my_ic)->my_a),((unsigned char*)my_tmp)); (my_ret)=((my_mkirtmp)((my_ic))); - (my_a)=((my_mkirop)((my_ic),(my_IOP_REF),(my_ret),((void *)0))); - (my_o)=((my_mkirop)((my_ic),(my_IOP_CALL),(my_a),(my_b))); + (my_b)=((my_mkirop)((my_ic),(my_IOP_REF),(my_ret),((void *)0))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_RETVAL),(my_b),((void *)0))); + ((my_o)->my_t)=((my_n)->my_t); + (my_iraddop)((my_ic),(my_o)); + (my_o)=((my_mkirop)((my_ic),(my_IOP_CALL),(my_fp),((void *)0))); + ((my_o)->my_n)=(my_count); (my_iraddop)((my_ic),(my_o)); (my_next)=((my_mkirblock)((my_ic))); (my_cur)=((my_ic)->my_cur); @@ -5218,11 +5269,11 @@ struct my_irop*( my_ircall)(struct my_ircomp* my_ic,struct my_node* my_n){ ((my_ic)->my_cur)=(my_next); return my_ret; } -struct my_irblock*( my_irfind_block)(struct my_ircomp* my_ic,unsigned char* my_name,unsigned long my_make){ +struct my_irblock*( my_irfind_block)(struct my_irfunc* my_ic,unsigned char* my_name,unsigned long my_make){ struct my_irlabel** my_link = 0; struct my_irlabel* my_l = 0; unsigned long my_dir = 0; - (my_link)=(&((my_ic)->my_labels)); + (my_link)=(&((my_ic)->my_labels_tree)); while (1) { (my_l)=(*(my_link)); if ((unsigned long)(!(my_l))) { @@ -5251,11 +5302,11 @@ struct my_irblock*( my_irfind_block)(struct my_ircomp* my_ic,unsigned char* my_n (*(my_link))=(my_l); return (my_l)->my_block; } -struct my_irvar*( my_irfind_var)(struct my_ircomp* my_ic,unsigned char* my_name,unsigned long my_make){ +struct my_irvar*( my_irfind_var)(struct my_irfunc* my_ic,unsigned char* my_name,unsigned long my_make){ struct my_irvar** my_link = 0; struct my_irvar* my_v = 0; unsigned long my_dir = 0; - (my_link)=(&((my_ic)->my_vars)); + (my_link)=(&((my_ic)->my_vars_tree)); while (1) { (my_v)=(*(my_link)); if ((unsigned long)(!(my_v))) { @@ -5276,16 +5327,12 @@ struct my_irvar*( my_irfind_var)(struct my_ircomp* my_ic,unsigned char* my_name, if ((unsigned long)(!(my_make))) { return (void *)0; } - (my_v)=((struct my_irvar*)(my_alloc)(((my_ic)->my_a),(32UL))); + (my_v)=((my_mkirvar)((my_ic))); ((my_v)->my_name)=(my_name); - ((my_v)->my_left)=((void *)0); - ((my_v)->my_right)=((void *)0); - ((my_v)->my_n)=((my_ic)->my_numvars); - ((my_ic)->my_numvars)=((unsigned long)(((unsigned long)((my_ic)->my_numvars))+((unsigned long)(1UL)))); (*(my_link))=(my_v); return my_v; } -void( my_irjump)(struct my_ircomp* my_ic,struct my_irblock* my_to,struct my_irblock* my_next){ +void( my_irjump)(struct my_irfunc* my_ic,struct my_irblock* my_to,struct my_irblock* my_next){ struct my_irblock* my_cur = 0; struct my_irop* my_o = 0; (my_o)=((my_mkirop)((my_ic),(my_IOP_JUMP),((void *)0),((void *)0))); @@ -5300,7 +5347,7 @@ void( my_irjump)(struct my_ircomp* my_ic,struct my_irblock* my_to,struct my_irbl } ((my_ic)->my_cur)=(my_next); } -void( my_irreturn)(struct my_ircomp* my_ic,struct my_irop* my_value){ +void( my_irreturn)(struct my_irfunc* my_ic,struct my_irop* my_value){ struct my_irblock* my_cur = 0; struct my_irop* my_o = 0; (my_o)=((my_mkirop)((my_ic),(my_IOP_RETURN),(my_value),((void *)0))); @@ -5314,7 +5361,7 @@ void( my_irreturn)(struct my_ircomp* my_ic,struct my_irop* my_value){ } ((my_ic)->my_cur)=((void *)0); } -void( my_labels_to_ir)(struct my_ircomp* my_ic,struct my_node* my_n){ +void( my_labels_to_ir)(struct my_irfunc* my_ic,struct my_node* my_n){ unsigned long my_kind = 0; unsigned char* my_name = 0; if ((unsigned long)(!(my_n))) { @@ -5480,7 +5527,7 @@ unsigned long( my_literal)(struct my_peg* my_c,unsigned char* my_s){ } return 1UL; } -void( my_locals_to_ir)(struct my_ircomp* my_ic,struct my_node* my_n){ +void( my_locals_to_ir)(struct my_irfunc* my_ic,struct my_node* my_n){ unsigned char* my_name = 0; struct my_type* my_t = 0; unsigned long my_kind = 0; @@ -5758,7 +5805,7 @@ void( my_memset)(unsigned char* my_dest,unsigned long my_c,unsigned long my_size (my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL)))); } } -struct my_irblock*( my_mkirblock)(struct my_ircomp* my_ic){ +struct my_irblock*( my_mkirblock)(struct my_irfunc* my_ic){ struct my_irblock* my_b = 0; (my_b)=((struct my_irblock*)(my_alloc)(((my_ic)->my_a),(56UL))); ((my_b)->my_ops)=((void *)0); @@ -5769,36 +5816,64 @@ struct my_irblock*( my_mkirblock)(struct my_ircomp* my_ic){ ((my_b)->my_alt)=((void *)0); return my_b; } -struct my_irop*( my_mkirconst)(struct my_ircomp* my_ic,unsigned long my_n){ +struct my_irop*( my_mkirconst)(struct my_irfunc* my_ic,unsigned long my_n){ struct my_irop* my_o = 0; (my_o)=((my_mkirop)((my_ic),(my_IOP_CONST),((void *)0),((void *)0))); ((my_o)->my_n)=(my_n); return my_o; } -struct my_irop*( my_mkirop)(struct my_ircomp* my_ic,unsigned long my_kind,struct my_irop* my_a,struct my_irop* my_b){ +struct my_irop*( my_mkirop)(struct my_irfunc* my_ic,unsigned long my_kind,struct my_irop* my_a,struct my_irop* my_b){ struct my_irop* my_o = 0; - (my_o)=((struct my_irop*)(my_alloc)(((my_ic)->my_a),(48UL))); + (my_o)=((struct my_irop*)(my_alloc)(((my_ic)->my_a),(72UL))); ((my_o)->my_kind)=(my_kind); ((my_o)->my_a)=(my_a); ((my_o)->my_b)=(my_b); ((my_o)->my_n)=(0UL); ((my_o)->my_s)=((void *)0); ((my_o)->my_t)=((void *)0); + ((my_o)->my_filename)=(((my_ic)->my_c)->my_filename); + ((my_o)->my_lineno)=(((my_ic)->my_c)->my_lineno); + ((my_o)->my_colno)=(((my_ic)->my_c)->my_colno); return my_o; } -struct my_irop*( my_mkirstr)(struct my_ircomp* my_ic,unsigned char* my_s){ +struct my_irop*( my_mkirstr)(struct my_irfunc* my_ic,unsigned char* my_s){ struct my_irop* my_o = 0; (my_o)=((my_mkirop)((my_ic),(my_IOP_STR),((void *)0),((void *)0))); ((my_o)->my_s)=(my_s); return my_o; } -struct my_irop*( my_mkirtmp)(struct my_ircomp* my_ic){ +struct my_irop*( my_mkirtmp)(struct my_irfunc* my_ic){ struct my_irop* my_o = 0; + struct my_irvar* my_v = 0; + (my_v)=((my_mkirvar)((my_ic))); (my_o)=((my_mkirop)((my_ic),(my_IOP_VAR),((void *)0),((void *)0))); - ((my_o)->my_n)=((my_ic)->my_numvars); - ((my_ic)->my_numvars)=((unsigned long)(((unsigned long)((my_ic)->my_numvars))+((unsigned long)(1UL)))); + ((my_o)->my_n)=((my_v)->my_n); return my_o; } +struct my_irvar*( my_mkirvar)(struct my_irfunc* my_ic){ + struct my_irvar* my_v = 0; + struct my_irvar** my_tmp = 0; + unsigned long my_i = 0; + if ((unsigned long)(((long)((my_ic)->my_vars_len))==((long)((my_ic)->my_vars_cap)))) { + ((my_ic)->my_vars_cap)=((unsigned long)(((unsigned long)((unsigned long)(((long)((my_ic)->my_vars_cap))*((long)(2UL)))))+((unsigned long)(16UL)))); + (my_tmp)=((struct my_irvar**)(my_alloc)(((my_ic)->my_a),((unsigned long)(((long)(8UL))*((long)((my_ic)->my_vars_cap)))))); + (my_i)=(0UL); + while (1) { + if ((unsigned long)(((long)(my_i))==((long)((my_ic)->my_vars_len)))) { + break; + } + ((my_tmp)[my_i])=(((my_ic)->my_vars)[my_i]); + (my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL)))); + } + ((my_ic)->my_vars)=(my_tmp); + } + (my_i)=((my_ic)->my_vars_len); + (my_v)=((struct my_irvar*)(my_alloc)(((my_ic)->my_a),(32UL))); + ((my_v)->my_n)=(my_i); + (((my_ic)->my_vars)[my_i])=(my_v); + ((my_ic)->my_vars_len)=((unsigned long)(((unsigned long)((my_ic)->my_vars_len))+((unsigned long)(1UL)))); + return my_v; +} struct my_label*( my_mklabel)(struct my_assembler* my_c){ struct my_label* my_l = 0; (my_l)=((struct my_label*)(my_alloc)(((my_c)->my_a),(24UL))); @@ -10198,8 +10273,8 @@ void( my_show_node)(struct my_file* my_out,struct my_node* my_n){ } (my_fputc)((my_out),(41)); } -void( my_stmt_to_ir)(struct my_ircomp* my_ic,struct my_node* my_n){ - struct my_irloopctx my_loopctx = {000}; +void( my_stmt_to_ir)(struct my_irfunc* my_ic,struct my_node* my_n){ + struct my_irloopctx my_loopctx = {0, 0, 0}; struct my_irblock* my_cond_body = 0; struct my_irblock* my_cond_next = 0; struct my_irblock* my_cond_out = 0; diff --git a/ir.om b/ir.om @@ -8,9 +8,12 @@ enum { // Memory operations IOP_LOAD, IOP_STORE, - IOP_ARG, IOP_REF, + // Calling convention + IOP_RETVAL, + IOP_ARG, + // Unary arithmetic IOP_NEG, IOP_NOT, @@ -49,6 +52,10 @@ struct irop { n: int; s: *byte; t: *type; + + filename: *byte; + lineno: int; + colno: int; } // A basic block is a sequence of expressions that end with a branch @@ -82,18 +89,21 @@ struct irvar { n: int; } -struct ircomp { +struct irfunc { c: *compiler; a: *alloc; + name: *byte; loopctx: *irloopctx; top: *irblock; cur: *irblock; - labels: *irlabel; - vars: *irvar; - numvars: int; + labels_tree: *irlabel; + vars_tree: *irvar; + vars: **irvar; + vars_len: int; + vars_cap: int; } -func mkirblock(ic: *ircomp): *irblock { +func mkirblock(ic: *irfunc): *irblock { var b: *irblock; b = alloc(ic.a, sizeof(*b)) as *irblock; @@ -108,7 +118,7 @@ func mkirblock(ic: *ircomp): *irblock { return b; } -func mkirop(ic: *ircomp, kind: int, a: *irop, b: *irop): *irop { +func mkirop(ic: *irfunc, kind: int, a: *irop, b: *irop): *irop { var o: *irop; o = alloc(ic.a, sizeof(*o)) as *irop; @@ -120,10 +130,14 @@ func mkirop(ic: *ircomp, kind: int, a: *irop, b: *irop): *irop { o.s = nil; o.t = nil; + o.filename = ic.c.filename; + o.lineno = ic.c.lineno; + o.colno = ic.c.colno; + return o; } -func mkirconst(ic: *ircomp, n: int): *irop { +func mkirconst(ic: *irfunc, n: int): *irop { var o: *irop; o = mkirop(ic, IOP_CONST, nil, nil); @@ -133,7 +147,7 @@ func mkirconst(ic: *ircomp, n: int): *irop { return o; } -func mkirstr(ic: *ircomp, s: *byte): *irop { +func mkirstr(ic: *irfunc, s: *byte): *irop { var o: *irop; o = mkirop(ic, IOP_STR, nil, nil); @@ -143,24 +157,60 @@ func mkirstr(ic: *ircomp, s: *byte): *irop { return o; } -func mkirtmp(ic: *ircomp): *irop { - var o: *irop; +func mkirvar(ic: *irfunc): *irvar { + var v: *irvar; + var tmp: **irvar; + var i: int; - o = mkirop(ic, IOP_VAR, nil, nil); + if ic.vars_len == ic.vars_cap { + ic.vars_cap = ic.vars_cap * 2 + 16; + + tmp = alloc(ic.a, sizeof(*tmp) * ic.vars_cap) as **irvar; + + i = 0; + loop { + if i == ic.vars_len { + break; + } + + tmp[i] = ic.vars[i]; + + i = i + 1; + } + + ic.vars = tmp; + } + + i = ic.vars_len; + + v = alloc(ic.a, sizeof(*v)) as *irvar; + + v.n = i; + + ic.vars[i] = v; + ic.vars_len = ic.vars_len + 1; - o.n = ic.numvars; + return v; +} - ic.numvars = ic.numvars + 1; +func mkirtmp(ic: *irfunc): *irop { + var o: *irop; + var v: *irvar; + + v = mkirvar(ic); + + o = mkirop(ic, IOP_VAR, nil, nil); + o.n = v.n; return o; } -func irfind_var(ic: *ircomp, name: *byte, make: int): *irvar { +func irfind_var(ic: *irfunc, name: *byte, make: int): *irvar { var link: **irvar; var v: *irvar; var dir: int; - link = &ic.vars; + link = &ic.vars_tree; loop { v = *link; @@ -187,29 +237,23 @@ func irfind_var(ic: *ircomp, name: *byte, make: int): *irvar { return nil; } - v = alloc(ic.a, sizeof(*v)) as *irvar; + v = mkirvar(ic); v.name = name; - v.left = nil; - v.right = nil; - v.n = ic.numvars; - - ic.numvars = ic.numvars + 1; - *link = v; return v; } -func iraddarg(ic: *ircomp, name: *byte, t: *type) { +func iraddarg(ic: *irfunc, name: *byte, t: *type) { irfind_var(ic, name, 1); } -func iraddvar(ic: *ircomp, name: *byte, t: *type) { +func iraddvar(ic: *irfunc, name: *byte, t: *type) { irfind_var(ic, name, 1); } -func ircall(ic: *ircomp, n: *node): *irop { +func ircall(ic: *irfunc, n: *node): *irop { var o: *irop; var a: *irop; var b: *irop; @@ -217,9 +261,35 @@ func ircall(ic: *ircomp, n: *node): *irop { var next: *irblock; var cur: *irblock; var arg: *node; + var tmp: **irop; + var fp: *irop; var i: int; + var count: int; - // Evaluate the arguments + // Evaluate the expression left to right starting with the function + fp = mkirtmp(ic); + b = expr_to_ir(ic, n.a); + a = mkirop(ic, IOP_REF, fp, nil); + o = mkirop(ic, IOP_STORE, a, b); + o.t = n.a.t; + iraddop(ic, o); + + // Count the number of arguments + arg = n.b; + count = 0; + loop { + if !arg { + break; + } + + count = count + 1; + + arg = arg.b; + } + + tmp = alloc(ic.a, sizeof(*tmp) * count) as **irop; + + // Evaluate the arguments left to right arg = n.b; i = 0; loop { @@ -227,9 +297,31 @@ func ircall(ic: *ircomp, n: *node): *irop { break; } + // Create a temporary for this argument + tmp[i] = mkirtmp(ic); + // Compute the argument value - a = expr_to_ir(ic, arg.a); - o = mkirop(ic, IOP_ARG, a, nil); + b = expr_to_ir(ic, arg.a); + + // Save the value + a = mkirop(ic, IOP_REF, tmp[i], nil); + o = mkirop(ic, IOP_STORE, a, b); + o.t = arg.a.t; + iraddop(ic, o); + + arg = arg.b; + i = i + 1; + } + + // Emit arg nodes just before the call left to right + arg = n.b; + i = 0; + loop { + if i == count { + break; + } + + o = mkirop(ic, IOP_ARG, tmp[i], nil); o.n = i; o.t = arg.a.t; iraddop(ic, o); @@ -238,13 +330,18 @@ func ircall(ic: *ircomp, n: *node): *irop { i = i + 1; } - // Compute the function pointer - b = expr_to_ir(ic, n.a); + free(ic.a, tmp as *byte); - // Emit the call + // Add a temporary for the return value ret = mkirtmp(ic); - a = mkirop(ic, IOP_REF, ret, nil); - o = mkirop(ic, IOP_CALL, a, b); + b = mkirop(ic, IOP_REF, ret, nil); + o = mkirop(ic, IOP_RETVAL, b, nil); + o.t = n.t; + iraddop(ic, o); + + // Emit the call + o = mkirop(ic, IOP_CALL, fp, nil); + o.n = count; iraddop(ic, o); // Link the return path @@ -266,7 +363,7 @@ func ircall(ic: *ircomp, n: *node): *irop { return ret; } -func expr_to_ir(ic: *ircomp, n: *node): *irop { +func expr_to_ir(ic: *irfunc, n: *node): *irop { var a: *irop; var b: *irop; var c: *irop; @@ -558,7 +655,7 @@ func expr_to_ir(ic: *ircomp, n: *node): *irop { } } -func iraddop(ic: *ircomp, o: *irop) { +func iraddop(ic: *irfunc, o: *irop) { var cur: *irblock; var ops: **irop; var i: int; @@ -594,7 +691,7 @@ func iraddop(ic: *ircomp, o: *irop) { cur.ops_len = cur.ops_len + 1; } -func irjump(ic: *ircomp, to: *irblock, next: *irblock) { +func irjump(ic: *irfunc, to: *irblock, next: *irblock) { var cur: *irblock; var o: *irop; @@ -614,7 +711,7 @@ func irjump(ic: *ircomp, to: *irblock, next: *irblock) { ic.cur = next; } -func irbranch(ic: *ircomp, cond: *irop, alt: *irblock, next: *irblock) { +func irbranch(ic: *irfunc, cond: *irop, alt: *irblock, next: *irblock) { var cur: *irblock; var o: *irop; @@ -635,7 +732,7 @@ func irbranch(ic: *ircomp, cond: *irop, alt: *irblock, next: *irblock) { ic.cur = next; } -func irreturn(ic: *ircomp, value: *irop) { +func irreturn(ic: *irfunc, value: *irop) { var cur: *irblock; var o: *irop; @@ -654,7 +751,7 @@ func irreturn(ic: *ircomp, value: *irop) { ic.cur = nil; } -func stmt_to_ir(ic: *ircomp, n: *node) { +func stmt_to_ir(ic: *irfunc, n: *node) { var loopctx: irloopctx; var cond_body: *irblock; var cond_next: *irblock; @@ -772,12 +869,12 @@ func stmt_to_ir(ic: *ircomp, n: *node) { } } -func irfind_block(ic: *ircomp, name: *byte, make: int): *irblock { +func irfind_block(ic: *irfunc, name: *byte, make: int): *irblock { var link: **irlabel; var l: *irlabel; var dir: int; - link = &ic.labels; + link = &ic.labels_tree; loop { l = *link; @@ -816,7 +913,7 @@ func irfind_block(ic: *ircomp, name: *byte, make: int): *irblock { return l.block; } -func labels_to_ir(ic: *ircomp, n: *node) { +func labels_to_ir(ic: *irfunc, n: *node) { var kind: int; var name: *byte; @@ -857,7 +954,7 @@ func labels_to_ir(ic: *ircomp, n: *node) { } } -func args_to_ir(ic: *ircomp, n: *node) { +func args_to_ir(ic: *irfunc, n: *node) { var name: *byte; var t: *type; @@ -876,7 +973,7 @@ func args_to_ir(ic: *ircomp, n: *node) { } } -func locals_to_ir(ic: *ircomp, n: *node) { +func locals_to_ir(ic: *irfunc, n: *node) { var name: *byte; var t: *type; var kind: int; @@ -921,39 +1018,40 @@ func locals_to_ir(ic: *ircomp, n: *node) { } } -func func_to_ir(c: *compiler, n: *node) { - var ic: ircomp; +func func_to_ir(c: *compiler, n: *node): *irfunc { + var ic: *irfunc; var value: *irop; var t: *type; if !n { - return; + return nil; } + ic = alloc(c.a, sizeof(*ic)) as *irfunc; + ic.c = c; ic.a = c.a; - ic.top = mkirblock(&ic); + ic.top = mkirblock(ic); ic.cur = ic.top; - args_to_ir(&ic, n.a.b.a); + ic.name = n.a.a.s; + + args_to_ir(ic, n.a.b.a); - locals_to_ir(&ic, n.b); + locals_to_ir(ic, n.b); - labels_to_ir(&ic, n.b); + labels_to_ir(ic, n.b); - stmt_to_ir(&ic, n.b); + stmt_to_ir(ic, n.b); t = prototype(c, n.a.b); if t.val.kind == TY_VOID { - value = mkirconst(&ic, 0); - irreturn(&ic, value); + value = mkirconst(ic, 0); + irreturn(ic, value); } - //fputs(nil, "\n"); - //fputs(nil, n.a.a.s); - //fputs(nil, "\n"); - //irshow(nil, ic.top); + return ic; } // Depth-first reset all the marks @@ -1005,16 +1103,20 @@ func irshow4(out: *file, o: *irop) { fputs(out, " "); irshow4(out, o.b); fputs(out, ")"); + } else if kind == IOP_REF { + fputs(out, "(ref "); + irshow4(out, o.a); + fputs(out, ")"); + } else if kind == IOP_RETVAL { + fputs(out, "(retval "); + irshow4(out, o.a); + fputs(out, ")"); } else if kind == IOP_ARG { fputs(out, "(arg "); fputd(out, o.n); fputs(out, " "); irshow4(out, o.a); fputs(out, ")"); - } else if kind == IOP_REF { - fputs(out, "(ref "); - irshow4(out, o.a); - fputs(out, ")"); } else if kind == IOP_NEG { fputs(out, "(neg "); irshow4(out, o.a); @@ -1122,8 +1224,6 @@ func irshow4(out: *file, o: *irop) { } else if kind == IOP_CALL { fputs(out, "(call "); irshow4(out, o.a); - fputs(out, " "); - irshow4(out, o.b); fputs(out, ")"); } else if kind == IOP_JUMP { fputs(out, "(jump)"); @@ -1193,23 +1293,23 @@ func irshow(out: *file, b: *irblock) { irreset(b); } -// value numbering -// flow control graph simplification -// loop detection - +// line numbers +// evaluator +// instruction selection +// register allocation +// assemble from ir // inline // intrinsics - // common subexpression // constant folding +// flow control graph simplification // dead code -// unrolling -// strength reduction - -// register allocation -// instruction selection - // c generator from ir -// assemble from ir -// proof check from ir // type check with ir +// parse to ir +// value numbering +// loop detection +// unrolling +// strength reduction / algebra +// loop motion / fusion +// proof check from ir