Added basic dead code elimination at the function level; bug fixes
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 23 Jul 2020 18:34:45 +0000 (13:34 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 23 Jul 2020 18:34:45 +0000 (13:34 -0500)
12 files changed:
.vimspector.json
docs/plan
include/onyxastnodes.h
include/onyxlex.h
include/onyxsempass.h
onyx
src/onyxchecker.c
src/onyxlex.c
src/onyxparser.c
src/onyxsempass.c
src/onyxsymres.c
src/onyxwasm.c

index f64d90eb482f11d516831e5c5b4712ede73a95e4..8a5ecd8927fad2ed3b2eaf075292cd2ec89be3f3 100644 (file)
@@ -6,7 +6,7 @@
                 "type": "cppdbg",
                 "request": "launch",
                 "program": "${workspaceFolder}/onyx",
-                "args": ["progs/structs.onyx"],
+                "args": ["progs/ufc.onyx"],
                 "stopAtEntry": true,
                 "cwd": "${workspaceFolder}",
                 "environment": [],
index b9e23256c24e76a94ef47c58ddc0ff5001dab74b..b9e28abff6d8a92450a18abf327cea7f75122d6c 100644 (file)
--- 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
 
index 164fb0d88a6e836433b13705e02c936221b42619..270cd5309202e74251f7a882e7d0790a6d2fc1a2 100644 (file)
@@ -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 {
index 913c48a0f8191204f441955e249b8e0ae0f512b4..e82c3fb107353ff8c1ea8d357c7ffd49cc4f7565 100644 (file)
@@ -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 {
index 5b3356fb52d2e43e472aa61e57c2212ce1569d03..3dce4427e7633024b7f306c29cd57fbc544aebd7 100644 (file)
@@ -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 d2b55da7adf36d2013726b73a2a8bc3c9355aed2..3d51e398539fae28ab568d20e94f047d11454acd 100755 (executable)
Binary files a/onyx and b/onyx differ
index 4ed68de1686835daf2867362e4da4cf2fc73bbb8..f28ba783da1b5c6180010e7b1284911bb3e3c440 100644 (file)
@@ -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;
index 3baef1cc85ffbcf25838708283b1f1cc6c99fdee..75eafd588d1dea3098a168488d685fe23ff3bf86 100644 (file)
@@ -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);
index 9dd5874af59ff25a289cede23962ac8c3ca67bce..9e46d397749554c6abd6f7b3de1b3b35a4207a16 100644 (file)
@@ -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;
index 33d55d6937aa76d22fe8e408d7895a3679626517..34f4ef5e7b118888bdee8c26d4bb691321ac2e55 100644 (file)
@@ -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;
 
index c269c6abcbc5074763335306c567679a2d01efda..7964578bb561f79c623b6d0d2758f7790ec45e29 100644 (file)
@@ -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;
index 517cd8e91ff78b4e937c733252cb6d17f63df58c..1dff1fda5710b12d31b124b92a8ce55860022c88 100644 (file)
@@ -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)