os

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

commit 66ce184ff6a09bdced8cb831276f44502f5b418d
parent 1428ead8e53fa5551aa10b9ce4d0ccee1239a55b
Author: erai <erai@omiltem.net>
Date:   Sun, 29 Sep 2024 21:58:40 -0400

separate typecheck pass

Diffstat:
Mcc0.c | 746+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Mcc1.c | 783++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
2 files changed, 998 insertions(+), 531 deletions(-)

diff --git a/cc0.c b/cc0.c @@ -827,6 +827,9 @@ void( my_translate_pattern)(struct my_peg_compiler* my_c,struct my_peg_node* my_ unsigned long( my_type_isint)(struct my_type* my_t); unsigned long( my_type_isprim)(struct my_type* my_t); unsigned long( my_type_sizeof)(struct my_compiler* my_c,struct my_type* my_t); +void( my_typecheck_expr)(struct my_compiler* my_c,struct my_decl* my_d,struct my_node* my_n,unsigned long my_rhs); +void( my_typecheck_func)(struct my_compiler* my_c,struct my_decl* my_d); +void( my_typecheck_stmt)(struct my_compiler* my_c,struct my_decl* my_d,struct my_node* my_n); unsigned long( my_unescape)(unsigned char* my_s,unsigned long* my_i,unsigned long my_len,unsigned long* my_ok); void( my_unify)(struct my_compiler* my_c,struct my_type* my_a,struct my_type* my_b); unsigned long( my_unlink)(unsigned char* my_name); @@ -1566,6 +1569,16 @@ void( my_compile)(struct my_compiler* my_c,struct my_node* my_p){ } (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 ((my_d)->my_func_defined) { + (my_typecheck_func)((my_c),(my_d)); + } + (my_d)=((my_next_decl)((my_c),(my_d))); + } (my_d)=((my_find)((my_c),((unsigned char *)"_start"),((unsigned char*)0UL),(0UL))); if ((unsigned long)((my_d)&&((my_d)->my_func_defined))) { ((my_c)->my_start)=((my_d)->my_func_label); @@ -1598,40 +1611,17 @@ void( my_compile_expr)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n ((my_c)->my_colno)=((my_n)->my_colno); (my_kind)=((my_n)->my_kind); if ((unsigned long)(((long)(my_kind))==((long)(my_N_STR)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"str is not an lexpr")); - } (my_emit_str)(((my_c)->my_as),((my_n)->my_s)); - ((my_n)->my_t)=((my_mktype1)((my_c),(my_TY_PTR),((my_mktype0)((my_c),(my_TY_BYTE))))); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NUM)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"num is not an lexpr")); - } (my_emit_num)(((my_c)->my_as),((my_n)->my_n)); - ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_CHAR)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"char is not an lexpr")); - } (my_emit_num)(((my_c)->my_as),((my_n)->my_n)); - ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_EXPRLIST)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"call is not an lexpr")); - } if ((my_n)->my_b) { (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); } (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); - if ((my_n)->my_b) { - ((my_n)->my_t)=((my_mktype2)((my_c),(my_TY_ARG),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t))); - } else { - ((my_n)->my_t)=((my_mktype1)((my_c),(my_TY_ARG),(((my_n)->my_a)->my_t))); - } } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_CALL)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"call is not an lexpr")); - } if ((my_n)->my_b) { (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); } @@ -1643,57 +1633,34 @@ void( my_compile_expr)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n (my_v)=((my_find)((my_c),((my_d)->my_name),(((my_n)->my_a)->my_s),(0UL))); if ((unsigned long)((my_v)&&((my_v)->my_var_defined))) { (my_emit_lea)(((my_c)->my_as),((my_v)->my_var_offset)); - (((my_n)->my_a)->my_t)=((my_v)->my_var_type); (my_emit_load)(((my_c)->my_as),(((my_n)->my_a)->my_t)); (my_emit_call)(((my_c)->my_as),((my_count_args)((my_c),((((my_n)->my_a)->my_t)->my_arg)))); } else if ((unsigned long)(!((my_strcmp)((((my_n)->my_a)->my_s),((unsigned char *)"_include"))))) { (my_v)=((my_find)((my_c),(((my_n)->my_a)->my_s),((unsigned char*)0UL),(0UL))); - if ((unsigned long)(((unsigned long)(!(my_v)))||((unsigned long)(!((my_v)->my_func_defined))))) { - (my_cdie)((my_c),((unsigned char *)"no such function")); - } - (((my_n)->my_a)->my_t)=((my_v)->my_func_type); (my_compile_include)((my_c),(my_n)); } else { (my_v)=((my_find)((my_c),(((my_n)->my_a)->my_s),((unsigned char*)0UL),(0UL))); - if ((unsigned long)(((unsigned long)(!(my_v)))||((unsigned long)(!((my_v)->my_func_defined))))) { - (my_cdie)((my_c),((unsigned char *)"no such function")); - } - (((my_n)->my_a)->my_t)=((my_v)->my_func_type); (my_emit_lcall)(((my_c)->my_as),((my_v)->my_func_label),((my_count_args)((my_c),((((my_n)->my_a)->my_t)->my_arg)))); } } else { (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_call)(((my_c)->my_as),((my_count_args)((my_c),((((my_n)->my_a)->my_t)->my_arg)))); } - if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))!=((long)(my_TY_FUNC)))) { - (my_cdie)((my_c),((unsigned char *)"calling not a function")); - } if ((my_n)->my_b) { (my_unify)((my_c),((((my_n)->my_a)->my_t)->my_arg),(((my_n)->my_b)->my_t)); } else { (my_unify)((my_c),((((my_n)->my_a)->my_t)->my_arg),((struct my_type*)0UL)); } - ((my_n)->my_t)=((((my_n)->my_a)->my_t)->my_val); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_DOT)))) { (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(0UL)); if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))==((long)(my_TY_PTR)))) { - if ((unsigned long)(((long)(((((my_n)->my_a)->my_t)->my_val)->my_kind))!=((long)(my_TY_STRUCT)))) { - (my_cdie)((my_c),((unsigned char *)"dot not a struct")); - } (my_v)=((my_find)((my_c),((((((my_n)->my_a)->my_t)->my_val)->my_st)->my_name),(((my_n)->my_b)->my_s),(0UL))); (my_emit_load)(((my_c)->my_as),(((my_n)->my_a)->my_t)); } else { - if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))!=((long)(my_TY_STRUCT)))) { - (my_cdie)((my_c),((unsigned char *)"dot not a struct")); - } (my_v)=((my_find)((my_c),(((((my_n)->my_a)->my_t)->my_st)->my_name),(((my_n)->my_b)->my_s),(0UL))); } - if ((unsigned long)(((unsigned long)(!(my_v)))||((unsigned long)(!((my_v)->my_member_defined))))) { - (my_cdie)((my_c),((unsigned char *)"no such member")); - } (my_emit_num)(((my_c)->my_as),((my_v)->my_member_offset)); (my_emit_add)(((my_c)->my_as)); - ((my_n)->my_t)=((my_v)->my_member_type); if (my_rhs) { (my_emit_load)(((my_c)->my_as),((my_n)->my_t)); } @@ -1701,13 +1668,11 @@ void( my_compile_expr)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n (my_v)=((my_find)((my_c),((my_n)->my_s),((unsigned char*)0UL),(0UL))); if ((unsigned long)((my_v)&&((my_v)->my_enum_defined))) { (my_emit_num)(((my_c)->my_as),((my_v)->my_enum_value)); - ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); return; } (my_v)=((my_find)((my_c),((my_d)->my_name),((my_n)->my_s),(0UL))); if ((unsigned long)((my_v)&&((my_v)->my_var_defined))) { (my_emit_lea)(((my_c)->my_as),((my_v)->my_var_offset)); - ((my_n)->my_t)=((my_v)->my_var_type); if (my_rhs) { (my_emit_load)(((my_c)->my_as),((my_n)->my_t)); } @@ -1716,23 +1681,13 @@ void( my_compile_expr)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n (my_v)=((my_find)((my_c),((my_n)->my_s),((unsigned char*)0UL),(0UL))); if ((unsigned long)((my_v)&&((my_v)->my_func_defined))) { (my_emit_ptr)(((my_c)->my_as),((my_v)->my_func_label)); - ((my_n)->my_t)=((my_v)->my_func_type); return; } - (my_cdie)((my_c),((unsigned char *)"no such variable")); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_ASSIGN)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"assign is not an lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(0UL)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - ((my_n)->my_t)=(((my_n)->my_a)->my_t); (my_emit_store)(((my_c)->my_as),((my_n)->my_t)); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_SIZEOF)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"sizeof is not an lexpr")); - } (my_out)=((my_mklabel)(((my_c)->my_as))); (my_emit_jmp)(((my_c)->my_as),(my_out)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(0UL)); @@ -1742,32 +1697,16 @@ void( my_compile_expr)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n } else { (my_emit_num)(((my_c)->my_as),((my_type_sizeof)((my_c),(((my_n)->my_a)->my_t)))); } - ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_REF)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"ref is not an lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(0UL)); - ((my_n)->my_t)=((my_mktype1)((my_c),(my_TY_PTR),(((my_n)->my_a)->my_t))); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_DEREF)))) { (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); - if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))!=((long)(my_TY_PTR)))) { - (my_cdie)((my_c),((unsigned char *)"deref not a pointer")); - } - ((my_n)->my_t)=((((my_n)->my_a)->my_t)->my_val); if (my_rhs) { (my_emit_load)(((my_c)->my_as),((my_n)->my_t)); } } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_INDEX)))) { (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); - if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))!=((long)(my_TY_PTR)))) { - (my_cdie)((my_c),((unsigned char *)"not a pointer")); - } - if ((unsigned long)(!((my_type_isint)((((my_n)->my_b)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"index: not an int")); - } - ((my_n)->my_t)=((((my_n)->my_a)->my_t)->my_val); if ((unsigned long)(((long)(((my_n)->my_t)->my_kind))==((long)(my_TY_BYTE)))) { (my_emit_num)(((my_c)->my_as),(1UL)); } else { @@ -1779,81 +1718,30 @@ void( my_compile_expr)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n (my_emit_load)(((my_c)->my_as),((my_n)->my_t)); } } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LT)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_lt)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"lt: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_GT)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_gt)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"gt: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LE)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_le)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"le: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_GE)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_ge)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"ge: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_EQ)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_eq)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"eq: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NE)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_ne)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"ne: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_BNOT)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_no)=((my_mklabel)(((my_c)->my_as))); (my_out)=((my_mklabel)(((my_c)->my_as))); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); @@ -1863,14 +1751,7 @@ void( my_compile_expr)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n (my_fixup_label)(((my_c)->my_as),(my_no)); (my_emit_num)(((my_c)->my_as),(1UL)); (my_fixup_label)(((my_c)->my_as),(my_out)); - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"not an prim")); - } - ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_BOR)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_no)=((my_mklabel)(((my_c)->my_as))); (my_out)=((my_mklabel)(((my_c)->my_as))); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); @@ -1886,17 +1767,7 @@ void( my_compile_expr)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n (my_fixup_label)(((my_c)->my_as),(my_no)); (my_emit_num)(((my_c)->my_as),(0UL)); (my_fixup_label)(((my_c)->my_as),(my_out)); - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"not an prim")); - } - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_b)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"not an prim")); - } - ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_BAND)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_no)=((my_mklabel)(((my_c)->my_as))); (my_out)=((my_mklabel)(((my_c)->my_as))); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); @@ -1908,171 +1779,56 @@ void( my_compile_expr)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n (my_fixup_label)(((my_c)->my_as),(my_no)); (my_emit_num)(((my_c)->my_as),(0UL)); (my_fixup_label)(((my_c)->my_as),(my_out)); - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"not an prim")); - } - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_b)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"not an prim")); - } - ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_POS)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"pos: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NEG)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_neg)(((my_c)->my_as)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"neg: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NOT)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_not)(((my_c)->my_as)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"not: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_ADD)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_add)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"add: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_SUB)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_sub)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"sub: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_MUL)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_mul)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"mul: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_DIV)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_div)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"div: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_MOD)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_mod)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"mod: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LSH)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_lsh)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"lsh: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_RSH)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_rsh)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"rsh: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_AND)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_and)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"and: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_OR)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_or)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"or: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_XOR)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); (my_emit_xor)(((my_c)->my_as)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); - if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"xor: not an int")); - } - ((my_n)->my_t)=(((my_n)->my_a)->my_t); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_CAST)))) { - if ((unsigned long)(!(my_rhs))) { - (my_cdie)((my_c),((unsigned char *)"not lexpr")); - } (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); - if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { - (my_cdie)((my_c),((unsigned char *)"not a primitive")); - } - ((my_n)->my_t)=((my_prototype)((my_c),((my_n)->my_b))); } else { (my_cdie)((my_c),((unsigned char *)"not an expression")); } @@ -2145,7 +1901,6 @@ void( my_compile_stmt)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n } (my_no)=((my_mklabel)(((my_c)->my_as))); if (((my_n)->my_a)->my_a) { - (my_call_check)((my_c),(((my_n)->my_a)->my_a)); (my_compile_expr)((my_c),(my_d),(((my_n)->my_a)->my_a),(1UL)); (my_emit_jz)(((my_c)->my_as),(my_no)); } @@ -2184,9 +1939,7 @@ void( my_compile_stmt)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n if ((unsigned long)(((long)((((my_d)->my_func_type)->my_val)->my_kind))==((long)(my_TY_VOID)))) { (my_cdie)((my_c),((unsigned char *)"returning a value in a void function")); } - (my_call_check)((my_c),((my_n)->my_a)); (my_compile_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); - (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_d)->my_func_type)->my_val)); } else { if ((unsigned long)(((long)((((my_d)->my_func_type)->my_val)->my_kind))!=((long)(my_TY_VOID)))) { (my_cdie)((my_c),((unsigned char *)"returning void in a non void function")); @@ -2204,7 +1957,6 @@ void( my_compile_stmt)(struct my_compiler* my_c,struct my_decl* my_d,struct my_n } (my_emit_jmp)(((my_c)->my_as),((my_v)->my_goto_label)); } else if ((unsigned long)(((long)(my_kind))!=((long)(my_N_VARDECL)))) { - (my_call_check)((my_c),(my_n)); (my_compile_expr)((my_c),(my_d),(my_n),(1UL)); (my_emit_pop)(((my_c)->my_as),(1UL)); } @@ -4720,6 +4472,9 @@ void( my_mark_expr_used)(struct my_compiler* my_c,struct my_decl* my_d,struct my if ((unsigned long)(!(my_n))) { return; } + ((my_c)->my_filename)=((my_n)->my_filename); + ((my_c)->my_lineno)=((my_n)->my_lineno); + ((my_c)->my_colno)=((my_n)->my_colno); (my_kind)=((my_n)->my_kind); if ((unsigned long)(((long)(my_kind))==((long)(my_N_EXPRLIST)))) { while (1) { @@ -4771,6 +4526,9 @@ void( my_mark_stmt_used)(struct my_compiler* my_c,struct my_decl* my_d,struct my if ((unsigned long)(!(my_n))) { return; } + ((my_c)->my_filename)=((my_n)->my_filename); + ((my_c)->my_lineno)=((my_n)->my_lineno); + ((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) { @@ -9377,6 +9135,472 @@ unsigned long( my_type_sizeof)(struct my_compiler* my_c,struct my_type* my_t){ (my_cdie)((my_c),((unsigned char *)"sizeof: invalid type")); } } +void( my_typecheck_expr)(struct my_compiler* my_c,struct my_decl* my_d,struct my_node* my_n,unsigned long my_rhs){ + struct my_decl* my_v = 0; + unsigned long my_kind = 0; + ((my_c)->my_filename)=((my_n)->my_filename); + ((my_c)->my_lineno)=((my_n)->my_lineno); + ((my_c)->my_colno)=((my_n)->my_colno); + (my_kind)=((my_n)->my_kind); + if ((unsigned long)(((long)(my_kind))==((long)(my_N_STR)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"str is not an lexpr")); + } + ((my_n)->my_t)=((my_mktype1)((my_c),(my_TY_PTR),((my_mktype0)((my_c),(my_TY_BYTE))))); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NUM)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"num is not an lexpr")); + } + ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_CHAR)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"char is not an lexpr")); + } + ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_EXPRLIST)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"call is not an lexpr")); + } + if ((my_n)->my_b) { + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + if ((my_n)->my_b) { + ((my_n)->my_t)=((my_mktype2)((my_c),(my_TY_ARG),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t))); + } else { + ((my_n)->my_t)=((my_mktype1)((my_c),(my_TY_ARG),(((my_n)->my_a)->my_t))); + } + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_CALL)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"call is not an lexpr")); + } + if ((my_n)->my_b) { + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + } + if ((unsigned long)(((long)(((my_n)->my_a)->my_kind))==((long)(my_N_IDENT)))) { + (my_v)=((my_find)((my_c),(((my_n)->my_a)->my_s),((unsigned char*)0UL),(0UL))); + if ((unsigned long)((my_v)&&((my_v)->my_enum_defined))) { + (my_cdie)((my_c),((unsigned char *)"type error")); + } + (my_v)=((my_find)((my_c),((my_d)->my_name),(((my_n)->my_a)->my_s),(0UL))); + if ((unsigned long)((my_v)&&((my_v)->my_var_defined))) { + (my_emit_lea)(((my_c)->my_as),((my_v)->my_var_offset)); + (((my_n)->my_a)->my_t)=((my_v)->my_var_type); + (my_emit_load)(((my_c)->my_as),(((my_n)->my_a)->my_t)); + (my_emit_call)(((my_c)->my_as),((my_count_args)((my_c),((((my_n)->my_a)->my_t)->my_arg)))); + } else if ((unsigned long)(!((my_strcmp)((((my_n)->my_a)->my_s),((unsigned char *)"_include"))))) { + (my_v)=((my_find)((my_c),(((my_n)->my_a)->my_s),((unsigned char*)0UL),(0UL))); + if ((unsigned long)(((unsigned long)(!(my_v)))||((unsigned long)(!((my_v)->my_func_defined))))) { + (my_cdie)((my_c),((unsigned char *)"no such function")); + } + (((my_n)->my_a)->my_t)=((my_v)->my_func_type); + } else { + (my_v)=((my_find)((my_c),(((my_n)->my_a)->my_s),((unsigned char*)0UL),(0UL))); + if ((unsigned long)(((unsigned long)(!(my_v)))||((unsigned long)(!((my_v)->my_func_defined))))) { + (my_cdie)((my_c),((unsigned char *)"no such function")); + } + (((my_n)->my_a)->my_t)=((my_v)->my_func_type); + (my_emit_lcall)(((my_c)->my_as),((my_v)->my_func_label),((my_count_args)((my_c),((((my_n)->my_a)->my_t)->my_arg)))); + } + } else { + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_emit_call)(((my_c)->my_as),((my_count_args)((my_c),((((my_n)->my_a)->my_t)->my_arg)))); + } + if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))!=((long)(my_TY_FUNC)))) { + (my_cdie)((my_c),((unsigned char *)"calling not a function")); + } + if ((my_n)->my_b) { + (my_unify)((my_c),((((my_n)->my_a)->my_t)->my_arg),(((my_n)->my_b)->my_t)); + } else { + (my_unify)((my_c),((((my_n)->my_a)->my_t)->my_arg),((struct my_type*)0UL)); + } + ((my_n)->my_t)=((((my_n)->my_a)->my_t)->my_val); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_DOT)))) { + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(0UL)); + if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))==((long)(my_TY_PTR)))) { + if ((unsigned long)(((long)(((((my_n)->my_a)->my_t)->my_val)->my_kind))!=((long)(my_TY_STRUCT)))) { + (my_cdie)((my_c),((unsigned char *)"dot not a struct")); + } + (my_v)=((my_find)((my_c),((((((my_n)->my_a)->my_t)->my_val)->my_st)->my_name),(((my_n)->my_b)->my_s),(0UL))); + } else { + if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))!=((long)(my_TY_STRUCT)))) { + (my_cdie)((my_c),((unsigned char *)"dot not a struct")); + } + (my_v)=((my_find)((my_c),(((((my_n)->my_a)->my_t)->my_st)->my_name),(((my_n)->my_b)->my_s),(0UL))); + } + if ((unsigned long)(((unsigned long)(!(my_v)))||((unsigned long)(!((my_v)->my_member_defined))))) { + (my_cdie)((my_c),((unsigned char *)"no such member")); + } + ((my_n)->my_t)=((my_v)->my_member_type); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_IDENT)))) { + (my_v)=((my_find)((my_c),((my_n)->my_s),((unsigned char*)0UL),(0UL))); + if ((unsigned long)((my_v)&&((my_v)->my_enum_defined))) { + ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); + return; + } + (my_v)=((my_find)((my_c),((my_d)->my_name),((my_n)->my_s),(0UL))); + if ((unsigned long)((my_v)&&((my_v)->my_var_defined))) { + ((my_n)->my_t)=((my_v)->my_var_type); + return; + } + (my_v)=((my_find)((my_c),((my_n)->my_s),((unsigned char*)0UL),(0UL))); + if ((unsigned long)((my_v)&&((my_v)->my_func_defined))) { + ((my_n)->my_t)=((my_v)->my_func_type); + return; + } + (my_cdie)((my_c),((unsigned char *)"no such variable")); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_ASSIGN)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"assign is not an lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(0UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_SIZEOF)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"sizeof is not an lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(0UL)); + ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_REF)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"ref is not an lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(0UL)); + ((my_n)->my_t)=((my_mktype1)((my_c),(my_TY_PTR),(((my_n)->my_a)->my_t))); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_DEREF)))) { + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))!=((long)(my_TY_PTR)))) { + (my_cdie)((my_c),((unsigned char *)"deref not a pointer")); + } + ((my_n)->my_t)=((((my_n)->my_a)->my_t)->my_val); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_INDEX)))) { + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + if ((unsigned long)(((long)((((my_n)->my_a)->my_t)->my_kind))!=((long)(my_TY_PTR)))) { + (my_cdie)((my_c),((unsigned char *)"not a pointer")); + } + if ((unsigned long)(!((my_type_isint)((((my_n)->my_b)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"index: not an int")); + } + ((my_n)->my_t)=((((my_n)->my_a)->my_t)->my_val); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LT)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"lt: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_GT)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"gt: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LE)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"le: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_GE)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"ge: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_EQ)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"eq: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NE)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"ne: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_BNOT)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_emit_num)(((my_c)->my_as),(1UL)); + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"not an prim")); + } + ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_BOR)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"not an prim")); + } + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_b)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"not an prim")); + } + ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_BAND)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"not an prim")); + } + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_b)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"not an prim")); + } + ((my_n)->my_t)=((my_mktype0)((my_c),(my_TY_INT))); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_POS)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"pos: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NEG)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"neg: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_NOT)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"not: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_ADD)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"add: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_SUB)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"sub: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_MUL)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"mul: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_DIV)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"div: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_MOD)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"mod: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LSH)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"lsh: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_RSH)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"rsh: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_AND)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"and: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_OR)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"or: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_XOR)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_b),(1UL)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_n)->my_b)->my_t)); + if ((unsigned long)(!((my_type_isint)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"xor: not an int")); + } + ((my_n)->my_t)=(((my_n)->my_a)->my_t); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_CAST)))) { + if ((unsigned long)(!(my_rhs))) { + (my_cdie)((my_c),((unsigned char *)"not lexpr")); + } + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + if ((unsigned long)(!((my_type_isprim)((((my_n)->my_a)->my_t))))) { + (my_cdie)((my_c),((unsigned char *)"not a primitive")); + } + ((my_n)->my_t)=((my_prototype)((my_c),((my_n)->my_b))); + } else { + (my_cdie)((my_c),((unsigned char *)"not an expression")); + } +} +void( my_typecheck_func)(struct my_compiler* my_c,struct my_decl* my_d){ + if ((unsigned long)(!((my_d)->my_func_def))) { + return; + } + (my_typecheck_stmt)((my_c),(my_d),(((my_d)->my_func_def)->my_b)); +} +void( my_typecheck_stmt)(struct my_compiler* my_c,struct my_decl* my_d,struct my_node* my_n){ + struct my_decl* my_v = 0; + unsigned long my_kind = 0; + if ((unsigned long)(!(my_n))) { + return; + } + ((my_c)->my_filename)=((my_n)->my_filename); + ((my_c)->my_lineno)=((my_n)->my_lineno); + ((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; + } + if (((my_n)->my_a)->my_a) { + (my_typecheck_expr)((my_c),(my_d),(((my_n)->my_a)->my_a),(1UL)); + } + (my_typecheck_stmt)((my_c),(my_d),(((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_typecheck_stmt)((my_c),(my_d),((my_n)->my_a)); + (my_n)=((my_n)->my_b); + } + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LOOP)))) { + (my_typecheck_stmt)((my_c),(my_d),((my_n)->my_a)); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_BREAK)))) { + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_CONTINUE)))) { + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_RETURN)))) { + if ((my_n)->my_a) { + if ((unsigned long)(((long)((((my_d)->my_func_type)->my_val)->my_kind))==((long)(my_TY_VOID)))) { + (my_cdie)((my_c),((unsigned char *)"returning a value in a void function")); + } + (my_call_check)((my_c),((my_n)->my_a)); + (my_typecheck_expr)((my_c),(my_d),((my_n)->my_a),(1UL)); + (my_unify)((my_c),(((my_n)->my_a)->my_t),(((my_d)->my_func_type)->my_val)); + } else { + if ((unsigned long)(((long)((((my_d)->my_func_type)->my_val)->my_kind))!=((long)(my_TY_VOID)))) { + (my_cdie)((my_c),((unsigned char *)"returning void in a non void function")); + } + } + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_LABEL)))) { + (my_v)=((my_find)((my_c),((my_d)->my_name),(((my_n)->my_a)->my_s),(0UL))); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_GOTO)))) { + (my_v)=((my_find)((my_c),((my_d)->my_name),(((my_n)->my_a)->my_s),(0UL))); + if ((unsigned long)(((unsigned long)(!(my_v)))||((unsigned long)(!((my_v)->my_goto_defined))))) { + (my_cdie)((my_c),((unsigned char *)"label not defined")); + } + } else if ((unsigned long)(((long)(my_kind))!=((long)(my_N_VARDECL)))) { + (my_call_check)((my_c),(my_n)); + (my_typecheck_expr)((my_c),(my_d),(my_n),(1UL)); + } +} unsigned long( my_unescape)(unsigned char* my_s,unsigned long* my_i,unsigned long my_len,unsigned long* my_ok){ unsigned long my_ch = 0; unsigned long my_hex = 0; diff --git a/cc1.c b/cc1.c @@ -152,6 +152,20 @@ compile(c: *compiler, p: *node) { d = next_decl(c, d); } + // Typecheck functions + d = first_decl(c); + loop { + if (!d) { + break; + } + + if d.func_defined { + typecheck_func(c, d); + } + + d = next_decl(c, d); + } + // Check usage d = find(c, "_start", 0:*byte, 0); if (d && d.func_defined) { @@ -200,6 +214,10 @@ mark_expr_used(c: *compiler, d: *decl, n: *node) { return; } + c.filename = n.filename; + c.lineno = n.lineno; + c.colno = n.colno; + kind = n.kind; if kind == N_EXPRLIST { loop { @@ -260,6 +278,10 @@ mark_stmt_used(c: *compiler, d: *decl, n: *node) { return; } + c.filename = n.filename; + c.lineno = n.lineno; + c.colno = n.colno; + kind = n.kind; if kind == N_CONDLIST { loop { @@ -528,108 +550,7 @@ compile_func(c: *compiler, d: *decl) { emit_ret(c.as); } -hoist_locals(c: *compiler, d: *decl, n: *node, offset: int): int { - var kind: int; - var name: *byte; - var t: *type; - var v: *decl; - - if (!n) { - return offset; - } - - kind = n.kind; - if (kind == N_CONDLIST) { - loop { - if (!n) { - return offset; - } - - hoist_locals(c, d, n.a.b, offset); - - n = n.b; - } - } else if (kind == N_STMTLIST) { - loop { - if (!n) { - return offset; - } - - offset = hoist_locals(c, d, n.a, offset); - - n = n.b; - } - } else if (kind == N_LOOP) { - return hoist_locals(c, d, n.a, offset); - } else if (kind == N_LABEL) { - name = n.a.s; - v = find(c, d.name, name, 1); - - if (v.goto_defined) { - cdie(c, "duplicate goto"); - } - v.goto_defined = 1; - - return offset; - } else if (kind != N_VARDECL) { - return offset; - } - - name = n.a.s; - t = prototype(c, n.b); - - n.t = t; - - v = find(c, d.name, name, 1); - - if (v.var_defined) { - cdie(c, "duplicate variable"); - } - - v.var_type = t; - v.var_defined = 1; - - offset = offset + type_sizeof(c, t); - - v.var_offset = -offset; - - return offset; -} - -compile_include(c: *compiler, n: *node) { - var filename: *byte; - var fd: int; - var blob: *byte; - var len: int; - - if n.b.a.kind != N_STR { - die("non literal include"); - } - - filename = n.b.a.s; - - fd = open(filename, O_RDONLY, 0); - if fd < 0 { - die("failed to open include"); - } - - blob = readall(fd, &len, c.a); - - close(fd); - - as_opr(c.as, OP_POPR, R_RAX); - as_opr(c.as, OP_POPR, R_RDI); - as_opri64(c.as, OP_MOVABS, R_RAX, len); - as_modrm(c.as, OP_STORE, R_RAX, R_RDI, 0, 0, 0); - emit_blob(c.as, blob, len); - - free(c.a, blob); -} - -// Translate an expression -compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { - var no: *label; - var out: *label; +typecheck_expr(c: *compiler, d: *decl, n: *node, rhs: int) { var v: *decl; var kind: int; @@ -643,24 +564,18 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "str is not an lexpr"); } - emit_str(c.as, n.s); - n.t = mktype1(c, TY_PTR, mktype0(c, TY_BYTE)); } else if (kind == N_NUM) { if (!rhs) { cdie(c, "num is not an lexpr"); } - emit_num(c.as, n.n); - n.t = mktype0(c, TY_INT); } else if (kind == N_CHAR) { if (!rhs) { cdie(c, "char is not an lexpr"); } - emit_num(c.as, n.n); - n.t = mktype0(c, TY_INT); } else if (kind == N_EXPRLIST) { if (!rhs) { @@ -668,10 +583,10 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { } if (n.b) { - compile_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.b, 1); } - compile_expr(c, d, n.a, 1); + typecheck_expr(c, d, n.a, 1); if (n.b) { n.t = mktype2(c, TY_ARG, n.a.t, n.b.t); @@ -684,7 +599,7 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { } if (n.b) { - compile_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.b, 1); } if (n.a.kind == N_IDENT) { @@ -705,7 +620,6 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "no such function"); } n.a.t = v.func_type; - compile_include(c, n); } else { v = find(c, n.a.s, 0:*byte, 0); if (!v || !v.func_defined) { @@ -715,7 +629,7 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { emit_lcall(c.as, v.func_label, count_args(c, n.a.t.arg)); } } else { - compile_expr(c, d, n.a, 1); + typecheck_expr(c, d, n.a, 1); emit_call(c.as, count_args(c, n.a.t.arg)); } @@ -731,7 +645,7 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { n.t = n.a.t.val; } else if (kind == N_DOT) { - compile_expr(c, d, n.a, 0); + typecheck_expr(c, d, n.a, 0); if (n.a.t.kind == TY_PTR) { if (n.a.t.val.kind != TY_STRUCT) { @@ -739,8 +653,6 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { } v = find(c, n.a.t.val.st.name, n.b.s, 0); - - emit_load(c.as, n.a.t); } else { if (n.a.t.kind != TY_STRUCT) { cdie(c, "dot not a struct"); @@ -753,35 +665,22 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "no such member"); } - emit_num(c.as, v.member_offset); - emit_add(c.as); - n.t = v.member_type; - - if (rhs) { - emit_load(c.as, n.t); - } } else if (kind == N_IDENT) { v = find(c, n.s, 0:*byte, 0); if (v && v.enum_defined) { - emit_num(c.as, v.enum_value); n.t = mktype0(c, TY_INT); return; } v = find(c, d.name, n.s, 0); if (v && v.var_defined) { - emit_lea(c.as, v.var_offset); n.t = v.var_type; - if (rhs) { - emit_load(c.as, n.t); - } return; } v = find(c, n.s, 0:*byte, 0); if (v && v.func_defined) { - emit_ptr(c.as, v.func_label); n.t = v.func_type; return; } @@ -792,32 +691,18 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "assign is not an lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 0); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 0); unify(c, n.a.t, n.b.t); n.t = n.a.t; - - emit_store(c.as, n.t); } else if (kind == N_SIZEOF) { if (!rhs) { cdie(c, "sizeof is not an lexpr"); } - out = mklabel(c.as); - - emit_jmp(c.as, out); - - compile_expr(c, d, n.a, 0); - - fixup_label(c.as, out); - - if (n.a.t.kind == TY_BYTE) { - emit_num(c.as, 1); - } else { - emit_num(c.as, type_sizeof(c, n.a.t)); - } + typecheck_expr(c, d, n.a, 0); n.t = mktype0(c, TY_INT); } else if (kind == N_REF) { @@ -825,24 +710,20 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "ref is not an lexpr"); } - compile_expr(c, d, n.a, 0); + typecheck_expr(c, d, n.a, 0); n.t = mktype1(c, TY_PTR, n.a.t); } else if (kind == N_DEREF) { - compile_expr(c, d, n.a, 1); + typecheck_expr(c, d, n.a, 1); if (n.a.t.kind != TY_PTR) { cdie(c, "deref not a pointer"); } n.t = n.a.t.val; - - if (rhs) { - emit_load(c.as, n.t); - } } else if (kind == N_INDEX) { - compile_expr(c, d, n.a, 1); - compile_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); + typecheck_expr(c, d, n.b, 1); if (n.a.t.kind != TY_PTR) { cdie(c, "not a pointer"); @@ -853,27 +734,13 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { } n.t = n.a.t.val; - - if (n.t.kind == TY_BYTE) { - emit_num(c.as, 1); - } else { - emit_num(c.as, type_sizeof(c, n.t)); - } - - emit_mul(c.as); - emit_add(c.as); - - if (rhs) { - emit_load(c.as, n.t); - } } else if (kind == N_LT) { if (!rhs) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_lt(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -887,9 +754,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_gt(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -903,9 +769,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_le(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -919,9 +784,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_ge(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -935,9 +799,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_eq(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -951,9 +814,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_ne(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -967,17 +829,9 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - no = mklabel(c.as); - out = mklabel(c.as); - - compile_expr(c, d, n.a, 1); + typecheck_expr(c, d, n.a, 1); - emit_jz(c.as, no); - emit_num(c.as, 0); - emit_jmp(c.as, out); - fixup_label(c.as, no); emit_num(c.as, 1); - fixup_label(c.as, out); if (!type_isprim(n.a.t)) { cdie(c, "not an prim"); @@ -989,26 +843,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - no = mklabel(c.as); - out = mklabel(c.as); - - compile_expr(c, d, n.a, 1); - emit_jz(c.as, no); - emit_num(c.as, 1); - emit_jmp(c.as, out); - - fixup_label(c.as, no); - no = mklabel(c.as); - - compile_expr(c, d, n.b, 1); - emit_jz(c.as, no); - emit_num(c.as, 1); - emit_jmp(c.as, out); - - fixup_label(c.as, no); - emit_num(c.as, 0); - - fixup_label(c.as, out); + typecheck_expr(c, d, n.a, 1); + typecheck_expr(c, d, n.b, 1); if (!type_isprim(n.a.t)) { cdie(c, "not an prim"); @@ -1024,22 +860,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - no = mklabel(c.as); - out = mklabel(c.as); - - compile_expr(c, d, n.a, 1); - emit_jz(c.as, no); - - compile_expr(c, d, n.b, 1); - emit_jz(c.as, no); - - emit_num(c.as, 1); - emit_jmp(c.as, out); - - fixup_label(c.as, no); - emit_num(c.as, 0); - - fixup_label(c.as, out); + typecheck_expr(c, d, n.a, 1); + typecheck_expr(c, d, n.b, 1); if (!type_isprim(n.a.t)) { cdie(c, "not an prim"); @@ -1055,7 +877,7 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.a, 1); + typecheck_expr(c, d, n.a, 1); if (!type_isint(n.a.t)) { cdie(c, "pos: not an int"); @@ -1067,8 +889,7 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.a, 1); - emit_neg(c.as); + typecheck_expr(c, d, n.a, 1); if (!type_isint(n.a.t)) { cdie(c, "neg: not an int"); @@ -1080,8 +901,7 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.a, 1); - emit_not(c.as); + typecheck_expr(c, d, n.a, 1); if (!type_isint(n.a.t)) { cdie(c, "not: not an int"); @@ -1093,9 +913,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_add(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -1109,9 +928,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_sub(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -1125,9 +943,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_mul(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -1141,9 +958,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_div(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -1157,9 +973,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_mod(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -1173,9 +988,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_lsh(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -1189,9 +1003,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_rsh(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -1205,9 +1018,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_and(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -1221,9 +1033,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_or(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -1237,9 +1048,8 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_xor(c.as); + typecheck_expr(c, d, n.b, 1); + typecheck_expr(c, d, n.a, 1); unify(c, n.a.t, n.b.t); @@ -1253,7 +1063,7 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { cdie(c, "not lexpr"); } - compile_expr(c, d, n.a, 1); + typecheck_expr(c, d, n.a, 1); if (!type_isprim(n.a.t)) { cdie(c, "not a primitive"); } @@ -1264,6 +1074,443 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { } } +typecheck_stmt(c: *compiler, d: *decl, n: *node) { + var v: *decl; + var kind: int; + + if (!n) { + return; + } + + c.filename = n.filename; + c.lineno = n.lineno; + c.colno = n.colno; + + kind = n.kind; + if (kind == N_CONDLIST) { + loop { + if (!n) { + break; + } + + if (n.a.a) { + typecheck_expr(c, d, n.a.a, 1); + } + + typecheck_stmt(c, d, n.a.b); + + n = n.b; + } + } else if (kind == N_STMTLIST) { + loop { + if (!n) { + break; + } + typecheck_stmt(c, d, n.a); + n = n.b; + } + } else if (kind == N_LOOP) { + typecheck_stmt(c, d, n.a); + } else if (kind == N_BREAK) { + } else if (kind == N_CONTINUE) { + } else if (kind == N_RETURN) { + if (n.a) { + if (d.func_type.val.kind == TY_VOID) { + cdie(c, "returning a value in a void function"); + } + call_check(c, n.a); + typecheck_expr(c, d, n.a, 1); + unify(c, n.a.t, d.func_type.val); + } else { + if (d.func_type.val.kind != TY_VOID) { + cdie(c, "returning void in a non void function"); + } + } + } else if (kind == N_LABEL) { + v = find(c, d.name, n.a.s, 0); + } else if (kind == N_GOTO) { + v = find(c, d.name, n.a.s, 0); + if (!v || !v.goto_defined) { + cdie(c, "label not defined"); + } + } else if (kind != N_VARDECL) { + call_check(c, n); + typecheck_expr(c, d, n, 1); + } +} + +typecheck_func(c: *compiler, d: *decl) { + if (!d.func_def) { + return; + } + + typecheck_stmt(c, d, d.func_def.b); +} + +hoist_locals(c: *compiler, d: *decl, n: *node, offset: int): int { + var kind: int; + var name: *byte; + var t: *type; + var v: *decl; + + if (!n) { + return offset; + } + + kind = n.kind; + if (kind == N_CONDLIST) { + loop { + if (!n) { + return offset; + } + + hoist_locals(c, d, n.a.b, offset); + + n = n.b; + } + } else if (kind == N_STMTLIST) { + loop { + if (!n) { + return offset; + } + + offset = hoist_locals(c, d, n.a, offset); + + n = n.b; + } + } else if (kind == N_LOOP) { + return hoist_locals(c, d, n.a, offset); + } else if (kind == N_LABEL) { + name = n.a.s; + v = find(c, d.name, name, 1); + + if (v.goto_defined) { + cdie(c, "duplicate goto"); + } + v.goto_defined = 1; + + return offset; + } else if (kind != N_VARDECL) { + return offset; + } + + name = n.a.s; + t = prototype(c, n.b); + + n.t = t; + + v = find(c, d.name, name, 1); + + if (v.var_defined) { + cdie(c, "duplicate variable"); + } + + v.var_type = t; + v.var_defined = 1; + + offset = offset + type_sizeof(c, t); + + v.var_offset = -offset; + + return offset; +} + +compile_include(c: *compiler, n: *node) { + var filename: *byte; + var fd: int; + var blob: *byte; + var len: int; + + if n.b.a.kind != N_STR { + die("non literal include"); + } + + filename = n.b.a.s; + + fd = open(filename, O_RDONLY, 0); + if fd < 0 { + die("failed to open include"); + } + + blob = readall(fd, &len, c.a); + + close(fd); + + as_opr(c.as, OP_POPR, R_RAX); + as_opr(c.as, OP_POPR, R_RDI); + as_opri64(c.as, OP_MOVABS, R_RAX, len); + as_modrm(c.as, OP_STORE, R_RAX, R_RDI, 0, 0, 0); + emit_blob(c.as, blob, len); + + free(c.a, blob); +} + +// Translate an expression +compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { + var no: *label; + var out: *label; + var v: *decl; + var kind: int; + + c.filename = n.filename; + c.lineno = n.lineno; + c.colno = n.colno; + + kind = n.kind; + if (kind == N_STR) { + emit_str(c.as, n.s); + } else if (kind == N_NUM) { + emit_num(c.as, n.n); + } else if (kind == N_CHAR) { + emit_num(c.as, n.n); + } else if (kind == N_EXPRLIST) { + if (n.b) { + compile_expr(c, d, n.b, 1); + } + + compile_expr(c, d, n.a, 1); + } else if (kind == N_CALL) { + if (n.b) { + compile_expr(c, d, n.b, 1); + } + + if (n.a.kind == N_IDENT) { + v = find(c, n.a.s, 0:*byte, 0); + if (v && v.enum_defined) { + cdie(c, "type error"); + } + + v = find(c, d.name, n.a.s, 0); + if (v && v.var_defined) { + emit_lea(c.as, v.var_offset); + emit_load(c.as, n.a.t); + emit_call(c.as, count_args(c, n.a.t.arg)); + } else if !strcmp(n.a.s, "_include") { + v = find(c, n.a.s, 0:*byte, 0); + compile_include(c, n); + } else { + v = find(c, n.a.s, 0:*byte, 0); + emit_lcall(c.as, v.func_label, count_args(c, n.a.t.arg)); + } + } else { + compile_expr(c, d, n.a, 1); + emit_call(c.as, count_args(c, n.a.t.arg)); + } + + if (n.b) { + unify(c, n.a.t.arg, n.b.t); + } else { + unify(c, n.a.t.arg, 0: *type); + } + } else if (kind == N_DOT) { + compile_expr(c, d, n.a, 0); + + if (n.a.t.kind == TY_PTR) { + v = find(c, n.a.t.val.st.name, n.b.s, 0); + emit_load(c.as, n.a.t); + } else { + v = find(c, n.a.t.st.name, n.b.s, 0); + } + + emit_num(c.as, v.member_offset); + emit_add(c.as); + + if (rhs) { + emit_load(c.as, n.t); + } + } else if (kind == N_IDENT) { + v = find(c, n.s, 0:*byte, 0); + if (v && v.enum_defined) { + emit_num(c.as, v.enum_value); + return; + } + + v = find(c, d.name, n.s, 0); + if (v && v.var_defined) { + emit_lea(c.as, v.var_offset); + if (rhs) { + emit_load(c.as, n.t); + } + return; + } + + v = find(c, n.s, 0:*byte, 0); + if (v && v.func_defined) { + emit_ptr(c.as, v.func_label); + return; + } + } else if (kind == N_ASSIGN) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 0); + + emit_store(c.as, n.t); + } else if (kind == N_SIZEOF) { + out = mklabel(c.as); + + emit_jmp(c.as, out); + + compile_expr(c, d, n.a, 0); + + fixup_label(c.as, out); + + if (n.a.t.kind == TY_BYTE) { + emit_num(c.as, 1); + } else { + emit_num(c.as, type_sizeof(c, n.a.t)); + } + } else if (kind == N_REF) { + compile_expr(c, d, n.a, 0); + } else if (kind == N_DEREF) { + compile_expr(c, d, n.a, 1); + + if (rhs) { + emit_load(c.as, n.t); + } + } else if (kind == N_INDEX) { + compile_expr(c, d, n.a, 1); + compile_expr(c, d, n.b, 1); + + if (n.t.kind == TY_BYTE) { + emit_num(c.as, 1); + } else { + emit_num(c.as, type_sizeof(c, n.t)); + } + + emit_mul(c.as); + emit_add(c.as); + + if (rhs) { + emit_load(c.as, n.t); + } + } else if (kind == N_LT) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_lt(c.as); + } else if (kind == N_GT) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_gt(c.as); + } else if (kind == N_LE) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_le(c.as); + } else if (kind == N_GE) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_ge(c.as); + } else if (kind == N_EQ) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_eq(c.as); + } else if (kind == N_NE) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_ne(c.as); + } else if (kind == N_BNOT) { + no = mklabel(c.as); + out = mklabel(c.as); + + compile_expr(c, d, n.a, 1); + + emit_jz(c.as, no); + emit_num(c.as, 0); + emit_jmp(c.as, out); + fixup_label(c.as, no); + emit_num(c.as, 1); + fixup_label(c.as, out); + } else if (kind == N_BOR) { + no = mklabel(c.as); + out = mklabel(c.as); + + compile_expr(c, d, n.a, 1); + emit_jz(c.as, no); + emit_num(c.as, 1); + emit_jmp(c.as, out); + + fixup_label(c.as, no); + no = mklabel(c.as); + + compile_expr(c, d, n.b, 1); + emit_jz(c.as, no); + emit_num(c.as, 1); + emit_jmp(c.as, out); + + fixup_label(c.as, no); + emit_num(c.as, 0); + + fixup_label(c.as, out); + } else if (kind == N_BAND) { + no = mklabel(c.as); + out = mklabel(c.as); + + compile_expr(c, d, n.a, 1); + emit_jz(c.as, no); + + compile_expr(c, d, n.b, 1); + emit_jz(c.as, no); + + emit_num(c.as, 1); + emit_jmp(c.as, out); + + fixup_label(c.as, no); + emit_num(c.as, 0); + + fixup_label(c.as, out); + } else if (kind == N_POS) { + compile_expr(c, d, n.a, 1); + } else if (kind == N_NEG) { + compile_expr(c, d, n.a, 1); + emit_neg(c.as); + } else if (kind == N_NOT) { + compile_expr(c, d, n.a, 1); + emit_not(c.as); + } else if (kind == N_ADD) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_add(c.as); + } else if (kind == N_SUB) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_sub(c.as); + } else if (kind == N_MUL) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_mul(c.as); + } else if (kind == N_DIV) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_div(c.as); + } else if (kind == N_MOD) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_mod(c.as); + } else if (kind == N_LSH) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_lsh(c.as); + } else if (kind == N_RSH) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_rsh(c.as); + } else if (kind == N_AND) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_and(c.as); + } else if (kind == N_OR) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_or(c.as); + } else if (kind == N_XOR) { + compile_expr(c, d, n.b, 1); + compile_expr(c, d, n.a, 1); + emit_xor(c.as); + } else if (kind == N_CAST) { + compile_expr(c, d, n.a, 1); + } else { + cdie(c, "not an expression"); + } +} + call_check(c: *compiler, n: *node): int { var result: int; var ret: int; @@ -1354,7 +1601,6 @@ compile_stmt(c: *compiler, d: *decl, n: *node, top: *label, out: *label) { no = mklabel(c.as); if (n.a.a) { - call_check(c, n.a.a); compile_expr(c, d, n.a.a, 1); emit_jz(c.as, no); } @@ -1395,9 +1641,7 @@ compile_stmt(c: *compiler, d: *decl, n: *node, top: *label, out: *label) { if (d.func_type.val.kind == TY_VOID) { cdie(c, "returning a value in a void function"); } - call_check(c, n.a); compile_expr(c, d, n.a, 1); - unify(c, n.a.t, d.func_type.val); } else { if (d.func_type.val.kind != TY_VOID) { cdie(c, "returning void in a non void function"); @@ -1415,7 +1659,6 @@ compile_stmt(c: *compiler, d: *decl, n: *node, top: *label, out: *label) { } emit_jmp(c.as, v.goto_label); } else if (kind != N_VARDECL) { - call_check(c, n); compile_expr(c, d, n, 1); emit_pop(c.as, 1); }