diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/all_types.hpp | 3 | ||||
| -rw-r--r-- | src/analyze.cpp | 23 | ||||
| -rw-r--r-- | src/main.cpp | 12 | ||||
| -rw-r--r-- | src/stack_report.cpp | 121 | ||||
| -rw-r--r-- | src/stack_report.hpp | 16 |
5 files changed, 166 insertions, 9 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index 2f3f56f0ed..60b292662d 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1972,6 +1972,8 @@ struct CodeGen { ZigFn *panic_fn; TldFn *panic_tld_fn; + ZigFn *largest_frame_fn; + WantPIC want_pic; WantStackCheck want_stack_check; CacheHash cache_hash; @@ -2004,6 +2006,7 @@ struct CodeGen { bool generate_error_name_table; bool enable_cache; // mutually exclusive with output_dir bool enable_time_report; + bool enable_stack_report; bool system_linker_hack; bool reported_bad_link_libc_error; bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl. diff --git a/src/analyze.cpp b/src/analyze.cpp index b845dc8388..4347f06699 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5737,11 +5737,19 @@ static void mark_suspension_point(Scope *scope) { return; case ScopeIdVarDecl: case ScopeIdDefer: + case ScopeIdBlock: looking_for_exprs = false; continue; - case ScopeIdLoop: case ScopeIdRuntime: continue; + case ScopeIdLoop: { + ScopeLoop *loop_scope = reinterpret_cast<ScopeLoop *>(scope); + if (loop_scope->spill_scope != nullptr) { + loop_scope->spill_scope->need_spill = MemoizedBoolTrue; + } + looking_for_exprs = false; + continue; + } case ScopeIdExpr: { if (!looking_for_exprs) { // Now we're only looking for a block, to see if it's in a loop (see the case ScopeIdBlock) @@ -5758,14 +5766,6 @@ static void mark_suspension_point(Scope *scope) { child_expr_scope = parent_expr_scope; continue; } - case ScopeIdBlock: - if (scope->parent->parent->id == ScopeIdLoop) { - ScopeLoop *loop_scope = reinterpret_cast<ScopeLoop *>(scope->parent->parent); - if (loop_scope->spill_scope != nullptr) { - loop_scope->spill_scope->need_spill = MemoizedBoolTrue; - } - } - return; } } } @@ -6082,6 +6082,11 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size; frame_type->abi_align = frame_type->data.frame.locals_struct->abi_align; frame_type->size_in_bits = frame_type->data.frame.locals_struct->size_in_bits; + + if (g->largest_frame_fn == nullptr || frame_type->abi_size > g->largest_frame_fn->frame_type->abi_size) { + g->largest_frame_fn = fn; + } + return ErrorNone; } diff --git a/src/main.cpp b/src/main.cpp index 9e8f2b7d4f..006d62dfa9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,7 @@ #include "libc_installation.hpp" #include "userland.h" #include "glibc.hpp" +#include "stack_report.hpp" #include <stdio.h> @@ -62,6 +63,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " -fPIC enable Position Independent Code\n" " -fno-PIC disable Position Independent Code\n" " -ftime-report print timing diagnostics\n" + " -fstack-report print stack size diagnostics\n" " --libc [file] Provide a file which specifies libc paths\n" " --name [name] override output name\n" " --output-dir [dir] override output directory (defaults to cwd)\n" @@ -476,6 +478,7 @@ int main(int argc, char **argv) { size_t ver_minor = 0; size_t ver_patch = 0; bool timing_info = false; + bool stack_report = false; const char *cache_dir = nullptr; CliPkg *cur_pkg = allocate<CliPkg>(1); BuildMode build_mode = BuildModeDebug; @@ -664,6 +667,8 @@ int main(int argc, char **argv) { each_lib_rpath = true; } else if (strcmp(arg, "-ftime-report") == 0) { timing_info = true; + } else if (strcmp(arg, "-fstack-report") == 0) { + stack_report = true; } else if (strcmp(arg, "--enable-valgrind") == 0) { valgrind_support = ValgrindSupportEnabled; } else if (strcmp(arg, "--disable-valgrind") == 0) { @@ -1136,6 +1141,7 @@ int main(int argc, char **argv) { g->subsystem = subsystem; g->enable_time_report = timing_info; + g->enable_stack_report = stack_report; codegen_set_out_name(g, buf_out_name); codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); g->want_single_threaded = want_single_threaded; @@ -1223,6 +1229,8 @@ int main(int argc, char **argv) { codegen_build_and_link(g); if (timing_info) codegen_print_timing_report(g, stdout); + if (stack_report) + zig_print_stack_report(g, stdout); if (cmd == CmdRun) { const char *exec_path = buf_ptr(&g->output_file_path); @@ -1272,6 +1280,10 @@ int main(int argc, char **argv) { codegen_print_timing_report(g, stdout); } + if (stack_report) { + zig_print_stack_report(g, stdout); + } + Buf *test_exe_path_unresolved = &g->output_file_path; Buf *test_exe_path = buf_alloc(); *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1); diff --git a/src/stack_report.cpp b/src/stack_report.cpp new file mode 100644 index 0000000000..3a0abd6cef --- /dev/null +++ b/src/stack_report.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2019 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#include "stack_report.hpp" + +static void tree_print(FILE *f, ZigType *ty, size_t indent); + +static void pretty_print_bytes(FILE *f, double n) { + if (n > 1024.0 * 1024.0 * 1024.0) { + fprintf(f, "%.02f GiB", n / 1024.0 / 1024.0 / 1024.0); + return; + } + if (n > 1024.0 * 1024.0) { + fprintf(f, "%.02f MiB", n / 1024.0 / 1024.0); + return; + } + if (n > 1024.0) { + fprintf(f, "%.02f KiB", n / 1024.0); + return; + } + fprintf(f, "%.02f bytes", n ); + return; +} + +static int compare_type_abi_sizes_desc(const void *a, const void *b) { + uint64_t size_a = (*(ZigType * const*)(a))->abi_size; + uint64_t size_b = (*(ZigType * const*)(b))->abi_size; + if (size_a > size_b) + return -1; + if (size_a < size_b) + return 1; + return 0; +} + +static void start_child(FILE *f, size_t indent) { + fprintf(f, "\n"); + for (size_t i = 0; i < indent; i += 1) { + fprintf(f, " "); + } +} + +static void start_peer(FILE *f, size_t indent) { + fprintf(f, ",\n"); + for (size_t i = 0; i < indent; i += 1) { + fprintf(f, " "); + } +} + +static void tree_print_struct(FILE *f, ZigType *struct_type, size_t indent) { + ZigList<ZigType *> children = {}; + uint64_t sum_from_fields = 0; + for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { + TypeStructField *field = &struct_type->data.structure.fields[i]; + children.append(field->type_entry); + sum_from_fields += field->type_entry->abi_size; + } + qsort(children.items, children.length, sizeof(ZigType *), compare_type_abi_sizes_desc); + + start_peer(f, indent); + fprintf(f, "\"padding\": \"%" ZIG_PRI_u64 "\"", struct_type->abi_size - sum_from_fields); + + start_peer(f, indent); + fprintf(f, "\"fields\": ["); + + for (size_t i = 0; i < children.length; i += 1) { + if (i == 0) { + start_child(f, indent + 1); + } else { + start_peer(f, indent + 1); + } + fprintf(f, "{"); + + ZigType *child_type = children.at(i); + tree_print(f, child_type, indent + 2); + + start_child(f, indent + 1); + fprintf(f, "}"); + } + + start_child(f, indent); + fprintf(f, "]"); +} + +static void tree_print(FILE *f, ZigType *ty, size_t indent) { + start_child(f, indent); + fprintf(f, "\"type\": \"%s\"", buf_ptr(&ty->name)); + + start_peer(f, indent); + fprintf(f, "\"sizef\": \""); + pretty_print_bytes(f, ty->abi_size); + fprintf(f, "\""); + + start_peer(f, indent); + fprintf(f, "\"size\": \"%" ZIG_PRI_u64 "\"", ty->abi_size); + + switch (ty->id) { + case ZigTypeIdFnFrame: + return tree_print_struct(f, ty->data.frame.locals_struct, indent); + case ZigTypeIdStruct: + return tree_print_struct(f, ty, indent); + default: + start_child(f, indent); + return; + } +} + +void zig_print_stack_report(CodeGen *g, FILE *f) { + if (g->largest_frame_fn == nullptr) { + fprintf(f, "{\"error\": \"No async function frames in entire compilation.\"}\n"); + return; + } + fprintf(f, "{"); + tree_print(f, g->largest_frame_fn->frame_type, 1); + + start_child(f, 0); + fprintf(f, "}\n"); +} diff --git a/src/stack_report.hpp b/src/stack_report.hpp new file mode 100644 index 0000000000..8a644466f9 --- /dev/null +++ b/src/stack_report.hpp @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2019 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_STACK_REPORT_HPP +#define ZIG_STACK_REPORT_HPP + +#include "all_types.hpp" +#include <stdio.h> + +void zig_print_stack_report(CodeGen *g, FILE *f); + +#endif |
