From f0a9b88ac473338f60b2937b2ef4cafca317ad4c Mon Sep 17 00:00:00 2001 From: Emily Hudson Date: Fri, 29 May 2020 02:06:27 +0100 Subject: [PATCH] all: add stdcall attribute, unhandled exception handler, get_raw_stdin, v_realloc --- vlib/builtin/builtin.v | 9 ++++++ vlib/builtin/builtin_windows.c.v | 54 ++++++++++++++++++++++++++++++++ vlib/os/const_windows.c.v | 35 +++++++++++++++++++++ vlib/os/os.v | 24 ++++++++++++++ vlib/os/os_windows.c.v | 35 +++++++++++++++++++++ vlib/v/gen/fn.v | 14 +++++++-- 6 files changed, 169 insertions(+), 2 deletions(-) diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index 9881200c05..845696985a 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -158,7 +158,16 @@ TODO print_backtrace() #endif */ +} +[unsafe_fn] +pub fn v_realloc(b byteptr, n int) byteptr { + ptr := C.realloc(b, n) + if ptr == 0 { + panic('realloc($n) failed') + } + + return ptr } pub fn v_calloc(n int) byteptr { diff --git a/vlib/builtin/builtin_windows.c.v b/vlib/builtin/builtin_windows.c.v index 7d98553a19..8bc2412d6c 100644 --- a/vlib/builtin/builtin_windows.c.v +++ b/vlib/builtin/builtin_windows.c.v @@ -64,6 +64,7 @@ fn builtin_init() { C.SetConsoleMode(C.GetStdHandle(C.STD_OUTPUT_HANDLE), C.ENABLE_PROCESSED_OUTPUT | 0x0004) // enable_virtual_terminal_processing C.setbuf(C.stdout, 0) } + add_unhandled_exception_handler() } fn print_backtrace_skipping_top_frames(skipframes int) bool { @@ -139,3 +140,56 @@ fn print_backtrace_skipping_top_frames_mingw(skipframes int) bool { eprintln('print_backtrace_skipping_top_frames_mingw is not implemented') return false } + + +//TODO copypaste from os +// we want to be able to use this here without having to `import os` +struct ExceptionRecord { +pub: + // status_ constants + code u32 + flags u32 + + record &ExceptionRecord + address voidptr + param_count u32 + // params []voidptr +} + + struct ContextRecord { + // TODO +} + +struct ExceptionPointers { +pub: + exception_record &ExceptionRecord + context_record &ContextRecord +} + +type VectoredExceptionHandler fn(&ExceptionPointers)u32 + +fn C.AddVectoredExceptionHandler(u32, VectoredExceptionHandler) +fn add_vectored_exception_handler(handler VectoredExceptionHandler) { + C.AddVectoredExceptionHandler(1, handler) +} + +[windows_stdcall] +fn unhandled_exception_handler(e &ExceptionPointers) u32 { + match e.exception_record.code { + // These are 'used' by the backtrace printer + // so we dont want to catch them... + 0x4001000A, 0x40010006 { + return 0 + } + else { + println('Unhandled Exception 0x${e.exception_record.code:X}') + print_backtrace_skipping_top_frames(5) + } + } + + return 0 +} + +pub fn add_unhandled_exception_handler() { + add_vectored_exception_handler(unhandled_exception_handler) +} \ No newline at end of file diff --git a/vlib/os/const_windows.c.v b/vlib/os/const_windows.c.v index bd558e9943..fba66a8685 100644 --- a/vlib/os/const_windows.c.v +++ b/vlib/os/const_windows.c.v @@ -102,3 +102,38 @@ const ( o_noctty = 0 // make file non-controlling tty (ignored on Windows) o_nonblock = 0 // don't block on opening file (ignored on Windows) ) + +const ( + status_access_violation = 0xC0000005 + status_in_page_error = 0xC0000006 + status_invalid_handle = 0xC0000008 + status_invalid_parameter = 0xC000000D + status_no_memory = 0xC0000017 + status_illegal_instruction = 0xC000001D + status_noncontinuable_exception = 0xC0000025 + status_invalid_disposition = 0xC0000026 + status_array_bounds_exceeded = 0xC000008C + status_float_denormal_operand = 0xC000008D + status_float_divide_by_zero = 0xC000008E + status_float_inexact_result = 0xC000008F + status_float_invalid_operation = 0xC0000090 + status_float_overflow = 0xC0000091 + status_float_stack_check = 0xC0000092 + status_float_underflow = 0xC0000093 + status_integer_divide_by_zero = 0xC0000094 + status_integer_overflow = 0xC0000095 + status_privileged_instruction = 0xC0000096 + status_stack_overflow = 0xC00000FD + status_dll_not_found = 0xC0000135 + status_ordinal_not_found = 0xC0000138 + status_entrypoint_not_found = 0xC0000139 + status_control_c_exit = 0xC000013A + status_dll_init_failed = 0xC0000142 + status_float_multiple_faults = 0xC00002B4 + status_float_multiple_traps = 0xC00002B5 + status_reg_nat_consumption = 0xC00002C9 + status_heap_corruption = 0xC0000374 + status_stack_buffer_overrun = 0xC0000409 + status_invalid_cruntime_parameter = 0xC0000417 + status_assertion_failure = 0xC0000420 +) \ No newline at end of file diff --git a/vlib/os/os.v b/vlib/os/os.v index 0408c82dbb..a571e0e60a 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -787,6 +787,30 @@ pub fn get_raw_line() string { } } +pub fn get_raw_stdin() []byte { + $if windows { + unsafe { + block_bytes := 512 + mut buf := malloc(block_bytes) + h_input := C.GetStdHandle(std_input_handle) + mut bytes_read := 0 + mut offset := 0 + for { + pos := buf + offset + res := C.ReadFile(h_input, pos, block_bytes, &bytes_read, 0) + if !res { + break + } + offset += bytes_read + buf = v_realloc(buf, offset + block_bytes + (block_bytes-bytes_read)) + } + return array{element_size: 1 data: voidptr(buf) len: offset cap: offset } + } + } $else { + panic('get_raw_stdin not implemented on this platform...') + } +} + pub fn get_lines() []string { mut line := '' mut inputstr := []string{} diff --git a/vlib/os/os_windows.c.v b/vlib/os/os_windows.c.v index c290df8ffc..fce4bf666e 100644 --- a/vlib/os/os_windows.c.v +++ b/vlib/os/os_windows.c.v @@ -311,3 +311,38 @@ pub fn (mut f File) close() { C.fflush(f.cfile) C.fclose(f.cfile) } + +pub struct ExceptionRecord { +pub: + // status_ constants + code u32 + flags u32 + + record &ExceptionRecord + address voidptr + param_count u32 + // params []voidptr +} + +pub struct ContextRecord { + // TODO +} + +pub struct ExceptionPointers { +pub: + exception_record &ExceptionRecord + context_record &ContextRecord +} + +pub type VectoredExceptionHandler fn(&ExceptionPointers)u32 + +// This is defined in builtin because we use vectored exception handling +// for our unhandled exception handler on windows + +// As a result this definition is commented out to prevent +// duplicate definitions from displeasing the compiler +// fn C.AddVectoredExceptionHandler(u32, VectoredExceptionHandler) + +pub fn add_vectored_exception_handler(first bool, handler VectoredExceptionHandler) { + C.AddVectoredExceptionHandler(u32(first), handler) +} \ No newline at end of file diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index 5e2aa62b23..47512ccca4 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -37,6 +37,8 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) { } // fn_start_pos := g.out.len + + mut msvc_attrs := '' match g.attr { 'inline' { g.write('inline ') @@ -95,6 +97,14 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) { '_pure' { g.write('__attribute__((const)) ') } + + // windows attributes (msvc/mingw) + // prefixed by windows to indicate they're for advanced users only and not really supported by V. + + 'windows_stdcall' { + msvc_attrs += '__stdcall ' + } + else { // nothing but keep V happy } @@ -174,8 +184,8 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) { g.write('static ') g.definitions.write('static ') } - g.definitions.write('$type_name ${name}(') - g.write('$type_name ${name}(') + g.definitions.write('$type_name $msvc_attrs ${name}(') + g.write('$type_name $msvc_attrs ${name}(') } fargs, fargtypes := g.fn_args(it.args, it.is_variadic) if it.no_body || (g.pref.use_cache && it.is_builtin) {