commit 05b32ee564117ad4d0a2ab3ca0316695530b0a15
parent 72cc7d4b486a26e5340dcda7488c8bb727a53a4e
Author: erai <erai@omiltem.net>
Date: Mon, 27 Jan 2025 04:19:12 +0000
Add ir code
Diffstat:
M | bootstrap.sh | | | 2 | +- |
M | cc0.c | | | 741 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- |
M | cc1.om | | | 2 | +- |
A | ir.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