os

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

commit db41f9afc1e19a2d7c1fe05c58049293507d0959
parent 40ea0f1bd97d414eca0b25738dc2607ee5d99a21
Author: erai <erai@omiltem.net>
Date:   Fri, 11 Oct 2024 12:01:12 -0400

Add unions

Diffstat:
Mcc0.c | 420+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mcc1.c | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcc3.peg | 3++-
Mcout.c | 27+++++++++++++++++++++++++--
Mnode.c | 2++
Mparse2.c | 14++++++++++++++
Mtype.c | 20++++++++++++++++++--
7 files changed, 439 insertions(+), 129 deletions(-)

diff --git a/cc0.c b/cc0.c @@ -247,64 +247,65 @@ enum { my_LOOK_AND = 2, my_LOOK_NORMAL = 0, my_LOOK_NOT = 1, - my_N_ADD = 42, - my_N_AND = 50, + my_N_ADD = 43, + my_N_AND = 51, my_N_ARGDECL = 10, my_N_ARGLIST = 8, - my_N_ASSIGN = 30, - my_N_BAND = 49, - my_N_BNOT = 47, - my_N_BOR = 48, - my_N_BREAK = 24, + my_N_ASSIGN = 31, + my_N_BAND = 50, + my_N_BNOT = 48, + my_N_BOR = 49, + my_N_BREAK = 25, my_N_CALL = 6, - my_N_CAST = 34, + my_N_CAST = 35, my_N_CHAR = 2, - my_N_COND = 19, - my_N_CONDLIST = 18, - my_N_CONTINUE = 25, - my_N_DEREF = 33, - my_N_DIV = 56, + my_N_COND = 20, + my_N_CONDLIST = 19, + my_N_CONTINUE = 26, + my_N_DEREF = 34, + my_N_DIV = 57, my_N_DOT = 7, - my_N_ENUM = 20, - my_N_ENUMITEM = 21, - my_N_ENUMLIST = 22, - my_N_EQ = 40, + my_N_ENUM = 21, + my_N_ENUMITEM = 22, + my_N_ENUMLIST = 23, + my_N_EQ = 41, my_N_EXPRLIST = 5, my_N_FUNC = 9, my_N_FUNCDECL = 11, my_N_FUNCTYPE = 13, - my_N_GE = 39, - my_N_GOTO = 29, - my_N_GT = 37, + my_N_GE = 40, + my_N_GOTO = 30, + my_N_GT = 38, my_N_IDENT = 0, - my_N_INDEX = 35, - my_N_LABEL = 28, - my_N_LE = 38, - my_N_LOOP = 23, - my_N_LSH = 45, - my_N_LT = 36, - my_N_MEMBERDECL = 16, - my_N_MEMBERLIST = 17, - my_N_MOD = 57, - my_N_MUL = 44, - my_N_NE = 41, - my_N_NEG = 55, - my_N_NOT = 53, + my_N_INDEX = 36, + my_N_LABEL = 29, + my_N_LE = 39, + my_N_LOOP = 24, + my_N_LSH = 46, + my_N_LT = 37, + my_N_MEMBERDECL = 17, + my_N_MEMBERLIST = 18, + my_N_MOD = 58, + my_N_MUL = 45, + my_N_NE = 42, + my_N_NEG = 56, + my_N_NOT = 54, my_N_NUM = 1, - my_N_OR = 51, - my_N_POS = 54, + my_N_OR = 52, + my_N_POS = 55, my_N_PROGRAM = 12, my_N_PTRTYPE = 14, - my_N_REF = 32, - my_N_RETURN = 26, - my_N_RSH = 46, - my_N_SIZEOF = 31, + my_N_REF = 33, + my_N_RETURN = 27, + my_N_RSH = 47, + my_N_SIZEOF = 32, my_N_STMTLIST = 4, my_N_STR = 3, my_N_STRUCT = 15, - my_N_SUB = 43, - my_N_VARDECL = 27, - my_N_XOR = 52, + my_N_SUB = 44, + my_N_UNION = 16, + my_N_VARDECL = 28, + my_N_XOR = 53, my_ONE_OR_MORE = 3, my_OP_ADCRM = 19, my_OP_ADDI = 129, @@ -402,92 +403,93 @@ enum { my_POLLNVAL = 32, my_POLLOUT = 4, my_POLLPRI = 2, - my_P_add_expr = 40, - my_P_add_op = 36, - my_P_and_op = 44, - my_P_arg_decl = 8, - my_P_assign_stmt = 21, - my_P_band_op = 26, - my_P_bnot_op = 54, - my_P_bool_expr = 28, - my_P_bor_op = 27, - my_P_break = 69, - my_P_break_stmt = 15, - my_P_byte = 80, - my_P_call_expr = 57, - my_P_cast_expr = 59, - my_P_char = 66, - my_P_comp_expr = 35, - my_P_compound_stmt = 24, - my_P_continue = 74, - my_P_continue_stmt = 16, - my_P_dec = 64, - my_P_deref_op = 50, - my_P_div_op = 42, - my_P_elif_stmt = 11, - my_P_else = 72, - my_P_else_stmt = 12, - my_P_empty_stmt = 23, - my_P_enum = 77, + my_P_add_expr = 41, + my_P_add_op = 37, + my_P_and_op = 45, + my_P_arg_decl = 9, + my_P_assign_stmt = 22, + my_P_band_op = 27, + my_P_bnot_op = 55, + my_P_bool_expr = 29, + my_P_bor_op = 28, + my_P_break = 70, + my_P_break_stmt = 16, + my_P_byte = 81, + my_P_call_expr = 58, + my_P_cast_expr = 60, + my_P_char = 67, + my_P_comp_expr = 36, + my_P_compound_stmt = 25, + my_P_continue = 75, + my_P_continue_stmt = 17, + my_P_dec = 65, + my_P_deref_op = 51, + my_P_div_op = 43, + my_P_elif_stmt = 12, + my_P_else = 73, + my_P_else_stmt = 13, + my_P_empty_stmt = 24, + my_P_enum = 78, my_P_enum_decl = 2, my_P_enum_item = 1, - my_P_eq_op = 33, - my_P_expr = 25, - my_P_expr_stmt = 22, - my_P_func = 83, - my_P_func_decl = 5, - my_P_func_type = 9, - my_P_ge_op = 30, - my_P_goto = 75, - my_P_goto_stmt = 20, + my_P_eq_op = 34, + my_P_expr = 26, + my_P_expr_stmt = 23, + my_P_func = 84, + my_P_func_decl = 6, + my_P_func_type = 10, + my_P_ge_op = 31, + my_P_goto = 76, + my_P_goto_stmt = 21, my_P_grammar = 0, - my_P_gt_op = 32, - my_P_hex = 63, - my_P_ident = 84, - my_P_if = 71, - my_P_if_stmt = 13, - my_P_index_expr = 56, - my_P_int = 81, - my_P_label_stmt = 19, - my_P_le_op = 29, - my_P_loop = 73, - my_P_loop_stmt = 14, - my_P_lsh_op = 46, - my_P_lt_op = 31, + my_P_gt_op = 33, + my_P_hex = 64, + my_P_ident = 85, + my_P_if = 72, + my_P_if_stmt = 14, + my_P_index_expr = 57, + my_P_int = 82, + my_P_label_stmt = 20, + my_P_le_op = 30, + my_P_loop = 74, + my_P_loop_stmt = 15, + my_P_lsh_op = 47, + my_P_lt_op = 32, my_P_member_decl = 3, - my_P_member_expr = 58, - my_P_mod_op = 43, - my_P_mul_expr = 45, - my_P_mul_op = 41, - my_P_ne_op = 34, - my_P_neg_op = 52, - my_P_not_op = 53, - my_P_or_op = 38, - my_P_pos_op = 51, - my_P_post_expr = 60, - my_P_primary = 61, - my_P_ptr_type = 7, - my_P_ref_op = 49, - my_P_reserved = 67, - my_P_return = 68, - my_P_return_stmt = 17, - my_P_rsh_op = 47, - my_P_shift_expr = 48, - my_P_sizeof = 70, - my_P_sizeof_expr = 62, - my_P_sp = 85, - my_P_stmt = 10, - my_P_str = 65, - my_P_struct = 78, + my_P_member_expr = 59, + my_P_mod_op = 44, + my_P_mul_expr = 46, + my_P_mul_op = 42, + my_P_ne_op = 35, + my_P_neg_op = 53, + my_P_not_op = 54, + my_P_or_op = 39, + my_P_pos_op = 52, + my_P_post_expr = 61, + my_P_primary = 62, + my_P_ptr_type = 8, + my_P_ref_op = 50, + my_P_reserved = 68, + my_P_return = 69, + my_P_return_stmt = 18, + my_P_rsh_op = 48, + my_P_shift_expr = 49, + my_P_sizeof = 71, + my_P_sizeof_expr = 63, + my_P_sp = 86, + my_P_stmt = 11, + my_P_str = 66, + my_P_struct = 79, my_P_struct_decl = 4, - my_P_sub_op = 37, - my_P_type = 6, - my_P_unary_expr = 55, - my_P_union = 79, - my_P_var = 76, - my_P_var_stmt = 18, - my_P_void = 82, - my_P_xor_op = 39, + my_P_sub_op = 38, + my_P_type = 7, + my_P_unary_expr = 56, + my_P_union = 80, + my_P_union_decl = 5, + my_P_var = 77, + my_P_var_stmt = 19, + my_P_void = 83, + my_P_xor_op = 40, my_R_CR0 = 0, my_R_CR1 = 1, my_R_CR2 = 2, @@ -537,6 +539,7 @@ enum { my_TY_INT = 1, my_TY_PTR = 3, my_TY_STRUCT = 6, + my_TY_UNION = 7, my_TY_VOID = 0, my_WNOHANG = 1, my_ZERO_OR_MORE = 2, @@ -599,6 +602,7 @@ void( my_defenum)(struct my_compiler* my_c,struct my_node* my_n); struct my_decl*( my_defextern)(struct my_compiler* my_c,struct my_node* my_n); void( my_defstruct)(struct my_compiler* my_c,struct my_node* my_n); void( my_defun)(struct my_compiler* my_c,struct my_node* my_n); +void( my_defunion)(struct my_compiler* my_c,struct my_node* my_n); void( my_die)(unsigned char* my_msg); void( my_emit)(struct my_assembler* my_c,unsigned long my_x); void( my_emit_add)(struct my_assembler* my_c); @@ -672,6 +676,7 @@ unsigned long( my_hex2int)(unsigned char* my_s,unsigned long my_len,unsigned lon 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_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_main)(unsigned long my_argc,unsigned char** my_argv,unsigned char** my_envp); @@ -689,6 +694,7 @@ struct my_type*( my_mktype0)(struct my_compiler* my_c,unsigned long my_kind); struct my_type*( my_mktype1)(struct my_compiler* my_c,unsigned long my_kind,struct my_type* my_a); struct my_type*( my_mktype2)(struct my_compiler* my_c,unsigned long my_kind,struct my_type* my_a,struct my_type* my_b); struct my_type*( my_mktype_struct)(struct my_compiler* my_c,struct my_decl* my_st); +struct my_type*( my_mktype_union)(struct my_compiler* my_c,struct my_decl* my_st); unsigned long( my_mmap)(unsigned long my_addr,unsigned long my_len,unsigned long my_prot,unsigned long my_flags,unsigned long my_fd,unsigned long my_off); struct my_decl*( my_next_decl)(struct my_compiler* my_c,struct my_decl* my_d); unsigned char*( my_node_to_str)(unsigned long my_kind); @@ -794,6 +800,7 @@ unsigned long( my_peg_P_sub_op)(struct my_peg* my_c); unsigned long( my_peg_P_type)(struct my_peg* my_c); unsigned long( my_peg_P_unary_expr)(struct my_peg* my_c); unsigned long( my_peg_P_union)(struct my_peg* my_c); +unsigned long( my_peg_P_union_decl)(struct my_peg* my_c); unsigned long( my_peg_P_var)(struct my_peg* my_c); unsigned long( my_peg_P_var_stmt)(struct my_peg* my_c); unsigned long( my_peg_P_void)(struct my_peg* my_c); @@ -846,6 +853,7 @@ struct my_node*( my_reconstruct_str)(struct my_parser* my_c,struct my_peg_node* struct my_node*( my_reconstruct_struct)(struct my_parser* my_c,struct my_peg_node* my_pn); struct my_node*( my_reconstruct_type)(struct my_parser* my_c,struct my_peg_node* my_pn); struct my_node*( my_reconstruct_unary)(struct my_parser* my_c,struct my_peg_node* my_pn); +struct my_node*( my_reconstruct_union)(struct my_parser* my_c,struct my_peg_node* my_pn); struct my_node*( my_reconstruct_var)(struct my_parser* my_c,struct my_peg_node* my_pn); void( my_reserve)(struct my_assembler* my_c,unsigned long my_n); void( my_setup_alloc)(struct my_alloc* my_c); @@ -935,6 +943,9 @@ unsigned char*( my_P_tag_to_str)(unsigned long my_tag){ if ((unsigned long)(((long)(my_tag))==((long)(my_P_struct_decl)))) { return (unsigned char *)"struct_decl"; } + if ((unsigned long)(((long)(my_tag))==((long)(my_P_union_decl)))) { + return (unsigned char *)"union_decl"; + } if ((unsigned long)(((long)(my_tag))==((long)(my_P_func_decl)))) { return (unsigned char *)"func_decl"; } @@ -1616,6 +1627,8 @@ void( my_compile)(struct my_compiler* my_c,struct my_node* my_p){ (my_kind)=(((my_n)->my_a)->my_kind); if ((unsigned long)(((long)(my_kind))==((long)(my_N_STRUCT)))) { (my_defstruct)((my_c),((my_n)->my_a)); + } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_UNION)))) { + (my_defunion)((my_c),((my_n)->my_a)); } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_ENUM)))) { (my_defenum)((my_c),((my_n)->my_a)); } else if ((unsigned long)(((unsigned long)(((long)(my_kind))!=((long)(my_N_FUNC))))&&((unsigned long)(((long)(my_kind))!=((long)(my_N_FUNCDECL)))))) { @@ -2150,7 +2163,11 @@ void( my_ctranslate)(struct my_compiler* my_c){ break; } if ((my_d)->my_struct_defined) { + if ((unsigned long)(((long)(((my_d)->my_struct_def)->my_kind))==((long)(my_N_UNION)))) { + (my_fputs)(((my_c)->my_cout),((unsigned char *)"union my_")); + } else { (my_fputs)(((my_c)->my_cout),((unsigned char *)"struct my_")); + } (my_fputs)(((my_c)->my_cout),((my_d)->my_name)); (my_fputs)(((my_c)->my_cout),((unsigned char *)";\012")); } @@ -2537,7 +2554,11 @@ void( my_ctranslate_str)(struct my_compiler* my_c,unsigned char* my_s){ void( my_ctranslate_struct)(struct my_compiler* my_c,struct my_decl* my_d){ struct my_decl* my_v = 0; struct my_node* my_n = 0; + if ((unsigned long)(((long)(((my_d)->my_struct_def)->my_kind))==((long)(my_N_UNION)))) { + (my_fputs)(((my_c)->my_cout),((unsigned char *)"union my_")); + } else { (my_fputs)(((my_c)->my_cout),((unsigned char *)"struct my_")); + } (my_fputs)(((my_c)->my_cout),((my_d)->my_name)); (my_fputs)(((my_c)->my_cout),((unsigned char *)" {\012")); (my_n)=(((my_d)->my_struct_def)->my_b); @@ -2576,6 +2597,9 @@ void( my_ctranslate_type1)(struct my_compiler* my_c,struct my_type* my_ty,unsign } else if ((unsigned long)(((long)((my_ty)->my_kind))==((long)(my_TY_STRUCT)))) { (my_fputs)(((my_c)->my_cout),((unsigned char *)"struct my_")); (my_fputs)(((my_c)->my_cout),(((my_ty)->my_st)->my_name)); + } else if ((unsigned long)(((long)((my_ty)->my_kind))==((long)(my_TY_UNION)))) { + (my_fputs)(((my_c)->my_cout),((unsigned char *)"union my_")); + (my_fputs)(((my_c)->my_cout),(((my_ty)->my_st)->my_name)); } else { (my_die)(((unsigned char *)"invalid type")); } @@ -2675,6 +2699,18 @@ void( my_ctranslate_zero)(struct my_compiler* my_c,struct my_type* my_ty){ (my_n)=((my_n)->my_b); } (my_fputs)(((my_c)->my_cout),((unsigned char *)"}")); + } else if ((unsigned long)(((long)((my_ty)->my_kind))==((long)(my_TY_UNION)))) { + (my_fputs)(((my_c)->my_cout),((unsigned char *)"{")); + (my_n)=((((my_ty)->my_st)->my_struct_def)->my_b); + while (1) { + if ((unsigned long)(!(my_n))) { + break; + } + (my_v)=((my_find)((my_c),(((my_ty)->my_st)->my_name),((((my_n)->my_a)->my_a)->my_s),(0UL))); + (my_ctranslate_zero)((my_c),((my_v)->my_member_type)); + (my_n)=((my_n)->my_b); + } + (my_fputs)(((my_c)->my_cout),((unsigned char *)"}")); } else { (my_die)(((unsigned char *)"invalid type")); } @@ -2854,6 +2890,23 @@ void( my_defun)(struct my_compiler* my_c,struct my_node* my_n){ (my_offset)=((my_hoist_locals)((my_c),(my_d),(((my_d)->my_func_def)->my_b),(0UL))); ((my_d)->my_func_preamble)=(my_offset); } +void( my_defunion)(struct my_compiler* my_c,struct my_node* my_n){ + unsigned char* my_name = 0; + struct my_decl* my_d = 0; + (my_name)=(((my_n)->my_a)->my_s); + ((my_c)->my_filename)=((my_n)->my_filename); + ((my_c)->my_lineno)=((my_n)->my_lineno); + ((my_c)->my_colno)=((my_n)->my_colno); + if ((unsigned long)(((unsigned long)(!((my_strcmp)((my_name),((unsigned char *)"int")))))||((unsigned long)(((unsigned long)(!((my_strcmp)((my_name),((unsigned char *)"byte")))))||((unsigned long)(!((my_strcmp)((my_name),((unsigned char *)"func"))))))))) { + (my_cdie)((my_c),((unsigned char *)"reserved word")); + } + (my_d)=((my_find)((my_c),(my_name),((unsigned char*)0UL),(1UL))); + if ((my_d)->my_struct_defined) { + (my_cdie)((my_c),((unsigned char *)"duplicate struct")); + } + ((my_d)->my_struct_defined)=(1UL); + ((my_d)->my_struct_def)=(my_n); +} void( my_die)(unsigned char* my_msg){ (my_fdputs)((2UL),(my_msg)); (my_fdputs)((2UL),((unsigned char *)"\012")); @@ -4663,6 +4716,48 @@ void( my_layout_struct)(struct my_compiler* my_c,struct my_decl* my_d){ ((my_d)->my_struct_size)=(my_offset); ((my_d)->my_struct_layout_done)=(1UL); } +void( my_layout_union)(struct my_compiler* my_c,struct my_decl* my_d){ + struct my_node* my_m = 0; + unsigned long my_size = 0; + unsigned long my_member_size = 0; + unsigned char* my_name = 0; + struct my_decl* my_md = 0; + struct my_type* my_t = 0; + if ((my_d)->my_struct_layout_done) { + if ((unsigned long)(((long)((my_d)->my_struct_layout_done))==((long)(2UL)))) { + (my_cdie)((my_c),((unsigned char *)"circular struct definition")); + } + return; + } + ((my_d)->my_struct_layout_done)=(2UL); + (my_m)=(((my_d)->my_struct_def)->my_b); + (my_size)=(0UL); + while (1) { + if ((unsigned long)(!(my_m))) { + break; + } + ((my_c)->my_filename)=(((my_m)->my_a)->my_filename); + ((my_c)->my_lineno)=(((my_m)->my_a)->my_lineno); + ((my_c)->my_colno)=(((my_m)->my_a)->my_colno); + (my_name)=((((my_m)->my_a)->my_a)->my_s); + (my_t)=((my_prototype)((my_c),(((my_m)->my_a)->my_b))); + (my_md)=((my_find)((my_c),((my_d)->my_name),(my_name),(1UL))); + if ((my_d)->my_member_defined) { + (my_cdie)((my_c),((unsigned char *)"duplicate member")); + } + ((my_md)->my_member_defined)=(1UL); + ((my_md)->my_member_type)=(my_t); + ((my_md)->my_member_offset)=(0UL); + ((my_md)->my_member_def)=(my_m); + (my_member_size)=((my_type_sizeof)((my_c),(my_t))); + if ((unsigned long)(((long)(my_member_size))>((long)(my_size)))) { + (my_size)=(my_member_size); + } + (my_m)=((my_m)->my_b); + } + ((my_d)->my_struct_size)=(my_size); + ((my_d)->my_struct_layout_done)=(1UL); +} void( my_leave)(struct my_peg* my_c,unsigned long my_tag){ unsigned long my_nargs = 0; unsigned long my_start = 0; @@ -5000,6 +5095,9 @@ struct my_type*( my_mktype2)(struct my_compiler* my_c,unsigned long my_kind,stru struct my_type*( my_mktype_struct)(struct my_compiler* my_c,struct my_decl* my_st){ return (my_mktype)((my_c),(my_TY_STRUCT),((struct my_type*)0UL),((struct my_type*)0UL),(my_st)); } +struct my_type*( my_mktype_union)(struct my_compiler* my_c,struct my_decl* my_st){ + return (my_mktype)((my_c),(my_TY_UNION),((struct my_type*)0UL),((struct my_type*)0UL),(my_st)); +} unsigned long( my_mmap)(unsigned long my_addr,unsigned long my_len,unsigned long my_prot,unsigned long my_flags,unsigned long my_fd,unsigned long my_off){ return (my_syscall)((9UL),(my_addr),(my_len),(my_prot),(my_flags),(my_fd),(my_off)); } @@ -5075,6 +5173,9 @@ unsigned char*( my_node_to_str)(unsigned long my_kind){ if ((unsigned long)(((long)(my_kind))==((long)(my_N_STRUCT)))) { return (unsigned char *)"N_STRUCT"; } + if ((unsigned long)(((long)(my_kind))==((long)(my_N_UNION)))) { + return (unsigned char *)"N_UNION"; + } if ((unsigned long)(((long)(my_kind))==((long)(my_N_MEMBERDECL)))) { return (unsigned char *)"N_MEMBERDECL"; } @@ -6777,6 +6878,10 @@ unsigned long( my_peg_P_grammar)(struct my_peg* my_c){ } if ((unsigned long)(!(my_ok))) { (my_choice)((my_c)); + (my_ok)=((my_peg_P_union_decl)((my_c))); + } + if ((unsigned long)(!(my_ok))) { + (my_choice)((my_c)); (my_ok)=((my_peg_P_func_decl)((my_c))); } if (my_ok) { @@ -8072,6 +8177,49 @@ unsigned long( my_peg_P_union)(struct my_peg* my_c){ } return my_ok; } +unsigned long( my_peg_P_union_decl)(struct my_peg* my_c){ + unsigned long my_ok = 0; + (my_enter)((my_c),(my_P_union_decl)); + (my_ok)=((my_peg_P_union)((my_c))); + if (my_ok) { + (my_ok)=((my_peg_P_sp)((my_c))); + } + if (my_ok) { + (my_ok)=((my_peg_P_ident)((my_c))); + } + if (my_ok) { + (my_ok)=((my_peg_P_sp)((my_c))); + } + if (my_ok) { + (my_ok)=((my_literal)((my_c),((unsigned char *)"{"))); + } + if (my_ok) { + (my_ok)=((my_peg_P_sp)((my_c))); + } + if (my_ok) { + while (1) { + (my_choice)((my_c)); + (my_ok)=((my_peg_P_member_decl)((my_c))); + if ((unsigned long)(!(my_ok))) { + (my_ok)=(1UL); + break; + } + (my_commit)((my_c)); + } + } + if (my_ok) { + (my_ok)=((my_literal)((my_c),((unsigned char *)"}"))); + } + if (my_ok) { + (my_ok)=((my_peg_P_sp)((my_c))); + } + if (my_ok) { + (my_leave)((my_c),(my_P_union_decl)); + } else { + (my_fail)((my_c)); + } + return my_ok; +} unsigned long( my_peg_P_var)(struct my_peg* my_c){ unsigned long my_ok = 0; (my_enter)((my_c),(my_P_var)); @@ -8292,7 +8440,11 @@ struct my_type*( my_prototype)(struct my_compiler* my_c,struct my_node* my_n){ if ((unsigned long)(((unsigned long)(!(my_st)))||((unsigned long)(!((my_st)->my_struct_defined))))) { (my_cdie)((my_c),((unsigned char *)"unknown struct")); } + if ((unsigned long)(((long)(((my_st)->my_struct_def)->my_kind))==((long)(my_N_STRUCT)))) { return (my_mktype_struct)((my_c),(my_st)); + } else { + return (my_mktype_union)((my_c),(my_st)); + } } else if ((unsigned long)(((long)(my_kind))==((long)(my_N_ARGLIST)))) { (my_a)=((my_prototype)((my_c),(((my_n)->my_a)->my_b))); (my_b)=((my_prototype)((my_c),((my_n)->my_b))); @@ -8376,6 +8528,8 @@ struct my_node*( my_reconstruct)(struct my_parser* my_c,struct my_peg_node* my_p (my_n)=((my_reconstruct_enum)((my_c),(my_pn))); } else if ((unsigned long)(((long)((my_pn)->my_tag))==((long)(my_P_struct_decl)))) { (my_n)=((my_reconstruct_struct)((my_c),(my_pn))); + } else if ((unsigned long)(((long)((my_pn)->my_tag))==((long)(my_P_union_decl)))) { + (my_n)=((my_reconstruct_union)((my_c),(my_pn))); } else if ((unsigned long)(((long)((my_pn)->my_tag))==((long)(my_P_func_decl)))) { (my_n)=((my_reconstruct_func)((my_c),(my_pn))); } else { @@ -9086,6 +9240,17 @@ struct my_node*( my_reconstruct_unary)(struct my_parser* my_c,struct my_peg_node (my_pn)=((my_pn)->my_next); } } +struct my_node*( my_reconstruct_union)(struct my_parser* my_c,struct my_peg_node* my_pn){ + struct my_node* my_n = 0; + struct my_node* my_a = 0; + struct my_node* my_b = 0; + (my_assert)(((unsigned long)(((long)((my_pn)->my_tag))==((long)(my_P_union_decl)))),((unsigned char *)"union_def")); + (my_a)=((my_reconstruct_ident)((my_c),(((my_pn)->my_child)->my_next))); + (my_b)=((my_reconstruct_member_list)((my_c),((((my_pn)->my_child)->my_next)->my_next))); + (my_n)=((my_mknode)((my_c),(my_N_UNION),(my_a),(my_b))); + (my_copypos)((my_n),(my_pn)); + return my_n; +} struct my_node*( my_reconstruct_var)(struct my_parser* my_c,struct my_peg_node* my_pn){ struct my_node* my_a = 0; struct my_node* my_b = 0; @@ -9507,7 +9672,7 @@ unsigned long( my_type_isint)(struct my_type* my_t){ return (unsigned long)(((unsigned long)(((long)((my_t)->my_kind))==((long)(my_TY_INT))))||((unsigned long)(((long)((my_t)->my_kind))==((long)(my_TY_BYTE))))); } unsigned long( my_type_isprim)(struct my_type* my_t){ - return (unsigned long)(((unsigned long)(((long)((my_t)->my_kind))!=((long)(my_TY_VOID))))&&((unsigned long)(((long)((my_t)->my_kind))!=((long)(my_TY_STRUCT))))); + return (unsigned long)(((unsigned long)(((long)((my_t)->my_kind))!=((long)(my_TY_VOID))))&&((unsigned long)(((unsigned long)(((long)((my_t)->my_kind))!=((long)(my_TY_STRUCT))))&&((unsigned long)(((long)((my_t)->my_kind))!=((long)(my_TY_UNION))))))); } unsigned long( my_type_sizeof)(struct my_compiler* my_c,struct my_type* my_t){ unsigned long my_kind = 0; @@ -9523,6 +9688,9 @@ unsigned long( my_type_sizeof)(struct my_compiler* my_c,struct my_type* my_t){ } else if ((unsigned long)(((long)(my_kind))==((long)(my_TY_STRUCT)))) { (my_layout_struct)((my_c),((my_t)->my_st)); return ((my_t)->my_st)->my_struct_size; + } else if ((unsigned long)(((long)(my_kind))==((long)(my_TY_UNION)))) { + (my_layout_union)((my_c),((my_t)->my_st)); + return ((my_t)->my_st)->my_struct_size; } else { (my_cdie)((my_c),((unsigned char *)"sizeof: invalid type")); } @@ -10066,6 +10234,10 @@ void( my_unify)(struct my_compiler* my_c,struct my_type* my_a,struct my_type* my if ((unsigned long)(((long)((my_a)->my_st))!=((long)((my_b)->my_st)))) { (my_cdie)((my_c),((unsigned char *)"type error")); } + } else if ((unsigned long)(((long)(my_kind))==((long)(my_TY_UNION)))) { + if ((unsigned long)(((long)((my_a)->my_st))!=((long)((my_b)->my_st)))) { + (my_cdie)((my_c),((unsigned char *)"type error")); + } } else if ((unsigned long)(((unsigned long)(((long)(my_kind))!=((long)(my_TY_VOID))))&&((unsigned long)(((unsigned long)(((long)(my_kind))!=((long)(my_TY_INT))))&&((unsigned long)(((long)(my_kind))!=((long)(my_TY_BYTE)))))))) { (my_cdie)((my_c),((unsigned char *)"unify: invalid type")); } diff --git a/cc1.c b/cc1.c @@ -112,6 +112,8 @@ compile(c: *compiler, p: *node) { kind = n.a.kind; if (kind == N_STRUCT) { defstruct(c, n.a); + } else if (kind == N_UNION) { + defunion(c, n.a); } else if (kind == N_ENUM) { defenum(c, n.a); } else if (kind != N_FUNC && kind != N_FUNCDECL) { @@ -433,6 +435,30 @@ defstruct(c: *compiler, n: *node) { d.struct_def = n; } +defunion(c: *compiler, n: *node) { + var name: *byte; + var d: *decl; + + name = n.a.s; + + c.filename = n.filename; + c.lineno = n.lineno; + c.colno = n.colno; + + if (!strcmp(name, "int") || !strcmp(name, "byte") || !strcmp(name, "func")) { + cdie(c, "reserved word"); + } + + d = find(c, name, 0:*byte, 1); + + if (d.struct_defined) { + cdie(c, "duplicate struct"); + } + + d.struct_defined = 1; + d.struct_def = n; +} + defenum(c: *compiler, n: *node) { var d: *decl; var i: int; @@ -521,6 +547,62 @@ layout_struct(c: *compiler, d: *decl) { d.struct_layout_done = 1; } +layout_union(c: *compiler, d: *decl) { + var m: *node; + var size: int; + var member_size: int; + var name: *byte; + var md: *decl; + var t: *type; + + if (d.struct_layout_done) { + if (d.struct_layout_done == 2) { + cdie(c, "circular struct definition"); + } + + return; + } + + d.struct_layout_done = 2; + + m = d.struct_def.b; + + size = 0; + loop { + if (!m) { + break; + } + + c.filename = m.a.filename; + c.lineno = m.a.lineno; + c.colno = m.a.colno; + + name = m.a.a.s; + t = prototype(c, m.a.b); + + md = find(c, d.name, name, 1); + + if (d.member_defined) { + cdie(c, "duplicate member"); + } + + md.member_defined = 1; + md.member_type = t; + md.member_offset = 0; + md.member_def = m; + + member_size = type_sizeof(c, t); + if member_size > size { + size = member_size; + } + + m = m.b; + } + + d.struct_size = size; + d.struct_layout_done = 1; +} + compile_func(c: *compiler, d: *decl) { var pragma: int; diff --git a/cc3.peg b/cc3.peg @@ -1,10 +1,11 @@ -grammar <- sp (enum_decl / struct_decl / func_decl)* !. +grammar <- sp (enum_decl / struct_decl / union_decl / func_decl)* !. enum_item <- ident sp ('=' sp expr)? enum_decl <- enum sp '{' sp (enum_item (',' sp enum_item)*)? (',' sp)? '}' sp member_decl <- ident sp ':' sp type ';' sp struct_decl <- struct sp ident sp '{' sp member_decl* '}' sp +union_decl <- union sp ident sp '{' sp member_decl* '}' sp func_decl <- ident sp func_type (';' sp / compound_stmt) diff --git a/cout.c b/cout.c @@ -18,7 +18,11 @@ ctranslate(c: *compiler) { } if d.struct_defined { - fputs(c.cout, "struct my_"); + if d.struct_def.kind == N_UNION { + fputs(c.cout, "union my_"); + } else { + fputs(c.cout, "struct my_"); + } fputs(c.cout, d.name); fputs(c.cout, ";\n"); } @@ -124,6 +128,9 @@ ctranslate_type1(c: *compiler, ty: *type, name: *byte, decl: int) { } else if ty.kind == TY_STRUCT { fputs(c.cout, "struct my_"); fputs(c.cout, ty.st.name); + } else if ty.kind == TY_UNION { + fputs(c.cout, "union my_"); + fputs(c.cout, ty.st.name); } else { die("invalid type"); } @@ -198,6 +205,18 @@ ctranslate_zero(c: *compiler, ty: *type) { n = n.b; } fputs(c.cout, "}"); + } else if ty.kind == TY_UNION { + fputs(c.cout, "{"); + n = ty.st.struct_def.b; + loop { + if !n { + break; + } + v = find(c, ty.st.name, n.a.a.s, 0); + ctranslate_zero(c, v.member_type); + n = n.b; + } + fputs(c.cout, "}"); } else { die("invalid type"); } @@ -206,7 +225,11 @@ ctranslate_zero(c: *compiler, ty: *type) { ctranslate_struct(c: *compiler, d: *decl) { var v: *decl; var n: *node; - fputs(c.cout, "struct my_"); + if d.struct_def.kind == N_UNION { + fputs(c.cout, "union my_"); + } else { + fputs(c.cout, "struct my_"); + } fputs(c.cout, d.name); fputs(c.cout, " {\n"); n = d.struct_def.b; diff --git a/node.c b/node.c @@ -27,6 +27,7 @@ enum { N_FUNCTYPE, N_PTRTYPE, N_STRUCT, + N_UNION, N_MEMBERDECL, N_MEMBERLIST, N_CONDLIST, @@ -137,6 +138,7 @@ node_to_str(kind: int): *byte { if kind == N_FUNCTYPE { return "N_FUNCTYPE"; } if kind == N_PTRTYPE { return "N_PTRTYPE"; } if kind == N_STRUCT { return "N_STRUCT"; } + if kind == N_UNION { return "N_UNION"; } if kind == N_MEMBERDECL { return "N_MEMBERDECL"; } if kind == N_MEMBERLIST { return "N_MEMBERLIST"; } if kind == N_CONDLIST { return "N_CONDLIST"; } diff --git a/parse2.c b/parse2.c @@ -69,6 +69,8 @@ reconstruct(c: *parser, pn: *peg_node): *node { n = reconstruct_enum(c, pn); } else if pn.tag == P_struct_decl { n = reconstruct_struct(c, pn); + } else if pn.tag == P_union_decl { + n = reconstruct_union(c, pn); } else if pn.tag == P_func_decl { n = reconstruct_func(c, pn); } else { @@ -285,6 +287,18 @@ reconstruct_struct(c: *parser, pn: *peg_node): *node { return n; } +reconstruct_union(c: *parser, pn: *peg_node): *node { + var n: *node; + var a: *node; + var b: *node; + assert(pn.tag == P_union_decl, "union_def"); + a = reconstruct_ident(c, pn.child.next); + b = reconstruct_member_list(c, pn.child.next.next); + n = mknode(c, N_UNION, a, b); + copypos(n, pn); + return n; +} + reconstruct_expr(c: *parser, pn: *peg_node): *node { assert(pn.tag == P_expr, "expr"); return reconstruct_bool(c, pn.child); diff --git a/type.c b/type.c @@ -13,6 +13,7 @@ enum { TY_ARG, TY_FUNC, TY_STRUCT, + TY_UNION, } type_sizeof(c: *compiler, t: *type): int { @@ -30,6 +31,9 @@ type_sizeof(c: *compiler, t: *type): int { } else if (kind == TY_STRUCT) { layout_struct(c, t.st); return t.st.struct_size; + } else if (kind == TY_UNION) { + layout_union(c, t.st); + return t.st.struct_size; } else { cdie(c, "sizeof: invalid type"); } @@ -60,6 +64,10 @@ unify(c: *compiler, a: *type, b: *type) { if (a.st != b.st) { cdie(c, "type error"); } + } else if (kind == TY_UNION) { + if (a.st != b.st) { + cdie(c, "type error"); + } } else if (kind != TY_VOID && kind != TY_INT && kind != TY_BYTE) { cdie(c, "unify: invalid type"); } @@ -98,6 +106,10 @@ mktype_struct(c: *compiler, st: *decl): *type { return mktype(c, TY_STRUCT, 0:*type, 0:*type, st); } +mktype_union(c: *compiler, st: *decl): *type { + return mktype(c, TY_UNION, 0:*type, 0:*type, st); +} + mktype0(c: *compiler, kind: int): *type { return mktype(c, kind, 0:*type, 0:*type, 0:*decl); } @@ -115,7 +127,7 @@ type_isint(t: *type): int { } type_isprim(t: *type): int { - return t.kind != TY_VOID && t.kind != TY_STRUCT; + return t.kind != TY_VOID && t.kind != TY_STRUCT && t.kind != TY_UNION; } prototype(c: *compiler, n: *node): *type { @@ -150,7 +162,11 @@ prototype(c: *compiler, n: *node): *type { cdie(c, "unknown struct"); } - return mktype_struct(c, st); + if st.struct_def.kind == N_STRUCT { + return mktype_struct(c, st); + } else { + return mktype_union(c, st); + } } else if (kind == N_ARGLIST) { a = prototype(c, n.a.b); b = prototype(c, n.b);