os

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

commit 05b32ee564117ad4d0a2ab3ca0316695530b0a15
parent 72cc7d4b486a26e5340dcda7488c8bb727a53a4e
Author: erai <erai@omiltem.net>
Date:   Mon, 27 Jan 2025 04:19:12 +0000

Add ir code

Diffstat:
Mbootstrap.sh | 2+-
Mcc0.c | 741++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mcc1.om | 2+-
Air.om | 1215+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 1935 insertions(+), 25 deletions(-)

diff --git a/bootstrap.sh b/bootstrap.sh @@ -2,7 +2,7 @@ BOOTSTRAP="cc0.c" LIBS="bufio.om lib.om alloc.om syscall.om" -SOURCES="cc1.om type.om parse2.om parse3.om peglib.om as.om decl.om node.om cout.om peg.om parsepeg.om" +SOURCES="cc1.om type.om parse2.om parse3.om peglib.om as.om decl.om node.om cout.om peg.om parsepeg.om ir.om" # Build the bootstrap compiler from c gcc -std=c99 ${BOOTSTRAP} -o cc0 diff --git a/cc0.c b/cc0.c @@ -118,12 +118,13 @@ struct my_fixup { unsigned long my_at; }; struct my_irblock { - struct my_irop* my_ops; + struct my_irop** my_ops; unsigned long my_ops_len; unsigned long my_ops_cap; unsigned long my_done; struct my_irblock* my_out; struct my_irblock* my_alt; + unsigned long my_mark; }; struct my_ircomp { struct my_compiler* my_c; @@ -133,6 +134,7 @@ struct my_ircomp { struct my_irblock* my_cur; struct my_irlabel* my_labels; struct my_irvar* my_vars; + unsigned long my_numvars; }; struct my_irlabel { unsigned char* my_name; @@ -146,7 +148,7 @@ struct my_irloopctx { struct my_irblock* my_out; }; struct my_irop { - unsigned long my_code; + unsigned long my_kind; struct my_irop* my_a; struct my_irop* my_b; unsigned long my_n; @@ -157,6 +159,7 @@ struct my_irvar { unsigned char* my_name; struct my_irvar* my_left; struct my_irvar* my_right; + unsigned long my_n; }; struct my_label { struct my_fixup* my_fix; @@ -297,36 +300,36 @@ enum { my_EINTR = 4, my_EPIPE = 32, my_EXACTLY_ONE = 1, - my_IOP_ADD = 11, - my_IOP_AND = 12, - my_IOP_ARG = 7, + my_IOP_ADD = 10, + my_IOP_AND = 11, + my_IOP_ARG = 6, my_IOP_BRANCH = 28, - my_IOP_CALL = 8, + my_IOP_CALL = 26, my_IOP_CONST = 2, - my_IOP_DIV = 15, - my_IOP_EQ = 21, + my_IOP_DIV = 14, + my_IOP_EQ = 20, my_IOP_FUNC = 1, - my_IOP_GE = 24, - my_IOP_GT = 23, + my_IOP_GE = 23, + my_IOP_GT = 22, my_IOP_JUMP = 27, - my_IOP_LE = 26, + my_IOP_LE = 25, my_IOP_LOAD = 4, - 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_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 = 18, + my_IOP_RSH = 17, my_IOP_STORE = 5, my_IOP_STR = 3, - my_IOP_SUB = 20, + my_IOP_SUB = 19, my_IOP_VAR = 0, - my_IOP_XOR = 14, + my_IOP_XOR = 13, my_LOOK_AND = 2, my_LOOK_NORMAL = 0, my_LOOK_NOT = 1, @@ -642,6 +645,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_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); @@ -739,6 +743,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); 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); @@ -762,20 +767,37 @@ 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); 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_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_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_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); @@ -956,6 +978,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); 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); @@ -1404,6 +1427,19 @@ 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){ + unsigned char* my_name = 0; + struct my_type* my_t = 0; + while (1) { + if ((unsigned long)(!(my_n))) { + break; + } + (my_name)=((((my_n)->my_a)->my_a)->my_s); + (my_t)=((my_prototype)(((my_ic)->my_c),(((my_n)->my_a)->my_b))); + (my_iraddarg)((my_ic),(my_name),(my_t)); + (my_n)=((my_n)->my_b); + } +} void( my_as_emit)(struct my_assembler* my_a,unsigned long my_b){ (my_emit)((my_a),(my_b)); } @@ -1791,6 +1827,7 @@ void( my_compile)(struct my_compiler* my_c,struct my_node* my_p){ break; } if ((unsigned long)(((my_d)->my_func_used)&&((my_d)->my_func_defined))) { + (my_func_to_ir)((my_c),((my_d)->my_func_def)); (my_compile_func)((my_c),(my_d)); } (my_d)=((my_next_decl)((my_c),(my_d))); @@ -4343,6 +4380,270 @@ 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_a = 0; + struct my_irop* my_b = 0; + struct my_irop* my_c = 0; + struct my_irop* my_d = 0; + struct my_irop* my_e = 0; + struct my_irop* my_o = 0; + struct my_irblock* my_bool_body = 0; + struct my_irblock* my_bool_next = 0; + struct my_irblock* my_bool_final = 0; + struct my_irblock* my_bool_out = 0; + struct my_decl* my_v = 0; + struct my_irvar* my_iv = 0; + unsigned long my_kind = 0; + unsigned long my_size = 0; + (my_assert)(((unsigned long)(!((unsigned long)(!(my_n))))),((unsigned char *)"expected node")); + (((my_ic)->my_c)->my_filename)=((my_n)->my_filename); + (((my_ic)->my_c)->my_lineno)=((my_n)->my_lineno); + (((my_ic)->my_c)->my_colno)=((my_n)->my_colno); + (my_kind)=((my_n)->my_kind); + if ((unsigned long)(((long)(my_kind))==((long)(my_N_NIL)))) { + (my_o)=((my_mkirconst)((my_ic),(0UL))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NUM)))) { + (my_o)=((my_mkirconst)((my_ic),((my_n)->my_n))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_CHAR)))) { + (my_o)=((my_mkirconst)((my_ic),((my_n)->my_n))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_SIZEOF)))) { + if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))==((long)(my_TY_BYTE)))) { + (my_size)=(1UL); + } else { + (my_size)=((my_type_sizeof)(((my_ic)->my_c),(((my_n)->my_a)->my_t))); + } + (my_o)=((my_mkirconst)((my_ic),(my_size))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_STR)))) { + (my_o)=((my_mkirstr)((my_ic),((my_n)->my_s))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_CALL)))) { + (my_o)=((my_ircall)((my_ic),(my_n))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_IDENT)))) { + (my_v)=((my_find)(((my_ic)->my_c),((my_n)->my_s),((void *)0),(0UL))); + if ((unsigned long)((my_v)&&((my_v)->my_enum_defined))) { + (my_o)=((my_mkirconst)((my_ic),((my_v)->my_enum_value))); + return my_o; + } + (my_iv)=((my_irfind_var)((my_ic),((my_n)->my_s),(0UL))); + if (my_iv) { + (my_o)=((my_mkirop)((my_ic),(my_IOP_VAR),((void *)0),((void *)0))); + ((my_o)->my_n)=((my_iv)->my_n); + return my_o; + } + if ((unsigned long)((my_v)&&((my_v)->my_func_defined))) { + (my_o)=((my_mkirop)((my_ic),(my_IOP_FUNC),((void *)0),((void *)0))); + ((my_o)->my_s)=((my_n)->my_s); + return my_o; + } + (my_cdie)(((my_ic)->my_c),((unsigned char *)"no such symbol")); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_DOT)))) { + if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))==((long)(my_TY_PTR)))) { + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_v)=((my_find)(((my_ic)->my_c),((((((my_n)->my_a)->my_t)->my_val)->my_st)->my_name),(((my_n)->my_b)->my_s),(0UL))); + } else { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_mkirop)((my_ic),(my_IOP_REF),(my_a),((void *)0))); + (my_v)=((my_find)(((my_ic)->my_c),(((((my_n)->my_a)->my_t)->my_st)->my_name),(((my_n)->my_b)->my_s),(0UL))); + } + (my_c)=((my_mkirconst)((my_ic),((my_v)->my_member_offset))); + (my_d)=((my_mkirop)((my_ic),(my_IOP_ADD),(my_b),(my_c))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_LOAD),(my_d),((void *)0))); + ((my_o)->my_t)=((my_n)->my_t); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_REF)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_REF),(my_a),((void *)0))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_DEREF)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_LOAD),(my_a),((void *)0))); + ((my_o)->my_t)=((my_n)->my_t); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_INDEX)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_size)=((my_type_sizeof)(((my_ic)->my_c),((my_n)->my_t))); + (my_c)=((my_mkirconst)((my_ic),(my_size))); + (my_d)=((my_mkirop)((my_ic),(my_IOP_MUL),(my_b),(my_c))); + (my_e)=((my_mkirop)((my_ic),(my_IOP_ADD),(my_a),(my_d))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_LOAD),(my_e),((void *)0))); + ((my_o)->my_t)=((my_n)->my_t); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_ASSIGN)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_d)=((my_mkirop)((my_ic),(my_IOP_REF),(my_a),((void *)0))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_STORE),(my_d),(my_b))); + ((my_o)->my_t)=((my_n)->my_t); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_POS)))) { + (my_o)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_CAST)))) { + (my_o)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NEG)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_NEG),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NOT)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_NOT),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_BNOT)))) { + (my_bool_body)=((my_mkirblock)((my_ic))); + (my_bool_next)=((my_mkirblock)((my_ic))); + (my_bool_out)=((my_mkirblock)((my_ic))); + (my_e)=((my_mkirtmp)((my_ic))); + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_irbranch)((my_ic),(my_a),(my_bool_next),(my_bool_body)); + (my_a)=((my_mkirconst)((my_ic),(0UL))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_STORE),(my_e),(my_a))); + (my_iraddop)((my_ic),(my_o)); + (my_irjump)((my_ic),(my_bool_out),(my_bool_next)); + (my_a)=((my_mkirconst)((my_ic),(1UL))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_STORE),(my_e),(my_a))); + (my_iraddop)((my_ic),(my_o)); + (my_irjump)((my_ic),(my_bool_out),(my_bool_out)); + (my_o)=((my_mkirop)((my_ic),(my_IOP_LOAD),(my_e),((void *)0))); + ((my_o)->my_t)=((my_n)->my_t); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_BOR)))) { + (my_bool_body)=((my_mkirblock)((my_ic))); + (my_bool_next)=((my_mkirblock)((my_ic))); + (my_bool_final)=((my_mkirblock)((my_ic))); + (my_bool_out)=((my_mkirblock)((my_ic))); + (my_e)=((my_mkirtmp)((my_ic))); + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_irbranch)((my_ic),(my_a),(my_bool_next),(my_bool_body)); + (my_a)=((my_mkirconst)((my_ic),(1UL))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_STORE),(my_e),(my_a))); + (my_iraddop)((my_ic),(my_o)); + (my_irjump)((my_ic),(my_bool_out),(my_bool_next)); + (my_bool_next)=((my_mkirblock)((my_ic))); + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_irbranch)((my_ic),(my_a),(my_bool_next),(my_bool_final)); + (my_a)=((my_mkirconst)((my_ic),(1UL))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_STORE),(my_e),(my_a))); + (my_iraddop)((my_ic),(my_o)); + (my_irjump)((my_ic),(my_bool_out),(my_bool_next)); + (my_a)=((my_mkirconst)((my_ic),(0UL))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_STORE),(my_e),(my_a))); + (my_iraddop)((my_ic),(my_o)); + (my_irjump)((my_ic),(my_bool_out),(my_bool_out)); + (my_o)=((my_mkirop)((my_ic),(my_IOP_LOAD),(my_e),((void *)0))); + ((my_o)->my_t)=((my_n)->my_t); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_BAND)))) { + (my_bool_body)=((my_mkirblock)((my_ic))); + (my_bool_next)=((my_mkirblock)((my_ic))); + (my_bool_final)=((my_mkirblock)((my_ic))); + (my_bool_out)=((my_mkirblock)((my_ic))); + (my_e)=((my_mkirtmp)((my_ic))); + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_irbranch)((my_ic),(my_a),(my_bool_next),(my_bool_body)); + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_irbranch)((my_ic),(my_a),(my_bool_next),(my_bool_final)); + (my_a)=((my_mkirconst)((my_ic),(1UL))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_STORE),(my_e),(my_a))); + (my_iraddop)((my_ic),(my_o)); + (my_irjump)((my_ic),(my_bool_out),(my_bool_next)); + (my_a)=((my_mkirconst)((my_ic),(0UL))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_STORE),(my_e),(my_a))); + (my_iraddop)((my_ic),(my_o)); + (my_irjump)((my_ic),(my_bool_out),(my_bool_out)); + (my_o)=((my_mkirop)((my_ic),(my_IOP_LOAD),(my_e),((void *)0))); + ((my_o)->my_t)=((my_n)->my_t); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LT)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_LT),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_GT)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_GT),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LE)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_LE),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_GE)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_GE),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_EQ)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_EQ),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NE)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_NE),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_ADD)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_ADD),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_SUB)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_SUB),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_MUL)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_MUL),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_DIV)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_DIV),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_MOD)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_MOD),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LSH)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_LSH),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_RSH)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_RSH),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_AND)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_AND),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_OR)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_OR),(my_a),(my_b))); + return my_o; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_XOR)))) { + (my_a)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + (my_b)=((my_expr_to_ir)((my_ic),((my_n)->my_b))); + (my_o)=((my_mkirop)((my_ic),(my_IOP_XOR),(my_a),(my_b))); + return my_o; + } else { + (my_cdie)(((my_ic)->my_c),((unsigned char *)"unknown expression")); + } +} void( my_fail)(struct my_peg* my_c){ if ((unsigned long)(((long)((my_c)->my_sp))==((long)(0UL)))) { (my_die)(((unsigned char *)"fail underflow")); @@ -4686,6 +4987,27 @@ 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_irop* my_value = 0; + struct my_type* my_t = 0; + if ((unsigned long)(!(my_n))) { + return; + } + ((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_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)); + } +} unsigned long( my_get)(struct my_peg* my_c){ unsigned long my_ch = 0; if ((unsigned long)(((long)((my_c)->my_pos))==((long)((my_c)->my_size)))) { @@ -4808,6 +5130,223 @@ 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){ + (my_irfind_var)((my_ic),(my_name),(1UL)); +} +void( my_iraddop)(struct my_ircomp* my_ic,struct my_irop* my_o){ + struct my_irblock* my_cur = 0; + struct my_irop** my_ops = 0; + unsigned long my_i = 0; + (my_cur)=((my_ic)->my_cur); + if ((unsigned long)(!(my_cur))) { + return; + } + (my_assert)(((unsigned long)(!((unsigned long)(!(my_o))))),((unsigned char *)"expected op to add")); + (my_assert)(((unsigned long)(!((my_cur)->my_done))),((unsigned char *)"block already closed")); + if ((unsigned long)(((long)((my_cur)->my_ops_len))==((long)((my_cur)->my_ops_cap)))) { + ((my_cur)->my_ops_cap)=((unsigned long)(((unsigned long)((unsigned long)(((long)((my_cur)->my_ops_cap))*((long)(2UL)))))+((unsigned long)(16UL)))); + (my_ops)=((struct my_irop**)(my_alloc)(((my_ic)->my_a),((unsigned long)(((long)((my_cur)->my_ops_cap))*((long)(8UL)))))); + (my_i)=(0UL); + while (1) { + if ((unsigned long)(((long)(my_i))==((long)((my_cur)->my_ops_len)))) { + break; + } + ((my_ops)[my_i])=(((my_cur)->my_ops)[my_i]); + (my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL)))); + } + ((my_cur)->my_ops)=(my_ops); + } + (((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){ + (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){ + 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))); + (my_iraddop)((my_ic),(my_o)); + (my_cur)=((my_ic)->my_cur); + if (my_cur) { + if ((my_cur)->my_done) { + (my_cdie)(((my_ic)->my_c),((unsigned char *)"block already done")); + } + ((my_cur)->my_done)=(1UL); + ((my_cur)->my_alt)=(my_alt); + ((my_cur)->my_out)=(my_next); + } + ((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_o = 0; + struct my_irop* my_a = 0; + struct my_irop* my_b = 0; + struct my_irop* my_ret = 0; + struct my_irblock* my_next = 0; + struct my_irblock* my_cur = 0; + struct my_node* my_arg = 0; + unsigned long my_i = 0; + (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_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_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_iraddop)((my_ic),(my_o)); + (my_next)=((my_mkirblock)((my_ic))); + (my_cur)=((my_ic)->my_cur); + if (my_cur) { + if ((my_cur)->my_done) { + (my_cdie)(((my_ic)->my_c),((unsigned char *)"block already done")); + } + ((my_cur)->my_done)=(1UL); + ((my_cur)->my_out)=(my_next); + } + ((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_irlabel** my_link = 0; + struct my_irlabel* my_l = 0; + unsigned long my_dir = 0; + (my_link)=(&((my_ic)->my_labels)); + while (1) { + (my_l)=(*(my_link)); + if ((unsigned long)(!(my_l))) { + break; + } + (my_dir)=((my_strcmp)((my_name),((my_l)->my_name))); + if ((unsigned long)(((long)(my_dir))==((long)(0UL)))) { + if (my_make) { + (my_cdie)(((my_ic)->my_c),((unsigned char *)"duplicate label")); + } + return (my_l)->my_block; + } else if ((unsigned long)(((long)(my_dir))<((long)(0UL)))) { + (my_link)=(&((my_l)->my_left)); + } else { + (my_link)=(&((my_l)->my_right)); + } + } + if ((unsigned long)(!(my_make))) { + (my_cdie)(((my_ic)->my_c),((unsigned char *)"no such label")); + } + (my_l)=((struct my_irlabel*)(my_alloc)(((my_ic)->my_a),(32UL))); + ((my_l)->my_name)=(my_name); + ((my_l)->my_left)=((void *)0); + ((my_l)->my_right)=((void *)0); + ((my_l)->my_block)=((my_mkirblock)((my_ic))); + (*(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_link = 0; + struct my_irvar* my_v = 0; + unsigned long my_dir = 0; + (my_link)=(&((my_ic)->my_vars)); + while (1) { + (my_v)=(*(my_link)); + if ((unsigned long)(!(my_v))) { + break; + } + (my_dir)=((my_strcmp)((my_name),((my_v)->my_name))); + if ((unsigned long)(((long)(my_dir))==((long)(0UL)))) { + if (my_make) { + (my_cdie)(((my_ic)->my_c),((unsigned char *)"duplicate var")); + } + return my_v; + } else if ((unsigned long)(((long)(my_dir))<((long)(0UL)))) { + (my_link)=(&((my_v)->my_left)); + } else { + (my_link)=(&((my_v)->my_right)); + } + } + if ((unsigned long)(!(my_make))) { + return (void *)0; + } + (my_v)=((struct my_irvar*)(my_alloc)(((my_ic)->my_a),(32UL))); + ((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){ + 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))); + (my_iraddop)((my_ic),(my_o)); + (my_cur)=((my_ic)->my_cur); + if (my_cur) { + if ((my_cur)->my_done) { + (my_cdie)(((my_ic)->my_c),((unsigned char *)"block already done")); + } + ((my_cur)->my_done)=(1UL); + ((my_cur)->my_out)=(my_to); + } + ((my_ic)->my_cur)=(my_next); +} +void( my_irreturn)(struct my_ircomp* 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))); + (my_iraddop)((my_ic),(my_o)); + (my_cur)=((my_ic)->my_cur); + if (my_cur) { + if ((my_cur)->my_done) { + (my_cdie)(((my_ic)->my_c),((unsigned char *)"block already done")); + } + ((my_cur)->my_done)=(1UL); + } + ((my_ic)->my_cur)=((void *)0); +} +void( my_labels_to_ir)(struct my_ircomp* my_ic,struct my_node* my_n){ + unsigned long my_kind = 0; + unsigned char* my_name = 0; + if ((unsigned long)(!(my_n))) { + return; + } + (((my_ic)->my_c)->my_filename)=((my_n)->my_filename); + (((my_ic)->my_c)->my_lineno)=((my_n)->my_lineno); + (((my_ic)->my_c)->my_colno)=((my_n)->my_colno); + (my_kind)=((my_n)->my_kind); + if ((unsigned long)(((long)(my_kind))==((long)(my_N_CONDLIST)))) { + while (1) { + if ((unsigned long)(!(my_n))) { + break; + } + (my_labels_to_ir)((my_ic),(((my_n)->my_a)->my_b)); + (my_n)=((my_n)->my_b); + } + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_STMTLIST)))) { + while (1) { + if ((unsigned long)(!(my_n))) { + break; + } + (my_labels_to_ir)((my_ic),((my_n)->my_a)); + (my_n)=((my_n)->my_b); + } + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LOOP)))) { + (my_labels_to_ir)((my_ic),((my_n)->my_a)); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LABEL)))) { + (my_name)=(((my_n)->my_a)->my_s); + (my_irfind_block)((my_ic),(my_name),(1UL)); + } +} void( my_layout_struct)(struct my_compiler* my_c,struct my_decl* my_d){ struct my_node* my_m = 0; unsigned long my_offset = 0; @@ -4941,6 +5480,41 @@ 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){ + unsigned char* my_name = 0; + struct my_type* my_t = 0; + unsigned long my_kind = 0; + if ((unsigned long)(!(my_n))) { + return; + } + (((my_ic)->my_c)->my_filename)=((my_n)->my_filename); + (((my_ic)->my_c)->my_lineno)=((my_n)->my_lineno); + (((my_ic)->my_c)->my_colno)=((my_n)->my_colno); + (my_kind)=((my_n)->my_kind); + if ((unsigned long)(((long)(my_kind))==((long)(my_N_CONDLIST)))) { + while (1) { + if ((unsigned long)(!(my_n))) { + break; + } + (my_locals_to_ir)((my_ic),(((my_n)->my_a)->my_b)); + (my_n)=((my_n)->my_b); + } + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_STMTLIST)))) { + while (1) { + if ((unsigned long)(!(my_n))) { + break; + } + (my_locals_to_ir)((my_ic),((my_n)->my_a)); + (my_n)=((my_n)->my_b); + } + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LOOP)))) { + (my_locals_to_ir)((my_ic),((my_n)->my_a)); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_VARDECL)))) { + (my_name)=(((my_n)->my_a)->my_s); + (my_t)=((my_prototype)(((my_ic)->my_c),((my_n)->my_b))); + (my_iraddvar)((my_ic),(my_name),(my_t)); + } +} void( my_main)(unsigned long my_argc,unsigned char** my_argv,unsigned char** my_envp){ struct my_alloc my_a = {0}; struct my_compiler* my_c = 0; @@ -5184,6 +5758,47 @@ 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_b = 0; + (my_b)=((struct my_irblock*)(my_alloc)(((my_ic)->my_a),(56UL))); + ((my_b)->my_ops)=((void *)0); + ((my_b)->my_ops_len)=(0UL); + ((my_b)->my_ops_cap)=(0UL); + ((my_b)->my_done)=(0UL); + ((my_b)->my_out)=((void *)0); + ((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_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_o = 0; + (my_o)=((struct my_irop*)(my_alloc)(((my_ic)->my_a),(48UL))); + ((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); + return my_o; +} +struct my_irop*( my_mkirstr)(struct my_ircomp* 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_o = 0; + (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)))); + return my_o; +} 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))); @@ -9583,6 +10198,86 @@ 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}; + struct my_irblock* my_cond_body = 0; + struct my_irblock* my_cond_next = 0; + struct my_irblock* my_cond_out = 0; + struct my_irblock* my_label = 0; + struct my_irop* my_value = 0; + unsigned long my_kind = 0; + if ((unsigned long)(!(my_n))) { + return; + } + (((my_ic)->my_c)->my_filename)=((my_n)->my_filename); + (((my_ic)->my_c)->my_lineno)=((my_n)->my_lineno); + (((my_ic)->my_c)->my_colno)=((my_n)->my_colno); + (my_kind)=((my_n)->my_kind); + if ((unsigned long)(((long)(my_kind))==((long)(my_N_CONDLIST)))) { + (my_cond_out)=((my_mkirblock)((my_ic))); + while (1) { + if ((unsigned long)(!(my_n))) { + break; + } + if ((unsigned long)(!(((my_n)->my_a)->my_a))) { + (my_stmt_to_ir)((my_ic),(((my_n)->my_a)->my_b)); + break; + } + (my_cond_body)=((my_mkirblock)((my_ic))); + (my_cond_next)=((my_mkirblock)((my_ic))); + (my_value)=((my_expr_to_ir)((my_ic),(((my_n)->my_a)->my_a))); + (my_irbranch)((my_ic),(my_value),(my_cond_next),(my_cond_body)); + (my_stmt_to_ir)((my_ic),(((my_n)->my_a)->my_b)); + (my_irjump)((my_ic),(my_cond_out),(my_cond_next)); + (my_n)=((my_n)->my_b); + } + (my_irjump)((my_ic),(my_cond_out),(my_cond_out)); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_STMTLIST)))) { + while (1) { + if ((unsigned long)(!(my_n))) { + break; + } + (my_stmt_to_ir)((my_ic),((my_n)->my_a)); + (my_n)=((my_n)->my_b); + } + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LOOP)))) { + ((my_loopctx).my_up)=((my_ic)->my_loopctx); + ((my_loopctx).my_top)=((my_mkirblock)((my_ic))); + ((my_loopctx).my_out)=((my_mkirblock)((my_ic))); + ((my_ic)->my_loopctx)=(&(my_loopctx)); + (my_irjump)((my_ic),((my_loopctx).my_top),((my_loopctx).my_top)); + (my_stmt_to_ir)((my_ic),((my_n)->my_a)); + (my_irjump)((my_ic),((my_loopctx).my_top),((my_loopctx).my_out)); + ((my_ic)->my_loopctx)=((my_loopctx).my_up); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_BREAK)))) { + if ((unsigned long)(!((my_ic)->my_loopctx))) { + (my_cdie)(((my_ic)->my_c),((unsigned char *)"break not in loop")); + } + (my_irjump)((my_ic),(((my_ic)->my_loopctx)->my_out),((void *)0)); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_CONTINUE)))) { + if ((unsigned long)(!((my_ic)->my_loopctx))) { + (my_cdie)(((my_ic)->my_c),((unsigned char *)"continue not in loop")); + } + (my_irjump)((my_ic),(((my_ic)->my_loopctx)->my_top),((void *)0)); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_RETURN)))) { + if ((my_n)->my_a) { + (my_value)=((my_expr_to_ir)((my_ic),((my_n)->my_a))); + } else { + (my_value)=((my_mkirconst)((my_ic),(0UL))); + } + (my_irreturn)((my_ic),(my_value)); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LABEL)))) { + (my_label)=((my_irfind_block)((my_ic),(((my_n)->my_a)->my_s),(0UL))); + (my_irjump)((my_ic),(my_label),(my_label)); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_GOTO)))) { + (my_label)=((my_irfind_block)((my_ic),(((my_n)->my_a)->my_s),(0UL))); + (my_irjump)((my_ic),(my_label),((void *)0)); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_VARDECL)))) { + } else { + (my_value)=((my_expr_to_ir)((my_ic),(my_n))); + (my_iraddop)((my_ic),(my_value)); + } +} unsigned long( my_strcmp)(unsigned char* my_a,unsigned char* my_b){ unsigned long my_i = 0; (my_i)=(0UL); diff --git a/cc1.om b/cc1.om @@ -191,7 +191,7 @@ func compile(c: *compiler, p: *node) { } if d.func_used && d.func_defined { - //func_to_ir(c, d.func_def); + func_to_ir(c, d.func_def); compile_func(c, d); } diff --git a/ir.om b/ir.om @@ -0,0 +1,1215 @@ +enum { + // Places + IOP_VAR, + IOP_FUNC, + IOP_CONST, + IOP_STR, + + // Memory operations + IOP_LOAD, + IOP_STORE, + IOP_ARG, + IOP_REF, + + // Unary arithmetic + IOP_NEG, + IOP_NOT, + + // Binary arithmetic + IOP_ADD, + IOP_AND, + IOP_OR, + IOP_XOR, + IOP_DIV, + IOP_MOD, + IOP_LSH, + IOP_RSH, + IOP_MUL, + IOP_SUB, + + // Comparison + IOP_EQ, + IOP_NE, + IOP_GT, + IOP_GE, + IOP_LT, + IOP_LE, + + // End of block + IOP_CALL, + IOP_JUMP, + IOP_BRANCH, + IOP_RETURN, +} + +struct irop { + kind: int; + a: *irop; + b: *irop; + n: int; + s: *byte; + t: *type; +} + +// A basic block is a sequence of expressions that end with a branch +struct irblock { + ops: **irop; + ops_len: int; + ops_cap: int; + done: int; + out: *irblock; + alt: *irblock; + mark: int; +} + +struct irloopctx { + up: *irloopctx; + top: *irblock; + out: *irblock; +} + +struct irlabel { + name: *byte; + left: *irlabel; + right: *irlabel; + block: *irblock; +} + +struct irvar { + name: *byte; + left: *irvar; + right: *irvar; + n: int; +} + +struct ircomp { + c: *compiler; + a: *alloc; + loopctx: *irloopctx; + top: *irblock; + cur: *irblock; + labels: *irlabel; + vars: *irvar; + numvars: int; +} + +func mkirblock(ic: *ircomp): *irblock { + var b: *irblock; + + b = alloc(ic.a, sizeof(*b)) as *irblock; + + b.ops = nil; + b.ops_len = 0; + b.ops_cap = 0; + b.done = 0; + b.out = nil; + b.alt = nil; + + return b; +} + +func mkirop(ic: *ircomp, kind: int, a: *irop, b: *irop): *irop { + var o: *irop; + + o = alloc(ic.a, sizeof(*o)) as *irop; + + o.kind = kind; + o.a = a; + o.b = b; + o.n = 0; + o.s = nil; + o.t = nil; + + return o; +} + +func mkirconst(ic: *ircomp, n: int): *irop { + var o: *irop; + + o = mkirop(ic, IOP_CONST, nil, nil); + + o.n = n; + + return o; +} + +func mkirstr(ic: *ircomp, s: *byte): *irop { + var o: *irop; + + o = mkirop(ic, IOP_STR, nil, nil); + + o.s = s; + + return o; +} + +func mkirtmp(ic: *ircomp): *irop { + var o: *irop; + + o = mkirop(ic, IOP_VAR, nil, nil); + + o.n = ic.numvars; + + ic.numvars = ic.numvars + 1; + + return o; +} + +func irfind_var(ic: *ircomp, name: *byte, make: int): *irvar { + var link: **irvar; + var v: *irvar; + var dir: int; + + link = &ic.vars; + loop { + v = *link; + + if !v { + break; + } + + dir = strcmp(name, v.name); + + if dir == 0 { + if make { + cdie(ic.c, "duplicate var"); + } + + return v; + } else if dir < 0 { + link = &v.left; + } else { // dir > 0 + link = &v.right; + } + } + + if !make { + return nil; + } + + v = alloc(ic.a, sizeof(*v)) as *irvar; + + 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) { + irfind_var(ic, name, 1); +} + +func iraddvar(ic: *ircomp, name: *byte, t: *type) { + irfind_var(ic, name, 1); +} + +func ircall(ic: *ircomp, n: *node): *irop { + var o: *irop; + var a: *irop; + var b: *irop; + var ret: *irop; + var next: *irblock; + var cur: *irblock; + var arg: *node; + var i: int; + + // Evaluate the arguments + arg = n.b; + i = 0; + loop { + if !arg { + break; + } + + // Compute the argument value + a = expr_to_ir(ic, arg.a); + o = mkirop(ic, IOP_ARG, a, nil); + o.n = i; + o.t = arg.a.t; + iraddop(ic, o); + + arg = arg.b; + i = i + 1; + } + + // Compute the function pointer + b = expr_to_ir(ic, n.a); + + // Emit the call + ret = mkirtmp(ic); + a = mkirop(ic, IOP_REF, ret, nil); + o = mkirop(ic, IOP_CALL, a, b); + iraddop(ic, o); + + // Link the return path + next = mkirblock(ic); + + cur = ic.cur; + if cur { + if cur.done { + cdie(ic.c, "block already done"); + } + + cur.done = 1; + cur.out = next; + } + + ic.cur = next; + + // Return an expression that contains the return value + return ret; +} + +func expr_to_ir(ic: *ircomp, n: *node): *irop { + var a: *irop; + var b: *irop; + var c: *irop; + var d: *irop; + var e: *irop; + var o: *irop; + var bool_body: *irblock; + var bool_next: *irblock; + var bool_final: *irblock; + var bool_out: *irblock; + var v: *decl; + var iv: *irvar; + var kind: int; + var size: int; + + assert(!!n, "expected node"); + + ic.c.filename = n.filename; + ic.c.lineno = n.lineno; + ic.c.colno = n.colno; + + kind = n.kind; + if kind == N_NIL { + o = mkirconst(ic, 0); + return o; + } else if kind == N_NUM { + o = mkirconst(ic, n.n); + return o; + } else if kind == N_CHAR { + o = mkirconst(ic, n.n); + return o; + } else if kind == N_SIZEOF { + if n.a.t.kind == TY_BYTE { + size = 1; + } else { + size = type_sizeof(ic.c, n.a.t); + } + + o = mkirconst(ic, size); + return o; + } else if kind == N_STR { + o = mkirstr(ic, n.s); + return o; + } else if kind == N_CALL { + o = ircall(ic, n); + return o; + } else if kind == N_IDENT { + v = find(ic.c, n.s, nil, 0); + + // enum constant + if v && v.enum_defined { + o = mkirconst(ic, v.enum_value); + return o; + } + + // variable + iv = irfind_var(ic, n.s, 0); + if iv { + o = mkirop(ic, IOP_VAR, nil, nil); + o.n = iv.n; + return o; + } + + // function + if v && v.func_defined { + o = mkirop(ic, IOP_FUNC, nil, nil); + o.s = n.s; + return o; + } + + cdie(ic.c, "no such symbol"); + } else if kind == N_DOT { + if n.a.t.kind == TY_PTR { + b = expr_to_ir(ic, n.a); + v = find(ic.c, n.a.t.val.st.name, n.b.s, 0); + } else { + a = expr_to_ir(ic, n.a); + b = mkirop(ic, IOP_REF, a, nil); + v = find(ic.c, n.a.t.st.name, n.b.s, 0); + } + c = mkirconst(ic, v.member_offset); + d = mkirop(ic, IOP_ADD, b, c); + o = mkirop(ic, IOP_LOAD, d, nil); + o.t = n.t; + return o; + } else if kind == N_REF { + a = expr_to_ir(ic, n.a); + o = mkirop(ic, IOP_REF, a, nil); + return o; + } else if kind == N_DEREF { + a = expr_to_ir(ic, n.a); + o = mkirop(ic, IOP_LOAD, a, nil); + o.t = n.t; + return o; + } else if kind == N_INDEX { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + size = type_sizeof(ic.c, n.t); + c = mkirconst(ic, size); + d = mkirop(ic, IOP_MUL, b, c); + e = mkirop(ic, IOP_ADD, a, d); + o = mkirop(ic, IOP_LOAD, e, nil); + o.t = n.t; + return o; + } else if kind == N_ASSIGN { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + d = mkirop(ic, IOP_REF, a, nil); + o = mkirop(ic, IOP_STORE, d, b); + o.t = n.t; + return o; + } else if kind == N_POS { + o = expr_to_ir(ic, n.a); + return o; + } else if kind == N_CAST { + o = expr_to_ir(ic, n.a); + return o; + } else if kind == N_NEG { + a = expr_to_ir(ic, n.a); + o = mkirop(ic, IOP_NEG, a, b); + return o; + } else if kind == N_NOT { + a = expr_to_ir(ic, n.a); + o = mkirop(ic, IOP_NOT, a, b); + return o; + } else if kind == N_BNOT { + bool_body = mkirblock(ic); + bool_next = mkirblock(ic); + bool_out = mkirblock(ic); + e = mkirtmp(ic); + + a = expr_to_ir(ic, n.a); + irbranch(ic, a, bool_next, bool_body); + + a = mkirconst(ic, 0); + o = mkirop(ic, IOP_STORE, e, a); + iraddop(ic, o); + irjump(ic, bool_out, bool_next); + + a = mkirconst(ic, 1); + o = mkirop(ic, IOP_STORE, e, a); + iraddop(ic, o); + irjump(ic, bool_out, bool_out); + + o = mkirop(ic, IOP_LOAD, e, nil); + o.t = n.t; + return o; + } else if kind == N_BOR { + bool_body = mkirblock(ic); + bool_next = mkirblock(ic); + bool_final = mkirblock(ic); + bool_out = mkirblock(ic); + e = mkirtmp(ic); + + a = expr_to_ir(ic, n.a); + irbranch(ic, a, bool_next, bool_body); + + a = mkirconst(ic, 1); + o = mkirop(ic, IOP_STORE, e, a); + iraddop(ic, o); + irjump(ic, bool_out, bool_next); + + bool_next = mkirblock(ic); + + a = expr_to_ir(ic, n.b); + irbranch(ic, a, bool_next, bool_final); + + a = mkirconst(ic, 1); + o = mkirop(ic, IOP_STORE, e, a); + iraddop(ic, o); + irjump(ic, bool_out, bool_next); + + a = mkirconst(ic, 0); + o = mkirop(ic, IOP_STORE, e, a); + iraddop(ic, o); + irjump(ic, bool_out, bool_out); + + o = mkirop(ic, IOP_LOAD, e, nil); + o.t = n.t; + return o; + } else if kind == N_BAND { + bool_body = mkirblock(ic); + bool_next = mkirblock(ic); + bool_final = mkirblock(ic); + bool_out = mkirblock(ic); + e = mkirtmp(ic); + + a = expr_to_ir(ic, n.a); + irbranch(ic, a, bool_next, bool_body); + + a = expr_to_ir(ic, n.b); + irbranch(ic, a, bool_next, bool_final); + + a = mkirconst(ic, 1); + o = mkirop(ic, IOP_STORE, e, a); + iraddop(ic, o); + irjump(ic, bool_out, bool_next); + + a = mkirconst(ic, 0); + o = mkirop(ic, IOP_STORE, e, a); + iraddop(ic, o); + irjump(ic, bool_out, bool_out); + + o = mkirop(ic, IOP_LOAD, e, nil); + o.t = n.t; + return o; + } else if kind == N_LT { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_LT, a, b); + return o; + } else if kind == N_GT { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_GT, a, b); + return o; + } else if kind == N_LE { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_LE, a, b); + return o; + } else if kind == N_GE { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_GE, a, b); + return o; + } else if kind == N_EQ { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_EQ, a, b); + return o; + } else if kind == N_NE { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_NE, a, b); + return o; + } else if kind == N_ADD { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_ADD, a, b); + return o; + } else if kind == N_SUB { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_SUB, a, b); + return o; + } else if kind == N_MUL { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_MUL, a, b); + return o; + } else if kind == N_DIV { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_DIV, a, b); + return o; + } else if kind == N_MOD { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_MOD, a, b); + return o; + } else if kind == N_LSH { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_LSH, a, b); + return o; + } else if kind == N_RSH { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_RSH, a, b); + return o; + } else if kind == N_AND { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_AND, a, b); + return o; + } else if kind == N_OR { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_OR, a, b); + return o; + } else if kind == N_XOR { + a = expr_to_ir(ic, n.a); + b = expr_to_ir(ic, n.b); + o = mkirop(ic, IOP_XOR, a, b); + return o; + } else { + cdie(ic.c, "unknown expression"); + } +} + +func iraddop(ic: *ircomp, o: *irop) { + var cur: *irblock; + var ops: **irop; + var i: int; + + cur = ic.cur; + if !cur { + return; + } + + assert(!!o, "expected op to add"); + assert(!cur.done, "block already closed"); + + if cur.ops_len == cur.ops_cap { + cur.ops_cap = cur.ops_cap * 2 + 16; + + ops = alloc(ic.a, cur.ops_cap * sizeof(*ops)) as **irop; + + i = 0; + loop { + if i == cur.ops_len { + break; + } + + ops[i] = cur.ops[i]; + + i = i + 1; + } + + cur.ops = ops; + } + + cur.ops[cur.ops_len] = o; + cur.ops_len = cur.ops_len + 1; +} + +func irjump(ic: *ircomp, to: *irblock, next: *irblock) { + var cur: *irblock; + var o: *irop; + + o = mkirop(ic, IOP_JUMP, nil, nil); + iraddop(ic, o); + + cur = ic.cur; + if cur { + if cur.done { + cdie(ic.c, "block already done"); + } + + cur.done = 1; + cur.out = to; + } + + ic.cur = next; +} + +func irbranch(ic: *ircomp, cond: *irop, alt: *irblock, next: *irblock) { + var cur: *irblock; + var o: *irop; + + o = mkirop(ic, IOP_BRANCH, cond, nil); + iraddop(ic, o); + + cur = ic.cur; + if cur { + if cur.done { + cdie(ic.c, "block already done"); + } + + cur.done = 1; + cur.alt = alt; + cur.out = next; + } + + ic.cur = next; +} + +func irreturn(ic: *ircomp, value: *irop) { + var cur: *irblock; + var o: *irop; + + o = mkirop(ic, IOP_RETURN, value, nil); + iraddop(ic, o); + + cur = ic.cur; + if cur { + if cur.done { + cdie(ic.c, "block already done"); + } + + cur.done = 1; + } + + ic.cur = nil; +} + +func stmt_to_ir(ic: *ircomp, n: *node) { + var loopctx: irloopctx; + var cond_body: *irblock; + var cond_next: *irblock; + var cond_out: *irblock; + var label: *irblock; + var value: *irop; + var kind: int; + + if !n { + return; + } + + ic.c.filename = n.filename; + ic.c.lineno = n.lineno; + ic.c.colno = n.colno; + + kind = n.kind; + if kind == N_CONDLIST { + // Create join point for out + cond_out = mkirblock(ic); + + loop { + // No more conditions + if !n { + break; + } + + // Final else branch + if !n.a.a { + stmt_to_ir(ic, n.a.b); + break; + } + + cond_body = mkirblock(ic); + cond_next = mkirblock(ic); + + // Compile condition, else branch to out + value = expr_to_ir(ic, n.a.a); + irbranch(ic, value, cond_next, cond_body); + + // Compile body on the taken branch + stmt_to_ir(ic, n.a.b); + irjump(ic, cond_out, cond_next); + + n = n.b; + } + + // Jump to out + irjump(ic, cond_out, cond_out); + } else if kind == N_STMTLIST { + loop { + if !n { + break; + } + + // Compile each statement in the list + stmt_to_ir(ic, n.a); + + n = n.b; + } + } else if kind == N_LOOP { + // Push a new loopctx onto the stack + loopctx.up = ic.loopctx; + loopctx.top = mkirblock(ic); + loopctx.out = mkirblock(ic); + ic.loopctx = &loopctx; + + // Jump to top + irjump(ic, loopctx.top, loopctx.top); + + // Compile the body + stmt_to_ir(ic, n.a); + + // Jump to top + irjump(ic, loopctx.top, loopctx.out); + + // Pop the loopctx + ic.loopctx = loopctx.up; + } else if kind == N_BREAK { + if !ic.loopctx { + cdie(ic.c, "break not in loop"); + } + + // jump to out + irjump(ic, ic.loopctx.out, nil); + } else if kind == N_CONTINUE { + if !ic.loopctx { + cdie(ic.c, "continue not in loop"); + } + + // jump to top + irjump(ic, ic.loopctx.top, nil); + } else if kind == N_RETURN { + if n.a { + value = expr_to_ir(ic, n.a); + } else { + value = mkirconst(ic, 0); + } + irreturn(ic, value); + } else if kind == N_LABEL { + // jump to label and fill in it's definition + label = irfind_block(ic, n.a.s, 0); + irjump(ic, label, label); + } else if kind == N_GOTO { + // jump + label = irfind_block(ic, n.a.s, 0); + irjump(ic, label, nil); + } else if kind == N_VARDECL { + // Nothing to do. + // Vardecl creates a variable for the whole function. + // Crossing the declaration itself does nothing. + } else { + value = expr_to_ir(ic, n); + iraddop(ic, value); + } +} + +func irfind_block(ic: *ircomp, name: *byte, make: int): *irblock { + var link: **irlabel; + var l: *irlabel; + var dir: int; + + link = &ic.labels; + loop { + l = *link; + + if !l { + break; + } + + dir = strcmp(name, l.name); + + if dir == 0 { + if make { + cdie(ic.c, "duplicate label"); + } + + return l.block; + } else if dir < 0 { + link = &l.left; + } else { // dir > 0 + link = &l.right; + } + } + + if !make { + cdie(ic.c, "no such label"); + } + + l = alloc(ic.a, sizeof(*l)) as *irlabel; + + l.name = name; + l.left = nil; + l.right = nil; + l.block = mkirblock(ic); + + *link = l; + + return l.block; +} + +func labels_to_ir(ic: *ircomp, n: *node) { + var kind: int; + var name: *byte; + + if !n { + return; + } + + ic.c.filename = n.filename; + ic.c.lineno = n.lineno; + ic.c.colno = n.colno; + + kind = n.kind; + if kind == N_CONDLIST { + loop { + if !n { + break; + } + + labels_to_ir(ic, n.a.b); + + n = n.b; + } + } else if kind == N_STMTLIST { + loop { + if !n { + break; + } + + labels_to_ir(ic, n.a); + + n = n.b; + } + } else if kind == N_LOOP { + labels_to_ir(ic, n.a); + } else if kind == N_LABEL { + name = n.a.s; + irfind_block(ic, name, 1); + } +} + +func args_to_ir(ic: *ircomp, n: *node) { + var name: *byte; + var t: *type; + + loop { + if !n { + break; + } + + name = n.a.a.s; + + t = prototype(ic.c, n.a.b); + + iraddarg(ic, name, t); + + n = n.b; + } +} + +func locals_to_ir(ic: *ircomp, n: *node) { + var name: *byte; + var t: *type; + var kind: int; + + if !n { + return; + } + + ic.c.filename = n.filename; + ic.c.lineno = n.lineno; + ic.c.colno = n.colno; + + kind = n.kind; + if kind == N_CONDLIST { + loop { + if !n { + break; + } + + locals_to_ir(ic, n.a.b); + + n = n.b; + } + } else if kind == N_STMTLIST { + loop { + if !n { + break; + } + + locals_to_ir(ic, n.a); + + n = n.b; + } + } else if kind == N_LOOP { + locals_to_ir(ic, n.a); + } else if kind == N_VARDECL { + name = n.a.s; + + t = prototype(ic.c, n.b); + + iraddvar(ic, name, t); + } +} + +func func_to_ir(c: *compiler, n: *node) { + var ic: ircomp; + var value: *irop; + var t: *type; + + if !n { + return; + } + + ic.c = c; + ic.a = c.a; + + ic.top = mkirblock(&ic); + ic.cur = ic.top; + + args_to_ir(&ic, n.a.b.a); + + locals_to_ir(&ic, n.b); + + labels_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); + } + + //fputs(nil, "\n"); + //fputs(nil, n.a.a.s); + //fputs(nil, "\n"); + //irshow(nil, ic.top); +} + +// Depth-first reset all the marks +func irreset(b: *irblock) { + if !b { + return; + } + + if !b.mark { + return; + } + + b.mark = 0; + + irreset(b.out); + irreset(b.alt); +} + +func irshow4(out: *file, o: *irop) { + var kind: int; + + if !o { + fputs(out, "(nil)"); + return; + } + + kind = o.kind; + if kind == IOP_VAR { + fputs(out, "(var "); + fputd(out, o.n); + fputs(out, ")"); + } else if kind == IOP_FUNC { + fputs(out, "(func "); + fputs(out, o.s); + fputs(out, ")"); + } else if kind == IOP_CONST { + fputs(out, "(const "); + fputd(out, o.n); + fputs(out, ")"); + } else if kind == IOP_STR { + fputs(out, "(str)"); + } else if kind == IOP_LOAD { + fputs(out, "(load "); + irshow4(out, o.a); + fputs(out, ")"); + } else if kind == IOP_STORE { + fputs(out, "(store "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + 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); + fputs(out, ")"); + } else if kind == IOP_NOT { + fputs(out, "(not "); + irshow4(out, o.a); + fputs(out, ")"); + } else if kind == IOP_ADD { + fputs(out, "(add "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_AND { + fputs(out, "(and "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_OR { + fputs(out, "(or "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_XOR { + fputs(out, "(xor "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_DIV { + fputs(out, "(div "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_MOD { + fputs(out, "(mod "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_LSH { + fputs(out, "(lsh "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_RSH { + fputs(out, "(rsh "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_MUL { + fputs(out, "(mul "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_SUB { + fputs(out, "(sub "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_EQ { + fputs(out, "(eq "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_NE { + fputs(out, "(ne "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_GT { + fputs(out, "(gt "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_GE { + fputs(out, "(ge "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_LT { + fputs(out, "(lt "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } else if kind == IOP_LE { + fputs(out, "(le "); + irshow4(out, o.a); + fputs(out, " "); + irshow4(out, o.b); + fputs(out, ")"); + } 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)"); + } else if kind == IOP_BRANCH { + fputs(out, "(branch "); + irshow4(out, o.a); + fputs(out, ")"); + } else if kind == IOP_RETURN { + fputs(out, "(return "); + irshow4(out, o.a); + fputs(out, ")"); + } else { + die("invalid iop"); + } +} + +func irshow3(out: *file, b: *irblock) { + var i: int; + + fputd(out, b.mark); + fputs(out, "{\n"); + + i = 0; + loop { + if i == b.ops_len { + break; + } + + fputs(out, " "); + irshow4(out, b.ops[i]); + fputs(out, "\n"); + + i = i + 1; + } + + fputs(out, "}\n"); +} + +// Depth-first visit all nodes +func irshow2(out: *file, b: *irblock, id: *int) { + if !b { + return; + } + + if b.mark { + return; + } + + b.mark = *id; + *id = *id + 1; + + irshow3(out, b); + + if b.out { + irshow2(out, b.out, id); + } + + if b.alt { + irshow2(out, b.alt, id); + } +} + +func irshow(out: *file, b: *irblock) { + var id: int; + id = 1; + irshow2(out, b, &id); + irreset(b); +} + +// value numbering +// flow control graph simplification +// loop detection + +// inline +// intrinsics + +// common subexpression +// constant folding +// dead code +// unrolling +// strength reduction + +// register allocation +// instruction selection + +// c generator from ir +// assemble from ir +// proof check from ir +// type check with ir