Illegal instruction handler
This commit is contained in:
parent
e5fccefec0
commit
0545282292
5 changed files with 294 additions and 252 deletions
252
main.odin
252
main.odin
|
|
@ -1,252 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import rl "libraries/raylib"
|
|
||||||
import "core:log"
|
|
||||||
|
|
||||||
import "libraries/back"
|
|
||||||
import "core:mem"
|
|
||||||
import "core:c"
|
|
||||||
import "base:intrinsics"
|
|
||||||
import "base:runtime"
|
|
||||||
import "core:strings"
|
|
||||||
import "core:fmt"
|
|
||||||
|
|
||||||
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
|
||||||
@(private="file") web_context: runtime.Context
|
|
||||||
|
|
||||||
@export main_start :: proc "c" () {
|
|
||||||
context = runtime.default_context()
|
|
||||||
|
|
||||||
// The WASM allocator doesn't seem to work properly in combination with
|
|
||||||
// emscripten. There is some kind of conflict with how the manage memory.
|
|
||||||
// So this sets up an allocator that uses emscripten's malloc.
|
|
||||||
context.allocator = emscripten_allocator()
|
|
||||||
runtime.init_global_temporary_allocator(1*mem.Megabyte)
|
|
||||||
|
|
||||||
// Since we now use js_wasm32 we should be able to remove this and use
|
|
||||||
// context.logger = log.create_console_logger(). However, that one produces
|
|
||||||
// extra newlines on web. So it's a bug in that core lib.
|
|
||||||
context.logger = create_emscripten_logger()
|
|
||||||
|
|
||||||
web_context = context
|
|
||||||
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
|
|
||||||
@export main_update :: proc "c" () -> bool {
|
|
||||||
context = web_context
|
|
||||||
update()
|
|
||||||
return should_run()
|
|
||||||
}
|
|
||||||
|
|
||||||
@export main_end :: proc "c" () {
|
|
||||||
context = web_context
|
|
||||||
shutdown()
|
|
||||||
}
|
|
||||||
|
|
||||||
@export web_window_size_changed :: proc "c" (w: c.int, h: c.int) {
|
|
||||||
context = web_context
|
|
||||||
parent_window_size_changed(int(w), int(h))
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
/// EMSCRIPTEN ALLOCATOR ///
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// This will create bindings to emscripten's implementation of libc
|
|
||||||
// memory allocation features.
|
|
||||||
@(default_calling_convention = "c")
|
|
||||||
foreign {
|
|
||||||
calloc :: proc(num, size: c.size_t) -> rawptr ---
|
|
||||||
free :: proc(ptr: rawptr) ---
|
|
||||||
malloc :: proc(size: c.size_t) -> rawptr ---
|
|
||||||
realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---
|
|
||||||
}
|
|
||||||
|
|
||||||
emscripten_allocator :: proc "contextless" () -> mem.Allocator {
|
|
||||||
return mem.Allocator{emscripten_allocator_proc, nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
emscripten_allocator_proc :: proc(allocator_data: rawptr,mode: mem.Allocator_Mode,size, alignment: int,old_memory: rawptr,old_size: int,location := #caller_location) -> (data: []byte, err: mem.Allocator_Error) {
|
|
||||||
// These aligned alloc procs are almost indentical those in
|
|
||||||
// `_heap_allocator_proc` in `core:os`. Without the proper alignment you
|
|
||||||
// cannot use maps and simd features.
|
|
||||||
|
|
||||||
aligned_alloc :: proc(size, alignment: int, zero_memory: bool, old_ptr: rawptr = nil) -> ([]byte, mem.Allocator_Error) {
|
|
||||||
a := max(alignment, align_of(rawptr))
|
|
||||||
space := size + a - 1
|
|
||||||
|
|
||||||
allocated_mem: rawptr
|
|
||||||
if old_ptr != nil {
|
|
||||||
original_old_ptr := mem.ptr_offset((^rawptr)(old_ptr), -1)^
|
|
||||||
allocated_mem = realloc(original_old_ptr, c.size_t(space+size_of(rawptr)))
|
|
||||||
} else if zero_memory {
|
|
||||||
// calloc automatically zeros memory, but it takes a number + size
|
|
||||||
// instead of just size.
|
|
||||||
allocated_mem = calloc(c.size_t(space+size_of(rawptr)), 1)
|
|
||||||
} else {
|
|
||||||
allocated_mem = malloc(c.size_t(space+size_of(rawptr)))
|
|
||||||
}
|
|
||||||
aligned_mem := rawptr(mem.ptr_offset((^u8)(allocated_mem), size_of(rawptr)))
|
|
||||||
|
|
||||||
ptr := uintptr(aligned_mem)
|
|
||||||
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
|
|
||||||
diff := int(aligned_ptr - ptr)
|
|
||||||
if (size + diff) > space || allocated_mem == nil {
|
|
||||||
return nil, .Out_Of_Memory
|
|
||||||
}
|
|
||||||
|
|
||||||
aligned_mem = rawptr(aligned_ptr)
|
|
||||||
mem.ptr_offset((^rawptr)(aligned_mem), -1)^ = allocated_mem
|
|
||||||
|
|
||||||
return mem.byte_slice(aligned_mem, size), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
aligned_free :: proc(p: rawptr) {
|
|
||||||
if p != nil {
|
|
||||||
free(mem.ptr_offset((^rawptr)(p), -1)^)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int) -> ([]byte, mem.Allocator_Error) {
|
|
||||||
if p == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return aligned_alloc(new_size, new_alignment, true, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch mode {
|
|
||||||
case .Alloc:
|
|
||||||
return aligned_alloc(size, alignment, true)
|
|
||||||
|
|
||||||
case .Alloc_Non_Zeroed:
|
|
||||||
return aligned_alloc(size, alignment, false)
|
|
||||||
|
|
||||||
case .Free:
|
|
||||||
aligned_free(old_memory)
|
|
||||||
return nil, nil
|
|
||||||
|
|
||||||
case .Resize:
|
|
||||||
if old_memory == nil {
|
|
||||||
return aligned_alloc(size, alignment, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes := aligned_resize(old_memory, old_size, size, alignment) or_return
|
|
||||||
|
|
||||||
// realloc doesn't zero the new bytes, so we do it manually.
|
|
||||||
if size > old_size {
|
|
||||||
new_region := raw_data(bytes[old_size:])
|
|
||||||
intrinsics.mem_zero(new_region, size - old_size)
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes, nil
|
|
||||||
|
|
||||||
case .Resize_Non_Zeroed:
|
|
||||||
if old_memory == nil {
|
|
||||||
return aligned_alloc(size, alignment, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
return aligned_resize(old_memory, old_size, size, alignment)
|
|
||||||
|
|
||||||
case .Query_Features:
|
|
||||||
set := (^mem.Allocator_Mode_Set)(old_memory)
|
|
||||||
if set != nil {
|
|
||||||
set^ = {.Alloc, .Free, .Resize, .Query_Features}
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
|
|
||||||
case .Free_All, .Query_Info:
|
|
||||||
return nil, .Mode_Not_Implemented
|
|
||||||
}
|
|
||||||
return nil, .Mode_Not_Implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
/// EMSCRIPTEN LOGGER ///
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
Emscripten_Logger_Opts :: log.Options{.Level, .Short_File_Path, .Line}
|
|
||||||
|
|
||||||
create_emscripten_logger :: proc (lowest := log.Level.Debug, opt := Emscripten_Logger_Opts) -> log.Logger {
|
|
||||||
return log.Logger{data = nil, procedure = logger_proc, lowest_level = lowest, options = opt}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This create's a binding to `puts` which will be linked in as part of the
|
|
||||||
// emscripten runtime.
|
|
||||||
@(default_calling_convention = "c")
|
|
||||||
foreign {
|
|
||||||
puts :: proc(buffer: cstring) -> c.int ---
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private="file")
|
|
||||||
logger_proc :: proc(logger_data: rawptr,level: log.Level,text: string,options: log.Options,location := #caller_location) {
|
|
||||||
b := strings.builder_make(context.temp_allocator)
|
|
||||||
strings.write_string(&b, Level_Headers[level])
|
|
||||||
do_location_header(options, &b, location)
|
|
||||||
fmt.sbprint(&b, text)
|
|
||||||
|
|
||||||
if bc, bc_err := strings.to_cstring(&b); bc_err == nil {
|
|
||||||
puts(bc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private="file")
|
|
||||||
Level_Headers := [?]string {
|
|
||||||
0 ..< 10 = "[DEBUG] --- ",
|
|
||||||
10 ..< 20 = "[INFO ] --- ",
|
|
||||||
20 ..< 30 = "[WARN ] --- ",
|
|
||||||
30 ..< 40 = "[ERROR] --- ",
|
|
||||||
40 ..< 50 = "[FATAL] --- ",
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private="file")
|
|
||||||
do_location_header :: proc(opts: log.Options, buf: ^strings.Builder, location := #caller_location) {
|
|
||||||
if log.Location_Header_Opts & opts == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.sbprint(buf, "[")
|
|
||||||
file := location.file_path
|
|
||||||
if .Short_File_Path in opts {
|
|
||||||
last := 0
|
|
||||||
for r, i in location.file_path {
|
|
||||||
if r == '/' {
|
|
||||||
last = i + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file = location.file_path[last:]
|
|
||||||
}
|
|
||||||
|
|
||||||
if log.Location_File_Opts & opts != nil {
|
|
||||||
fmt.sbprint(buf, file)
|
|
||||||
}
|
|
||||||
if .Line in opts {
|
|
||||||
if log.Location_File_Opts & opts != nil {
|
|
||||||
fmt.sbprint(buf, ":")
|
|
||||||
}
|
|
||||||
fmt.sbprint(buf, location.line)
|
|
||||||
}
|
|
||||||
|
|
||||||
if .Procedure in opts {
|
|
||||||
if (log.Location_File_Opts | {.Line}) & opts != nil {
|
|
||||||
fmt.sbprint(buf, ":")
|
|
||||||
}
|
|
||||||
fmt.sbprintf(buf, "%s()", location.procedure)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.sbprint(buf, "] ")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
main :: proc() {
|
|
||||||
// exe_path := os.args[0]
|
|
||||||
// exe_dir := filepath.dir(string(exe_path))
|
|
||||||
// os.set_working_directory(exe_dir)
|
|
||||||
rl.ChangeDirectory(rl.GetApplicationDirectory())
|
|
||||||
back.register_segfault_handler()
|
|
||||||
context.logger = log.create_console_logger()
|
|
||||||
|
|
||||||
init()
|
|
||||||
for should_run() {
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
shutdown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
20
main_desktop.odin
Normal file
20
main_desktop.odin
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import rl "libraries/raylib"
|
||||||
|
import "libraries/back"
|
||||||
|
import "core:log"
|
||||||
|
|
||||||
|
main :: proc() {
|
||||||
|
// exe_path := os.args[0]
|
||||||
|
// exe_dir := filepath.dir(string(exe_path))
|
||||||
|
// os.set_working_directory(exe_dir)
|
||||||
|
rl.ChangeDirectory(rl.GetApplicationDirectory())
|
||||||
|
back.register_segfault_handler()
|
||||||
|
context.logger = log.create_console_logger()
|
||||||
|
|
||||||
|
init()
|
||||||
|
for should_run() {
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
shutdown()
|
||||||
|
}
|
||||||
231
main_web.odin
Normal file
231
main_web.odin
Normal file
|
|
@ -0,0 +1,231 @@
|
||||||
|
#+build wasm32, wasm64p32
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "core:log"
|
||||||
|
import "core:mem"
|
||||||
|
import "core:c"
|
||||||
|
import "base:intrinsics"
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:strings"
|
||||||
|
import "core:fmt"
|
||||||
|
|
||||||
|
@(private="file") web_context: runtime.Context
|
||||||
|
|
||||||
|
@export main_start :: proc "c" () {
|
||||||
|
context = runtime.default_context()
|
||||||
|
|
||||||
|
// The WASM allocator doesn't seem to work properly in combination with
|
||||||
|
// emscripten. There is some kind of conflict with how the manage memory.
|
||||||
|
// So this sets up an allocator that uses emscripten's malloc.
|
||||||
|
context.allocator = emscripten_allocator()
|
||||||
|
runtime.init_global_temporary_allocator(1*mem.Megabyte)
|
||||||
|
|
||||||
|
// Since we now use js_wasm32 we should be able to remove this and use
|
||||||
|
// context.logger = log.create_console_logger(). However, that one produces
|
||||||
|
// extra newlines on web. So it's a bug in that core lib.
|
||||||
|
context.logger = create_emscripten_logger()
|
||||||
|
|
||||||
|
web_context = context
|
||||||
|
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
|
||||||
|
@export main_update :: proc "c" () -> bool {
|
||||||
|
context = web_context
|
||||||
|
update()
|
||||||
|
return should_run()
|
||||||
|
}
|
||||||
|
|
||||||
|
@export main_end :: proc "c" () {
|
||||||
|
context = web_context
|
||||||
|
shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
@export web_window_size_changed :: proc "c" (w: c.int, h: c.int) {
|
||||||
|
context = web_context
|
||||||
|
parent_window_size_changed(int(w), int(h))
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
/// EMSCRIPTEN ALLOCATOR ///
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// This will create bindings to emscripten's implementation of libc
|
||||||
|
// memory allocation features.
|
||||||
|
@(default_calling_convention = "c")
|
||||||
|
foreign {
|
||||||
|
calloc :: proc(num, size: c.size_t) -> rawptr ---
|
||||||
|
free :: proc(ptr: rawptr) ---
|
||||||
|
malloc :: proc(size: c.size_t) -> rawptr ---
|
||||||
|
realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---
|
||||||
|
}
|
||||||
|
|
||||||
|
emscripten_allocator :: proc "contextless" () -> mem.Allocator {
|
||||||
|
return mem.Allocator{emscripten_allocator_proc, nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
emscripten_allocator_proc :: proc(allocator_data: rawptr,mode: mem.Allocator_Mode,size, alignment: int,old_memory: rawptr,old_size: int,location := #caller_location) -> (data: []byte, err: mem.Allocator_Error) {
|
||||||
|
// These aligned alloc procs are almost indentical those in
|
||||||
|
// `_heap_allocator_proc` in `core:os`. Without the proper alignment you
|
||||||
|
// cannot use maps and simd features.
|
||||||
|
|
||||||
|
aligned_alloc :: proc(size, alignment: int, zero_memory: bool, old_ptr: rawptr = nil) -> ([]byte, mem.Allocator_Error) {
|
||||||
|
a := max(alignment, align_of(rawptr))
|
||||||
|
space := size + a - 1
|
||||||
|
|
||||||
|
allocated_mem: rawptr
|
||||||
|
if old_ptr != nil {
|
||||||
|
original_old_ptr := mem.ptr_offset((^rawptr)(old_ptr), -1)^
|
||||||
|
allocated_mem = realloc(original_old_ptr, c.size_t(space+size_of(rawptr)))
|
||||||
|
} else if zero_memory {
|
||||||
|
// calloc automatically zeros memory, but it takes a number + size
|
||||||
|
// instead of just size.
|
||||||
|
allocated_mem = calloc(c.size_t(space+size_of(rawptr)), 1)
|
||||||
|
} else {
|
||||||
|
allocated_mem = malloc(c.size_t(space+size_of(rawptr)))
|
||||||
|
}
|
||||||
|
aligned_mem := rawptr(mem.ptr_offset((^u8)(allocated_mem), size_of(rawptr)))
|
||||||
|
|
||||||
|
ptr := uintptr(aligned_mem)
|
||||||
|
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
|
||||||
|
diff := int(aligned_ptr - ptr)
|
||||||
|
if (size + diff) > space || allocated_mem == nil {
|
||||||
|
return nil, .Out_Of_Memory
|
||||||
|
}
|
||||||
|
|
||||||
|
aligned_mem = rawptr(aligned_ptr)
|
||||||
|
mem.ptr_offset((^rawptr)(aligned_mem), -1)^ = allocated_mem
|
||||||
|
|
||||||
|
return mem.byte_slice(aligned_mem, size), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
aligned_free :: proc(p: rawptr) {
|
||||||
|
if p != nil {
|
||||||
|
free(mem.ptr_offset((^rawptr)(p), -1)^)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int) -> ([]byte, mem.Allocator_Error) {
|
||||||
|
if p == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return aligned_alloc(new_size, new_alignment, true, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch mode {
|
||||||
|
case .Alloc:
|
||||||
|
return aligned_alloc(size, alignment, true)
|
||||||
|
|
||||||
|
case .Alloc_Non_Zeroed:
|
||||||
|
return aligned_alloc(size, alignment, false)
|
||||||
|
|
||||||
|
case .Free:
|
||||||
|
aligned_free(old_memory)
|
||||||
|
return nil, nil
|
||||||
|
|
||||||
|
case .Resize:
|
||||||
|
if old_memory == nil {
|
||||||
|
return aligned_alloc(size, alignment, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes := aligned_resize(old_memory, old_size, size, alignment) or_return
|
||||||
|
|
||||||
|
// realloc doesn't zero the new bytes, so we do it manually.
|
||||||
|
if size > old_size {
|
||||||
|
new_region := raw_data(bytes[old_size:])
|
||||||
|
intrinsics.mem_zero(new_region, size - old_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes, nil
|
||||||
|
|
||||||
|
case .Resize_Non_Zeroed:
|
||||||
|
if old_memory == nil {
|
||||||
|
return aligned_alloc(size, alignment, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return aligned_resize(old_memory, old_size, size, alignment)
|
||||||
|
|
||||||
|
case .Query_Features:
|
||||||
|
set := (^mem.Allocator_Mode_Set)(old_memory)
|
||||||
|
if set != nil {
|
||||||
|
set^ = {.Alloc, .Free, .Resize, .Query_Features}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
|
||||||
|
case .Free_All, .Query_Info:
|
||||||
|
return nil, .Mode_Not_Implemented
|
||||||
|
}
|
||||||
|
return nil, .Mode_Not_Implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
/// EMSCRIPTEN LOGGER ///
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
Emscripten_Logger_Opts :: log.Options{.Level, .Short_File_Path, .Line}
|
||||||
|
|
||||||
|
create_emscripten_logger :: proc (lowest := log.Level.Debug, opt := Emscripten_Logger_Opts) -> log.Logger {
|
||||||
|
return log.Logger{data = nil, procedure = logger_proc, lowest_level = lowest, options = opt}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This create's a binding to `puts` which will be linked in as part of the
|
||||||
|
// emscripten runtime.
|
||||||
|
@(default_calling_convention = "c")
|
||||||
|
foreign {
|
||||||
|
puts :: proc(buffer: cstring) -> c.int ---
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private="file") logger_proc :: proc(logger_data: rawptr,level: log.Level,text: string,options: log.Options,location := #caller_location) {
|
||||||
|
b := strings.builder_make(context.temp_allocator)
|
||||||
|
strings.write_string(&b, Level_Headers[level])
|
||||||
|
do_location_header(options, &b, location)
|
||||||
|
fmt.sbprint(&b, text)
|
||||||
|
|
||||||
|
if bc, bc_err := strings.to_cstring(&b); bc_err == nil {
|
||||||
|
puts(bc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private="file") Level_Headers := [?]string {
|
||||||
|
0 ..< 10 = "[DEBUG] --- ",
|
||||||
|
10 ..< 20 = "[INFO ] --- ",
|
||||||
|
20 ..< 30 = "[WARN ] --- ",
|
||||||
|
30 ..< 40 = "[ERROR] --- ",
|
||||||
|
40 ..< 50 = "[FATAL] --- ",
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private="file") do_location_header :: proc(opts: log.Options, buf: ^strings.Builder, location := #caller_location) {
|
||||||
|
if log.Location_Header_Opts & opts == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.sbprint(buf, "[")
|
||||||
|
file := location.file_path
|
||||||
|
if .Short_File_Path in opts {
|
||||||
|
last := 0
|
||||||
|
for r, i in location.file_path {
|
||||||
|
if r == '/' {
|
||||||
|
last = i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file = location.file_path[last:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if log.Location_File_Opts & opts != nil {
|
||||||
|
fmt.sbprint(buf, file)
|
||||||
|
}
|
||||||
|
if .Line in opts {
|
||||||
|
if log.Location_File_Opts & opts != nil {
|
||||||
|
fmt.sbprint(buf, ":")
|
||||||
|
}
|
||||||
|
fmt.sbprint(buf, location.line)
|
||||||
|
}
|
||||||
|
|
||||||
|
if .Procedure in opts {
|
||||||
|
if (log.Location_File_Opts | {.Line}) & opts != nil {
|
||||||
|
fmt.sbprint(buf, ":")
|
||||||
|
}
|
||||||
|
fmt.sbprintf(buf, "%s()", location.procedure)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.sbprint(buf, "] ")
|
||||||
|
}
|
||||||
36
signal_handler_linux.odin
Normal file
36
signal_handler_linux.odin
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#+build linux
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "libraries/back"
|
||||||
|
import "core:sys/posix"
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:mem"
|
||||||
|
import "core:fmt"
|
||||||
|
|
||||||
|
_register_illegal_instruction_handler :: proc() {
|
||||||
|
posix.signal(.SIGILL, proc "c" (code: posix.Signal) {
|
||||||
|
context = runtime.default_context()
|
||||||
|
|
||||||
|
space: [16*mem.Kilobyte]byte
|
||||||
|
arena: mem.Arena
|
||||||
|
mem.arena_init(&arena, space[:])
|
||||||
|
allocator := mem.arena_allocator(&arena)
|
||||||
|
|
||||||
|
context.allocator = allocator
|
||||||
|
context.temp_allocator = allocator
|
||||||
|
|
||||||
|
backtrace: {
|
||||||
|
lines, err := back.lines(back.trace(), allocator, allocator)
|
||||||
|
if err != nil {
|
||||||
|
fmt.eprintf("Exception (Code: %i)\nCould not get backtrace: %v\n", code, err)
|
||||||
|
break backtrace
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.eprintf("Exception (Code: %i)\n[back trace]\n", code)
|
||||||
|
back.print(lines, temp_allocator=allocator)
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.exit(int(code))
|
||||||
|
})
|
||||||
|
}
|
||||||
7
signal_handler_other.odin
Normal file
7
signal_handler_other.odin
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#+build !linux
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
_register_illegal_instruction_handler :: proc() {
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue