os

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

commit ff1a009f88d2eff66c17da40a34ad8773f4e507d
parent 79f1b8bdb324674a38da381255a159793775a0e1
Author: erai <erai@omiltem.net>
Date:   Sat,  1 Feb 2025 17:46:58 +0000

really dumb constant folding

Diffstat:
Mcc0.c | 318++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Mcc1.om | 14++++++++++++++
Mir.om | 238+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 467 insertions(+), 103 deletions(-)

diff --git a/cc0.c b/cc0.c @@ -68,6 +68,7 @@ struct my_chunk { }; struct my_compiler { struct my_alloc* my_a; + struct my_file* my_err; struct my_parser* my_p; unsigned char* my_filename; unsigned long my_lineno; @@ -699,7 +700,7 @@ void( my_check_usage)(struct my_compiler* my_c); void( my_choice)(struct my_peg* my_c); unsigned long( my_close)(unsigned long my_fd); void( my_commit)(struct my_peg* my_c); -struct my_compiler*( my_comp_setup)(struct my_alloc* my_a); +struct my_compiler*( my_comp_setup)(struct my_alloc* my_a,struct my_file* my_err); void( my_compile)(struct my_compiler* my_c,struct my_node* my_p); struct my_node*( my_concat_program)(struct my_node* my_a,struct my_node* my_b); struct my_peg_node*( my_construct)(struct my_peg* my_c,unsigned long my_sp); @@ -740,9 +741,6 @@ void( my_exit)(unsigned long 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); -void( my_fdputd)(unsigned long my_fd,unsigned long my_n); -void( my_fdputs)(unsigned long my_fd,unsigned char* my_msg); void( my_ffill)(struct my_file* my_f); void( my_fflush)(struct my_file* my_f); unsigned long( my_fgetc)(struct my_file* my_f); @@ -767,11 +765,15 @@ 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_ir_optimize)(struct my_irfunc* my_ic); 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_irblock_dead_expr)(struct my_irfunc* my_ic,struct my_irblock* my_b); +void( my_irblock_fold)(struct my_irfunc* my_ic,struct my_irblock* my_b); 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_irop*( my_irexpr_fold)(struct my_irfunc* my_ic,struct my_irblock* my_b,struct my_irop* my_o); 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); void( my_irjump)(struct my_irfunc* my_ic,struct my_irblock* my_to,struct my_irblock* my_next); @@ -824,7 +826,7 @@ void( my_output_irretval)(struct my_irfunc* my_ic,struct my_irblock* my_b,struct void( my_output_irstmt)(struct my_irfunc* my_ic,struct my_irblock* my_b,struct my_irop* my_o); void( my_output_irstr)(struct my_irfunc* my_ic,struct my_irblock* my_b,struct my_irop* my_o); void( my_output_irvars)(struct my_irfunc* my_ic); -struct my_node*( my_parse)(struct my_parser* my_c,unsigned char* my_filename); +struct my_node*( my_parse)(struct my_parser* my_c,unsigned char* my_filename,struct my_file* my_err); unsigned long( my_parse_escape)(unsigned char* my_s,unsigned long* my_i,unsigned long my_n); unsigned long( my_peg_PEG_alternative)(struct my_peg* my_c); unsigned long( my_peg_PEG_any)(struct my_peg* my_c); @@ -930,10 +932,10 @@ unsigned long( my_peg_P_var)(struct my_peg* my_c); unsigned long( my_peg_P_var_stmt)(struct my_peg* my_c); unsigned long( my_peg_P_void)(struct my_peg* my_c); unsigned long( my_peg_P_xor_op)(struct my_peg* my_c); -void( my_peg_compile)(struct my_peg_compiler* my_c,unsigned char* my_filename); +void( my_peg_compile)(struct my_peg_compiler* my_c,unsigned char* my_filename,struct my_file* my_err); struct my_peg*( my_peg_new)(unsigned char* my_filename,unsigned char* my_src,unsigned long my_len,struct my_alloc* my_a,unsigned long(* my_grammar)(struct my_peg*),unsigned char*(* my_tag_to_str)(unsigned long)); void( my_peg_open_output)(struct my_peg_compiler* my_c,unsigned char* my_filename); -struct my_peg_node*( my_peg_parse)(struct my_peg* my_c,unsigned long my_sp); +struct my_peg_node*( my_peg_parse)(struct my_peg* my_c,unsigned long my_sp,struct my_file* my_err); void( my_peg_reset)(struct my_peg* my_c,unsigned char* my_filename,unsigned char* my_src,unsigned long my_len); struct my_type*( my_prototype)(struct my_compiler* my_c,struct my_node* my_n); void( my_putchar)(struct my_assembler* my_c,unsigned long my_ch); @@ -1727,16 +1729,15 @@ unsigned long( my_call_check)(struct my_compiler* my_c,struct my_node* my_n){ (my_result)=((my_call_check)((my_c),((my_n)->my_a))); } else if ((unsigned long)(((unsigned long)(((long)((my_n)->my_kind))==((long)(my_N_STR))))||((unsigned long)(((unsigned long)(((long)((my_n)->my_kind))==((long)(my_N_NUM))))||((unsigned long)(((unsigned long)(((long)((my_n)->my_kind))==((long)(my_N_CHAR))))||((unsigned long)(((unsigned long)(((long)((my_n)->my_kind))==((long)(my_N_IDENT))))||((unsigned long)(((unsigned long)(((long)((my_n)->my_kind))==((long)(my_N_SIZEOF))))||((unsigned long)(((long)((my_n)->my_kind))==((long)(my_N_NIL)))))))))))))) { } else { - (my_fdputd)((2UL),((my_n)->my_kind)); (my_die)(((unsigned char *)"invalid expr")); } return my_result; } void( my_cdie)(struct my_compiler* my_c,unsigned char* my_msg){ (my_cshow_context)((my_c)); - (my_fdputs)((2UL),((unsigned char *)"cdie: ")); - (my_fdputs)((2UL),(my_msg)); - (my_fdputs)((2UL),((unsigned char *)"\012")); + (my_fputs)(((my_c)->my_err),((unsigned char *)"cdie: ")); + (my_fputs)(((my_c)->my_err),(my_msg)); + (my_fputs)(((my_c)->my_err),((unsigned char *)"\012")); (my_exit)((1UL)); } unsigned long( my_charset)(struct my_peg* my_c,unsigned char* my_s){ @@ -1790,10 +1791,11 @@ void( my_commit)(struct my_peg* my_c){ } ((my_c)->my_sp)=((unsigned long)(((unsigned long)((my_c)->my_sp))-((unsigned long)(1UL)))); } -struct my_compiler*( my_comp_setup)(struct my_alloc* my_a){ +struct my_compiler*( my_comp_setup)(struct my_alloc* my_a,struct my_file* my_err){ struct my_compiler* my_c = 0; - (my_c)=((struct my_compiler*)(my_alloc)((my_a),(104UL))); + (my_c)=((struct my_compiler*)(my_alloc)((my_a),(112UL))); ((my_c)->my_a)=(my_a); + ((my_c)->my_err)=(my_err); ((my_c)->my_p)=((my_setup_parser)((my_a))); ((my_c)->my_filename)=((void *)0); ((my_c)->my_lineno)=(0UL); @@ -1904,6 +1906,16 @@ void( my_compile)(struct my_compiler* my_c,struct my_node* my_p){ break; } if ((unsigned long)(((my_d)->my_func_used)&&((unsigned long)(((my_d)->my_func_defined)&&((my_d)->my_func_def))))) { + (my_ir_optimize)(((my_d)->my_func_ir)); + } + (my_d)=((my_next_decl)((my_c),(my_d))); + } + (my_d)=((my_first_decl)((my_c))); + while (1) { + if ((unsigned long)(!(my_d))) { + break; + } + if ((unsigned long)(((my_d)->my_func_used)&&((unsigned long)(((my_d)->my_func_defined)&&((my_d)->my_func_def))))) { (my_output_ir)((my_c),(my_d)); } (my_d)=((my_next_decl)((my_c),(my_d))); @@ -1983,15 +1995,15 @@ void( my_copypos)(struct my_node* my_n,struct my_peg_node* my_pn){ ((my_n)->my_colno)=((my_pn)->my_col); } void( my_cshow_context)(struct my_compiler* my_c){ - (my_fdputs)((2UL),((unsigned char *)"on ")); + (my_fputs)(((my_c)->my_err),((unsigned char *)"on ")); if ((my_c)->my_filename) { - (my_fdputs)((2UL),((my_c)->my_filename)); + (my_fputs)(((my_c)->my_err),((my_c)->my_filename)); } - (my_fdputs)((2UL),((unsigned char *)":")); - (my_fdputd)((2UL),((my_c)->my_lineno)); - (my_fdputs)((2UL),((unsigned char *)":")); - (my_fdputd)((2UL),((my_c)->my_colno)); - (my_fdputs)((2UL),((unsigned char *)"\012")); + (my_fputs)(((my_c)->my_err),((unsigned char *)":")); + (my_fputd)(((my_c)->my_err),((my_c)->my_lineno)); + (my_fputs)(((my_c)->my_err),((unsigned char *)":")); + (my_fputd)(((my_c)->my_err),((my_c)->my_colno)); + (my_fputs)(((my_c)->my_err),((unsigned char *)"\012")); } void( my_ctranslate)(struct my_compiler* my_c){ struct my_decl* my_d = 0; @@ -2296,7 +2308,6 @@ void( my_ctranslate_expr)(struct my_compiler* my_c,struct my_node* my_n){ (my_fputs)(((my_c)->my_cout),((unsigned char *)")")); (my_ctranslate_expr)((my_c),((my_n)->my_a)); } else { - (my_fdputd)((2UL),((my_n)->my_kind)); (my_die)(((unsigned char *)"invalid expr")); } } @@ -2761,9 +2772,11 @@ void( my_defunion)(struct my_compiler* my_c,struct my_node* my_n){ ((my_d)->my_struct_def)=(my_n); } void( my_die)(unsigned char* my_msg){ - (my_fdputs)((2UL),(my_msg)); - (my_fdputs)((2UL),((unsigned char *)"\012")); - (my_exit)((1UL)); + unsigned long my_len = 0; + (my_len)=((my_strlen)((my_msg))); + (my_write)((2UL),(my_msg),(my_len)); + (my_write)((2UL),((unsigned char *)"\012"),(1UL)); + (my_exit)((2UL)); } void( my_emit)(struct my_assembler* my_c,unsigned long my_x){ (my_emit_hook)((my_c)); @@ -4056,47 +4069,6 @@ void( my_fclose)(struct my_file* my_f){ (my_free)(((my_f)->my_a),((my_f)->my_buf)); (my_free)(((my_f)->my_a),((unsigned char*)my_f)); } -void( my_fdputc)(unsigned long my_fd,unsigned long my_ch){ - unsigned char my_b = 0; - unsigned long my_ret = 0; - (my_b)=((unsigned char)my_ch); - (my_ret)=((my_write)((my_fd),(&(my_b)),(1UL))); - if ((unsigned long)(((long)(my_ret))!=((long)(1UL)))) { - (my_exit)((3UL)); - } -} -void( my_fdputd)(unsigned long my_fd,unsigned long my_n){ - unsigned long my_a = 0; - if ((unsigned long)(((long)(my_n))<((long)(0UL)))) { - (my_fdputc)((my_fd),(45)); - (my_a)=((unsigned long)(-(unsigned long)((unsigned long)(((long)(my_n))%((long)(10UL)))))); - (my_n)=((unsigned long)(((long)(my_n))/((long)((unsigned long)(-(unsigned long)(10UL)))))); - } else { - (my_a)=((unsigned long)(((long)(my_n))%((long)(10UL)))); - (my_n)=((unsigned long)(((long)(my_n))/((long)(10UL)))); - } - if ((unsigned long)(((long)(my_n))!=((long)(0UL)))) { - (my_fdputd)((my_fd),(my_n)); - } - (my_fdputc)((my_fd),((unsigned long)(((unsigned long)(48))+((unsigned long)(my_a))))); -} -void( my_fdputs)(unsigned long my_fd,unsigned char* my_msg){ - unsigned long my_len = 0; - unsigned long my_ret = 0; - unsigned long my_off = 0; - (my_len)=((my_strlen)((my_msg))); - (my_off)=(0UL); - while (1) { - if ((unsigned long)(((long)(my_off))==((long)(my_len)))) { - break; - } - (my_ret)=((my_write)((my_fd),(my_msg),((unsigned long)(((unsigned long)(my_len))-((unsigned long)(my_off)))))); - if ((unsigned long)(((long)(my_ret))<((long)(0UL)))) { - (my_exit)((3UL)); - } - (my_off)=((unsigned long)(((unsigned long)(my_off))+((unsigned long)(my_ret)))); - } -} void( my_ffill)(struct my_file* my_f){ unsigned long my_ret = 0; if ((my_f)->my_eof) { @@ -4292,8 +4264,12 @@ void( my_fputb)(struct my_file* my_f,unsigned char* my_s,unsigned long my_n){ } } void( my_fputc)(struct my_file* my_f,unsigned long my_ch){ + unsigned char my_b = 0; if ((unsigned long)(!(my_f))) { - (my_fdputc)((1UL),(my_ch)); + (my_b)=((unsigned char)my_ch); + if ((unsigned long)(((long)((my_write)((1UL),(&(my_b)),(1UL))))!=((long)(1UL)))) { + (my_exit)((3UL)); + } return; } if ((unsigned long)(((long)((my_f)->my_w))==((long)((my_f)->my_cap)))) { @@ -4530,6 +4506,25 @@ 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_ir_optimize)(struct my_irfunc* my_ic){ + unsigned long my_i = 0; + (my_i)=(0UL); + while (1) { + if ((unsigned long)(((long)(my_i))==((long)((my_ic)->my_blocks_len)))) { + break; + } + (my_irblock_dead_expr)((my_ic),(((my_ic)->my_blocks)[my_i])); + (my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL)))); + } + (my_i)=(0UL); + while (1) { + if ((unsigned long)(((long)(my_i))==((long)((my_ic)->my_blocks_len)))) { + break; + } + (my_irblock_fold)((my_ic),(((my_ic)->my_blocks)[my_i])); + (my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL)))); + } +} void( my_iraddarg)(struct my_irfunc* my_ic,unsigned char* my_name,struct my_type* my_t){ struct my_irvar** my_iv = 0; (my_iv)=((my_irfind_var)((my_ic),(my_name))); @@ -4573,6 +4568,46 @@ void( my_iraddvar)(struct my_irfunc* my_ic,unsigned char* my_name,struct my_type } (*(my_iv))=((my_mkirvar)((my_ic),(my_name),(my_t))); } +void( my_irblock_dead_expr)(struct my_irfunc* my_ic,struct my_irblock* my_b){ + unsigned long my_i = 0; + unsigned long my_j = 0; + struct my_irop* my_o = 0; + unsigned long my_kind = 0; + if ((unsigned long)(!((my_b)->my_done))) { + return; + } + (my_i)=(0UL); + (my_j)=(0UL); + while (1) { + if ((unsigned long)(((long)(my_i))==((long)((my_b)->my_ops_len)))) { + break; + } + (my_o)=(((my_b)->my_ops)[my_i]); + (my_kind)=((my_o)->my_kind); + if ((unsigned long)(((unsigned long)(((long)(my_kind))==((long)(my_IOP_STORE))))||((unsigned long)(((unsigned long)(((long)(my_kind))==((long)(my_IOP_RETVAL))))||((unsigned long)(((unsigned long)(((long)(my_kind))==((long)(my_IOP_ARG))))||((unsigned long)(((unsigned long)(((long)(my_kind))==((long)(my_IOP_CALL))))||((unsigned long)(((unsigned long)(((long)(my_kind))==((long)(my_IOP_JUMP))))||((unsigned long)(((unsigned long)(((long)(my_kind))==((long)(my_IOP_BRANCH))))||((unsigned long)(((long)(my_kind))==((long)(my_IOP_RETURN)))))))))))))))) { + (((my_b)->my_ops)[my_j])=(my_o); + (my_j)=((unsigned long)(((unsigned long)(my_j))+((unsigned long)(1UL)))); + } + (my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL)))); + } + ((my_b)->my_ops_len)=(my_j); +} +void( my_irblock_fold)(struct my_irfunc* my_ic,struct my_irblock* my_b){ + unsigned long my_i = 0; + struct my_irop* my_o = 0; + if ((unsigned long)(!((my_b)->my_done))) { + return; + } + (my_i)=(0UL); + while (1) { + if ((unsigned long)(((long)(my_i))==((long)((my_b)->my_ops_len)))) { + break; + } + (my_o)=((my_irexpr_fold)((my_ic),(my_b),(((my_b)->my_ops)[my_i]))); + (((my_b)->my_ops)[my_i])=(my_o); + (my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL)))); + } +} 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; @@ -4681,6 +4716,108 @@ struct my_irop*( my_ircall)(struct my_irfunc* my_ic,struct my_node* my_n){ ((my_ic)->my_cur)=(my_next); return my_ret; } +struct my_irop*( my_irexpr_fold)(struct my_irfunc* my_ic,struct my_irblock* my_b,struct my_irop* my_o){ + unsigned long my_kind = 0; + (my_kind)=((my_o)->my_kind); + if ((my_o)->my_a) { + ((my_o)->my_a)=((my_irexpr_fold)((my_ic),(my_b),((my_o)->my_a))); + } else { + return my_o; + } + if ((my_o)->my_b) { + ((my_o)->my_b)=((my_irexpr_fold)((my_ic),(my_b),((my_o)->my_b))); + } + if ((unsigned long)(((unsigned long)(((long)(my_kind))==((long)(my_IOP_REF))))&&((unsigned long)(((long)(((my_o)->my_a)->my_kind))==((long)(my_IOP_LOAD)))))) { + ((((my_o)->my_a)->my_a)->my_t)=((my_o)->my_t); + return ((my_o)->my_a)->my_a; + } + if ((unsigned long)(((unsigned long)(((long)(my_kind))==((long)(my_IOP_LOAD))))&&((unsigned long)(((long)(((my_o)->my_a)->my_kind))==((long)(my_IOP_REF)))))) { + ((((my_o)->my_a)->my_a)->my_t)=((my_o)->my_t); + return ((my_o)->my_a)->my_a; + } + if ((unsigned long)(((long)(((my_o)->my_a)->my_kind))!=((long)(my_IOP_CONST)))) { + return my_o; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_NEG)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(-(unsigned long)(((my_o)->my_a)->my_n))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_NOT)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(~(unsigned long)(((my_o)->my_a)->my_n))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_BRANCH)))) { + if ((unsigned long)(!(((my_o)->my_a)->my_n))) { + ((my_b)->my_out)=((my_b)->my_alt); + } + ((my_o)->my_kind)=(my_IOP_JUMP); + return my_o; + } + if ((unsigned long)(((unsigned long)(!((my_o)->my_b)))||((unsigned long)(((long)(((my_o)->my_b)->my_kind))!=((long)(my_IOP_CONST)))))) { + return my_o; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_ADD)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((unsigned long)(((my_o)->my_a)->my_n))+((unsigned long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_OR)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((unsigned long)(((my_o)->my_a)->my_n))|((unsigned long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_XOR)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((unsigned long)(((my_o)->my_a)->my_n))^((unsigned long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_DIV)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((long)(((my_o)->my_a)->my_n))/((long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_MOD)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((long)(((my_o)->my_a)->my_n))%((long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_LSH)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((unsigned long)(((my_o)->my_a)->my_n))<<((unsigned long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_RSH)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((unsigned long)(((my_o)->my_a)->my_n))>>((unsigned long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_MUL)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((long)(((my_o)->my_a)->my_n))*((long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_SUB)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((unsigned long)(((my_o)->my_a)->my_n))-((unsigned long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_EQ)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((long)(((my_o)->my_a)->my_n))==((long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_NE)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((long)(((my_o)->my_a)->my_n))!=((long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_GT)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((long)(((my_o)->my_a)->my_n))>((long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_GE)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((long)(((my_o)->my_a)->my_n))>=((long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_LT)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((long)(((my_o)->my_a)->my_n))<((long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_LE)))) { + (((my_o)->my_a)->my_n)=((unsigned long)(((long)(((my_o)->my_a)->my_n))<=((long)(((my_o)->my_b)->my_n)))); + return (my_o)->my_a; + } + return my_o; +} 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; @@ -4989,7 +5126,8 @@ void( my_main)(unsigned long my_argc,unsigned char** my_argv,unsigned char** my_ struct my_peg_compiler* my_peg = 0; (my_link)=(&(my_input)); (my_setup_alloc)((&(my_a))); - (my_c)=((my_comp_setup)((&(my_a)))); + (my_err)=((my_fopen)((2UL),(&(my_a)))); + (my_c)=((my_comp_setup)((&(my_a)),(my_err))); (my_show)=(0UL); (my_filename)=((unsigned char *)"a.out"); (my_i)=(1UL); @@ -5063,7 +5201,7 @@ void( my_main)(unsigned long my_argc,unsigned char** my_argv,unsigned char** my_ if ((unsigned long)(!(my_tmp))) { break; } - (my_peg_compile)((my_peg),((my_tmp)->my_name)); + (my_peg_compile)((my_peg),((my_tmp)->my_name),(my_err)); (my_tmp)=((my_tmp)->my_next); } return; @@ -5073,11 +5211,10 @@ void( my_main)(unsigned long my_argc,unsigned char** my_argv,unsigned char** my_ if ((unsigned long)(!(my_tmp))) { break; } - (my_p)=((my_concat_program)((my_p),((my_parse)(((my_c)->my_p),((my_tmp)->my_name))))); + (my_p)=((my_concat_program)((my_p),((my_parse)(((my_c)->my_p),((my_tmp)->my_name),(my_err))))); (my_tmp)=((my_tmp)->my_next); } if (my_show) { - (my_err)=((my_fopen)((2UL),(&(my_a)))); (my_show_node)((my_err),(my_p)); (my_fflush)((my_err)); return; @@ -6073,7 +6210,7 @@ void( my_output_irvars)(struct my_irfunc* my_ic){ (my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL)))); } } -struct my_node*( my_parse)(struct my_parser* my_c,unsigned char* my_filename){ +struct my_node*( my_parse)(struct my_parser* my_c,unsigned char* my_filename,struct my_file* my_err){ struct my_file* my_f = 0; unsigned long my_fd = 0; unsigned long my_len = 0; @@ -6081,16 +6218,16 @@ struct my_node*( my_parse)(struct my_parser* my_c,unsigned char* my_filename){ struct my_peg_node* my_pn = 0; (my_fd)=((my_open)((my_filename),(0UL),(0UL))); if ((unsigned long)(((long)(my_fd))<((long)(0UL)))) { - (my_fdputs)((2UL),((unsigned char *)"failed to open ")); - (my_fdputs)((2UL),(my_filename)); - (my_fdputs)((2UL),((unsigned char *)"\012")); + (my_fputs)((my_err),((unsigned char *)"failed to open ")); + (my_fputs)((my_err),(my_filename)); + (my_fputs)((my_err),((unsigned char *)"\012")); (my_exit)((1UL)); } (my_f)=((my_fopen)((my_fd),((my_c)->my_a))); (my_src)=((my_freadall)((my_f),(&(my_len)))); (my_fclose)((my_f)); (my_peg_reset)(((my_c)->my_p),(my_filename),(my_src),(my_len)); - (my_pn)=((my_peg_parse)(((my_c)->my_p),(my_P_sp))); + (my_pn)=((my_peg_parse)(((my_c)->my_p),(my_P_sp),(my_err))); return (my_reconstruct)((my_c),(my_pn)); } unsigned long( my_parse_escape)(unsigned char* my_s,unsigned long* my_i,unsigned long my_n){ @@ -9112,7 +9249,7 @@ unsigned long( my_peg_P_xor_op)(struct my_peg* my_c){ } return my_ok; } -void( my_peg_compile)(struct my_peg_compiler* my_c,unsigned char* my_filename){ +void( my_peg_compile)(struct my_peg_compiler* my_c,unsigned char* my_filename,struct my_file* my_err){ unsigned long my_fd = 0; struct my_file* my_f = 0; unsigned char* my_src = 0; @@ -9130,7 +9267,7 @@ void( my_peg_compile)(struct my_peg_compiler* my_c,unsigned char* my_filename){ (my_src)=((my_freadall)((my_f),(&(my_len)))); (my_fclose)((my_f)); ((my_c)->my_p)=((my_peg_new)((my_filename),(my_src),(my_len),((my_c)->my_a),(my_peg_PEG_grammar),(my_PEG_tag_to_str))); - (my_node)=((my_peg_parse)(((my_c)->my_p),(my_PEG_sp))); + (my_node)=((my_peg_parse)(((my_c)->my_p),(my_PEG_sp),(my_err))); (my_translate)((my_c),(my_node)); (my_fflush)(((my_c)->my_out)); } @@ -9176,23 +9313,23 @@ void( my_peg_open_output)(struct my_peg_compiler* my_c,unsigned char* my_filenam (my_f)=((my_fopen)((my_fd),((my_c)->my_a))); ((my_c)->my_out)=(my_f); } -struct my_peg_node*( my_peg_parse)(struct my_peg* my_c,unsigned long my_sp){ +struct my_peg_node*( my_peg_parse)(struct my_peg* my_c,unsigned long my_sp,struct my_file* my_err){ (my_choice)((my_c)); if ((unsigned long)(!(((my_c)->my_grammar)((my_c))))) { - (my_fdputs)((2UL),((unsigned char *)"syntax error at ")); - (my_fdputs)((2UL),((my_c)->my_filename)); - (my_fdputs)((2UL),((unsigned char *)":")); - (my_fdputd)((2UL),((my_c)->my_fail_line)); - (my_fdputs)((2UL),((unsigned char *)":")); - (my_fdputd)((2UL),((my_c)->my_fail_col)); - (my_fdputs)((2UL),((unsigned char *)" expected ")); - (my_fdputs)((2UL),(((my_c)->my_tag_to_str)(((my_c)->my_fail_tag)))); + (my_fputs)((my_err),((unsigned char *)"syntax error at ")); + (my_fputs)((my_err),((my_c)->my_filename)); + (my_fputs)((my_err),((unsigned char *)":")); + (my_fputd)((my_err),((my_c)->my_fail_line)); + (my_fputs)((my_err),((unsigned char *)":")); + (my_fputd)((my_err),((my_c)->my_fail_col)); + (my_fputs)((my_err),((unsigned char *)" expected ")); + (my_fputs)((my_err),(((my_c)->my_tag_to_str)(((my_c)->my_fail_tag)))); if ((my_c)->my_fail_literal) { - (my_fdputs)((2UL),((unsigned char *)" '")); - (my_fdputs)((2UL),((my_c)->my_fail_literal)); - (my_fdputs)((2UL),((unsigned char *)"'")); + (my_fputs)((my_err),((unsigned char *)" '")); + (my_fputs)((my_err),((my_c)->my_fail_literal)); + (my_fputs)((my_err),((unsigned char *)"'")); } - (my_fdputs)((2UL),((unsigned char *)"\012")); + (my_fputs)((my_err),((unsigned char *)"\012")); (my_exit)((1UL)); } (my_commit)((my_c)); @@ -10560,7 +10697,6 @@ void( my_translate_pattern)(struct my_peg_compiler* my_c,struct my_peg_node* my_ (my_n)=((my_n)->my_next); continue; } else { - (my_fdputs)((2UL),((my_PEG_tag_to_str)(((my_n)->my_tag)))); (my_die)(((unsigned char *)"invalid tag")); } break; diff --git a/cc1.om b/cc1.om @@ -221,6 +221,20 @@ func compile(c: *compiler, p: *node) { d = next_decl(c, d); } + // Do optimization passes + d = first_decl(c); + loop { + if (!d) { + break; + } + + if d.func_used && d.func_defined && d.func_def { + ir_optimize(d.func_ir); + } + + d = next_decl(c, d); + } + // Compile the ir to output d = first_decl(c); loop { diff --git a/ir.om b/ir.om @@ -2087,22 +2087,236 @@ func output_irexpr(ic: *irfunc, b: *irblock, o: *irop) { } } -// constant folding -// common subexpression -// register allocation -// inline -// intrinsics -// instruction selection -// flow control graph simplification -// dead code +// Eliminate expressions which have no possible side effects +func irblock_dead_expr(ic: *irfunc, b: *irblock) { + var i: int; + var j: int; + var o: *irop; + var kind: int; -// type check with ir -// parse to ir -// c generator from ir + if !b.done { + return; + } + + i = 0; + j = 0; + loop { + if i == b.ops_len { + break; + } + + o = b.ops[i]; + + kind = o.kind; + if ( + kind == IOP_STORE || kind == IOP_RETVAL || kind == IOP_ARG + || kind == IOP_CALL || kind == IOP_JUMP || kind == IOP_BRANCH || kind == IOP_RETURN + ) { + b.ops[j] = o; + j = j + 1; + } + + + i = i + 1; + } + + b.ops_len = j; +} + +func irexpr_fold(ic: *irfunc, b: *irblock, o: *irop): *irop { + var kind: int; + + kind = o.kind; + + if o.a { + o.a = irexpr_fold(ic, b, o.a); + } else { + return o; + } + + if o.b { + o.b = irexpr_fold(ic, b, o.b); + } + + if kind == IOP_REF && o.a.kind == IOP_LOAD { + o.a.a.t = o.t; + return o.a.a; + } + + if kind == IOP_LOAD && o.a.kind == IOP_REF { + o.a.a.t = o.t; + return o.a.a; + } + + if o.a.kind != IOP_CONST { + return o; + } + + if kind == IOP_NEG { + o.a.n = -o.a.n; + return o.a; + } + + if kind == IOP_NOT { + o.a.n = ~o.a.n; + return o.a; + } + + if kind == IOP_BRANCH { + if !o.a.n { + b.out = b.alt; + } + o.kind = IOP_JUMP; + return o; + } + + if !o.b || o.b.kind != IOP_CONST { + return o; + } + + if kind == IOP_ADD { + o.a.n = o.a.n + o.b.n; + return o.a; + } + + if kind == IOP_OR { + o.a.n = o.a.n | o.b.n; + return o.a; + } + + if kind == IOP_XOR { + o.a.n = o.a.n ^ o.b.n; + return o.a; + } + + if kind == IOP_DIV { + o.a.n = o.a.n / o.b.n; + return o.a; + } + + if kind == IOP_MOD { + o.a.n = o.a.n % o.b.n; + return o.a; + } + + if kind == IOP_LSH { + o.a.n = o.a.n << o.b.n; + return o.a; + } + + if kind == IOP_RSH { + o.a.n = o.a.n >> o.b.n; + return o.a; + } + + if kind == IOP_MUL { + o.a.n = o.a.n * o.b.n; + return o.a; + } + + if kind == IOP_SUB { + o.a.n = o.a.n - o.b.n; + return o.a; + } + + if kind == IOP_EQ { + o.a.n = o.a.n == o.b.n; + return o.a; + } + + if kind == IOP_NE { + o.a.n = o.a.n != o.b.n; + return o.a; + } + + if kind == IOP_GT { + o.a.n = o.a.n > o.b.n; + return o.a; + } + + if kind == IOP_GE { + o.a.n = o.a.n >= o.b.n; + return o.a; + } + + if kind == IOP_LT { + o.a.n = o.a.n < o.b.n; + return o.a; + } + + if kind == IOP_LE { + o.a.n = o.a.n <= o.b.n; + return o.a; + } + + return o; +} + +// Fold constant expressions +func irblock_fold(ic: *irfunc, b: *irblock) { + var i: int; + var o: *irop; + + if !b.done { + return; + } + + i = 0; + loop { + if i == b.ops_len { + break; + } + + o = irexpr_fold(ic, b, b.ops[i]); + b.ops[i] = o; + + i = i + 1; + } +} + +func ir_optimize(ic: *irfunc) { + var i: int; + + // First scan eliminate useless expressions + i = 0; + loop { + if i == ic.blocks_len { + break; + } + + irblock_dead_expr(ic, ic.blocks[i]); + + i = i + 1; + } + + // Try to evaluate constants as much as possible + i = 0; + loop { + if i == ic.blocks_len { + break; + } + + irblock_fold(ic, ic.blocks[i]); + + i = i + 1; + } + + // live values + // value forwarding + // common subexpression + // flow control simplification + + // inlining + // register allocation + // instruction selection +} // loop detection // unrolling // loop motion / fusion - // strength reduction / algebra // alias analysis +// type check with ir +// parse to ir +// c generator from ir +// intrinsics