Cthulhu  0.2.10
Cthulhu compiler collection
panic.cpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-3.0-only
2 #include "stdafx.hpp"
3 
4 #include "editor/panic.hpp"
5 
6 #include "backtrace/backtrace.h"
7 
9 #include "memory/memory.h"
10 #include "std/str.h"
11 
12 using namespace ed;
13 
14 static std::jmp_buf gPanicEnv = {};
15 static ed::PanicInfo gPanicInfo = {};
16 
18 {
19  gPanicHandler = [](source_info_t location, const char *fmt, va_list args) {
20  gPanicInfo.capture_trace(location, fmt, args);
21  std::longjmp(gPanicEnv, 1); // NOLINT
22  };
23 }
24 
26 {
27  if (std::setjmp(gPanicEnv)) // NOLINT
28  {
29  CompileError error = {
31  .panic = gPanicInfo,
32  };
33 
34  gPanicInfo.reset();
35  return error;
36  }
37 
38  info.init();
39 
40  if (!info.check_reports())
41  {
42  CompileError error = {
44  };
45  return error;
46  }
47 
48 #if 0
49  for (size_t i = 0; i < info.sources.count(); i++)
50  {
51  char *message = info.parse_source(i);
52  if (message)
53  {
54  CompileError error = {
56  .error = message,
57  };
58  return error;
59  }
60  }
61 #endif
62  if (!info.check_reports())
63  {
64  CompileError error = {
66  };
67  return error;
68  }
69 
70  for (size_t stage = 0; stage < ePassCount; stage++)
71  {
72  broker_run_pass(info.broker, broker_pass_t(stage));
73  if (!info.check_reports())
74  {
75  CompileError error = {
77  };
78  return error;
79  }
80  }
81 
82  broker_resolve(info.broker);
83  if (!info.check_reports())
84  {
85  CompileError error = {
87  };
88  return error;
89  }
90 
91  CompileError error = {
92  .code = eCompileOk,
93  };
94  return error;
95 }
96 
98 {
99  bt_symbol_t symbol = {};
100  PanicInfo *info = nullptr;
101 };
102 
103 static void trace_callback(bt_address_t frame, void *user)
104 {
105  auto& [symbol, info] = *reinterpret_cast<trace_capture_t*>(user);
106 
107  bt_resolve_symbol(frame, &symbol);
108 
109  text_t path = symbol.path;
110  text_t name = symbol.name;
111 
112  stack_frame_t stack_frame = {
113  .address = frame,
114  .line = symbol.line,
115  .symbol = std::string(name.text, name.length),
116  .file = std::string(path.text, path.length),
117  };
118 
119  info->frames.push_back(stack_frame);
120 }
121 
122 void PanicInfo::capture_trace(source_info_t location, const char *fmt, va_list args)
123 {
124  arena_t *arena = get_global_arena();
125  trace_capture_t capture = {
126  .info = this,
127  };
128 
129  frames.clear();
130  frames.reserve(64);
131 
132  bt_read(trace_callback, &capture);
133 
134  info = location;
135  message = str_vformat(arena, fmt, args);
136  has_error = true;
137 }
138 
140 {
141  has_error = false;
142  info = {};
143  message.clear();
144  frames.clear();
145 }
146 
147 static const ImGuiTableFlags kTableFlags
148  = ImGuiTableFlags_BordersV
149  | ImGuiTableFlags_BordersOuterH
150  | ImGuiTableFlags_Resizable
151  | ImGuiTableFlags_RowBg
152  | ImGuiTableFlags_NoHostExtendX
153  | ImGuiTableFlags_NoBordersInBody
154  | ImGuiTableFlags_SizingStretchProp;
155 
157 {
158  if (ImGui::BeginTable("Backtrace", 4, kTableFlags))
159  {
160  ImGui::TableSetupColumn("Address", ImGuiTableColumnFlags_WidthFixed, 150.0f);
161  ImGui::TableSetupColumn("Symbol");
162  ImGui::TableSetupColumn("File");
163  ImGui::TableSetupColumn("Line");
164 
165  ImGui::TableHeadersRow();
166 
167  for (const stack_frame_t& frame : frames)
168  {
169  ImGui::TableNextRow();
170 
171  ImGui::TableNextColumn();
172  ImGui::Text("0x%p", reinterpret_cast<void*>(frame.address));
173 
174  ImGui::TableNextColumn();
175  ImGui::Text("%s", frame.symbol.c_str());
176 
177  ImGui::TableNextColumn();
178  ImGui::Text("%s", frame.file.c_str());
179 
180  ImGui::TableNextColumn();
181  ImGui::Text("%zu", frame.line);
182  }
183 
184  ImGui::EndTable();
185  }
186 }
broker_t * broker
Definition: compile.hpp:24
bool check_reports() const
check if there are any reports
Definition: compile.cpp:87
void init()
Definition: compile.cpp:75
char * parse_source(size_t index)
parse a source file
Definition: compile.cpp:43
compile_code_t code
Definition: panic.hpp:54
std::vector< stack_frame_t > frames
Definition: panic.hpp:31
std::string message
Definition: panic.hpp:30
void reset()
Definition: panic.cpp:139
source_info_t info
Definition: panic.hpp:29
void draw()
Definition: panic.cpp:156
bool has_error
Definition: panic.hpp:27
void capture_trace(source_info_t location, const char *fmt, va_list args)
Definition: panic.cpp:122
uint_least64_t bt_address_t
an address of a symbol
Definition: backtrace.h:26
CT_BACKTRACE_API bt_resolve_t bt_resolve_symbol(bt_address_t frame, bt_symbol_t *symbol)
resolve a frame to a symbol
Definition: common.c:14
CT_BACKTRACE_API void bt_read(bt_trace_t callback, void *user)
get a backtrace from the current location using a callback
Definition: common.c:35
CT_BROKER_API void broker_run_pass(broker_t *broker, broker_pass_t pass)
Definition: broker.c:419
broker_pass_t
Definition: broker.h:56
CT_BROKER_API void broker_resolve(broker_t *broker)
Definition: broker.c:450
@ ePassCount
Definition: broker.h:60
CT_MEMORY_API arena_t * get_global_arena(void)
get the global memory arena
Definition: memory.c:16
CT_BASE_API panic_handler_t gPanicHandler
the global panic handler.
Definition: panic.c:5
CT_NODISCARD STA_FORMAT_STRING const char * fmt
Definition: str.h:68
CT_NODISCARD STA_FORMAT_STRING const char CT_NODISCARD CT_STD_API char * str_vformat(arena_t *arena, const char *fmt, va_list args)
format a string
Definition: str.c:110
Definition: compile.hpp:13
void install_panic_handler()
Definition: panic.cpp:17
@ eCompilePanic
Definition: panic.hpp:44
@ eCompileOk
Definition: panic.hpp:42
@ eCompileError
Definition: panic.hpp:43
CompileError run_compile(Broker &info)
Definition: panic.cpp:25
an allocator object
Definition: arena.h:86
a symbol
Definition: backtrace.h:33
bt_address_t address
Definition: panic.hpp:18
panic location information
Definition: source_info.h:26
a range of text
Definition: text.h:14
size_t length
the number of characters in the text
Definition: text.h:19
PanicInfo * info
Definition: panic.cpp:100