commit ff1a009f88d2eff66c17da40a34ad8773f4e507d
parent 79f1b8bdb324674a38da381255a159793775a0e1
Author: erai <erai@omiltem.net>
Date: Sat, 1 Feb 2025 17:46:58 +0000
really dumb constant folding
Diffstat:
M | cc0.c | | | 318 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
M | cc1.om | | | 14 | ++++++++++++++ |
M | ir.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