authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-19 12:42:32-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-10-19 12:42:32-04:00
log63dfca97159fd66563693039606c0bca30aa1f85
tree7975692d2f2934f19d13a1784db87619c525bcaf
parente42d86b657c2fae093fb2545e8b4b85614a0c906
parent4e985123447dba40e282e9663e3ca669d3f9243a
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3482 from ziglang/mem-usage-report

add -DZIG_ENABLE_MEM_PROFILE option and -fmem-report flag

13 files changed, 315 insertions(+), 83 deletions(-)

CMakeLists.txt+2
...@@ -46,6 +46,7 @@ message("Configuring zig version ${ZIG_VERSION}")...@@ -46,6 +46,7 @@ message("Configuring zig version ${ZIG_VERSION}")
46set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)")46set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)")
47set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries")47set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries")
48set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix")48set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix")
49set(ZIG_ENABLE_MEM_PROFILE off CACHE BOOL "Activate memory usage instrumentation")
4950
50if(ZIG_STATIC)51if(ZIG_STATIC)
51 set(ZIG_STATIC_LLVM "on")52 set(ZIG_STATIC_LLVM "on")
...@@ -455,6 +456,7 @@ set(ZIG_SOURCES...@@ -455,6 +456,7 @@ set(ZIG_SOURCES
455 "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"456 "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
456 "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"457 "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"
457 "${CMAKE_SOURCE_DIR}/src/link.cpp"458 "${CMAKE_SOURCE_DIR}/src/link.cpp"
459 "${CMAKE_SOURCE_DIR}/src/memory_profiling.cpp"
458 "${CMAKE_SOURCE_DIR}/src/os.cpp"460 "${CMAKE_SOURCE_DIR}/src/os.cpp"
459 "${CMAKE_SOURCE_DIR}/src/parser.cpp"461 "${CMAKE_SOURCE_DIR}/src/parser.cpp"
460 "${CMAKE_SOURCE_DIR}/src/range_set.cpp"462 "${CMAKE_SOURCE_DIR}/src/range_set.cpp"
src/all_types.hpp+3-3
...@@ -2569,12 +2569,12 @@ enum IrInstructionId {...@@ -2569,12 +2569,12 @@ enum IrInstructionId {
2569struct IrInstruction {2569struct IrInstruction {
2570 Scope *scope;2570 Scope *scope;
2571 AstNode *source_node;2571 AstNode *source_node;
2572 ConstExprValue value;
2573 size_t debug_id;
2574 LLVMValueRef llvm_value;2572 LLVMValueRef llvm_value;
2573 ConstExprValue value;
2574 uint32_t debug_id;
2575 // if ref_count is zero and the instruction has no side effects,2575 // if ref_count is zero and the instruction has no side effects,
2576 // the instruction can be omitted in codegen2576 // the instruction can be omitted in codegen
2577 size_t ref_count;2577 uint32_t ref_count;
2578 // When analyzing IR, instructions that point to this instruction in the "old ir"2578 // When analyzing IR, instructions that point to this instruction in the "old ir"
2579 // can find the instruction that corresponds to this value in the "new ir"2579 // can find the instruction that corresponds to this value in the "new ir"
2580 // with this child field.2580 // with this child field.
src/analyze.cpp+2-2
...@@ -5783,8 +5783,8 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_...@@ -5783,8 +5783,8 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_
57835783
57845784
5785ConstExprValue *create_const_vals(size_t count) {5785ConstExprValue *create_const_vals(size_t count) {
5786 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(count);5786 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(count, "ConstGlobalRefs");
5787 ConstExprValue *vals = allocate<ConstExprValue>(count);5787 ConstExprValue *vals = allocate<ConstExprValue>(count, "ConstExprValue");
5788 for (size_t i = 0; i < count; i += 1) {5788 for (size_t i = 0; i < count; i += 1) {
5789 vals[i].global_refs = &global_refs[i];5789 vals[i].global_refs = &global_refs[i];
5790 }5790 }
src/config.h.in+2-3
...@@ -13,9 +13,6 @@...@@ -13,9 +13,6 @@
13#define ZIG_VERSION_PATCH @ZIG_VERSION_PATCH@13#define ZIG_VERSION_PATCH @ZIG_VERSION_PATCH@
14#define ZIG_VERSION_STRING "@ZIG_VERSION@"14#define ZIG_VERSION_STRING "@ZIG_VERSION@"
1515
16// Only used for running tests before installing.
17#define ZIG_TEST_DIR "@CMAKE_SOURCE_DIR@/test"
18
19// Used for communicating build information to self hosted build.16// Used for communicating build information to self hosted build.
20#define ZIG_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@"17#define ZIG_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@"
21#define ZIG_CXX_COMPILER "@CMAKE_CXX_COMPILER@"18#define ZIG_CXX_COMPILER "@CMAKE_CXX_COMPILER@"
...@@ -24,4 +21,6 @@...@@ -24,4 +21,6 @@
24#define ZIG_LLVM_CONFIG_EXE "@LLVM_CONFIG_EXE@"21#define ZIG_LLVM_CONFIG_EXE "@LLVM_CONFIG_EXE@"
25#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@"22#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@"
2623
24#cmakedefine ZIG_ENABLE_MEM_PROFILE
25
27#endif26#endif
src/dump_analysis.cpp+1-18
...@@ -240,23 +240,6 @@ static void jw_string(JsonWriter *jw, const char *s) {...@@ -240,23 +240,6 @@ static void jw_string(JsonWriter *jw, const char *s) {
240240
241static void tree_print(FILE *f, ZigType *ty, size_t indent);241static void tree_print(FILE *f, ZigType *ty, size_t indent);
242242
243static void pretty_print_bytes(FILE *f, double n) {
244 if (n > 1024.0 * 1024.0 * 1024.0) {
245 fprintf(f, "%.02f GiB", n / 1024.0 / 1024.0 / 1024.0);
246 return;
247 }
248 if (n > 1024.0 * 1024.0) {
249 fprintf(f, "%.02f MiB", n / 1024.0 / 1024.0);
250 return;
251 }
252 if (n > 1024.0) {
253 fprintf(f, "%.02f KiB", n / 1024.0);
254 return;
255 }
256 fprintf(f, "%.02f bytes", n );
257 return;
258}
259
260static int compare_type_abi_sizes_desc(const void *a, const void *b) {243static int compare_type_abi_sizes_desc(const void *a, const void *b) {
261 uint64_t size_a = (*(ZigType * const*)(a))->abi_size;244 uint64_t size_a = (*(ZigType * const*)(a))->abi_size;
262 uint64_t size_b = (*(ZigType * const*)(b))->abi_size;245 uint64_t size_b = (*(ZigType * const*)(b))->abi_size;
...@@ -322,7 +305,7 @@ static void tree_print(FILE *f, ZigType *ty, size_t indent) {...@@ -322,7 +305,7 @@ static void tree_print(FILE *f, ZigType *ty, size_t indent) {
322305
323 start_peer(f, indent);306 start_peer(f, indent);
324 fprintf(f, "\"sizef\": \"");307 fprintf(f, "\"sizef\": \"");
325 pretty_print_bytes(f, ty->abi_size);308 zig_pretty_print_bytes(f, ty->abi_size);
326 fprintf(f, "\"");309 fprintf(f, "\"");
327310
328 start_peer(f, indent);311 start_peer(f, indent);
src/ir.cpp+35-24
...@@ -413,7 +413,7 @@ ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) {...@@ -413,7 +413,7 @@ ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) {
413}413}
414414
415static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) {415static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) {
416 IrBasicBlock *result = allocate<IrBasicBlock>(1);416 IrBasicBlock *result = allocate<IrBasicBlock>(1, "IrBasicBlock");
417 result->scope = scope;417 result->scope = scope;
418 result->name_hint = name_hint;418 result->name_hint = name_hint;
419 result->debug_id = exec_next_debug_id(irb->exec);419 result->debug_id = exec_next_debug_id(irb->exec);
...@@ -1085,13 +1085,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillEnd *) {...@@ -1085,13 +1085,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillEnd *) {
10851085
1086template<typename T>1086template<typename T>
1087static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {1087static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
1088 T *special_instruction = allocate<T>(1);1088 const char *name = nullptr;
1089#ifdef ZIG_ENABLE_MEM_PROFILE
1090 T *dummy = nullptr;
1091 name = ir_instruction_type_str(ir_instruction_id(dummy));
1092#endif
1093 T *special_instruction = allocate<T>(1, name);
1089 special_instruction->base.id = ir_instruction_id(special_instruction);1094 special_instruction->base.id = ir_instruction_id(special_instruction);
1090 special_instruction->base.scope = scope;1095 special_instruction->base.scope = scope;
1091 special_instruction->base.source_node = source_node;1096 special_instruction->base.source_node = source_node;
1092 special_instruction->base.debug_id = exec_next_debug_id(irb->exec);1097 special_instruction->base.debug_id = exec_next_debug_id(irb->exec);
1093 special_instruction->base.owner_bb = irb->current_basic_block;1098 special_instruction->base.owner_bb = irb->current_basic_block;
1094 special_instruction->base.value.global_refs = allocate<ConstGlobalRefs>(1);1099 special_instruction->base.value.global_refs = allocate<ConstGlobalRefs>(1, "ConstGlobalRefs");
1095 return special_instruction;1100 return special_instruction;
1096}1101}
10971102
...@@ -3569,7 +3574,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3569,7 +3574,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3569 switch (node->data.return_expr.kind) {3574 switch (node->data.return_expr.kind) {
3570 case ReturnKindUnconditional:3575 case ReturnKindUnconditional:
3571 {3576 {
3572 ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);3577 ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1, "ResultLocReturn");
3573 result_loc_ret->base.id = ResultLocIdReturn;3578 result_loc_ret->base.id = ResultLocIdReturn;
3574 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);3579 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
35753580
...@@ -3664,7 +3669,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3664,7 +3669,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3664 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val, nullptr));3669 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val, nullptr));
3665 IrInstructionSpillBegin *spill_begin = ir_build_spill_begin(irb, scope, node, err_val,3670 IrInstructionSpillBegin *spill_begin = ir_build_spill_begin(irb, scope, node, err_val,
3666 SpillIdRetErrCode);3671 SpillIdRetErrCode);
3667 ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);3672 ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1, "ResultLocReturn");
3668 result_loc_ret->base.id = ResultLocIdReturn;3673 result_loc_ret->base.id = ResultLocIdReturn;
3669 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);3674 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
3670 ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base);3675 ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base);
...@@ -3692,7 +3697,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s...@@ -3692,7 +3697,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
3692 Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime,3697 Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime,
3693 bool skip_name_check)3698 bool skip_name_check)
3694{3699{
3695 ZigVar *variable_entry = allocate<ZigVar>(1);3700 ZigVar *variable_entry = allocate<ZigVar>(1, "ZigVar");
3696 variable_entry->parent_scope = parent_scope;3701 variable_entry->parent_scope = parent_scope;
3697 variable_entry->shadowable = is_shadowable;3702 variable_entry->shadowable = is_shadowable;
3698 variable_entry->mem_slot_index = SIZE_MAX;3703 variable_entry->mem_slot_index = SIZE_MAX;
...@@ -3767,7 +3772,7 @@ static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *n...@@ -3767,7 +3772,7 @@ static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *n
3767}3772}
37683773
3769static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) {3774static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) {
3770 ResultLocPeer *result = allocate<ResultLocPeer>(1);3775 ResultLocPeer *result = allocate<ResultLocPeer>(1, "ResultLocPeer");
3771 result->base.id = ResultLocIdPeer;3776 result->base.id = ResultLocIdPeer;
3772 result->base.source_instruction = peer_parent->base.source_instruction;3777 result->base.source_instruction = peer_parent->base.source_instruction;
3773 result->parent = peer_parent;3778 result->parent = peer_parent;
...@@ -3806,7 +3811,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3806,7 +3811,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3806 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,3811 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,
3807 ir_should_inline(irb->exec, parent_scope));3812 ir_should_inline(irb->exec, parent_scope));
38083813
3809 scope_block->peer_parent = allocate<ResultLocPeerParent>(1);3814 scope_block->peer_parent = allocate<ResultLocPeerParent>(1, "ResultLocPeerParent");
3810 scope_block->peer_parent->base.id = ResultLocIdPeerParent;3815 scope_block->peer_parent->base.id = ResultLocIdPeerParent;
3811 scope_block->peer_parent->base.source_instruction = scope_block->is_comptime;3816 scope_block->peer_parent->base.source_instruction = scope_block->is_comptime;
3812 scope_block->peer_parent->end_bb = scope_block->end_block;3817 scope_block->peer_parent->end_bb = scope_block->end_block;
...@@ -3933,7 +3938,7 @@ static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -3933,7 +3938,7 @@ static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node)
3933 if (lvalue == irb->codegen->invalid_instruction)3938 if (lvalue == irb->codegen->invalid_instruction)
3934 return irb->codegen->invalid_instruction;3939 return irb->codegen->invalid_instruction;
39353940
3936 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);3941 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1, "ResultLocInstruction");
3937 result_loc_inst->base.id = ResultLocIdInstruction;3942 result_loc_inst->base.id = ResultLocIdInstruction;
3938 result_loc_inst->base.source_instruction = lvalue;3943 result_loc_inst->base.source_instruction = lvalue;
3939 ir_ref_instruction(lvalue, irb->current_basic_block);3944 ir_ref_instruction(lvalue, irb->current_basic_block);
...@@ -4005,10 +4010,10 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node...@@ -4005,10 +4010,10 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node
40054010
4006 ir_set_cursor_at_end_and_append_block(irb, true_block);4011 ir_set_cursor_at_end_and_append_block(irb, true_block);
40074012
4008 IrInstruction **incoming_values = allocate<IrInstruction *>(2);4013 IrInstruction **incoming_values = allocate<IrInstruction *>(2, "IrInstruction *");
4009 incoming_values[0] = val1;4014 incoming_values[0] = val1;
4010 incoming_values[1] = val2;4015 incoming_values[1] = val2;
4011 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);4016 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2, "IrBasicBlock *");
4012 incoming_blocks[0] = post_val1_block;4017 incoming_blocks[0] = post_val1_block;
4013 incoming_blocks[1] = post_val2_block;4018 incoming_blocks[1] = post_val2_block;
40144019
...@@ -8017,7 +8022,8 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A...@@ -8017,7 +8022,8 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A
8017 err_set_type->abi_size = irb->codegen->builtin_types.entry_global_error_set->abi_size;8022 err_set_type->abi_size = irb->codegen->builtin_types.entry_global_error_set->abi_size;
8018 err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(err_count);8023 err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(err_count);
80198024
8020 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(irb->codegen->errors_by_index.length + err_count);8025 size_t errors_count = irb->codegen->errors_by_index.length + err_count;
8026 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(errors_count, "ErrorTableEntry *");
80218027
8022 for (uint32_t i = 0; i < err_count; i += 1) {8028 for (uint32_t i = 0; i < err_count; i += 1) {
8023 AstNode *field_node = node->data.err_set_decl.decls.at(i);8029 AstNode *field_node = node->data.err_set_decl.decls.at(i);
...@@ -8048,7 +8054,7 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A...@@ -8048,7 +8054,7 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A
8048 }8054 }
8049 errors[err->value] = err;8055 errors[err->value] = err;
8050 }8056 }
8051 free(errors);8057 deallocate(errors, errors_count, "ErrorTableEntry *");
8052 return ir_build_const_type(irb, parent_scope, node, err_set_type);8058 return ir_build_const_type(irb, parent_scope, node, err_set_type);
8053}8059}
80548060
...@@ -9574,7 +9580,8 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp...@@ -9574,7 +9580,8 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
9574 if (type_is_global_error_set(set2)) {9580 if (type_is_global_error_set(set2)) {
9575 return set1;9581 return set1;
9576 }9582 }
9577 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);9583 size_t errors_count = ira->codegen->errors_by_index.length;
9584 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(errors_count, "ErrorTableEntry *");
9578 populate_error_set_table(errors, set1);9585 populate_error_set_table(errors, set1);
9579 ZigList<ErrorTableEntry *> intersection_list = {};9586 ZigList<ErrorTableEntry *> intersection_list = {};
95809587
...@@ -9595,7 +9602,7 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp...@@ -9595,7 +9602,7 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
9595 buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&existing_entry_with_docs->name));9602 buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&existing_entry_with_docs->name));
9596 }9603 }
9597 }9604 }
9598 free(errors);9605 deallocate(errors, errors_count, "ErrorTableEntry *");
95999606
9600 err_set_type->data.error_set.err_count = intersection_list.length;9607 err_set_type->data.error_set.err_count = intersection_list.length;
9601 err_set_type->data.error_set.errors = intersection_list.items;9608 err_set_type->data.error_set.errors = intersection_list.items;
...@@ -9792,7 +9799,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -9792,7 +9799,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9792 return result;9799 return result;
9793 }9800 }
97949801
9795 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(g->errors_by_index.length);9802 size_t errors_count = g->errors_by_index.length;
9803 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(errors_count, "ErrorTableEntry *");
9796 for (uint32_t i = 0; i < container_set->data.error_set.err_count; i += 1) {9804 for (uint32_t i = 0; i < container_set->data.error_set.err_count; i += 1) {
9797 ErrorTableEntry *error_entry = container_set->data.error_set.errors[i];9805 ErrorTableEntry *error_entry = container_set->data.error_set.errors[i];
9798 assert(errors[error_entry->value] == nullptr);9806 assert(errors[error_entry->value] == nullptr);
...@@ -9809,7 +9817,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -9809,7 +9817,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9809 result.data.error_set_mismatch->missing_errors.append(contained_error_entry);9817 result.data.error_set_mismatch->missing_errors.append(contained_error_entry);
9810 }9818 }
9811 }9819 }
9812 free(errors);9820 deallocate(errors, errors_count, "ErrorTableEntry *");
9813 return result;9821 return result;
9814 }9822 }
98159823
...@@ -10814,7 +10822,8 @@ static IrInstruction *ira_suspend(IrAnalyze *ira, IrInstruction *old_instruction...@@ -10814,7 +10822,8 @@ static IrInstruction *ira_suspend(IrAnalyze *ira, IrInstruction *old_instruction
10814 IrSuspendPosition *suspend_pos)10822 IrSuspendPosition *suspend_pos)
10815{10823{
10816 if (ira->codegen->verbose_ir) {10824 if (ira->codegen->verbose_ir) {
10817 fprintf(stderr, "suspend %s_%zu %s_%zu #%zu (%zu,%zu)\n", ira->old_irb.current_basic_block->name_hint,10825 fprintf(stderr, "suspend %s_%zu %s_%zu #%" PRIu32 " (%zu,%zu)\n",
10826 ira->old_irb.current_basic_block->name_hint,
10818 ira->old_irb.current_basic_block->debug_id,10827 ira->old_irb.current_basic_block->debug_id,
10819 ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->name_hint,10828 ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->name_hint,
10820 ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->debug_id,10829 ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->debug_id,
...@@ -10852,7 +10861,7 @@ static IrInstruction *ira_resume(IrAnalyze *ira) {...@@ -10852,7 +10861,7 @@ static IrInstruction *ira_resume(IrAnalyze *ira) {
10852 ira->instruction_index = pos.instruction_index;10861 ira->instruction_index = pos.instruction_index;
10853 assert(pos.instruction_index < ira->old_irb.current_basic_block->instruction_list.length);10862 assert(pos.instruction_index < ira->old_irb.current_basic_block->instruction_list.length);
10854 if (ira->codegen->verbose_ir) {10863 if (ira->codegen->verbose_ir) {
10855 fprintf(stderr, "%s_%zu #%zu\n", ira->old_irb.current_basic_block->name_hint,10864 fprintf(stderr, "%s_%zu #%" PRIu32 "\n", ira->old_irb.current_basic_block->name_hint,
10856 ira->old_irb.current_basic_block->debug_id,10865 ira->old_irb.current_basic_block->debug_id,
10857 ira->old_irb.current_basic_block->instruction_list.at(pos.instruction_index)->debug_id);10866 ira->old_irb.current_basic_block->instruction_list.at(pos.instruction_index)->debug_id);
10858 }10867 }
...@@ -14686,14 +14695,15 @@ static IrInstruction *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira,...@@ -14686,14 +14695,15 @@ static IrInstruction *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira,
14686 return ira->codegen->invalid_instruction;14695 return ira->codegen->invalid_instruction;
14687 }14696 }
1468814697
14689 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);14698 size_t errors_count = ira->codegen->errors_by_index.length;
14699 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(errors_count, "ErrorTableEntry *");
14690 for (uint32_t i = 0, count = op1_type->data.error_set.err_count; i < count; i += 1) {14700 for (uint32_t i = 0, count = op1_type->data.error_set.err_count; i < count; i += 1) {
14691 ErrorTableEntry *error_entry = op1_type->data.error_set.errors[i];14701 ErrorTableEntry *error_entry = op1_type->data.error_set.errors[i];
14692 assert(errors[error_entry->value] == nullptr);14702 assert(errors[error_entry->value] == nullptr);
14693 errors[error_entry->value] = error_entry;14703 errors[error_entry->value] = error_entry;
14694 }14704 }
14695 ZigType *result_type = get_error_set_union(ira->codegen, errors, op1_type, op2_type, instruction->type_name);14705 ZigType *result_type = get_error_set_union(ira->codegen, errors, op1_type, op2_type, instruction->type_name);
14696 free(errors);14706 deallocate(errors, errors_count, "ErrorTableEntry *");
1469714707
14698 return ir_const_type(ira, &instruction->base, result_type);14708 return ir_const_type(ira, &instruction->base, result_type);
14699}14709}
...@@ -24034,7 +24044,8 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,...@@ -24034,7 +24044,8 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
24034 return ira->codegen->invalid_instruction;24044 return ira->codegen->invalid_instruction;
24035 }24045 }
2403624046
24037 AstNode **field_prev_uses = allocate<AstNode *>(ira->codegen->errors_by_index.length);24047 size_t field_prev_uses_count = ira->codegen->errors_by_index.length;
24048 AstNode **field_prev_uses = allocate<AstNode *>(field_prev_uses_count, "AstNode *");
2403824049
24039 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {24050 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
24040 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];24051 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
...@@ -24091,7 +24102,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,...@@ -24091,7 +24102,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
24091 }24102 }
24092 }24103 }
2409324104
24094 free(field_prev_uses);24105 deallocate(field_prev_uses, field_prev_uses_count, "AstNode *");
24095 } else if (switch_type->id == ZigTypeIdInt) {24106 } else if (switch_type->id == ZigTypeIdInt) {
24096 RangeSet rs = {0};24107 RangeSet rs = {0};
24097 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {24108 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
...@@ -26318,7 +26329,7 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_...@@ -26318,7 +26329,7 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
26318 }26329 }
2631926330
26320 if (ira->codegen->verbose_ir) {26331 if (ira->codegen->verbose_ir) {
26321 fprintf(stderr, "analyze #%zu\n", old_instruction->debug_id);26332 fprintf(stderr, "analyze #%" PRIu32 "\n", old_instruction->debug_id);
26322 }26333 }
26323 IrInstruction *new_instruction = ir_analyze_instruction_base(ira, old_instruction);26334 IrInstruction *new_instruction = ir_analyze_instruction_base(ira, old_instruction);
26324 if (new_instruction != nullptr) {26335 if (new_instruction != nullptr) {
src/ir_print.cpp+6-6
...@@ -38,8 +38,8 @@ struct IrPrint {...@@ -38,8 +38,8 @@ struct IrPrint {
3838
39static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction);39static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction);
4040
41static const char* ir_instruction_type_str(IrInstruction* instruction) {41const char* ir_instruction_type_str(IrInstructionId id) {
42 switch (instruction->id) {42 switch (id) {
43 case IrInstructionIdInvalid:43 case IrInstructionIdInvalid:
44 return "Invalid";44 return "Invalid";
45 case IrInstructionIdShuffleVector:45 case IrInstructionIdShuffleVector:
...@@ -385,9 +385,9 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction, bool trail...@@ -385,9 +385,9 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction, bool trail
385 const char mark = trailing ? ':' : '#';385 const char mark = trailing ? ':' : '#';
386 const char *type_name = instruction->value.type ? buf_ptr(&instruction->value.type->name) : "(unknown)";386 const char *type_name = instruction->value.type ? buf_ptr(&instruction->value.type->name) : "(unknown)";
387 const char *ref_count = ir_has_side_effects(instruction) ?387 const char *ref_count = ir_has_side_effects(instruction) ?
388 "-" : buf_ptr(buf_sprintf("%" ZIG_PRI_usize "", instruction->ref_count));388 "-" : buf_ptr(buf_sprintf("%" PRIu32 "", instruction->ref_count));
389 fprintf(irp->f, "%c%-3zu| %-22s| %-12s| %-2s| ", mark, instruction->debug_id,389 fprintf(irp->f, "%c%-3" PRIu32 "| %-22s| %-12s| %-2s| ", mark, instruction->debug_id,
390 ir_instruction_type_str(instruction), type_name, ref_count);390 ir_instruction_type_str(instruction->id), type_name, ref_count);
391}391}
392392
393static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {393static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {
...@@ -398,7 +398,7 @@ static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {...@@ -398,7 +398,7 @@ static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {
398}398}
399399
400static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) {400static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) {
401 fprintf(irp->f, "#%" ZIG_PRI_usize "", instruction->debug_id);401 fprintf(irp->f, "#%" PRIu32 "", instruction->debug_id);
402 if (irp->pass != IrPassSrc && irp->printed.maybe_get(instruction) == nullptr) {402 if (irp->pass != IrPassSrc && irp->printed.maybe_get(instruction) == nullptr) {
403 irp->printed.put(instruction, 0);403 irp->printed.put(instruction, 0);
404 irp->pending.append(instruction);404 irp->pending.append(instruction);
src/ir_print.hpp+2
...@@ -15,4 +15,6 @@...@@ -15,4 +15,6 @@
15void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, IrPass pass);15void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, IrPass pass);
16void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, IrPass pass);16void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, IrPass pass);
1717
18const char* ir_instruction_type_str(IrInstructionId id);
19
18#endif20#endif
src/main.cpp+52-23
...@@ -64,6 +64,9 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -64,6 +64,9 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
64 " -fno-PIC disable Position Independent Code\n"64 " -fno-PIC disable Position Independent Code\n"
65 " -ftime-report print timing diagnostics\n"65 " -ftime-report print timing diagnostics\n"
66 " -fstack-report print stack size diagnostics\n"66 " -fstack-report print stack size diagnostics\n"
67#ifdef ZIG_ENABLE_MEM_PROFILE
68 " -fmem-report print memory usage diagnostics\n"
69#endif
67 " -fdump-analysis write analysis.json file with type information\n"70 " -fdump-analysis write analysis.json file with type information\n"
68 " -femit-docs create a docs/ dir with html documentation\n"71 " -femit-docs create a docs/ dir with html documentation\n"
69 " -fno-emit-bin skip emitting machine code\n"72 " -fno-emit-bin skip emitting machine code\n"
...@@ -306,9 +309,29 @@ static int zig_error_no_build_file(void) {...@@ -306,9 +309,29 @@ static int zig_error_no_build_file(void) {
306309
307extern "C" int ZigClang_main(int argc, char **argv);310extern "C" int ZigClang_main(int argc, char **argv);
308311
312#ifdef ZIG_ENABLE_MEM_PROFILE
313bool mem_report = false;
314#endif
315
316int main_exit(Stage2ProgressNode *root_progress_node, int exit_code) {
317 if (root_progress_node != nullptr) {
318 stage2_progress_end(root_progress_node);
319 }
320#ifdef ZIG_ENABLE_MEM_PROFILE
321 if (mem_report) {
322 memprof_dump_stats(stderr);
323 }
324#endif
325 return exit_code;
326}
327
309int main(int argc, char **argv) {328int main(int argc, char **argv) {
310 stage2_attach_segfault_handler();329 stage2_attach_segfault_handler();
311330
331#ifdef ZIG_ENABLE_MEM_PROFILE
332 memprof_init();
333#endif
334
312 char *arg0 = argv[0];335 char *arg0 = argv[0];
313 Error err;336 Error err;
314337
...@@ -670,6 +693,13 @@ int main(int argc, char **argv) {...@@ -670,6 +693,13 @@ int main(int argc, char **argv) {
670 timing_info = true;693 timing_info = true;
671 } else if (strcmp(arg, "-fstack-report") == 0) {694 } else if (strcmp(arg, "-fstack-report") == 0) {
672 stack_report = true;695 stack_report = true;
696 } else if (strcmp(arg, "-fmem-report") == 0) {
697#ifdef ZIG_ENABLE_MEM_PROFILE
698 mem_report = true;
699#else
700 fprintf(stderr, "-fmem-report requires configuring with -DZIG_ENABLE_MEM_PROFILE=ON\n");
701 return print_error_usage(arg0);
702#endif
673 } else if (strcmp(arg, "-fdump-analysis") == 0) {703 } else if (strcmp(arg, "-fdump-analysis") == 0) {
674 enable_dump_analysis = true;704 enable_dump_analysis = true;
675 } else if (strcmp(arg, "-femit-docs") == 0) {705 } else if (strcmp(arg, "-femit-docs") == 0) {
...@@ -1038,16 +1068,14 @@ int main(int argc, char **argv) {...@@ -1038,16 +1068,14 @@ int main(int argc, char **argv) {
1038 if (in_file) {1068 if (in_file) {
1039 ZigLibCInstallation libc;1069 ZigLibCInstallation libc;
1040 if ((err = zig_libc_parse(&libc, buf_create_from_str(in_file), &target, true)))1070 if ((err = zig_libc_parse(&libc, buf_create_from_str(in_file), &target, true)))
1041 return EXIT_FAILURE;1071 return main_exit(root_progress_node, EXIT_FAILURE);
1042 stage2_progress_end(root_progress_node);1072 return main_exit(root_progress_node, EXIT_SUCCESS);
1043 return EXIT_SUCCESS;
1044 }1073 }
1045 ZigLibCInstallation libc;1074 ZigLibCInstallation libc;
1046 if ((err = zig_libc_find_native(&libc, true)))1075 if ((err = zig_libc_find_native(&libc, true)))
1047 return EXIT_FAILURE;1076 return main_exit(root_progress_node, EXIT_FAILURE);
1048 zig_libc_render(&libc, stdout);1077 zig_libc_render(&libc, stdout);
1049 stage2_progress_end(root_progress_node);1078 return main_exit(root_progress_node, EXIT_SUCCESS);
1050 return EXIT_SUCCESS;
1051 }1079 }
1052 case CmdBuiltin: {1080 case CmdBuiltin: {
1053 CodeGen *g = codegen_create(main_pkg_path, nullptr, &target,1081 CodeGen *g = codegen_create(main_pkg_path, nullptr, &target,
...@@ -1065,10 +1093,9 @@ int main(int argc, char **argv) {...@@ -1065,10 +1093,9 @@ int main(int argc, char **argv) {
1065 Buf *builtin_source = codegen_generate_builtin_source(g);1093 Buf *builtin_source = codegen_generate_builtin_source(g);
1066 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {1094 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
1067 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));1095 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
1068 return EXIT_FAILURE;1096 return main_exit(root_progress_node, EXIT_FAILURE);
1069 }1097 }
1070 stage2_progress_end(root_progress_node);1098 return main_exit(root_progress_node, EXIT_SUCCESS);
1071 return EXIT_SUCCESS;
1072 }1099 }
1073 case CmdRun:1100 case CmdRun:
1074 case CmdBuild:1101 case CmdBuild:
...@@ -1142,7 +1169,7 @@ int main(int argc, char **argv) {...@@ -1142,7 +1169,7 @@ int main(int argc, char **argv) {
1142 libc = allocate<ZigLibCInstallation>(1);1169 libc = allocate<ZigLibCInstallation>(1);
1143 if ((err = zig_libc_parse(libc, buf_create_from_str(libc_txt), &target, true))) {1170 if ((err = zig_libc_parse(libc, buf_create_from_str(libc_txt), &target, true))) {
1144 fprintf(stderr, "Unable to parse --libc text file: %s\n", err_str(err));1171 fprintf(stderr, "Unable to parse --libc text file: %s\n", err_str(err));
1145 return EXIT_FAILURE;1172 return main_exit(root_progress_node, EXIT_FAILURE);
1146 }1173 }
1147 }1174 }
1148 Buf *cache_dir_buf;1175 Buf *cache_dir_buf;
...@@ -1219,7 +1246,7 @@ int main(int argc, char **argv) {...@@ -1219,7 +1246,7 @@ int main(int argc, char **argv) {
1219 codegen_set_rdynamic(g, rdynamic);1246 codegen_set_rdynamic(g, rdynamic);
1220 if (mmacosx_version_min && mios_version_min) {1247 if (mmacosx_version_min && mios_version_min) {
1221 fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n");1248 fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n");
1222 return EXIT_FAILURE;1249 return main_exit(root_progress_node, EXIT_FAILURE);
1223 }1250 }
12241251
1225 if (mmacosx_version_min) {1252 if (mmacosx_version_min) {
...@@ -1259,6 +1286,11 @@ int main(int argc, char **argv) {...@@ -1259,6 +1286,11 @@ int main(int argc, char **argv) {
1259 zig_print_stack_report(g, stdout);1286 zig_print_stack_report(g, stdout);
12601287
1261 if (cmd == CmdRun) {1288 if (cmd == CmdRun) {
1289 stage2_progress_end(root_progress_node);
1290#ifdef ZIG_ENABLE_MEM_PROFILE
1291 memprof_dump_stats(stderr);
1292#endif
1293
1262 const char *exec_path = buf_ptr(&g->output_file_path);1294 const char *exec_path = buf_ptr(&g->output_file_path);
1263 ZigList<const char*> args = {0};1295 ZigList<const char*> args = {0};
12641296
...@@ -1282,10 +1314,9 @@ int main(int argc, char **argv) {...@@ -1282,10 +1314,9 @@ int main(int argc, char **argv) {
1282 buf_replace(&g->output_file_path, '/', '\\');1314 buf_replace(&g->output_file_path, '/', '\\');
1283#endif1315#endif
1284 if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0)1316 if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0)
1285 return EXIT_FAILURE;1317 return main_exit(root_progress_node, EXIT_FAILURE);
1286 }1318 }
1287 stage2_progress_end(root_progress_node);1319 return main_exit(root_progress_node, EXIT_SUCCESS);
1288 return EXIT_SUCCESS;
1289 } else {1320 } else {
1290 zig_unreachable();1321 zig_unreachable();
1291 }1322 }
...@@ -1293,8 +1324,7 @@ int main(int argc, char **argv) {...@@ -1293,8 +1324,7 @@ int main(int argc, char **argv) {
1293 codegen_translate_c(g, in_file_buf, stdout, cmd == CmdTranslateCUserland);1324 codegen_translate_c(g, in_file_buf, stdout, cmd == CmdTranslateCUserland);
1294 if (timing_info)1325 if (timing_info)
1295 codegen_print_timing_report(g, stderr);1326 codegen_print_timing_report(g, stderr);
1296 stage2_progress_end(root_progress_node);1327 return main_exit(root_progress_node, EXIT_SUCCESS);
1297 return EXIT_SUCCESS;
1298 } else if (cmd == CmdTest) {1328 } else if (cmd == CmdTest) {
1299 codegen_set_emit_file_type(g, emit_file_type);1329 codegen_set_emit_file_type(g, emit_file_type);
13001330
...@@ -1314,7 +1344,7 @@ int main(int argc, char **argv) {...@@ -1314,7 +1344,7 @@ int main(int argc, char **argv) {
13141344
1315 if (g->disable_bin_generation) {1345 if (g->disable_bin_generation) {
1316 fprintf(stderr, "Semantic analysis complete. No binary produced due to -fno-emit-bin.\n");1346 fprintf(stderr, "Semantic analysis complete. No binary produced due to -fno-emit-bin.\n");
1317 return 0;1347 return main_exit(root_progress_node, EXIT_SUCCESS);
1318 }1348 }
13191349
1320 Buf *test_exe_path_unresolved = &g->output_file_path;1350 Buf *test_exe_path_unresolved = &g->output_file_path;
...@@ -1324,7 +1354,7 @@ int main(int argc, char **argv) {...@@ -1324,7 +1354,7 @@ int main(int argc, char **argv) {
1324 if (emit_file_type != EmitFileTypeBinary) {1354 if (emit_file_type != EmitFileTypeBinary) {
1325 fprintf(stderr, "Created %s but skipping execution because it is non executable.\n",1355 fprintf(stderr, "Created %s but skipping execution because it is non executable.\n",
1326 buf_ptr(test_exe_path));1356 buf_ptr(test_exe_path));
1327 return 0;1357 return main_exit(root_progress_node, EXIT_SUCCESS);
1328 }1358 }
13291359
1330 for (size_t i = 0; i < test_exec_args.length; i += 1) {1360 for (size_t i = 0; i < test_exec_args.length; i += 1) {
...@@ -1336,7 +1366,7 @@ int main(int argc, char **argv) {...@@ -1336,7 +1366,7 @@ int main(int argc, char **argv) {
1336 if (!target_can_exec(&native, &target) && test_exec_args.length == 0) {1366 if (!target_can_exec(&native, &target) && test_exec_args.length == 0) {
1337 fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",1367 fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",
1338 buf_ptr(test_exe_path));1368 buf_ptr(test_exe_path));
1339 return 0;1369 return main_exit(root_progress_node, EXIT_SUCCESS);
1340 }1370 }
13411371
1342 Termination term;1372 Termination term;
...@@ -1348,21 +1378,20 @@ int main(int argc, char **argv) {...@@ -1348,21 +1378,20 @@ int main(int argc, char **argv) {
1348 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");1378 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");
1349 fprintf(stderr, "%s\n", buf_ptr(test_exe_path));1379 fprintf(stderr, "%s\n", buf_ptr(test_exe_path));
1350 }1380 }
1351 stage2_progress_end(root_progress_node);1381 return main_exit(root_progress_node, (term.how == TerminationIdClean) ? term.code : -1);
1352 return (term.how == TerminationIdClean) ? term.code : -1;
1353 } else {1382 } else {
1354 zig_unreachable();1383 zig_unreachable();
1355 }1384 }
1356 }1385 }
1357 case CmdVersion:1386 case CmdVersion:
1358 printf("%s\n", ZIG_VERSION_STRING);1387 printf("%s\n", ZIG_VERSION_STRING);
1359 return EXIT_SUCCESS;1388 return main_exit(root_progress_node, EXIT_SUCCESS);
1360 case CmdZen: {1389 case CmdZen: {
1361 const char *ptr;1390 const char *ptr;
1362 size_t len;1391 size_t len;
1363 stage2_zen(&ptr, &len);1392 stage2_zen(&ptr, &len);
1364 fwrite(ptr, len, 1, stdout);1393 fwrite(ptr, len, 1, stdout);
1365 return EXIT_SUCCESS;1394 return main_exit(root_progress_node, EXIT_SUCCESS);
1366 }1395 }
1367 case CmdTargets:1396 case CmdTargets:
1368 return print_target_list(stdout);1397 return print_target_list(stdout);
src/memory_profiling.cpp created+139
...@@ -0,0 +1,139 @@
1#include "memory_profiling.hpp"
2#include "hash_map.hpp"
3#include "list.hpp"
4#include "util.hpp"
5#include <string.h>
6
7#ifdef ZIG_ENABLE_MEM_PROFILE
8
9static bool str_eql_str(const char *a, const char *b) {
10 return strcmp(a, b) == 0;
11}
12
13static uint32_t str_hash(const char *s) {
14 // FNV 32-bit hash
15 uint32_t h = 2166136261;
16 for (; *s; s += 1) {
17 h = h ^ *s;
18 h = h * 16777619;
19 }
20 return h;
21}
22
23struct CountAndSize {
24 size_t item_count;
25 size_t type_size;
26};
27
28ZigList<const char *> unknown_names = {};
29HashMap<const char *, CountAndSize, str_hash, str_eql_str> usage_table = {};
30bool table_active = false;
31
32
33static const char *get_default_name(const char *name_or_null, size_t type_size) {
34 if (name_or_null != nullptr) return name_or_null;
35 if (type_size >= unknown_names.length) {
36 table_active = false;
37 unknown_names.resize(type_size + 1);
38 table_active = true;
39 }
40 if (unknown_names.at(type_size) == nullptr) {
41 char buf[100];
42 sprintf(buf, "Unknown_%zu%c", type_size, 0);
43 unknown_names.at(type_size) = strdup(buf);
44 }
45 return unknown_names.at(type_size);
46}
47
48void memprof_alloc(const char *name, size_t count, size_t type_size) {
49 if (!table_active) return;
50 if (count == 0) return;
51 // temporarily disable during table put
52 table_active = false;
53 name = get_default_name(name, type_size);
54 auto existing_entry = usage_table.put_unique(name, {count, type_size});
55 if (existing_entry != nullptr) {
56 assert(existing_entry->value.type_size == type_size); // allocated name does not match type
57 existing_entry->value.item_count += count;
58 }
59 table_active = true;
60}
61
62void memprof_dealloc(const char *name, size_t count, size_t type_size) {
63 if (!table_active) return;
64 if (count == 0) return;
65 name = get_default_name(name, type_size);
66 auto existing_entry = usage_table.maybe_get(name);
67 if (existing_entry == nullptr) {
68 zig_panic("deallocated more than allocated; compromised memory usage stats");
69 }
70 if (existing_entry->value.type_size != type_size) {
71 zig_panic("deallocated name '%s' does not match expected type size %zu", name, type_size);
72 }
73 existing_entry->value.item_count -= count;
74}
75
76void memprof_init(void) {
77 usage_table.init(1024);
78 table_active = true;
79}
80
81struct MemItem {
82 const char *type_name;
83 CountAndSize count_and_size;
84};
85
86static size_t get_bytes(const MemItem *item) {
87 return item->count_and_size.item_count * item->count_and_size.type_size;
88}
89
90static int compare_bytes_desc(const void *a, const void *b) {
91 size_t size_a = get_bytes((const MemItem *)(a));
92 size_t size_b = get_bytes((const MemItem *)(b));
93 if (size_a > size_b)
94 return -1;
95 if (size_a < size_b)
96 return 1;
97 return 0;
98}
99
100void memprof_dump_stats(FILE *file) {
101 assert(table_active);
102 // disable modifications from this function
103 table_active = false;
104
105 ZigList<MemItem> list = {};
106
107 auto it = usage_table.entry_iterator();
108 for (;;) {
109 auto *entry = it.next();
110 if (!entry)
111 break;
112
113 list.append({entry->key, entry->value});
114 }
115
116 qsort(list.items, list.length, sizeof(MemItem), compare_bytes_desc);
117
118 size_t total_bytes_used = 0;
119
120 for (size_t i = 0; i < list.length; i += 1) {
121 const MemItem *item = &list.at(i);
122 fprintf(file, "%s: %zu items, %zu bytes each, total ", item->type_name,
123 item->count_and_size.item_count, item->count_and_size.type_size);
124 size_t bytes = get_bytes(item);
125 zig_pretty_print_bytes(file, bytes);
126 fprintf(file, "\n");
127
128 total_bytes_used += bytes;
129 }
130
131 fprintf(stderr, "Total bytes used: ");
132 zig_pretty_print_bytes(file, total_bytes_used);
133 fprintf(file, "\n");
134
135 list.deinit();
136 table_active = true;
137}
138
139#endif
src/memory_profiling.hpp created+22
...@@ -0,0 +1,22 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_MEMORY_PROFILING_HPP
9#define ZIG_MEMORY_PROFILING_HPP
10
11#include "config.h"
12
13#include <stddef.h>
14#include <stdio.h>
15
16void memprof_init(void);
17
18void memprof_alloc(const char *name, size_t item_count, size_t type_size);
19void memprof_dealloc(const char *name, size_t item_count, size_t type_size);
20
21void memprof_dump_stats(FILE *file);
22#endif
src/util.cpp+18
...@@ -119,3 +119,21 @@ Slice<uint8_t> SplitIterator_rest(SplitIterator *self) {...@@ -119,3 +119,21 @@ Slice<uint8_t> SplitIterator_rest(SplitIterator *self) {
119SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes) {119SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes) {
120 return SplitIterator{0, buffer, split_bytes};120 return SplitIterator{0, buffer, split_bytes};
121}121}
122
123void zig_pretty_print_bytes(FILE *f, double n) {
124 if (n > 1024.0 * 1024.0 * 1024.0) {
125 fprintf(f, "%.02f GiB", n / 1024.0 / 1024.0 / 1024.0);
126 return;
127 }
128 if (n > 1024.0 * 1024.0) {
129 fprintf(f, "%.02f MiB", n / 1024.0 / 1024.0);
130 return;
131 }
132 if (n > 1024.0) {
133 fprintf(f, "%.02f KiB", n / 1024.0);
134 return;
135 }
136 fprintf(f, "%.02f bytes", n );
137 return;
138}
139
src/util.hpp+31-4
...@@ -8,6 +8,8 @@...@@ -8,6 +8,8 @@
8#ifndef ZIG_UTIL_HPP8#ifndef ZIG_UTIL_HPP
9#define ZIG_UTIL_HPP9#define ZIG_UTIL_HPP
1010
11#include "memory_profiling.hpp"
12
11#include <stdlib.h>13#include <stdlib.h>
12#include <stdint.h>14#include <stdint.h>
13#include <string.h>15#include <string.h>
...@@ -96,7 +98,10 @@ static inline int ctzll(unsigned long long mask) {...@@ -96,7 +98,10 @@ static inline int ctzll(unsigned long long mask) {
9698
9799
98template<typename T>100template<typename T>
99ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) {101ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count, const char *name = nullptr) {
102#ifdef ZIG_ENABLE_MEM_PROFILE
103 memprof_alloc(name, count, sizeof(T));
104#endif
100#ifndef NDEBUG105#ifndef NDEBUG
101 // make behavior when size == 0 portable106 // make behavior when size == 0 portable
102 if (count == 0)107 if (count == 0)
...@@ -109,7 +114,10 @@ ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) {...@@ -109,7 +114,10 @@ ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) {
109}114}
110115
111template<typename T>116template<typename T>
112ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count) {117ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count, const char *name = nullptr) {
118#ifdef ZIG_ENABLE_MEM_PROFILE
119 memprof_alloc(name, count, sizeof(T));
120#endif
113#ifndef NDEBUG121#ifndef NDEBUG
114 // make behavior when size == 0 portable122 // make behavior when size == 0 portable
115 if (count == 0)123 if (count == 0)
...@@ -122,7 +130,7 @@ ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count) {...@@ -122,7 +130,7 @@ ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count) {
122}130}
123131
124template<typename T>132template<typename T>
125static inline T *reallocate(T *old, size_t old_count, size_t new_count) {133static inline T *reallocate(T *old, size_t old_count, size_t new_count, const char *name = nullptr) {
126 T *ptr = reallocate_nonzero(old, old_count, new_count);134 T *ptr = reallocate_nonzero(old, old_count, new_count);
127 if (new_count > old_count) {135 if (new_count > old_count) {
128 memset(&ptr[old_count], 0, (new_count - old_count) * sizeof(T));136 memset(&ptr[old_count], 0, (new_count - old_count) * sizeof(T));
...@@ -131,7 +139,11 @@ static inline T *reallocate(T *old, size_t old_count, size_t new_count) {...@@ -131,7 +139,11 @@ static inline T *reallocate(T *old, size_t old_count, size_t new_count) {
131}139}
132140
133template<typename T>141template<typename T>
134static inline T *reallocate_nonzero(T *old, size_t old_count, size_t new_count) {142static inline T *reallocate_nonzero(T *old, size_t old_count, size_t new_count, const char *name = nullptr) {
143#ifdef ZIG_ENABLE_MEM_PROFILE
144 memprof_dealloc(name, old_count, sizeof(T));
145 memprof_alloc(name, new_count, sizeof(T));
146#endif
135#ifndef NDEBUG147#ifndef NDEBUG
136 // make behavior when size == 0 portable148 // make behavior when size == 0 portable
137 if (new_count == 0 && old == nullptr)149 if (new_count == 0 && old == nullptr)
...@@ -143,6 +155,19 @@ static inline T *reallocate_nonzero(T *old, size_t old_count, size_t new_count)...@@ -143,6 +155,19 @@ static inline T *reallocate_nonzero(T *old, size_t old_count, size_t new_count)
143 return ptr;155 return ptr;
144}156}
145157
158template<typename T>
159static inline void deallocate(T *old, size_t count, const char *name = nullptr) {
160#ifdef ZIG_ENABLE_MEM_PROFILE
161 memprof_dealloc(name, count, sizeof(T));
162#endif
163 free(old);
164}
165
166template<typename T>
167static inline void destroy(T *old, const char *name = nullptr) {
168 return deallocate(old, 1);
169}
170
146template <typename T, size_t n>171template <typename T, size_t n>
147constexpr size_t array_length(const T (&)[n]) {172constexpr size_t array_length(const T (&)[n]) {
148 return n;173 return n;
...@@ -225,6 +250,8 @@ static inline double zig_f16_to_double(float16_t x) {...@@ -225,6 +250,8 @@ static inline double zig_f16_to_double(float16_t x) {
225 return z;250 return z;
226}251}
227252
253void zig_pretty_print_bytes(FILE *f, double n);
254
228template<typename T>255template<typename T>
229struct Optional {256struct Optional {
230 T value;257 T value;