all: add stdcall attribute, unhandled exception handler, get_raw_stdin, v_realloc
							parent
							
								
									a849d46e3f
								
							
						
					
					
						commit
						f0a9b88ac4
					
				|  | @ -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 { | ||||
|  |  | |||
|  | @ -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) | ||||
| } | ||||
|  | @ -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 | ||||
| ) | ||||
							
								
								
									
										24
									
								
								vlib/os/os.v
								
								
								
								
							
							
						
						
									
										24
									
								
								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{} | ||||
|  |  | |||
|  | @ -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) | ||||
| } | ||||
|  | @ -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) { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue