diff --git a/src/all_types.hpp b/src/all_types.hpp index 1f6160728..3842621c1 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -972,6 +972,7 @@ struct FnTableEntry { bool is_inline; bool internal_linkage; bool is_extern; + uint32_t ref_count; // if this is 0 we don't have to codegen it // reminder: hash tables must be initialized before use HashMap label_table; @@ -1000,6 +1001,7 @@ struct BuiltinFnEntry { int param_count; TypeTableEntry *return_type; TypeTableEntry **param_types; + uint32_t ref_count; LLVMValueRef fn_val; }; diff --git a/src/analyze.cpp b/src/analyze.cpp index 6e3abdac3..13d2212a8 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1123,6 +1123,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, fn_table_entry->is_extern = is_extern; fn_table_entry->label_table.init(8); fn_table_entry->member_of_struct = struct_type; + fn_table_entry->ref_count = (proto_node->data.fn_proto.visib_mod == VisibModExport) ? 1 : 0; if (struct_type) { buf_resize(&fn_table_entry->symbol_name, 0); @@ -2244,6 +2245,7 @@ static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode } static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn) { + fn->ref_count += 1; Expr *expr = get_resolved_expr(node); expr->const_val.ok = true; expr->const_val.data.x_fn = fn; @@ -3658,6 +3660,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry return g->builtin_types.entry_invalid; } + builtin_fn->ref_count += 1; + switch (builtin_fn->id) { case BuiltinFnIdInvalid: zig_unreachable(); @@ -3913,6 +3917,8 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import, node->data.fn_call_expr.fn_entry = fn_table_entry; + fn_table_entry->ref_count += 1; + return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type); } diff --git a/src/codegen.cpp b/src/codegen.cpp index c82b337c5..b443a6fc9 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2582,9 +2582,28 @@ static void gen_const_globals(CodeGen *g) { } } +static void delete_unused_builtin_fns(CodeGen *g) { + auto it = g->builtin_fn_table.entry_iterator(); + for (;;) { + auto *entry = it.next(); + if (!entry) + break; + + BuiltinFnEntry *builtin_fn = entry->value; + if (builtin_fn->ref_count == 0 && + builtin_fn->fn_val) + { + LLVMDeleteFunction(entry->value->fn_val); + } + } +} + static void do_code_gen(CodeGen *g) { assert(!g->errors.length); + delete_unused_builtin_fns(g); + + gen_const_globals(g); // Generate module level variables @@ -2633,6 +2652,12 @@ static void do_code_gen(CodeGen *g) { // Generate function prototypes for (int fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) { FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i); + if (fn_table_entry->ref_count == 0) { + // huge time saver + LLVMDeleteFunction(fn_table_entry->fn_value); + continue; + } + AstNode *proto_node = fn_table_entry->proto_node; assert(proto_node->type == NodeTypeFnProto); AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; @@ -2681,6 +2706,11 @@ static void do_code_gen(CodeGen *g) { // Generate function definitions. for (int fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) { FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i); + if (fn_table_entry->ref_count == 0) { + // huge time saver + continue; + } + ImportTableEntry *import = fn_table_entry->import_entry; AstNode *fn_def_node = fn_table_entry->fn_def_node; LLVMValueRef fn = fn_table_entry->fn_value; @@ -3064,6 +3094,7 @@ static void define_builtin_fns(CodeGen *g) { builtin_fn->param_types[0] = nullptr; // manually checked later builtin_fn->param_types[1] = nullptr; // manually checked later builtin_fn->param_types[2] = g->builtin_types.entry_isize; + builtin_fn->ref_count = 1; LLVMTypeRef param_types[] = { LLVMPointerType(LLVMInt8Type(), 0), @@ -3087,6 +3118,7 @@ static void define_builtin_fns(CodeGen *g) { builtin_fn->param_types[0] = nullptr; // manually checked later builtin_fn->param_types[1] = g->builtin_types.entry_u8; builtin_fn->param_types[2] = g->builtin_types.entry_isize; + builtin_fn->ref_count = 1; LLVMTypeRef param_types[] = { LLVMPointerType(LLVMInt8Type(), 0),