aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp3
-rw-r--r--src/analyze.cpp23
-rw-r--r--src/main.cpp12
-rw-r--r--src/stack_report.cpp121
-rw-r--r--src/stack_report.hpp16
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