From: Brendan Hansen Date: Thu, 23 Jul 2020 18:34:45 +0000 (-0500) Subject: Added basic dead code elimination at the function level; bug fixes X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=889e48f21568fef8930a9bce9192221ab9387e58;p=onyx.git Added basic dead code elimination at the function level; bug fixes --- diff --git a/.vimspector.json b/.vimspector.json index f64d90eb..8a5ecd89 100644 --- a/.vimspector.json +++ b/.vimspector.json @@ -6,7 +6,7 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/onyx", - "args": ["progs/structs.onyx"], + "args": ["progs/ufc.onyx"], "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], diff --git a/docs/plan b/docs/plan index b9e23256..b9e28abf 100644 --- a/docs/plan +++ b/docs/plan @@ -110,7 +110,10 @@ HOW: [X] Bitwise operators - [ ] Dead code elimination + [X] Dead code elimination + - Start with uncalled functions being removed + - Foreign functions will rename in the code because it is turning out + to be a nightmare to remove them. Lot's of refactoring... ugh [ ] Enum types diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 164fb0d8..270cd530 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -117,6 +117,7 @@ typedef enum AstFlags { // Function flags Ast_Flag_Inline = BH_BIT(8), Ast_Flag_Intrinsic = BH_BIT(9), + Ast_Flag_Function_Used = BH_BIT(10), // Expression flags Ast_Flag_Expr_Ignored = BH_BIT(8), @@ -155,22 +156,21 @@ typedef enum BinaryOp { Binary_Op_Bool_And = 17, Binary_Op_Bool_Or = 18, - Binary_Op_Bool_Xor = 19, - - Binary_Op_Assign_Start = 20, - Binary_Op_Assign = 21, - Binary_Op_Assign_Add = 22, - Binary_Op_Assign_Minus = 23, - Binary_Op_Assign_Multiply = 24, - Binary_Op_Assign_Divide = 25, - Binary_Op_Assign_Modulus = 26, - Binary_Op_Assign_And = 27, - Binary_Op_Assign_Or = 28, - Binary_Op_Assign_Xor = 29, - Binary_Op_Assign_Shl = 30, - Binary_Op_Assign_Shr = 31, - Binary_Op_Assign_Sar = 32, - Binary_Op_Assign_End = 33, + + Binary_Op_Assign_Start = 19, + Binary_Op_Assign = 20, + Binary_Op_Assign_Add = 21, + Binary_Op_Assign_Minus = 22, + Binary_Op_Assign_Multiply = 23, + Binary_Op_Assign_Divide = 24, + Binary_Op_Assign_Modulus = 25, + Binary_Op_Assign_And = 26, + Binary_Op_Assign_Or = 27, + Binary_Op_Assign_Xor = 28, + Binary_Op_Assign_Shl = 29, + Binary_Op_Assign_Shr = 30, + Binary_Op_Assign_Sar = 31, + Binary_Op_Assign_End = 32, } BinaryOp; typedef enum OnyxIntrinsic { diff --git a/include/onyxlex.h b/include/onyxlex.h index 913c48a0..e82c3fb1 100644 --- a/include/onyxlex.h +++ b/include/onyxlex.h @@ -44,21 +44,20 @@ typedef enum TokenType { Token_Type_Xor_Equal = 288, Token_Type_And_And = 289, Token_Type_Or_Or = 290, - Token_Type_Xor_Xor = 291, - Token_Type_Shift_Left = 292, - Token_Type_Shift_Right = 293, - Token_Type_Shift_Arith_Right = 294, - Token_Type_Shl_Equal = 295, - Token_Type_Shr_Equal = 296, - Token_Type_Sar_Equal = 297, - - Token_Type_Symbol = 298, - Token_Type_Literal_String = 299, - Token_Type_Literal_Numeric = 300, - Token_Type_Literal_True = 301, - Token_Type_Literal_False = 302, - - Token_Type_Count = 303, + Token_Type_Shift_Left = 291, + Token_Type_Shift_Right = 292, + Token_Type_Shift_Arith_Right = 293, + Token_Type_Shl_Equal = 294, + Token_Type_Shr_Equal = 295, + Token_Type_Sar_Equal = 296, + + Token_Type_Symbol = 297, + Token_Type_Literal_String = 298, + Token_Type_Literal_Numeric = 299, + Token_Type_Literal_True = 300, + Token_Type_Literal_False = 301, + + Token_Type_Count = 302, } TokenType; typedef struct OnyxFilePos { diff --git a/include/onyxsempass.h b/include/onyxsempass.h index 5b3356fb..3dce4427 100644 --- a/include/onyxsempass.h +++ b/include/onyxsempass.h @@ -12,6 +12,9 @@ typedef struct SemState { // to make any more node in the tree bh_allocator allocator, node_allocator; + // NOTE: Used wherever + ProgramInfo* program; + // NOTE: Used in symbol resolution phase Scope* global_scope; Scope* curr_scope; @@ -24,10 +27,10 @@ typedef struct SemState { extern SemState semstate; // NOTE: Resolving all symbols in the tree -void onyx_resolve_symbols(ProgramInfo* program); +void onyx_resolve_symbols(); // NOTE: Inferring and checking types in the tree -void onyx_type_check(ProgramInfo* program); +void onyx_type_check(); // NOTE: Full semantic pass void onyx_sempass_init(bh_allocator alloc, bh_allocator node_alloc); diff --git a/onyx b/onyx index d2b55da7..3d51e398 100755 Binary files a/onyx and b/onyx differ diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 4ed68de1..f28ba783 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -328,6 +328,8 @@ CHECK(call, AstCall* call) { return 1; } + callee->flags |= Ast_Flag_Function_Used; + return 0; } @@ -426,7 +428,7 @@ CHECK(binaryop, AstBinaryOp* binop, b32 assignment_is_ok) { } if (binop->operation >= Binary_Op_Bool_And - && binop->operation <= Binary_Op_Bool_Xor) { + && binop->operation <= Binary_Op_Bool_Or) { if (!type_is_bool(binop->left->type) || !type_is_bool(binop->right->type)) { onyx_message_add(Msg_Type_Literal, @@ -900,11 +902,13 @@ CHECK(node, AstNode* node) { } } -void onyx_type_check(ProgramInfo* program) { - bh_arr_each(Entity, entity, program->entities) { +void onyx_type_check() { + bh_arr_each(Entity, entity, semstate.program->entities) { switch (entity->type) { case Entity_Type_Function_Header: - if (entity->function->flags & Ast_Kind_Foreign) program->foreign_func_count++; + if (entity->function->flags & Ast_Kind_Foreign) + semstate.program->foreign_func_count++; + if (check_function_header(entity->function)) return; break; @@ -917,7 +921,8 @@ void onyx_type_check(ProgramInfo* program) { break; case Entity_Type_Global: - if (entity->global->flags & Ast_Kind_Foreign) program->foreign_global_count++; + if (entity->global->flags & Ast_Kind_Foreign) + semstate.program->foreign_global_count++; if (check_global(entity->global)) return; break; diff --git a/src/onyxlex.c b/src/onyxlex.c index 3baef1cc..75eafd58 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -37,6 +37,18 @@ static const char* token_type_names[] = { "*=", "/=", "%=", + "&=", + "|=", + "^=", + "&&", + "||", + "^^", + "<<", + ">>", + ">>>", + "<<=", + ">>=", + ">>>=" "TOKEN_TYPE_SYMBOL", "TOKEN_TYPE_LITERAL_STRING", @@ -151,7 +163,6 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) { LITERAL_TOKEN("---", 0, Token_Type_Empty_Block); LITERAL_TOKEN("&&", 0, Token_Type_And_And); LITERAL_TOKEN("||", 0, Token_Type_Or_Or); - LITERAL_TOKEN("^^", 0, Token_Type_Xor_Xor); LITERAL_TOKEN(">>>=", 0, Token_Type_Sar_Equal); LITERAL_TOKEN(">>=", 0, Token_Type_Shr_Equal); LITERAL_TOKEN("<<=", 0, Token_Type_Shl_Equal); diff --git a/src/onyxparser.c b/src/onyxparser.c index 9dd5874a..9e46d397 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -339,7 +339,6 @@ static inline i32 get_precedence(BinaryOp kind) { case Binary_Op_Bool_And: return 2; case Binary_Op_Bool_Or: return 2; - case Binary_Op_Bool_Xor: return 2; case Binary_Op_Equal: return 3; case Binary_Op_Not_Equal: return 3; @@ -421,7 +420,6 @@ static AstTyped* parse_expression(OnyxParser* parser) { case Token_Type_And_And: bin_op_kind = Binary_Op_Bool_And; break; case Token_Type_Or_Or: bin_op_kind = Binary_Op_Bool_Or; break; - case Token_Type_Xor_Xor: bin_op_kind = Binary_Op_Bool_Xor; break; case '=': bin_op_kind = Binary_Op_Assign; break; case Token_Type_Plus_Equal: bin_op_kind = Binary_Op_Assign_Add; break; diff --git a/src/onyxsempass.c b/src/onyxsempass.c index 33d55d69..34f4ef5e 100644 --- a/src/onyxsempass.c +++ b/src/onyxsempass.c @@ -15,6 +15,8 @@ void onyx_sempass_init(bh_allocator alloc, bh_allocator node_alloc) { } void onyx_sempass(ProgramInfo* program) { + semstate.program = program; + onyx_resolve_symbols(program); if (onyx_message_has_errors()) return; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index c269c6ab..7964578b 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -389,7 +389,7 @@ static void symres_overloaded_function(AstOverloadedFunction* ofunc) { } } -void onyx_resolve_symbols(ProgramInfo* program) { +void onyx_resolve_symbols() { semstate.global_scope = scope_create(semstate.node_allocator, NULL); scope_enter(semstate.global_scope); @@ -401,10 +401,10 @@ void onyx_resolve_symbols(ProgramInfo* program) { bsym++; } - bh_arr_each(AstBinding *, binding, program->bindings) + bh_arr_each(AstBinding *, binding, semstate.program->bindings) if (!symbol_introduce((*binding)->token, (*binding)->node)) return; - bh_arr_each(Entity, entity, program->entities) { + bh_arr_each(Entity, entity, semstate.program->entities) { switch (entity->type) { case Entity_Type_Function: symres_function(entity->function); break; case Entity_Type_Overloaded_Function: symres_overloaded_function(entity->overloaded_function); break; diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 517cd8e9..1dff1fda 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -596,7 +596,6 @@ static const WasmInstructionType binop_map[][4] = { /* BAND */ { WI_I32_AND, WI_I64_AND, WI_NOP, WI_NOP }, /* BOR */ { WI_I32_OR, WI_I64_OR, WI_NOP, WI_NOP }, - /* BXOR */ { WI_I32_XOR, WI_I64_XOR, WI_NOP, WI_NOP }, }; COMPILE_FUNC(binop, AstBinaryOp* binop) { @@ -1115,9 +1114,27 @@ static i32 generate_type_idx(OnyxWasmModule* mod, AstFunction* fd) { return type_idx; } +static inline b32 should_compile_function(AstFunction* fd) { + // NOTE: Don't output intrinsic functions + if (fd->flags & Ast_Flag_Intrinsic) return 0; + + if (fd->flags & Ast_Flag_Foreign) return 1; + + // NOTE: Don't output functions that are not used, only if + // they are also not exported. + if ((fd->flags & Ast_Flag_Function_Used) == 0) { + if (fd->flags & Ast_Flag_Exported) { + return 1; + } else { + return 0; + } + } + + return 1; +} + static void compile_function(OnyxWasmModule* mod, AstFunction* fd) { - // NOTE: Don't compile intrinsics - if (fd->flags & Ast_Flag_Intrinsic) return; + if (!should_compile_function(fd)) return; i32 type_idx = generate_type_idx(mod, fd); @@ -1351,7 +1368,7 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, ProgramInfo* program) { bh_arr_each(Entity, entity, program->entities) { switch (entity->type) { case Entity_Type_Function_Header: { - if (entity->function->flags & Ast_Flag_Intrinsic) break; + if (!should_compile_function(entity->function)) break; u64 func_idx; if ((entity->function->flags & Ast_Flag_Foreign) != 0)