diff --git a/core/_preload.odin b/core/_preload.odin index 0da7a8134..6d796dbeb 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -32,10 +32,11 @@ type ( } // NOTE(bill): This must match the compiler's CallingConvention enum { - Odin = 0, - C = 1, - Std = 2, - Fast = 3, + Invalid = 0, + Odin = 1, + C = 2, + Std = 3, + Fast = 4, } TypeInfoRecord struct #ordered { diff --git a/core/_soft_numbers.odin b/core/_soft_numbers.odin index a36d21680..523d04a97 100644 --- a/core/_soft_numbers.odin +++ b/core/_soft_numbers.odin @@ -1,26 +1,61 @@ #shared_global_scope; -proc __u128_mod(a, b: u128) -> u128 #cc_odin #link_name "__umodti3" { +proc __multi3(a, b: u128) -> u128 #cc_c #link_name "__multi3" { + const bits_in_dword_2 = size_of(i64) * 4; + const lower_mask = u128(~u64(0) >> bits_in_dword_2); + + + when ODIN_ENDIAN == "bit" { + type TWords raw_union { + all: u128, + using _: struct {lo, hi: u64}, + }; + } else { + type TWords raw_union { + all: u128, + using _: struct {hi, lo: u64}, + }; + } + + var r: TWords; + var t: u64; + + r.lo = u64(a & lower_mask) * u64(b & lower_mask); + t = r.lo >> bits_in_dword_2; + r.lo &= u64(lower_mask); + t += u64(a >> bits_in_dword_2) * u64(b & lower_mask); + r.lo += u64(t & u64(lower_mask)) << bits_in_dword_2; + r.hi = t >> bits_in_dword_2; + t = r.lo >> bits_in_dword_2; + r.lo &= u64(lower_mask); + t += u64(b >> bits_in_dword_2) * u64(a & lower_mask); + r.lo += u64(t & u64(lower_mask)) << bits_in_dword_2; + r.hi += t >> bits_in_dword_2; + r.hi += u64(a >> bits_in_dword_2) * u64(b >> bits_in_dword_2); + return r.all; +} + +proc __u128_mod(a, b: u128) -> u128 #cc_c #link_name "__umodti3" { var r: u128; __u128_quo_mod(a, b, &r); return r; } -proc __u128_quo(a, b: u128) -> u128 #cc_odin #link_name "__udivti3" { +proc __u128_quo(a, b: u128) -> u128 #cc_c #link_name "__udivti3" { return __u128_quo_mod(a, b, nil); } -proc __i128_mod(a, b: i128) -> i128 #cc_odin #link_name "__modti3" { +proc __i128_mod(a, b: i128) -> i128 #cc_c #link_name "__modti3" { var r: i128; __i128_quo_mod(a, b, &r); return r; } -proc __i128_quo(a, b: i128) -> i128 #cc_odin #link_name "__divti3" { +proc __i128_quo(a, b: i128) -> i128 #cc_c #link_name "__divti3" { return __i128_quo_mod(a, b, nil); } -proc __i128_quo_mod(a, b: i128, rem: ^i128) -> (quo: i128) #cc_odin #link_name "__divmodti4" { +proc __i128_quo_mod(a, b: i128, rem: ^i128) -> (quo: i128) #cc_c #link_name "__divmodti4" { var s: i128; s = b >> 127; b = (b~s) - s; @@ -39,7 +74,7 @@ proc __i128_quo_mod(a, b: i128, rem: ^i128) -> (quo: i128) #cc_odin #link_name " } -proc __u128_quo_mod(a, b: u128, rem: ^u128) -> (quo: u128) #cc_odin #link_name "__udivmodti4" { +proc __u128_quo_mod(a, b: u128, rem: ^u128) -> (quo: u128) #cc_c #link_name "__udivmodti4" { var alo, ahi = u64(a), u64(a>>64); var blo, bhi = u64(b), u64(b>>64); if b == 0 { @@ -68,7 +103,7 @@ proc __u128_quo_mod(a, b: u128, rem: ^u128) -> (quo: u128) #cc_odin #link_name " } /* -proc __f16_to_f32(f: f16) -> f32 #cc_odin #no_inline #link_name "__gnu_h2f_ieee" { +proc __f16_to_f32(f: f16) -> f32 #cc_c #no_inline #link_name "__gnu_h2f_ieee" { when true { // Source: https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/ const FP32 = raw_union {u: u32, f: f32}; @@ -92,7 +127,7 @@ proc __f16_to_f32(f: f16) -> f32 #cc_odin #no_inline #link_name "__gnu_h2f_ieee" return 0; } } -proc __f32_to_f16(f_: f32) -> f16 #cc_odin #no_inline #link_name "__gnu_f2h_ieee" { +proc __f32_to_f16(f_: f32) -> f16 #cc_c #no_inline #link_name "__gnu_f2h_ieee" { when false { // Source: https://gist.github.com/rygorous/2156668 const FP16 = raw_union {u: u16, f: f16}; @@ -182,11 +217,11 @@ proc __f32_to_f16(f_: f32) -> f16 #cc_odin #no_inline #link_name "__gnu_f2h_ieee } } -proc __f64_to_f16(f: f64) -> f16 #cc_odin #no_inline #link_name "__truncdfhf2" { +proc __f64_to_f16(f: f64) -> f16 #cc_c #no_inline #link_name "__truncdfhf2" { return __f32_to_f16(f32(f)); } -proc __f16_to_f64(f: f16) -> f64 #cc_odin #no_inline { +proc __f16_to_f64(f: f16) -> f64 #cc_c #no_inline { return f64(__f16_to_f32(f)); } */ diff --git a/core/sys/windows.odin b/core/sys/windows.odin index 0b9c07d11..1b64de1e2 100644 --- a/core/sys/windows.odin +++ b/core/sys/windows.odin @@ -285,164 +285,164 @@ const ( ) foreign kernel32 { - proc get_last_error () -> i32 #link_name "GetLastError"; - proc exit_process (exit_code: u32) #link_name "ExitProcess"; - proc get_module_handle_a(module_name: ^u8) -> Hinstance #link_name "GetModuleHandleA"; - proc sleep(ms: i32) -> i32 #link_name "Sleep"; - proc query_performance_frequency(result: ^i64) -> i32 #link_name "QueryPerformanceFrequency"; - proc query_performance_counter (result: ^i64) -> i32 #link_name "QueryPerformanceCounter"; - proc output_debug_string_a(c_str: ^u8) #link_name "OutputDebugStringA"; + proc get_last_error () -> i32 #cc_c #link_name "GetLastError"; + proc exit_process (exit_code: u32) #cc_c #link_name "ExitProcess"; + proc get_module_handle_a(module_name: ^u8) -> Hinstance #cc_c #link_name "GetModuleHandleA"; + proc sleep(ms: i32) -> i32 #cc_c #link_name "Sleep"; + proc query_performance_frequency(result: ^i64) -> i32 #cc_c #link_name "QueryPerformanceFrequency"; + proc query_performance_counter (result: ^i64) -> i32 #cc_c #link_name "QueryPerformanceCounter"; + proc output_debug_string_a(c_str: ^u8) #cc_c #link_name "OutputDebugStringA"; - proc get_command_line_a () -> ^u8 #link_name "GetCommandLineA"; - proc get_command_line_w () -> ^u16 #link_name "GetCommandLineW"; - proc get_system_metrics (index: i32) -> i32 #link_name "GetSystemMetrics"; - proc get_current_thread_id () -> u32 #link_name "GetCurrentThreadId"; + proc get_command_line_a () -> ^u8 #cc_c #link_name "GetCommandLineA"; + proc get_command_line_w () -> ^u16 #cc_c #link_name "GetCommandLineW"; + proc get_system_metrics (index: i32) -> i32 #cc_c #link_name "GetSystemMetrics"; + proc get_current_thread_id () -> u32 #cc_c #link_name "GetCurrentThreadId"; - proc get_system_time_as_file_time(system_time_as_file_time: ^Filetime) #link_name "GetSystemTimeAsFileTime"; - proc file_time_to_local_file_time(file_time: ^Filetime, local_file_time: ^Filetime) -> Bool #link_name "FileTimeToLocalFileTime"; - proc file_time_to_system_time (file_time: ^Filetime, system_time: ^Systemtime) -> Bool #link_name "FileTimeToSystemTime"; - proc system_time_to_file_time (system_time: ^Systemtime, file_time: ^Filetime) -> Bool #link_name "SystemTimeToFileTime"; + proc get_system_time_as_file_time(system_time_as_file_time: ^Filetime) #cc_c #link_name "GetSystemTimeAsFileTime"; + proc file_time_to_local_file_time(file_time: ^Filetime, local_file_time: ^Filetime) -> Bool #cc_c #link_name "FileTimeToLocalFileTime"; + proc file_time_to_system_time (file_time: ^Filetime, system_time: ^Systemtime) -> Bool #cc_c #link_name "FileTimeToSystemTime"; + proc system_time_to_file_time (system_time: ^Systemtime, file_time: ^Filetime) -> Bool #cc_c #link_name "SystemTimeToFileTime"; - proc close_handle (h: Handle) -> i32 #link_name "CloseHandle"; - proc get_std_handle(h: i32) -> Handle #link_name "GetStdHandle"; + proc close_handle (h: Handle) -> i32 #cc_c #link_name "CloseHandle"; + proc get_std_handle(h: i32) -> Handle #cc_c #link_name "GetStdHandle"; proc create_file_a (filename: ^u8, desired_access, share_mode: u32, security: rawptr, - creation, flags_and_attribs: u32, template_file: Handle) -> Handle #link_name "CreateFileA"; - proc read_file (h: Handle, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> Bool #link_name "ReadFile"; - proc write_file(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool #link_name "WriteFile"; + creation, flags_and_attribs: u32, template_file: Handle) -> Handle #cc_c #link_name "CreateFileA"; + proc read_file (h: Handle, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> Bool #cc_c #link_name "ReadFile"; + proc write_file(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool #cc_c #link_name "WriteFile"; - proc get_file_size_ex (file_handle: Handle, file_size: ^i64) -> Bool #link_name "GetFileSizeEx"; - proc get_file_attributes_a (filename: ^u8) -> u32 #link_name "GetFileAttributesA"; - proc get_file_attributes_ex_a (filename: ^u8, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool #link_name "GetFileAttributesExA"; - proc get_file_information_by_handle(file_handle: Handle, file_info: ^ByHandleFileInformation) -> Bool #link_name "GetFileInformationByHandle"; + proc get_file_size_ex (file_handle: Handle, file_size: ^i64) -> Bool #cc_c #link_name "GetFileSizeEx"; + proc get_file_attributes_a (filename: ^u8) -> u32 #cc_c #link_name "GetFileAttributesA"; + proc get_file_attributes_ex_a (filename: ^u8, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool #cc_c #link_name "GetFileAttributesExA"; + proc get_file_information_by_handle(file_handle: Handle, file_info: ^ByHandleFileInformation) -> Bool #cc_c #link_name "GetFileInformationByHandle"; - proc get_file_type (file_handle: Handle) -> u32 #link_name "GetFileType"; - proc set_file_pointer(file_handle: Handle, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 #link_name "SetFilePointer"; + proc get_file_type (file_handle: Handle) -> u32 #cc_c #link_name "GetFileType"; + proc set_file_pointer(file_handle: Handle, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 #cc_c #link_name "SetFilePointer"; - proc set_handle_information(obj: Handle, mask, flags: u32) -> Bool #link_name "SetHandleInformation"; + proc set_handle_information(obj: Handle, mask, flags: u32) -> Bool #cc_c #link_name "SetHandleInformation"; - proc find_first_file_a(file_name : ^u8, data : ^FindData) -> Handle #link_name "FindFirstFileA"; - proc find_next_file_a (file : Handle, data : ^FindData) -> Bool #link_name "FindNextFileA"; - proc find_close (file : Handle) -> Bool #link_name "FindClose"; + proc find_first_file_a(file_name : ^u8, data : ^FindData) -> Handle #cc_c #link_name "FindFirstFileA"; + proc find_next_file_a (file : Handle, data : ^FindData) -> Bool #cc_c #link_name "FindNextFileA"; + proc find_close (file : Handle) -> Bool #cc_c #link_name "FindClose"; - proc heap_alloc (h: Handle, flags: u32, bytes: int) -> rawptr #link_name "HeapAlloc"; - proc heap_realloc (h: Handle, flags: u32, memory: rawptr, bytes: int) -> rawptr #link_name "HeapReAlloc"; - proc heap_free (h: Handle, flags: u32, memory: rawptr) -> Bool #link_name "HeapFree"; - proc get_process_heap() -> Handle #link_name "GetProcessHeap"; + proc heap_alloc (h: Handle, flags: u32, bytes: int) -> rawptr #cc_c #link_name "HeapAlloc"; + proc heap_realloc (h: Handle, flags: u32, memory: rawptr, bytes: int) -> rawptr #cc_c #link_name "HeapReAlloc"; + proc heap_free (h: Handle, flags: u32, memory: rawptr) -> Bool #cc_c #link_name "HeapFree"; + proc get_process_heap() -> Handle #cc_c #link_name "GetProcessHeap"; - proc create_semaphore_a (attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: ^u8) -> Handle #link_name "CreateSemaphoreA"; - proc release_semaphore (semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool #link_name "ReleaseSemaphore"; - proc wait_for_single_object(handle: Handle, milliseconds: u32) -> u32 #link_name "WaitForSingleObject"; + proc create_semaphore_a (attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: ^u8) -> Handle #cc_c #link_name "CreateSemaphoreA"; + proc release_semaphore (semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool #cc_c #link_name "ReleaseSemaphore"; + proc wait_for_single_object(handle: Handle, milliseconds: u32) -> u32 #cc_c #link_name "WaitForSingleObject"; - proc interlocked_compare_exchange (dst: ^i32, exchange, comparand: i32) -> i32 #link_name "InterlockedCompareExchange"; - proc interlocked_exchange (dst: ^i32, desired: i32) -> i32 #link_name "InterlockedExchange"; - proc interlocked_exchange_add (dst: ^i32, desired: i32) -> i32 #link_name "InterlockedExchangeAdd"; - proc interlocked_and (dst: ^i32, desired: i32) -> i32 #link_name "InterlockedAnd"; - proc interlocked_or (dst: ^i32, desired: i32) -> i32 #link_name "InterlockedOr"; + proc interlocked_compare_exchange (dst: ^i32, exchange, comparand: i32) -> i32 #cc_c #link_name "InterlockedCompareExchange"; + proc interlocked_exchange (dst: ^i32, desired: i32) -> i32 #cc_c #link_name "InterlockedExchange"; + proc interlocked_exchange_add (dst: ^i32, desired: i32) -> i32 #cc_c #link_name "InterlockedExchangeAdd"; + proc interlocked_and (dst: ^i32, desired: i32) -> i32 #cc_c #link_name "InterlockedAnd"; + proc interlocked_or (dst: ^i32, desired: i32) -> i32 #cc_c #link_name "InterlockedOr"; - proc interlocked_compare_exchange64(dst: ^i64, exchange, comparand: i64) -> i64 #link_name "InterlockedCompareExchange64"; - proc interlocked_exchange64 (dst: ^i64, desired: i64) -> i64 #link_name "InterlockedExchange64"; - proc interlocked_exchange_add64 (dst: ^i64, desired: i64) -> i64 #link_name "InterlockedExchangeAdd64"; - proc interlocked_and64 (dst: ^i64, desired: i64) -> i64 #link_name "InterlockedAnd64"; - proc interlocked_or64 (dst: ^i64, desired: i64) -> i64 #link_name "InterlockedOr64"; + proc interlocked_compare_exchange64(dst: ^i64, exchange, comparand: i64) -> i64 #cc_c #link_name "InterlockedCompareExchange64"; + proc interlocked_exchange64 (dst: ^i64, desired: i64) -> i64 #cc_c #link_name "InterlockedExchange64"; + proc interlocked_exchange_add64 (dst: ^i64, desired: i64) -> i64 #cc_c #link_name "InterlockedExchangeAdd64"; + proc interlocked_and64 (dst: ^i64, desired: i64) -> i64 #cc_c #link_name "InterlockedAnd64"; + proc interlocked_or64 (dst: ^i64, desired: i64) -> i64 #cc_c #link_name "InterlockedOr64"; - proc mm_pause () #link_name "_mm_pause"; - proc read_write_barrier() #link_name "ReadWriteBarrier"; - proc write_barrier () #link_name "WriteBarrier"; - proc read_barrier () #link_name "ReadBarrier"; + proc mm_pause () #cc_c #link_name "_mm_pause"; + proc read_write_barrier() #cc_c #link_name "ReadWriteBarrier"; + proc write_barrier () #cc_c #link_name "WriteBarrier"; + proc read_barrier () #cc_c #link_name "ReadBarrier"; - proc load_library_a (c_str: ^u8) -> Hmodule #link_name "LoadLibraryA"; - proc free_library (h: Hmodule) #link_name "FreeLibrary"; - proc get_proc_address(h: Hmodule, c_str: ^u8) -> Proc #link_name "GetProcAddress"; + proc load_library_a (c_str: ^u8) -> Hmodule #cc_c #link_name "LoadLibraryA"; + proc free_library (h: Hmodule) #cc_c #link_name "FreeLibrary"; + proc get_proc_address(h: Hmodule, c_str: ^u8) -> Proc #cc_c #link_name "GetProcAddress"; } foreign user32 { - proc get_desktop_window () -> Hwnd #link_name "GetDesktopWindow"; - proc show_cursor (show : Bool) #link_name "ShowCursor"; - proc get_cursor_pos (p: ^Point) -> i32 #link_name "GetCursorPos"; - proc screen_to_client (h: Hwnd, p: ^Point) -> i32 #link_name "ScreenToClient"; - proc post_quit_message (exit_code: i32) #link_name "PostQuitMessage"; - proc set_window_text_a (hwnd: Hwnd, c_string: ^u8) -> Bool #link_name "SetWindowTextA"; - proc register_class_ex_a (wc: ^WndClassExA) -> i16 #link_name "RegisterClassExA"; + proc get_desktop_window () -> Hwnd #cc_c #link_name "GetDesktopWindow"; + proc show_cursor (show : Bool) #cc_c #link_name "ShowCursor"; + proc get_cursor_pos (p: ^Point) -> i32 #cc_c #link_name "GetCursorPos"; + proc screen_to_client (h: Hwnd, p: ^Point) -> i32 #cc_c #link_name "ScreenToClient"; + proc post_quit_message (exit_code: i32) #cc_c #link_name "PostQuitMessage"; + proc set_window_text_a (hwnd: Hwnd, c_string: ^u8) -> Bool #cc_c #link_name "SetWindowTextA"; + proc register_class_ex_a (wc: ^WndClassExA) -> i16 #cc_c #link_name "RegisterClassExA"; proc create_window_ex_a (ex_style: u32, class_name, title: ^u8, style: u32, x, y, w, h: i32, parent: Hwnd, menu: Hmenu, instance: Hinstance, - param: rawptr) -> Hwnd #link_name "CreateWindowExA"; + param: rawptr) -> Hwnd #cc_c #link_name "CreateWindowExA"; - proc show_window (hwnd: Hwnd, cmd_show: i32) -> Bool #link_name "ShowWindow"; - proc translate_message (msg: ^Msg) -> Bool #link_name "TranslateMessage"; - proc dispatch_message_a (msg: ^Msg) -> Lresult #link_name "DispatchMessageA"; - proc update_window (hwnd: Hwnd) -> Bool #link_name "UpdateWindow"; - proc get_message_a (msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool #link_name "GetMessageA"; + proc show_window (hwnd: Hwnd, cmd_show: i32) -> Bool #cc_c #link_name "ShowWindow"; + proc translate_message (msg: ^Msg) -> Bool #cc_c #link_name "TranslateMessage"; + proc dispatch_message_a (msg: ^Msg) -> Lresult #cc_c #link_name "DispatchMessageA"; + proc update_window (hwnd: Hwnd) -> Bool #cc_c #link_name "UpdateWindow"; + proc get_message_a (msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool #cc_c #link_name "GetMessageA"; proc peek_message_a (msg: ^Msg, hwnd: Hwnd, - msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool #link_name "PeekMessageA"; + msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool #cc_c #link_name "PeekMessageA"; - proc post_message (hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool #link_name "PostMessageA"; + proc post_message (hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool #cc_c #link_name "PostMessageA"; - proc def_window_proc_a (hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult #link_name "DefWindowProcA"; + proc def_window_proc_a (hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult #cc_c #link_name "DefWindowProcA"; - proc adjust_window_rect (rect: ^Rect, style: u32, menu: Bool) -> Bool #link_name "AdjustWindowRect"; - proc get_active_window () -> Hwnd #link_name "GetActiveWindow"; + proc adjust_window_rect (rect: ^Rect, style: u32, menu: Bool) -> Bool #cc_c #link_name "AdjustWindowRect"; + proc get_active_window () -> Hwnd #cc_c #link_name "GetActiveWindow"; - proc destroy_window (wnd: Hwnd) -> Bool #link_name "DestroyWindow"; - proc describe_pixel_format(dc: Hdc, pixel_format: i32, bytes : u32, pfd: ^PixelFormatDescriptor) -> i32 #link_name "DescribePixelFormat"; + proc destroy_window (wnd: Hwnd) -> Bool #cc_c #link_name "DestroyWindow"; + proc describe_pixel_format(dc: Hdc, pixel_format: i32, bytes : u32, pfd: ^PixelFormatDescriptor) -> i32 #cc_c #link_name "DescribePixelFormat"; - proc get_monitor_info_a (monitor: Hmonitor, mi: ^MonitorInfo) -> Bool #link_name "GetMonitorInfoA"; - proc monitor_from_window (wnd: Hwnd, flags : u32) -> Hmonitor #link_name "MonitorFromWindow"; + proc get_monitor_info_a (monitor: Hmonitor, mi: ^MonitorInfo) -> Bool #cc_c #link_name "GetMonitorInfoA"; + proc monitor_from_window (wnd: Hwnd, flags : u32) -> Hmonitor #cc_c #link_name "MonitorFromWindow"; - proc set_window_pos (wnd: Hwnd, wndInsertAfter: Hwnd, x, y, width, height: i32, flags: u32) #link_name "SetWindowPos"; + proc set_window_pos (wnd: Hwnd, wndInsertAfter: Hwnd, x, y, width, height: i32, flags: u32) #cc_c #link_name "SetWindowPos"; - proc get_window_placement (wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool #link_name "GetWindowPlacement"; - proc set_window_placement (wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool #link_name "SetWindowPlacement"; - proc get_window_rect (wnd: Hwnd, rect: ^Rect) -> Bool #link_name "GetWindowRect"; + proc get_window_placement (wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool #cc_c #link_name "GetWindowPlacement"; + proc set_window_placement (wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool #cc_c #link_name "SetWindowPlacement"; + proc get_window_rect (wnd: Hwnd, rect: ^Rect) -> Bool #cc_c #link_name "GetWindowRect"; - proc get_window_long_ptr_a(wnd: Hwnd, index: i32) -> i64 #link_name "GetWindowLongPtrA"; - proc set_window_long_ptr_a(wnd: Hwnd, index: i32, new: i64) -> i64 #link_name "SetWindowLongPtrA"; + proc get_window_long_ptr_a(wnd: Hwnd, index: i32) -> i64 #cc_c #link_name "GetWindowLongPtrA"; + proc set_window_long_ptr_a(wnd: Hwnd, index: i32, new: i64) -> i64 #cc_c #link_name "SetWindowLongPtrA"; - proc get_window_text (wnd: Hwnd, str: ^u8, maxCount: i32) -> i32 #link_name "GetWindowText"; + proc get_window_text (wnd: Hwnd, str: ^u8, maxCount: i32) -> i32 #cc_c #link_name "GetWindowText"; - proc get_client_rect (hwnd: Hwnd, rect: ^Rect) -> Bool #link_name "GetClientRect"; + proc get_client_rect (hwnd: Hwnd, rect: ^Rect) -> Bool #cc_c #link_name "GetClientRect"; - proc get_dc (h: Hwnd) -> Hdc #link_name "GetDC"; - proc release_dc (wnd: Hwnd, hdc: Hdc) -> i32 #link_name "ReleaseDC"; + proc get_dc (h: Hwnd) -> Hdc #cc_c #link_name "GetDC"; + proc release_dc (wnd: Hwnd, hdc: Hdc) -> i32 #cc_c #link_name "ReleaseDC"; - proc map_virtual_key(scancode : u32, map_type : u32) -> u32 #link_name "MapVirtualKeyA"; + proc map_virtual_key(scancode : u32, map_type : u32) -> u32 #cc_c #link_name "MapVirtualKeyA"; - proc get_key_state (v_key: i32) -> i16 #link_name "GetKeyState"; - proc get_async_key_state(v_key: i32) -> i16 #link_name "GetAsyncKeyState"; + proc get_key_state (v_key: i32) -> i16 #cc_c #link_name "GetKeyState"; + proc get_async_key_state(v_key: i32) -> i16 #cc_c #link_name "GetAsyncKeyState"; } foreign gdi32 { - proc get_stock_object(fn_object: i32) -> Hgdiobj #link_name "GetStockObject"; + proc get_stock_object(fn_object: i32) -> Hgdiobj #cc_c #link_name "GetStockObject"; proc stretch_dibits( hdc: Hdc, x_dst, y_dst, width_dst, height_dst: i32, x_src, y_src, width_src, header_src: i32, bits: rawptr, bits_info: ^BitmapInfo, usage: u32, - rop: u32) -> i32 #link_name "StretchDIBits"; + rop: u32) -> i32 #cc_c #link_name "StretchDIBits"; - proc set_pixel_format (hdc: Hdc, pixel_format: i32, pfd: ^PixelFormatDescriptor) -> Bool #link_name "SetPixelFormat"; - proc choose_pixel_format(hdc: Hdc, pfd: ^PixelFormatDescriptor) -> i32 #link_name "ChoosePixelFormat"; - proc swap_buffers (hdc: Hdc) -> Bool #link_name "SwapBuffers"; + proc set_pixel_format (hdc: Hdc, pixel_format: i32, pfd: ^PixelFormatDescriptor) -> Bool #cc_c #link_name "SetPixelFormat"; + proc choose_pixel_format(hdc: Hdc, pfd: ^PixelFormatDescriptor) -> i32 #cc_c #link_name "ChoosePixelFormat"; + proc swap_buffers (hdc: Hdc) -> Bool #cc_c #link_name "SwapBuffers"; } foreign shell32 { - proc command_line_to_argv_w(cmd_list: ^u16, num_args: ^i32) -> ^^u16 #link_name "CommandLineToArgvW"; + proc command_line_to_argv_w(cmd_list: ^u16, num_args: ^i32) -> ^^u16 #cc_c #link_name "CommandLineToArgvW"; } foreign winmm { - proc time_get_time() -> u32 #link_name "timeGetTime"; + proc time_get_time() -> u32 #cc_c #link_name "timeGetTime"; } diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 23b55b915..0c0c0a91c 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -269,7 +269,11 @@ void init_build_context(void) { #if defined(GB_SYSTEM_WINDOWS) bc->ODIN_OS = str_lit("windows"); - bc->ODIN_ARCH = str_lit("amd64"); + #if defined(GB_ARCH_64_BIT) + bc->ODIN_ARCH = str_lit("amd64"); + #else + bc->ODIN_ARCH = str_lit("x86"); + #endif bc->ODIN_ENDIAN = str_lit("little"); #elif defined(GB_SYSTEM_OSX) bc->ODIN_OS = str_lit("osx"); @@ -287,29 +291,27 @@ void init_build_context(void) { // across OSs. It doesn't make sense to allocate extra data on the heap // here, so I just #defined the linker flags to keep things concise. #if defined(GB_SYSTEM_WINDOWS) - - #define LINK_FLAG_X64 "/machine:x64" - #define LINK_FLAG_X86 "/machine:x86" + #define LINK_FLAG_X64 "/machine:x64" + #define LINK_FLAG_X86 "/machine:x86" #elif defined(GB_SYSTEM_OSX) + // NOTE(zangent): MacOS systems are x64 only, so ld doesn't have + // an architecture option. All compilation done on MacOS must be x64. + GB_ASSERT(bc->ODIN_ARCH == "amd64"); - // NOTE(zangent): MacOS systems are x64 only, so ld doesn't have - // an architecture option. All compilation done on MacOS must be x64. - GB_ASSERT(bc->ODIN_ARCH == "amd64"); - - #define LINK_FLAG_X64 "" - #define LINK_FLAG_X86 "" + #define LINK_FLAG_X64 "" + #define LINK_FLAG_X86 "" #else - // Linux, but also BSDs and the like. - // NOTE(zangent): When clang is swapped out with ld as the linker, - // the commented flags here should be used. Until then, we'll have - // to use alternative build flags made for clang. - /* - #define LINK_FLAG_X64 "-m elf_x86_64" - #define LINK_FLAG_X86 "-m elf_i386" - */ - #define LINK_FLAG_X64 "-arch x86-64" - #define LINK_FLAG_X86 "-arch x86" + // Linux, but also BSDs and the like. + // NOTE(zangent): When clang is swapped out with ld as the linker, + // the commented flags here should be used. Until then, we'll have + // to use alternative build flags made for clang. + /* + #define LINK_FLAG_X64 "-m elf_x86_64" + #define LINK_FLAG_X86 "-m elf_i386" + */ + #define LINK_FLAG_X64 "-arch x86-64" + #define LINK_FLAG_X86 "-arch x86" #endif if (bc->ODIN_ARCH == "amd64") { diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 6cb51102a..dede1a26c 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -12,7 +12,7 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex // TODO(bill): is this a good enough error message? // TODO(bill): Actually allow built in procedures to be passed around and thus be created on use - error_node(operand->expr, + error(operand->expr, "Cannot assign built-in procedure `%s` in %.*s", expr_str, LIT(context_name)); @@ -108,7 +108,7 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) { if (operand->mode != Addressing_Constant) { // TODO(bill): better error gbString str = expr_to_string(operand->expr); - error_node(operand->expr, "`%s` is not a constant", str); + error(operand->expr, "`%s` is not a constant", str); gb_string_free(str); if (e->type == NULL) { e->type = t_invalid; @@ -117,7 +117,7 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) { } if (!is_type_constant_type(operand->type)) { gbString type_str = type_to_string(operand->type); - error_node(operand->expr, "Invalid constant type: `%s`", type_str); + error(operand->expr, "Invalid constant type: `%s`", type_str); gb_string_free(type_str); if (e->type == NULL) { e->type = t_invalid; @@ -172,7 +172,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, Type *t = check_type(c, type_expr); if (!is_type_constant_type(t)) { gbString str = type_to_string(t); - error_node(type_expr, "Invalid constant type `%s`", str); + error(type_expr, "Invalid constant type `%s`", str); gb_string_free(str); e->type = t_invalid; return; @@ -279,18 +279,18 @@ void init_entity_foreign_library(Checker *c, Entity *e) { if (ident == NULL) { error(e->token, "foreign entiies must declare which library they are from"); } else if (ident->kind != AstNode_Ident) { - error_node(ident, "foreign library names must be an identifier"); + error(ident, "foreign library names must be an identifier"); } else { String name = ident->Ident.string; Entity *found = scope_lookup_entity(c->context.scope, name); if (found == NULL) { if (name == "_") { - error_node(ident, "`_` cannot be used as a value type"); + error(ident, "`_` cannot be used as a value type"); } else { - error_node(ident, "Undeclared name: %.*s", LIT(name)); + error(ident, "Undeclared name: %.*s", LIT(name)); } } else if (found->kind != Entity_LibraryName) { - error_node(ident, "`%.*s` cannot be used as a library name", LIT(name)); + error(ident, "`%.*s` cannot be used as a library name", LIT(name)); } else { // TODO(bill): Extra stuff to do with library names? *foreign_library = found; @@ -303,7 +303,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { GB_ASSERT(e->type == NULL); if (d->proc_decl->kind != AstNode_ProcDecl) { // TOOD(bill): Better error message - error_node(d->proc_decl, "Expected a procedure to check"); + error(d->proc_decl, "Expected a procedure to check"); return; } @@ -336,11 +336,11 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { } if (is_inline && is_no_inline) { - error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure"); + error(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure"); } if (is_foreign && is_export) { - error_node(pd->type, "A foreign procedure cannot have an `export` tag"); + error(pd->type, "A foreign procedure cannot have an `export` tag"); } @@ -352,10 +352,10 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { if (pd->body != NULL) { if (is_foreign) { - error_node(pd->body, "A foreign procedure cannot have a body"); + error(pd->body, "A foreign procedure cannot have a body"); } if (proc_type->Proc.c_vararg) { - error_node(pd->body, "A procedure with a `#c_vararg` field cannot have a body"); + error(pd->body, "A procedure with a `#c_vararg` field cannot have a body"); } d->scope = c->context.scope; @@ -367,7 +367,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { } if (pt->result_count == 0 && is_require_results) { - error_node(pd->type, "`#require_results` is not needed on a procedure with no results"); + error(pd->type, "`#require_results` is not needed on a procedure with no results"); } else { pt->require_results = is_require_results; } @@ -393,13 +393,13 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { Type *other_type = base_type(f->type); if (is_type_proc(this_type) && is_type_proc(other_type)) { if (!are_signatures_similar_enough(this_type, other_type)) { - error_node(d->proc_decl, + error(d->proc_decl, "Redeclaration of foreign procedure `%.*s` with different type signatures\n" "\tat %.*s(%td:%td)", LIT(name), LIT(pos.file), pos.line, pos.column); } } else if (!are_types_identical(this_type, other_type)) { - error_node(d->proc_decl, + error(d->proc_decl, "Foreign entity `%.*s` previously declared elsewhere with a different type\n" "\tat %.*s(%td:%td)", LIT(name), LIT(pos.file), pos.line, pos.column); @@ -424,7 +424,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { Entity *f = *found; TokenPos pos = f->token.pos; // TODO(bill): Better error message? - error_node(d->proc_decl, + error(d->proc_decl, "Non unique linking name for procedure `%.*s`\n" "\tother at %.*s(%td:%td)", LIT(name), LIT(pos.file), pos.line, pos.column); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index b7c813bac..92e14fa5b 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -25,7 +25,7 @@ Type * check_call_arguments (Checker *c, Operand *operand, Type *pro void error_operand_not_expression(Operand *o) { if (o->mode == Addressing_Type) { gbString err = expr_to_string(o->expr); - error_node(o->expr, "`%s` is not an expression but a type", err); + error(o->expr, "`%s` is not an expression but a type", err); gb_string_free(err); o->mode = Addressing_Invalid; } @@ -34,7 +34,7 @@ void error_operand_not_expression(Operand *o) { void error_operand_no_value(Operand *o) { if (o->mode == Addressing_NoValue) { gbString err = expr_to_string(o->expr); - error_node(o->expr, "`%s` used as value", err); + error(o->expr, "`%s` used as value", err); gb_string_free(err); o->mode = Addressing_Invalid; } @@ -290,7 +290,7 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n Type *target_type = type; if (type == NULL || is_type_any(type)) { if (type == NULL && is_type_untyped_nil(operand->type)) { - error_node(operand->expr, "Use of untyped nil in %.*s", LIT(context_name)); + error(operand->expr, "Use of untyped nil in %.*s", LIT(context_name)); operand->mode = Addressing_Invalid; return; } @@ -324,13 +324,13 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n if (operand->mode == Addressing_Builtin) { // TODO(bill): is this a good enough error message? // TODO(bill): Actually allow built in procedures to be passed around and thus be created on use - error_node(operand->expr, + error(operand->expr, "Cannot assign built-in procedure `%s` in %.*s", expr_str, LIT(context_name)); } else { // TODO(bill): is this a good enough error message? - error_node(operand->expr, + error(operand->expr, "Cannot assign value `%s` of type `%s` to `%s` in %.*s", expr_str, op_type_str, @@ -411,7 +411,7 @@ isize check_fields(Checker *c, AstNode *node, Array decls, if (is_using) { if (f->names.count > 1) { - error_node(f->names[0], "Cannot apply `using` to more than one of the same type"); + error(f->names[0], "Cannot apply `using` to more than one of the same type"); is_using = false; } } @@ -429,7 +429,7 @@ isize check_fields(Checker *c, AstNode *node, Array decls, if (name_token.string == "_") { fields[field_index++] = e; } else if (name_token.string == "__tag") { - error_node(name, "`__tag` is a reserved identifier for fields"); + error(name, "`__tag` is a reserved identifier for fields"); } else { HashKey key = hash_string(name_token.string); Entity **found = map_get(&entity_map, key); @@ -595,7 +595,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { if (st->align != NULL) { if (st->is_packed) { - syntax_error_node(st->align, "`#align` cannot be applied with `#packed`"); + syntax_error(st->align, "`#align` cannot be applied with `#packed`"); return; } @@ -603,7 +603,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { check_expr(c, &o, st->align); if (o.mode != Addressing_Constant) { if (o.mode != Addressing_Invalid) { - error_node(st->align, "#align must be a constant"); + error(st->align, "#align must be a constant"); } return; } @@ -613,21 +613,21 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { if (o.value.kind == ExactValue_Integer) { i64 align = i128_to_i64(o.value.value_integer); if (align < 1 || !gb_is_power_of_two(align)) { - error_node(st->align, "#align must be a power of 2, got %lld", align); + error(st->align, "#align must be a power of 2, got %lld", align); return; } // NOTE(bill): Success!!! i64 custom_align = gb_clamp(align, 1, build_context.max_align); if (custom_align < align) { - warning_node(st->align, "Custom alignment has been clamped to %lld from %lld", align, custom_align); + warning(st->align, "Custom alignment has been clamped to %lld from %lld", align, custom_align); } struct_type->Record.custom_align = custom_align; return; } } - error_node(st->align, "#align must be an integer"); + error(st->align, "#align must be an integer"); return; } @@ -792,11 +792,11 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod } if (base_type == NULL || !(is_type_integer(base_type) || is_type_float(base_type))) { - error_node(node, "Base type for enumeration must be numeric"); + error(node, "Base type for enumeration must be numeric"); return; } if (is_type_enum(base_type)) { - error_node(node, "Base type for enumeration cannot be another enumeration"); + error(node, "Base type for enumeration cannot be another enumeration"); return; } @@ -825,7 +825,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod if (field->kind == AstNode_FieldValue) { ast_node(fv, FieldValue, field); if (fv->field == NULL || fv->field->kind != AstNode_Ident) { - error_node(field, "An enum field's name must be an identifier"); + error(field, "An enum field's name must be an identifier"); continue; } ident = fv->field; @@ -833,7 +833,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod } else if (field->kind == AstNode_Ident) { ident = field; } else { - error_node(field, "An enum field's name must be an identifier"); + error(field, "An enum field's name must be an identifier"); continue; } String name = ident->Ident.string; @@ -842,7 +842,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod Operand o = {}; check_expr(c, &o, init); if (o.mode != Addressing_Constant) { - error_node(init, "Enumeration value must be a constant"); + error(init, "Enumeration value must be a constant"); o.mode = Addressing_Invalid; } if (o.mode != Addressing_Invalid) { @@ -862,19 +862,19 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod if (name == "_") { continue; } else if (name == "count") { - error_node(field, "`count` is a reserved identifier for enumerations"); + error(field, "`count` is a reserved identifier for enumerations"); continue; } else if (name == "min_value") { - error_node(field, "`min_value` is a reserved identifier for enumerations"); + error(field, "`min_value` is a reserved identifier for enumerations"); continue; } else if (name == "max_value") { - error_node(field, "`max_value` is a reserved identifier for enumerations"); + error(field, "`max_value` is a reserved identifier for enumerations"); continue; } else if (name == "names") { - error_node(field, "`names` is a reserved identifier for enumerations"); + error(field, "`names` is a reserved identifier for enumerations"); continue; }/* else if (name == "base_type") { - error_node(field, "`base_type` is a reserved identifier for enumerations"); + error(field, "`base_type` is a reserved identifier for enumerations"); continue; } */ @@ -891,7 +891,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod HashKey key = hash_string(name); if (map_get(&entity_map, key) != NULL) { - error_node(ident, "`%.*s` is already declared in this enumeration", LIT(name)); + error(ident, "`%.*s` is already declared in this enumeration", LIT(name)); } else { map_set(&entity_map, key, e); add_entity(c, c->context.scope, NULL, e); @@ -940,7 +940,7 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As AstNode *value = field->FieldValue.value; if (ident->kind != AstNode_Ident) { - error_node(field, "A bit field value's name must be an identifier"); + error(field, "A bit field value's name must be an identifier"); continue; } String name = ident->Ident.string; @@ -948,17 +948,17 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As Operand o = {}; check_expr(c, &o, value); if (o.mode != Addressing_Constant) { - error_node(value, "Bit field bit size must be a constant"); + error(value, "Bit field bit size must be a constant"); continue; } ExactValue v = exact_value_to_integer(o.value); if (v.kind != ExactValue_Integer) { - error_node(value, "Bit field bit size must be a constant integer"); + error(value, "Bit field bit size must be a constant integer"); continue; } i64 bits = i128_to_i64(v.value_integer); if (bits < 0 || bits > 128) { - error_node(value, "Bit field's bit size must be within the range 1..<128, got %lld", cast(long long)bits); + error(value, "Bit field's bit size must be within the range 1..<128, got %lld", cast(long long)bits); continue; } @@ -970,7 +970,7 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As HashKey key = hash_string(name); if (name != "_" && map_get(&entity_map, key) != NULL) { - error_node(ident, "`%.*s` is already declared in this bit field", LIT(name)); + error(ident, "`%.*s` is already declared in this bit field", LIT(name)); } else { map_set(&entity_map, key, e); add_entity(c, c->context.scope, NULL, e); @@ -998,7 +998,7 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As check_expr(c, &o, bft->align); if (o.mode != Addressing_Constant) { if (o.mode != Addressing_Invalid) { - error_node(bft->align, "#align must be a constant"); + error(bft->align, "#align must be a constant"); } return; } @@ -1008,21 +1008,21 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As if (o.value.kind == ExactValue_Integer) { i64 align = i128_to_i64(o.value.value_integer); if (align < 1 || !gb_is_power_of_two(align)) { - error_node(bft->align, "#align must be a power of 2, got %lld", align); + error(bft->align, "#align must be a power of 2, got %lld", align); return; } // NOTE(bill): Success!!! i64 custom_align = gb_clamp(align, 1, build_context.max_align); if (custom_align < align) { - warning_node(bft->align, "Custom alignment has been clamped to %lld from %lld", align, custom_align); + warning(bft->align, "Custom alignment has been clamped to %lld from %lld", align, custom_align); } bit_field_type->BitField.custom_align = custom_align; return; } } - error_node(bft->align, "#align must be an integer"); + error(bft->align, "#align must be an integer"); return; } } @@ -1079,7 +1079,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari if (is_operand_nil(o)) { default_is_nil = true; } else if (o.mode != Addressing_Constant) { - error_node(default_value, "Default parameter must be a constant"); + error(default_value, "Default parameter must be a constant"); } else { value = o.value; } @@ -1092,7 +1092,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari if (i+1 == params.count) { is_variadic = true; } else { - error_node(param, "Invalid AST: Invalid variadic parameter"); + error(param, "Invalid AST: Invalid variadic parameter"); } } if (type_expr->kind == AstNode_HelperType) { @@ -1115,7 +1115,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari if (is_operand_nil(o)) { default_is_nil = true; } else if (o.mode != Addressing_Constant) { - error_node(default_value, "Default parameter must be a constant"); + error(default_value, "Default parameter must be a constant"); } else { value = o.value; } @@ -1126,24 +1126,24 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari } if (type == NULL) { - error_node(params[i], "Invalid parameter type"); + error(params[i], "Invalid parameter type"); type = t_invalid; } if (is_type_untyped(type)) { - error_node(params[i], "Cannot determine parameter type from a nil"); + error(params[i], "Cannot determine parameter type from a nil"); type = t_invalid; } if (p->flags&FieldFlag_no_alias) { if (!is_type_pointer(type)) { - error_node(params[i], "`#no_alias` can only be applied to fields of pointer type"); + error(params[i], "`#no_alias` can only be applied to fields of pointer type"); p->flags &= ~FieldFlag_no_alias; // Remove the flag } } if (p->flags&FieldFlag_c_vararg) { if (p->type == NULL || p->type->kind != AstNode_Ellipsis) { - error_node(params[i], "`#c_vararg` can only be applied to variadic type fields"); + error(params[i], "`#c_vararg` can only be applied to variadic type fields"); p->flags &= ~FieldFlag_c_vararg; // Remove the flag } else { is_c_vararg = true; @@ -1234,7 +1234,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) { AstNode *name = field->names[j]; if (name->kind != AstNode_Ident) { - error_node(name, "Expected an identifer for as the field name"); + error(name, "Expected an identifer for as the field name"); } else { token = name->Ident; } @@ -1622,11 +1622,11 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type * case Entity_ImportName: if (!allow_import_name) { - error_node(n, "Use of import `%.*s` not in selector", LIT(name)); + error(n, "Use of import `%.*s` not in selector", LIT(name)); } return e; case Entity_LibraryName: - error_node(n, "Use of library `%.*s` not in foreign block", LIT(name)); + error(n, "Use of library `%.*s` not in foreign block", LIT(name)); return e; case Entity_Label: @@ -1660,9 +1660,9 @@ i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) { if (o.mode != Addressing_Constant) { if (o.mode != Addressing_Invalid) { if (is_map) { - error_node(e, "Fixed map count must be a constant"); + error(e, "Fixed map count must be a constant"); } else { - error_node(e, "Array count must be a constant"); + error(e, "Array count must be a constant"); } } return 0; @@ -1675,21 +1675,21 @@ i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) { if (count > 0) { return count; } - error_node(e, "Invalid fixed map count"); + error(e, "Invalid fixed map count"); } else { if (count >= 0) { return count; } - error_node(e, "Invalid array count"); + error(e, "Invalid array count"); } return 0; } } if (is_map) { - error_node(e, "Fixed map count must be an integer"); + error(e, "Fixed map count must be an integer"); } else { - error_node(e, "Array count must be an integer"); + error(e, "Array count must be an integer"); } return 0; } @@ -1714,17 +1714,17 @@ void check_map_type(Checker *c, Type *type, AstNode *node) { if (!is_type_valid_for_keys(key)) { if (is_type_boolean(key)) { - error_node(node, "A boolean cannot be used as a key for a map"); + error(node, "A boolean cannot be used as a key for a map"); } else { gbString str = type_to_string(key); - error_node(node, "Invalid type of a key for a map, got `%s`", str); + error(node, "Invalid type of a key for a map, got `%s`", str); gb_string_free(str); } } if (count > 0) { count = 0; - error_node(node, "Fixed map types are not yet implemented"); + error(node, "Fixed map types are not yet implemented"); } type->Map.count = count; @@ -1803,7 +1803,7 @@ void check_map_type(Checker *c, Type *type, AstNode *node) { type->Map.lookup_result_type = make_optional_ok_type(a, value); - // error_node(node, "`map` types are not yet implemented"); + // error(node, "`map` types are not yet implemented"); } bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) { @@ -1827,12 +1827,12 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) } break; case Addressing_NoValue: { gbString err_str = expr_to_string(e); - error_node(e, "`%s` used as a type", err_str); + error(e, "`%s` used as a type", err_str); gb_string_free(err_str); } break; default: { gbString err_str = expr_to_string(e); - error_node(e, "`%s` used as a type when not a type", err_str); + error(e, "`%s` used as a type when not a type", err_str); gb_string_free(err_str); } break; } @@ -1851,12 +1851,12 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) return true; case Addressing_NoValue: { gbString err_str = expr_to_string(e); - error_node(e, "`%s` used as a type", err_str); + error(e, "`%s` used as a type", err_str); gb_string_free(err_str); } break; default: { gbString err_str = expr_to_string(e); - error_node(e, "`%s` is not a type", err_str); + error(e, "`%s` is not a type", err_str); gb_string_free(err_str); } break; } @@ -1896,14 +1896,14 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) Type *elem = check_type(c, at->elem, NULL); i64 count = check_array_or_map_count(c, at->count, false); if (count < 0) { - error_node(at->count, ".. can only be used in conjuction with compound literals"); + error(at->count, ".. can only be used in conjuction with compound literals"); count = 0; } #if 0 i64 esz = type_size_of(c->allocator, elem); if (esz == 0) { gbString str = type_to_string(elem); - error_node(at->elem, "Zero sized element type `%s` is not allowed", str); + error(at->elem, "Zero sized element type `%s` is not allowed", str); gb_string_free(str); } #endif @@ -1914,7 +1914,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) i64 esz = type_size_of(c->allocator, elem); if (esz == 0) { gbString str = type_to_string(elem); - error_node(at->elem, "Zero sized element type `%s` is not allowed", str); + error(at->elem, "Zero sized element type `%s` is not allowed", str); gb_string_free(str); } #endif @@ -1929,7 +1929,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) #if 0 if (esz == 0) { gbString str = type_to_string(elem); - error_node(dat->elem, "Zero sized element type `%s` is not allowed", str); + error(dat->elem, "Zero sized element type `%s` is not allowed", str); gb_string_free(str); } #endif @@ -1945,7 +1945,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) i64 count = check_array_or_map_count(c, vt->count, false); if (is_type_vector(be) || (!is_type_boolean(be) && !is_type_numeric(be))) { gbString err_str = type_to_string(elem); - error_node(vt->elem, "Vector element type must be numerical or a boolean, got `%s`", err_str); + error(vt->elem, "Vector element type must be numerical or a boolean, got `%s`", err_str); gb_string_free(err_str); } *type = make_type_vector(c->allocator, elem, count); @@ -2039,7 +2039,7 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) { if (!ok) { gbString err_str = expr_to_string(e); - error_node(e, "`%s` is not a type", err_str); + error(e, "`%s` is not a type", err_str); gb_string_free(err_str); type = t_invalid; } @@ -2051,7 +2051,7 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) { if (type->kind == Type_Named) { if (type->Named.base == NULL) { gbString name = type_to_string(type); - error_node(e, "Invalid type definition of %s", name); + error(e, "Invalid type definition of %s", name); gb_string_free(name); type->Named.base = t_invalid; } @@ -2061,7 +2061,7 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) { add_type_and_value(&c->info, e, Addressing_Type, type, empty_exact_value); } else { gbString name = type_to_string(type); - error_node(e, "Invalid type definition of %s", name); + error(e, "Invalid type definition of %s", name); gb_string_free(name); type = t_invalid; } @@ -2074,7 +2074,7 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) { bool check_unary_op(Checker *c, Operand *o, Token op) { if (o->type == NULL) { gbString str = expr_to_string(o->expr); - error_node(o->expr, "Expression has no value `%s`", str); + error(o->expr, "Expression has no value `%s`", str); gb_string_free(str); return false; } @@ -2128,7 +2128,7 @@ bool check_binary_op(Checker *c, Operand *o, Token op) { } if (base_type(type) == t_rawptr) { gbString str = type_to_string(type); - error_node(o->expr, "Invalid pointer type for pointer arithmetic: `%s`", str); + error(o->expr, "Invalid pointer type for pointer arithmetic: `%s`", str); gb_string_free(str); return false; } @@ -2310,7 +2310,7 @@ void check_is_expressible(Checker *c, Operand *o, Type *type) { gbString b = type_to_string(type); if (is_type_numeric(o->type) && is_type_numeric(type)) { if (!is_type_integer(o->type) && is_type_integer(type)) { - error_node(o->expr, "`%s` truncated to `%s`", a, b); + error(o->expr, "`%s` truncated to `%s`", a, b); } else { char buf[127] = {}; String str = {}; @@ -2320,10 +2320,10 @@ void check_is_expressible(Checker *c, Operand *o, Type *type) { } else { str = i128_to_string(i, buf, gb_size_of(buf)); } - error_node(o->expr, "`%s = %.*s` overflows `%s`", a, str, b); + error(o->expr, "`%s = %.*s` overflows `%s`", a, str, b); } } else { - error_node(o->expr, "Cannot convert `%s` to `%s`", a, b); + error(o->expr, "Cannot convert `%s` to `%s`", a, b); } gb_string_free(b); @@ -2489,7 +2489,7 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) { } if (err_str != NULL) { - error_node(x->expr, "Cannot compare expression, %s", err_str); + error(x->expr, "Cannot compare expression, %s", err_str); x->type = t_untyped_bool; } else { if (x->mode == Addressing_Constant && @@ -2528,7 +2528,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { bool x_is_untyped = is_type_untyped(x->type); if (!(is_type_integer(x->type) || (x_is_untyped && x_val.kind == ExactValue_Integer))) { gbString err_str = expr_to_string(x->expr); - error_node(node, "Shifted operand `%s` must be an integer", err_str); + error(node, "Shifted operand `%s` must be an integer", err_str); gb_string_free(err_str); x->mode = Addressing_Invalid; return; @@ -2544,7 +2544,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { } } else { gbString err_str = expr_to_string(y->expr); - error_node(node, "Shift amount `%s` must be an unsigned integer", err_str); + error(node, "Shift amount `%s` must be an unsigned integer", err_str); gb_string_free(err_str); x->mode = Addressing_Invalid; return; @@ -2556,7 +2556,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { ExactValue y_val = exact_value_to_integer(y->value); if (y_val.kind != ExactValue_Integer) { gbString err_str = expr_to_string(y->expr); - error_node(node, "Shift amount `%s` must be an unsigned integer", err_str); + error(node, "Shift amount `%s` must be an unsigned integer", err_str); gb_string_free(err_str); x->mode = Addressing_Invalid; return; @@ -2565,7 +2565,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { i64 amount = i128_to_i64(y_val.value_integer); if (amount > 128) { gbString err_str = expr_to_string(y->expr); - error_node(node, "Shift amount too large: `%s`", err_str); + error(node, "Shift amount too large: `%s`", err_str); gb_string_free(err_str); x->mode = Addressing_Invalid; return; @@ -2599,13 +2599,13 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { if (y->mode == Addressing_Constant && i128_lt(y->value.value_integer, I128_ZERO)) { gbString err_str = expr_to_string(y->expr); - error_node(node, "Shift amount cannot be negative: `%s`", err_str); + error(node, "Shift amount cannot be negative: `%s`", err_str); gb_string_free(err_str); } if (!is_type_integer(x->type)) { gbString err_str = expr_to_string(y->expr); - error_node(node, "Shift operand `%s` must be an integer", err_str); + error(node, "Shift operand `%s` must be an integer", err_str); gb_string_free(err_str); x->mode = Addressing_Invalid; return; @@ -2658,7 +2658,7 @@ Operand check_ptr_addition(Checker *c, TokenKind op, Operand *ptr, Operand *offs if (base_type(ptr->type) == t_rawptr) { gbString str = type_to_string(ptr->type); - error_node(node, "Invalid pointer type for pointer arithmetic: `%s`", str); + error(node, "Invalid pointer type for pointer arithmetic: `%s`", str); gb_string_free(str); operand.mode = Addressing_Invalid; return operand; @@ -2670,7 +2670,7 @@ Operand check_ptr_addition(Checker *c, TokenKind op, Operand *ptr, Operand *offs if (elem_size <= 0) { gbString str = type_to_string(elem); - error_node(node, "Size of pointer's element type `%s` is zero and cannot be used for pointer arithmetic", str); + error(node, "Size of pointer's element type `%s` is zero and cannot be used for pointer arithmetic", str); gb_string_free(str); operand.mode = Addressing_Invalid; return operand; @@ -2758,7 +2758,7 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) { // NOTE(bill): This error should suppress the next casting error as it's at the same position gbString xs = type_to_string(x); gbString ys = type_to_string(y); - error_node(operand->expr, "Cannot cast from a union pointer `%s` to `%s`, try using `union_cast` or cast to a `rawptr`", xs, ys); + error(operand->expr, "Cannot cast from a union pointer `%s` to `%s`, try using `union_cast` or cast to a `rawptr`", xs, ys); gb_string_free(ys); gb_string_free(xs); return false; @@ -2829,7 +2829,7 @@ void check_cast(Checker *c, Operand *x, Type *type) { gbString expr_str = expr_to_string(x->expr); gbString to_type = type_to_string(type); gbString from_type = type_to_string(x->type); - error_node(x->expr, "Cannot cast `%s` as `%s` from `%s`", expr_str, to_type, from_type); + error(x->expr, "Cannot cast `%s` as `%s` from `%s`", expr_str, to_type, from_type); gb_string_free(from_type); gb_string_free(to_type); gb_string_free(expr_str); @@ -2911,7 +2911,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { if (op.kind == Token_Sub) { gbString lhs = expr_to_string(x->expr); gbString rhs = expr_to_string(y->expr); - error_node(node, "Invalid pointer arithmetic, did you mean `%s %.*s %s`?", rhs, LIT(op.string), lhs); + error(node, "Invalid pointer arithmetic, did you mean `%s %.*s %s`?", rhs, LIT(op.string), lhs); gb_string_free(rhs); gb_string_free(lhs); x->mode = Addressing_Invalid; @@ -2993,7 +2993,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { } if (fail) { - error_node(y->expr, "Division by zero not allowed"); + error(y->expr, "Division by zero not allowed"); x->mode = Addressing_Invalid; return; } @@ -3091,7 +3091,7 @@ void update_expr_type(Checker *c, AstNode *e, Type *type, bool final) { if (old.is_lhs && !is_type_integer(type)) { gbString expr_str = expr_to_string(e); gbString type_str = type_to_string(type); - error_node(e, "Shifted operand %s must be an integer, got %s", expr_str, type_str); + error(e, "Shifted operand %s must be an integer, got %s", expr_str, type_str); gb_string_free(type_str); gb_string_free(expr_str); return; @@ -3120,7 +3120,7 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) { } } } - error_node(operand->expr, "Cannot convert `%s` to `%s`%s", expr_str, type_str, extra_text); + error(operand->expr, "Cannot convert `%s` to `%s`%s", expr_str, type_str, extra_text); gb_string_free(type_str); gb_string_free(expr_str); @@ -3255,7 +3255,7 @@ bool check_index_value(Checker *c, bool open_range, AstNode *index_value, i64 ma if (!is_type_integer(operand.type)) { gbString expr_str = expr_to_string(operand.expr); - error_node(operand.expr, "Index `%s` must be an integer", expr_str); + error(operand.expr, "Index `%s` must be an integer", expr_str); gb_string_free(expr_str); if (value) *value = 0; return false; @@ -3266,7 +3266,7 @@ bool check_index_value(Checker *c, bool open_range, AstNode *index_value, i64 ma i64 i = i128_to_i64(exact_value_to_integer(operand.value).value_integer); if (i < 0) { gbString expr_str = expr_to_string(operand.expr); - error_node(operand.expr, "Index `%s` cannot be a negative value", expr_str); + error(operand.expr, "Index `%s` cannot be a negative value", expr_str); gb_string_free(expr_str); if (value) *value = 0; return false; @@ -3282,7 +3282,7 @@ bool check_index_value(Checker *c, bool open_range, AstNode *index_value, i64 ma } if (out_of_bounds) { gbString expr_str = expr_to_string(operand.expr); - error_node(operand.expr, "Index `%s` is out of bounds range 0..<%lld", expr_str, max_count); + error(operand.expr, "Index `%s` is out of bounds range 0..<%lld", expr_str, max_count); gb_string_free(expr_str); return false; } @@ -3350,7 +3350,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h if (selector->kind != AstNode_Ident && selector->kind != AstNode_BasicLit) { // if (selector->kind != AstNode_Ident) { - error_node(selector, "Illegal selector kind: `%.*s`", LIT(ast_node_strings[selector->kind])); + error(selector, "Illegal selector kind: `%.*s`", LIT(ast_node_strings[selector->kind])); operand->mode = Addressing_Invalid; operand->expr = node; return NULL; @@ -3385,7 +3385,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } } if (!is_declared) { - error_node(op_expr, "`%.*s` is not declared by `%.*s`", LIT(entity_name), LIT(import_name)); + error(op_expr, "`%.*s` is not declared by `%.*s`", LIT(entity_name), LIT(import_name)); operand->mode = Addressing_Invalid; operand->expr = node; return NULL; @@ -3406,7 +3406,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h if (is_not_exported) { gbString sel_str = expr_to_string(selector); - error_node(op_expr, "`%s` is not exported by `%.*s`", sel_str, LIT(import_name)); + error(op_expr, "`%s` is not exported by `%.*s`", sel_str, LIT(import_name)); gb_string_free(sel_str); operand->mode = Addressing_Invalid; operand->expr = node; @@ -3473,7 +3473,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h sel = lookup_field(c->allocator, operand->type, field_name, operand->mode == Addressing_Type); if (operand->mode != Addressing_Type && !check_is_field_exported(c, sel.entity)) { - error_node(op_expr, "`%.*s` is an unexported field", LIT(field_name)); + error(op_expr, "`%.*s` is an unexported field", LIT(field_name)); operand->mode = Addressing_Invalid; operand->expr = node; return NULL; @@ -3492,14 +3492,14 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h check_expr(c, &o, selector); if (o.mode != Addressing_Constant || !is_type_integer(o.type)) { - error_node(op_expr, "Indexed based selectors must be a constant integer %s"); + error(op_expr, "Indexed based selectors must be a constant integer %s"); operand->mode = Addressing_Invalid; operand->expr = node; return NULL; } i64 index = i128_to_i64(o.value.value_integer); if (index < 0) { - error_node(o.expr, "Index %lld cannot be a negative value", index); + error(o.expr, "Index %lld cannot be a negative value", index); operand->mode = Addressing_Invalid; operand->expr = node; return NULL; @@ -3512,7 +3512,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } if (index >= max_count) { - error_node(o.expr, "Index %lld is out of bounds range 0..<%lld", index, max_count); + error(o.expr, "Index %lld is out of bounds range 0..<%lld", index, max_count); operand->mode = Addressing_Invalid; operand->expr = node; return NULL; @@ -3524,7 +3524,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h GB_ASSERT(entity != NULL); } else { - error_node(op_expr, "Indexed based selectors may only be used on structs or tuples"); + error(op_expr, "Indexed based selectors may only be used on structs or tuples"); operand->mode = Addressing_Invalid; operand->expr = node; return NULL; @@ -3544,7 +3544,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h gbString op_str = expr_to_string(op_expr); gbString type_str = type_to_string(operand->type); gbString sel_str = expr_to_string(selector); - error_node(op_expr, "`%s` of type `%s` has no field `%s`", op_str, type_str, sel_str); + error(op_expr, "`%s` of type `%s` has no field `%s`", op_str, type_str, sel_str); gb_string_free(sel_str); gb_string_free(type_str); gb_string_free(op_str); @@ -3557,7 +3557,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h gbString op_str = expr_to_string(op_expr); gbString type_str = type_to_string(operand->type); gbString sel_str = expr_to_string(selector); - error_node(op_expr, "Cannot access non-constant field `%s` from `%s`", sel_str, op_str); + error(op_expr, "Cannot access non-constant field `%s` from `%s`", sel_str, op_str); gb_string_free(sel_str); gb_string_free(type_str); gb_string_free(op_str); @@ -3632,7 +3632,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (ce->args.count > 0) { if (ce->args[0]->kind == AstNode_FieldValue) { - error_node(call, "`field = value` calling is not allowed on built-in procedures"); + error(call, "`field = value` calling is not allowed on built-in procedures"); return false; } } @@ -3672,7 +3672,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id String name = bd->name; GB_ASSERT(name == "location"); if (ce->args.count > 1) { - error_node(ce->args[0], "`#location` expects either 0 or 1 arguments, got %td", ce->args.count); + error(ce->args[0], "`#location` expects either 0 or 1 arguments, got %td", ce->args.count); } if (ce->args.count > 0) { AstNode *arg = ce->args[0]; @@ -3684,7 +3684,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id e = check_selector(c, &o, arg, NULL); } if (e == NULL) { - error_node(ce->args[0], "`#location` expected a valid entity name"); + error(ce->args[0], "`#location` expected a valid entity name"); } } @@ -3731,7 +3731,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (mode == Addressing_Invalid) { String name = builtin_procs[id].name; gbString t = type_to_string(operand->type); - error_node(call, "`%.*s` is not supported for `%s`", LIT(name), t); + error(call, "`%.*s` is not supported for `%s`", LIT(name), t); return false; } @@ -3746,7 +3746,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id check_expr_or_type(c, &op, ce->args[0]); Type *type = op.type; if ((op.mode != Addressing_Type && type == NULL) || type == t_invalid) { - error_node(ce->args[0], "Expected a type for `new`"); + error(ce->args[0], "Expected a type for `new`"); return false; } operand->mode = Addressing_Value; @@ -3760,13 +3760,13 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id check_expr_or_type(c, &op, ce->args[0]); Type *type = op.type; if ((op.mode != Addressing_Type && type == NULL) || type == t_invalid) { - error_node(ce->args[0], "Expected a type for `new_slice`"); + error(ce->args[0], "Expected a type for `new_slice`"); return false; } isize arg_count = ce->args.count; if (arg_count < 2 || 3 < arg_count) { - error_node(ce->args[0], "`new_slice` expects 2 or 3 arguments, found %td", arg_count); + error(ce->args[0], "`new_slice` expects 2 or 3 arguments, found %td", arg_count); // NOTE(bill): Return the correct type to reduce errors } else { // If any are constant @@ -3782,7 +3782,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } if (size_count == 2 && sizes[0] > sizes[1]) { - error_node(ce->args[1], "`new_slice` count and capacity are swapped"); + error(ce->args[1], "`new_slice` count and capacity are swapped"); // No need quit } } @@ -3798,7 +3798,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id check_expr_or_type(c, &op, ce->args[0]); Type *type = op.type; if ((op.mode != Addressing_Type && type == NULL) || type == t_invalid) { - error_node(ce->args[0], "Expected a type for `make`"); + error(ce->args[0], "Expected a type for `make`"); return false; } @@ -3815,14 +3815,14 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id max_args = 3; } else { gbString str = type_to_string(type); - error_node(call, "Cannot `make` %s; type must be a slice, map, or dynamic array", str); + error(call, "Cannot `make` %s; type must be a slice, map, or dynamic array", str); gb_string_free(str); return false; } isize arg_count = ce->args.count; if (arg_count < min_args || max_args < arg_count) { - error_node(ce->args[0], "`make` expects %td or %d argument, found %td", min_args, max_args, arg_count); + error(ce->args[0], "`make` expects %td or %d argument, found %td", min_args, max_args, arg_count); return false; } @@ -3839,7 +3839,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } if (size_count == 2 && sizes[0] > sizes[1]) { - error_node(ce->args[1], "`make` count and capacity are swapped"); + error(ce->args[1], "`make` count and capacity are swapped"); // No need quit } @@ -3868,7 +3868,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (!ok) { gbString type_str = type_to_string(type); - error_node(operand->expr, "Invalid type for `free`, got `%s`", type_str); + error(operand->expr, "Invalid type for `free`, got `%s`", type_str); gb_string_free(type_str); return false; } @@ -3884,7 +3884,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Type *type = operand->type; if (!is_type_dynamic_array(type) && !is_type_dynamic_map(type)) { gbString str = type_to_string(type); - error_node(operand->expr, "Expected a dynamic array or dynamic map, got `%s`", str); + error(operand->expr, "Expected a dynamic array or dynamic map, got `%s`", str); gb_string_free(str); return false; } @@ -3897,7 +3897,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } Type *arg_type = base_type(op.type); if (!is_type_integer(arg_type)) { - error_node(operand->expr, "`reserve` capacities must be an integer"); + error(operand->expr, "`reserve` capacities must be an integer"); return false; } @@ -3911,7 +3911,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id type = base_type(type_deref(type)); if (!is_type_dynamic_array(type) && !is_type_map(type) && !is_type_slice(type)) { gbString str = type_to_string(type); - error_node(operand->expr, "Invalid type for `clear`, got `%s`", str); + error(operand->expr, "Invalid type for `clear`, got `%s`", str); gb_string_free(str); return false; } @@ -3930,7 +3930,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id type = base_type(type_deref(type)); if (!is_type_dynamic_array(type) && !is_type_slice(type)) { gbString str = type_to_string(type); - error_node(operand->expr, "Expected a slice or dynamic array, got `%s`", str); + error(operand->expr, "Expected a slice or dynamic array, got `%s`", str); gb_string_free(str); return false; } @@ -3940,7 +3940,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id is_addressable = true; } if (!is_addressable) { - error_node(operand->expr, "`append` can only operate on addressable values"); + error(operand->expr, "`append` can only operate on addressable values"); return false; } @@ -3973,7 +3973,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Type *type = operand->type; if (!is_type_map(type)) { gbString str = type_to_string(type); - error_node(operand->expr, "Expected a map, got `%s`", str); + error(operand->expr, "Expected a map, got `%s`", str); gb_string_free(str); return false; } @@ -3990,7 +3990,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (!check_is_assignable_to(c, &op, key)) { gbString kt = type_to_string(key); gbString ot = type_to_string(op.type); - error_node(operand->expr, "Expected a key of type `%s`, got `%s`", key, ot); + error(operand->expr, "Expected a key of type `%s`, got `%s`", key, ot); gb_string_free(ot); gb_string_free(kt); return false; @@ -4009,7 +4009,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } Type *t = o.type; if (t == NULL || t == t_invalid) { - error_node(ce->args[0], "Invalid argument for `size_of`"); + error(ce->args[0], "Invalid argument for `size_of`"); return false; } t = default_type(t); @@ -4028,7 +4028,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } Type *t = o.type; if (t == NULL || t == t_invalid) { - error_node(ce->args[0], "Invalid argument for `align_of`"); + error(ce->args[0], "Invalid argument for `align_of`"); return false; } t = default_type(t); @@ -4045,18 +4045,18 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Type *bt = check_type(c, ce->args[0]); Type *type = base_type(bt); if (type == NULL || type == t_invalid) { - error_node(ce->args[0], "Expected a type for `offset_of`"); + error(ce->args[0], "Expected a type for `offset_of`"); return false; } AstNode *field_arg = unparen_expr(ce->args[1]); if (field_arg == NULL || field_arg->kind != AstNode_Ident) { - error_node(field_arg, "Expected an identifier for field argument"); + error(field_arg, "Expected an identifier for field argument"); return false; } if (is_type_array(type) || is_type_vector(type)) { - error_node(field_arg, "Invalid type for `offset_of`"); + error(field_arg, "Invalid type for `offset_of`"); return false; } @@ -4065,14 +4065,14 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Selection sel = lookup_field(c->allocator, type, arg->string, operand->mode == Addressing_Type); if (sel.entity == NULL) { gbString type_str = type_to_string(bt); - error_node(ce->args[0], + error(ce->args[0], "`%s` has no field named `%.*s`", type_str, LIT(arg->string)); gb_string_free(type_str); return false; } if (sel.indirect) { gbString type_str = type_to_string(bt); - error_node(ce->args[0], + error(ce->args[0], "Field `%.*s` is embedded via a pointer in `%s`", LIT(arg->string), type_str); gb_string_free(type_str); return false; @@ -4091,7 +4091,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id return false; } if (operand->type == NULL || operand->type == t_invalid) { - error_node(operand->expr, "Invalid argument to `type_of_val`"); + error(operand->expr, "Invalid argument to `type_of_val`"); return false; } operand->mode = Addressing_Type; @@ -4114,7 +4114,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } Type *t = o.type; if (t == NULL || t == t_invalid) { - error_node(ce->args[0], "Invalid argument for `size_of`"); + error(ce->args[0], "Invalid argument for `size_of`"); return false; } t = default_type(t); @@ -4130,13 +4130,13 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) { gbString str = expr_to_string(ce->args[0]); - error_node(call, "`%s` is not a constant boolean", str); + error(call, "`%s` is not a constant boolean", str); gb_string_free(str); return false; } if (!operand->value.value_bool) { gbString str = expr_to_string(ce->args[0]); - error_node(call, "Compile time assertion: `%s`", str); + error(call, "Compile time assertion: `%s`", str); gb_string_free(str); } @@ -4163,7 +4163,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } if (dest_type == NULL || src_type == NULL) { - error_node(call, "`copy` only expects slices as arguments"); + error(call, "`copy` only expects slices as arguments"); return false; } @@ -4172,7 +4172,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id gbString s_arg = expr_to_string(ce->args[1]); gbString d_str = type_to_string(dest_type); gbString s_str = type_to_string(src_type); - error_node(call, + error(call, "Arguments to `copy`, %s, %s, have different elem types: %s vs %s", d_arg, s_arg, d_str, s_str); gb_string_free(s_str); @@ -4191,7 +4191,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Type *vector_type = base_type(operand->type); if (!is_type_vector(vector_type)) { gbString type_str = type_to_string(operand->type); - error_node(call, + error(call, "You can only `swizzle` a vector, got `%s`", type_str); gb_string_free(type_str); @@ -4213,17 +4213,17 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } Type *arg_type = base_type(op.type); if (!is_type_integer(arg_type) || op.mode != Addressing_Constant) { - error_node(op.expr, "Indices to `swizzle` must be constant integers"); + error(op.expr, "Indices to `swizzle` must be constant integers"); return false; } if (i128_lt(op.value.value_integer, I128_ZERO)) { - error_node(op.expr, "Negative `swizzle` index"); + error(op.expr, "Negative `swizzle` index"); return false; } if (i128_le(max_count128, op.value.value_integer)) { - error_node(op.expr, "`swizzle` index exceeds vector length"); + error(op.expr, "`swizzle` index exceeds vector length"); return false; } @@ -4231,7 +4231,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } if (arg_count > max_count) { - error_node(call, "Too many `swizzle` indices, %td > %td", arg_count, max_count); + error(call, "Too many `swizzle` indices, %td > %td", arg_count, max_count); return false; } @@ -4269,7 +4269,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (!are_types_identical(x.type, y.type)) { gbString tx = type_to_string(x.type); gbString ty = type_to_string(y.type); - error_node(call, "Mismatched types to `complex`, `%s` vs `%s`", tx, ty); + error(call, "Mismatched types to `complex`, `%s` vs `%s`", tx, ty); gb_string_free(ty); gb_string_free(tx); return false; @@ -4277,7 +4277,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (!is_type_float(x.type)) { gbString s = type_to_string(x.type); - error_node(call, "Arguments have type `%s`, expected a floating point", s); + error(call, "Arguments have type `%s`, expected a floating point", s); gb_string_free(s); return false; } @@ -4320,7 +4320,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (!is_type_complex(x->type)) { gbString s = type_to_string(x->type); - error_node(call, "Argument has type `%s`, expected a complex type", s); + error(call, "Argument has type `%s`, expected a complex type", s); gb_string_free(s); return false; } @@ -4358,7 +4358,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } } else { gbString s = type_to_string(x->type); - error_node(call, "Expected a complex or quaternion, got `%s`", s); + error(call, "Expected a complex or quaternion, got `%s`", s); gb_string_free(s); return false; } @@ -4372,19 +4372,19 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Type *ptr_type = base_type(operand->type); if (!is_type_pointer(ptr_type)) { gbString type_str = type_to_string(operand->type); - error_node(call, "Expected a pointer to `slice_ptr`, got `%s`", type_str); + error(call, "Expected a pointer to `slice_ptr`, got `%s`", type_str); gb_string_free(type_str); return false; } if (ptr_type == t_rawptr) { - error_node(call, "`rawptr` cannot have pointer arithmetic"); + error(call, "`rawptr` cannot have pointer arithmetic"); return false; } isize arg_count = ce->args.count; if (arg_count < 2 || 3 < arg_count) { - error_node(ce->args[0], "`slice_ptr` expects 2 or 3 arguments, found %td", arg_count); + error(ce->args[0], "`slice_ptr` expects 2 or 3 arguments, found %td", arg_count); // NOTE(bill): Return the correct type to reduce errors } else { // If any are constant @@ -4400,7 +4400,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } if (size_count == 2 && sizes[0] > sizes[1]) { - error_node(ce->args[1], "`slice_ptr` count and capacity are swapped"); + error(ce->args[1], "`slice_ptr` count and capacity are swapped"); // No need quit } } @@ -4413,7 +4413,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Type *slice_type = base_type(operand->type); if (!is_type_slice(slice_type)) { gbString type_str = type_to_string(operand->type); - error_node(call, "Expected a slice type, got `%s`", type_str); + error(call, "Expected a slice type, got `%s`", type_str); gb_string_free(type_str); return false; } @@ -4427,7 +4427,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Type *type = base_type(operand->type); if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) { gbString type_str = type_to_string(operand->type); - error_node(call, "Expected a ordered numeric type to `min`, got `%s`", type_str); + error(call, "Expected a ordered numeric type to `min`, got `%s`", type_str); gb_string_free(type_str); return false; } @@ -4441,7 +4441,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } if (!is_type_ordered(b.type) || !(is_type_numeric(b.type) || is_type_string(b.type))) { gbString type_str = type_to_string(b.type); - error_node(call, + error(call, "Expected a ordered numeric type to `min`, got `%s`", type_str); gb_string_free(type_str); @@ -4477,7 +4477,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (!are_types_identical(a.type, b.type)) { gbString type_a = type_to_string(a.type); gbString type_b = type_to_string(b.type); - error_node(call, + error(call, "Mismatched types to `min`, `%s` vs `%s`", type_a, type_b); gb_string_free(type_b); @@ -4493,7 +4493,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Type *type = base_type(operand->type); if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) { gbString type_str = type_to_string(operand->type); - error_node(call, + error(call, "Expected a ordered numeric or string type to `max`, got `%s`", type_str); gb_string_free(type_str); @@ -4509,7 +4509,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } if (!is_type_ordered(b.type) || !(is_type_numeric(b.type) || is_type_string(b.type))) { gbString type_str = type_to_string(b.type); - error_node(call, + error(call, "Expected a ordered numeric or string type to `max`, got `%s`", type_str); gb_string_free(type_str); @@ -4545,7 +4545,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (!are_types_identical(a.type, b.type)) { gbString type_a = type_to_string(a.type); gbString type_b = type_to_string(b.type); - error_node(call, + error(call, "Mismatched types to `max`, `%s` vs `%s`", type_a, type_b); gb_string_free(type_b); @@ -4560,7 +4560,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id // proc abs(n: numeric) -> numeric if (!is_type_numeric(operand->type) && !is_type_vector(operand->type)) { gbString type_str = type_to_string(operand->type); - error_node(call, "Expected a numeric type to `abs`, got `%s`", type_str); + error(call, "Expected a numeric type to `abs`, got `%s`", type_str); gb_string_free(type_str); return false; } @@ -4597,7 +4597,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id Type *type = base_type(operand->type); if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) { gbString type_str = type_to_string(operand->type); - error_node(call, "Expected a ordered numeric or string type to `clamp`, got `%s`", type_str); + error(call, "Expected a ordered numeric or string type to `clamp`, got `%s`", type_str); gb_string_free(type_str); return false; } @@ -4614,7 +4614,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } if (!is_type_ordered(y.type) || !(is_type_numeric(y.type) || is_type_string(y.type))) { gbString type_str = type_to_string(y.type); - error_node(call, "Expected a ordered numeric or string type to `clamp`, got `%s`", type_str); + error(call, "Expected a ordered numeric or string type to `clamp`, got `%s`", type_str); gb_string_free(type_str); return false; } @@ -4625,7 +4625,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } if (!is_type_ordered(z.type) || !(is_type_numeric(z.type) || is_type_string(z.type))) { gbString type_str = type_to_string(z.type); - error_node(call, "Expected a ordered numeric or string type to `clamp`, got `%s`", type_str); + error(call, "Expected a ordered numeric or string type to `clamp`, got `%s`", type_str); gb_string_free(type_str); return false; } @@ -4669,7 +4669,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id gbString type_x = type_to_string(x.type); gbString type_y = type_to_string(y.type); gbString type_z = type_to_string(z.type); - error_node(call, + error(call, "Mismatched types to `clamp`, `%s`, `%s`, `%s`", type_x, type_y, type_z); gb_string_free(type_z); @@ -4685,7 +4685,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id check_expr_or_type(c, &op, ce->args[0]); Type *t = op.type; if ((op.mode != Addressing_Type && t == NULL) || t == t_invalid) { - error_node(ce->args[0], "Expected a type for `transmute`"); + error(ce->args[0], "Expected a type for `transmute`"); return false; } AstNode *expr = ce->args[1]; @@ -4697,7 +4697,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (o->mode == Addressing_Constant) { gbString expr_str = expr_to_string(o->expr); - error_node(o->expr, "Cannot transmute a constant expression: `%s`", expr_str); + error(o->expr, "Cannot transmute a constant expression: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; o->expr = expr; @@ -4706,7 +4706,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (is_type_untyped(o->type)) { gbString expr_str = expr_to_string(o->expr); - error_node(o->expr, "Cannot transmute untyped expression: `%s`", expr_str); + error(o->expr, "Cannot transmute untyped expression: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; o->expr = expr; @@ -4718,7 +4718,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id if (srcz != dstz) { gbString expr_str = expr_to_string(o->expr); gbString type_str = type_to_string(t); - error_node(o->expr, "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, srcz, dstz); + error(o->expr, "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, srcz, dstz); gb_string_free(type_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; @@ -4891,7 +4891,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { if (show_error) { gbString proc_str = expr_to_string(ce->proc); - error_node(call, err_fmt, proc_str, param_count_excluding_defaults); + error(call, err_fmt, proc_str, param_count_excluding_defaults); gb_string_free(proc_str); } if (score_) *score_ = score; @@ -4915,7 +4915,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { if (o.mode == Addressing_Invalid) { continue; } else if (o.mode != Addressing_Type) { - error_node(o.expr, "Expected a type for the argument"); + error(o.expr, "Expected a type for the argument"); } continue; } @@ -4945,7 +4945,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { t = slice; if (operand_index != param_count) { if (show_error) { - error_node(o.expr, "`..` in a variadic procedure can only have one variadic argument at the end"); + error(o.expr, "`..` in a variadic procedure can only have one variadic argument at the end"); } if (score_) *score_ = score; return CallArgumentError_MultipleVariadicExpand; @@ -5008,7 +5008,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { if (fv->field->kind != AstNode_Ident) { if (show_error) { gbString expr_str = expr_to_string(fv->field); - error_node(arg, "Invalid parameter name `%s` in procedure call", expr_str); + error(arg, "Invalid parameter name `%s` in procedure call", expr_str); gb_string_free(expr_str); } err = CallArgumentError_InvalidFieldValue; @@ -5018,14 +5018,14 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { isize index = lookup_procedure_parameter(pt, name); if (index < 0) { if (show_error) { - error_node(arg, "No parameter named `%.*s` for this procedure type", LIT(name)); + error(arg, "No parameter named `%.*s` for this procedure type", LIT(name)); } err = CallArgumentError_ParameterNotFound; continue; } if (params_visited[index]) { if (show_error) { - error_node(arg, "Duplicate parameter `%.*s` in procedure call", LIT(name)); + error(arg, "Duplicate parameter `%.*s` in procedure call", LIT(name)); } err = CallArgumentError_DuplicateParameter; continue; @@ -5041,7 +5041,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { if (o->mode == Addressing_Invalid) { continue; } else if (o->mode != Addressing_Type) { - error_node(o->expr, "Expected a type for the argument"); + error(o->expr, "Expected a type for the argument"); } score += 1; } else { @@ -5081,7 +5081,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { if (show_error) { gbString str = type_to_string(e->type); - error_node(call, "Parameter `%.*s` of type `%s` is missing in procedure call", + error(call, "Parameter `%.*s` of type `%s` is missing in procedure call", LIT(e->token.string), str); gb_string_free(str); } @@ -5171,10 +5171,10 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod if (valid_count == 0) { - error_node(operand->expr, "No overloads for `%.*s` that match with the given arguments", LIT(name)); + error(operand->expr, "No overloads for `%.*s` that match with the given arguments", LIT(name)); proc_type = t_invalid; } else if (valid_count > 1) { - error_node(operand->expr, "Ambiguous procedure call `%.*s`, could be:", LIT(name)); + error(operand->expr, "Ambiguous procedure call `%.*s`, could be:", LIT(name)); for (isize i = 0; i < valid_count; i++) { Entity *proc = procs[valids[i].index]; TokenPos pos = proc->token.pos; @@ -5257,7 +5257,7 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { mix = arg->kind == AstNode_FieldValue; } if (mix) { - error_node(arg, "Mixture of `field = value` and value elements in a procedure all is not allowed"); + error(arg, "Mixture of `field = value` and value elements in a procedure all is not allowed"); fail = true; } } @@ -5288,12 +5288,12 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { operand->mode = Addressing_Invalid; isize arg_count = ce->args.count; switch (arg_count) { - case 0: error_node(call, "Missing argument in conversion to `%s`", str); break; - default: error_node(call, "Too many arguments in conversion to `%s`", str); break; + case 0: error(call, "Missing argument in conversion to `%s`", str); break; + default: error(call, "Too many arguments in conversion to `%s`", str); break; case 1: { AstNode *arg = ce->args[0]; if (arg->kind == AstNode_FieldValue) { - error_node(call, "`field = value` cannot be used in a type conversion"); + error(call, "`field = value` cannot be used in a type conversion"); arg = arg->FieldValue.value; // NOTE(bill): Carry on the cast regardless } @@ -5325,7 +5325,7 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { AstNode *e = operand->expr; gbString str = expr_to_string(e); gbString type_str = type_to_string(operand->type); - error_node(e, "Cannot call a non-procedure: `%s` of type `%s`", str, type_str); + error(e, "Cannot call a non-procedure: `%s` of type `%s`", str, type_str); gb_string_free(type_str); gb_string_free(str); @@ -5379,7 +5379,7 @@ ExprKind check_macro_call_expr(Checker *c, Operand *operand, AstNode *call) { GB_ASSERT(call->kind == AstNode_MacroCallExpr); ast_node(mce, MacroCallExpr, call); - error_node(call, "Macro call expressions are not yet supported"); + error(call, "Macro call expressions are not yet supported"); operand->mode = Addressing_Invalid; operand->expr = call; return Expr_Stmt; @@ -5402,7 +5402,7 @@ void check_expr_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t) { } if (err_str != NULL) { gbString str = expr_to_string(e); - error_node(e, "`%s` %s", str, err_str); + error(e, "`%s` %s", str, err_str); gb_string_free(str); o->mode = Addressing_Invalid; } @@ -5482,7 +5482,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t switch (i->kind) { case Token_context: if (c->context.proc_name.len == 0) { - error_node(node, "`context` is only allowed within procedures"); + error(node, "`context` is only allowed within procedures"); return kind; } @@ -5490,7 +5490,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t o->type = t_context; break; default: - error_node(node, "Illegal implicit name `%.*s`", LIT(i->string)); + error(node, "Illegal implicit name `%.*s`", LIT(i->string)); return kind; } case_end; @@ -5530,7 +5530,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t o->value = exact_value_i64(bd->token.pos.line); } else if (bd->name == "procedure") { if (c->proc_stack.count == 0) { - error_node(node, "#procedure may only be used within procedures"); + error(node, "#procedure may only be used within procedures"); o->type = t_untyped_string; o->value = exact_value_string(str_lit("")); } else { @@ -5539,7 +5539,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t } } else if (bd->name == "caller_location") { init_preload(c); - error_node(node, "#caller_location may only be used as a default argument parameter"); + error(node, "#caller_location may only be used as a default argument parameter"); o->type = t_source_code_location; o->mode = Addressing_Value; } else { @@ -5559,14 +5559,14 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t c->context.decl = decl; if (pl->tags != 0) { - error_node(node, "A procedure literal cannot have tags"); + error(node, "A procedure literal cannot have tags"); pl->tags = 0; // TODO(bill): Should I zero this?! } check_procedure_type(c, type, pl->type); if (!is_type_proc(type)) { gbString str = expr_to_string(node); - error_node(node, "Invalid procedure literal `%s`", str); + error(node, "Invalid procedure literal `%s`", str); gb_string_free(str); check_close_scope(c); return kind; @@ -5585,7 +5585,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t Operand cond = {Addressing_Invalid}; check_expr(c, &cond, te->cond); if (cond.mode != Addressing_Invalid && !is_type_boolean(cond.type)) { - error_node(te->cond, "Non-boolean condition in if expression"); + error(te->cond, "Non-boolean condition in if expression"); } Operand x = {Addressing_Invalid}; @@ -5595,7 +5595,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (te->y != NULL) { check_expr_with_type_hint(c, &y, te->y, type_hint); } else { - error_node(node, "A ternary expression must have an else clause"); + error(node, "A ternary expression must have an else clause"); return kind; } @@ -5618,7 +5618,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (!are_types_identical(x.type, y.type)) { gbString its = type_to_string(x.type); gbString ets = type_to_string(y.type); - error_node(node, "Mismatched types in ternary expression, %s vs %s", its, ets); + error(node, "Mismatched types in ternary expression, %s vs %s", its, ets); gb_string_free(ets); gb_string_free(its); return kind; @@ -5665,7 +5665,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t } if (type == NULL) { - error_node(node, "Missing type in compound literal"); + error(node, "Missing type in compound literal"); return kind; } @@ -5675,7 +5675,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (!is_type_struct(t) && !is_type_union(t)) { if (cl->elems.count != 0) { gbString type_str = type_to_string(type); - error_node(node, "Illegal compound literal type `%s`", type_str); + error(node, "Illegal compound literal type `%s`", type_str); gb_string_free(type_str); } break; @@ -5694,13 +5694,13 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t for_array(i, cl->elems) { AstNode *elem = cl->elems[i]; if (elem->kind != AstNode_FieldValue) { - error_node(elem, "Mixture of `field = value` and value elements in a structure literal is not allowed"); + error(elem, "Mixture of `field = value` and value elements in a structure literal is not allowed"); continue; } ast_node(fv, FieldValue, elem); if (fv->field->kind != AstNode_Ident) { gbString expr_str = expr_to_string(fv->field); - error_node(elem, "Invalid field name `%s` in structure literal", expr_str); + error(elem, "Invalid field name `%s` in structure literal", expr_str); gb_string_free(expr_str); continue; } @@ -5709,17 +5709,17 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t Selection sel = lookup_field(c->allocator, type, name, o->mode == Addressing_Type); bool is_unknown = sel.entity == NULL; if (is_unknown) { - error_node(elem, "Unknown field `%.*s` in structure literal", LIT(name)); + error(elem, "Unknown field `%.*s` in structure literal", LIT(name)); continue; } if (!is_unknown && !check_is_field_exported(c, sel.entity)) { - error_node(elem, "Cannot assign to an unexported field `%.*s` in structure literal", LIT(name)); + error(elem, "Cannot assign to an unexported field `%.*s` in structure literal", LIT(name)); continue; } if (sel.index.count > 1) { - error_node(elem, "Cannot assign to an anonymous field `%.*s` in a structure literal (at the moment)", LIT(name)); + error(elem, "Cannot assign to an anonymous field `%.*s` in a structure literal (at the moment)", LIT(name)); continue; } @@ -5727,7 +5727,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t add_entity_use(c, fv->field, field); if (fields_visited[sel.index[0]]) { - error_node(elem, "Duplicate field `%.*s` in structure literal", LIT(name)); + error(elem, "Duplicate field `%.*s` in structure literal", LIT(name)); continue; } @@ -5757,11 +5757,11 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t for_array(index, cl->elems) { AstNode *elem = cl->elems[index]; if (elem->kind == AstNode_FieldValue) { - error_node(elem, "Mixture of `field = value` and value elements in a structure literal is not allowed"); + error(elem, "Mixture of `field = value` and value elements in a structure literal is not allowed"); continue; } if (index >= field_count) { - error_node(o->expr, "Too many values in structure literal, expected %td", field_count); + error(o->expr, "Too many values in structure literal, expected %td", field_count); break; } @@ -5774,7 +5774,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (!check_is_field_exported(c, field)) { gbString t = type_to_string(type); - error_node(o->expr, "Implicit assignment to an unexported field `%.*s` in `%s` literal", + error(o->expr, "Implicit assignment to an unexported field `%.*s` in `%s` literal", LIT(field->token.string), t); gb_string_free(t); continue; @@ -5836,17 +5836,17 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t GB_ASSERT(cl->elems.data != NULL); AstNode *e = cl->elems[index]; if (e == NULL) { - error_node(node, "Invalid literal element"); + error(node, "Invalid literal element"); continue; } if (e->kind == AstNode_FieldValue) { - error_node(e, "`field = value` is only allowed in struct literals"); + error(e, "`field = value` is only allowed in struct literals"); continue; } if (0 <= max_type_count && max_type_count <= index) { - error_node(e, "Index %lld is out of bounds (>= %lld) for %.*s", index, max_type_count, LIT(context_name)); + error(e, "Index %lld is out of bounds (>= %lld) for %.*s", index, max_type_count, LIT(context_name)); } Operand operand = {}; @@ -5863,7 +5863,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (t->kind == Type_Vector) { if (t->Vector.count > 1 && gb_is_between(index, 2, t->Vector.count-1)) { - error_node(cl->elems[0], "Expected either 1 (broadcast) or %td elements in vector literal, got %td", t->Vector.count, index); + error(cl->elems[0], "Expected either 1 (broadcast) or %td elements in vector literal, got %td", t->Vector.count, index); } } @@ -5875,7 +5875,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t case Type_Basic: { if (!is_type_any(t)) { if (cl->elems.count != 0) { - error_node(node, "Illegal compound literal"); + error(node, "Illegal compound literal"); } break; } @@ -5891,13 +5891,13 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t for_array(i, cl->elems) { AstNode *elem = cl->elems[i]; if (elem->kind != AstNode_FieldValue) { - error_node(elem, "Mixture of `field = value` and value elements in a `any` literal is not allowed"); + error(elem, "Mixture of `field = value` and value elements in a `any` literal is not allowed"); continue; } ast_node(fv, FieldValue, elem); if (fv->field->kind != AstNode_Ident) { gbString expr_str = expr_to_string(fv->field); - error_node(elem, "Invalid field name `%s` in `any` literal", expr_str); + error(elem, "Invalid field name `%s` in `any` literal", expr_str); gb_string_free(expr_str); continue; } @@ -5905,14 +5905,14 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t Selection sel = lookup_field(c->allocator, type, name, o->mode == Addressing_Type); if (sel.entity == NULL) { - error_node(elem, "Unknown field `%.*s` in `any` literal", LIT(name)); + error(elem, "Unknown field `%.*s` in `any` literal", LIT(name)); continue; } isize index = sel.index[0]; if (fields_visited[index]) { - error_node(elem, "Duplicate field `%.*s` in `any` literal", LIT(name)); + error(elem, "Duplicate field `%.*s` in `any` literal", LIT(name)); continue; } @@ -5928,14 +5928,14 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t for_array(index, cl->elems) { AstNode *elem = cl->elems[index]; if (elem->kind == AstNode_FieldValue) { - error_node(elem, "Mixture of `field = value` and value elements in a `any` literal is not allowed"); + error(elem, "Mixture of `field = value` and value elements in a `any` literal is not allowed"); continue; } check_expr(c, o, elem); if (index >= field_count) { - error_node(o->expr, "Too many values in `any` literal, expected %td", field_count); + error(o->expr, "Too many values in `any` literal, expected %td", field_count); break; } @@ -5960,7 +5960,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t for_array(i, cl->elems) { AstNode *elem = cl->elems[i]; if (elem->kind != AstNode_FieldValue) { - error_node(elem, "Only `field = value` elements are allowed in a map literal"); + error(elem, "Only `field = value` elements are allowed in a map literal"); continue; } ast_node(fv, FieldValue, elem); @@ -5978,7 +5978,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t default: { gbString str = type_to_string(type); - error_node(node, "Invalid compound literal type `%s`", str); + error(node, "Invalid compound literal type `%s`", str); gb_string_free(str); return kind; } break; @@ -6000,7 +6000,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t case_ast_node(te, TagExpr, node); String name = te->name.string; - error_node(node, "Unknown tag expression, #%.*s", LIT(name)); + error(node, "Unknown tag expression, #%.*s", LIT(name)); if (te->expr) { kind = check_expr_base(c, o, te->expr, type_hint); } @@ -6023,7 +6023,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (o->mode == Addressing_Constant) { gbString expr_str = expr_to_string(o->expr); - error_node(o->expr, "A type assertion cannot be applied to a constant expression: `%s`", expr_str); + error(o->expr, "A type assertion cannot be applied to a constant expression: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; o->expr = node; @@ -6032,7 +6032,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (is_type_untyped(o->type)) { gbString expr_str = expr_to_string(o->expr); - error_node(o->expr, "A type assertion cannot be applied to an untyped expression: `%s`", expr_str); + error(o->expr, "A type assertion cannot be applied to an untyped expression: `%s`", expr_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; o->expr = node; @@ -6050,7 +6050,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (src_is_ptr != dst_is_ptr) { gbString src_type_str = type_to_string(o->type); gbString dst_type_str = type_to_string(t); - error_node(o->expr, "Invalid type assertion types: `%s` and `%s`", src_type_str, dst_type_str); + error(o->expr, "Invalid type assertion types: `%s` and `%s`", src_type_str, dst_type_str); gb_string_free(dst_type_str); gb_string_free(src_type_str); o->mode = Addressing_Invalid; @@ -6071,7 +6071,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (!ok) { gbString expr_str = expr_to_string(o->expr); gbString dst_type_str = type_to_string(t); - error_node(o->expr, "Cannot type assert `%s` to `%s`", expr_str, dst_type_str); + error(o->expr, "Cannot type assert `%s` to `%s`", expr_str, dst_type_str); gb_string_free(dst_type_str); gb_string_free(expr_str); o->mode = Addressing_Invalid; @@ -6091,7 +6091,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t add_type_info_type(c, o->type); add_type_info_type(c, t); } else { - error_node(o->expr, "Type assertions can only operate on unions"); + error(o->expr, "Type assertions can only operate on unions"); o->mode = Addressing_Invalid; o->expr = node; return kind; @@ -6170,9 +6170,9 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (!valid) { gbString str = expr_to_string(o->expr); if (is_const) { - error_node(o->expr, "Cannot index a constant `%s`", str); + error(o->expr, "Cannot index a constant `%s`", str); } else { - error_node(o->expr, "Cannot index `%s`", str); + error(o->expr, "Cannot index `%s`", str); } gb_string_free(str); o->mode = Addressing_Invalid; @@ -6182,7 +6182,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (ie->index == NULL) { gbString str = expr_to_string(o->expr); - error_node(o->expr, "Missing index for `%s`", str); + error(o->expr, "Missing index for `%s`", str); gb_string_free(str); o->mode = Addressing_Invalid; o->expr = node; @@ -6211,7 +6211,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t case Type_Basic: if (is_type_string(t)) { if (se->index3) { - error_node(node, "3-index slice on a string in not needed"); + error(node, "3-index slice on a string in not needed"); o->mode = Addressing_Invalid; o->expr = node; return kind; @@ -6229,7 +6229,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t max_count = t->Array.count; if (o->mode != Addressing_Variable) { gbString str = expr_to_string(node); - error_node(node, "Cannot slice array `%s`, value is not addressable", str); + error(node, "Cannot slice array `%s`, value is not addressable", str); gb_string_free(str); o->mode = Addressing_Invalid; o->expr = node; @@ -6250,7 +6250,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t if (!valid) { gbString str = expr_to_string(o->expr); - error_node(o->expr, "Cannot slice `%s`", str); + error(o->expr, "Cannot slice `%s`", str); gb_string_free(str); o->mode = Addressing_Invalid; o->expr = node; @@ -6338,7 +6338,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t o->type = t->Pointer.elem; } else { gbString str = expr_to_string(o->expr); - error_node(o->expr, "Cannot dereference `%s`", str); + error(o->expr, "Cannot dereference `%s`", str); gb_string_free(str); o->mode = Addressing_Invalid; o->expr = node; @@ -6419,7 +6419,7 @@ void check_not_tuple(Checker *c, Operand *o) { if (o->type->kind == Type_Tuple) { isize count = o->type->Tuple.variable_count; GB_ASSERT(count != 1); - error_node(o->expr, + error(o->expr, "%td-valued tuple found where single value expected", count); o->mode = Addressing_Invalid; } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 6c74e4017..c4ad2570e 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -30,7 +30,7 @@ void check_stmt_list(Checker *c, Array stmts, u32 flags) { if (i+1 < max) { switch (n->kind) { case AstNode_ReturnStmt: - error_node(n, "Statements after this `return` are never executed"); + error(n, "Statements after this `return` are never executed"); break; } } @@ -283,7 +283,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) { } gbString lhs_expr = expr_to_string(lhs.expr); gbString rhs_expr = expr_to_string(rhs->expr); - error_node(rhs->expr, "Cannot assign `%s` to bit field `%s`", rhs_expr, lhs_expr); + error(rhs->expr, "Cannot assign `%s` to bit field `%s`", rhs_expr, lhs_expr); gb_string_free(rhs_expr); gb_string_free(lhs_expr); return NULL; @@ -300,7 +300,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) { if (tav.mode != Addressing_Variable) { if (!is_type_pointer(tav.type)) { gbString str = expr_to_string(lhs.expr); - error_node(lhs.expr, "Cannot assign to the value of a map `%s`", str); + error(lhs.expr, "Cannot assign to the value of a map `%s`", str); gb_string_free(str); return NULL; } @@ -316,7 +316,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) { check_expr(c, &op_c, se->expr); if (op_c.mode == Addressing_MapIndex) { gbString str = expr_to_string(lhs.expr); - error_node(lhs.expr, "Cannot assign to record field `%s` in map", str); + error(lhs.expr, "Cannot assign to record field `%s` in map", str); gb_string_free(str); return NULL; } @@ -324,9 +324,9 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) { gbString str = expr_to_string(lhs.expr); if (lhs.mode == Addressing_Immutable) { - error_node(lhs.expr, "Cannot assign to an immutable: `%s`", str); + error(lhs.expr, "Cannot assign to an immutable: `%s`", str); } else { - error_node(lhs.expr, "Cannot assign to `%s`", str); + error(lhs.expr, "Cannot assign to `%s`", str); } gb_string_free(str); } break; @@ -394,11 +394,11 @@ void check_when_stmt(Checker *c, AstNodeWhenStmt *ws, u32 flags) { Operand operand = {Addressing_Invalid}; check_expr(c, &operand, ws->cond); if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) { - error_node(ws->cond, "Non-constant boolean `when` condition"); + error(ws->cond, "Non-constant boolean `when` condition"); return; } if (ws->body == NULL || ws->body->kind != AstNode_BlockStmt) { - error_node(ws->cond, "Invalid body for `when` statement"); + error(ws->cond, "Invalid body for `when` statement"); return; } if (operand.value.kind == ExactValue_Bool && @@ -413,7 +413,7 @@ void check_when_stmt(Checker *c, AstNodeWhenStmt *ws, u32 flags) { check_when_stmt(c, &ws->else_stmt->WhenStmt, flags); break; default: - error_node(ws->else_stmt, "Invalid `else` statement in `when` statement"); + error(ws->else_stmt, "Invalid `else` statement in `when` statement"); break; } } @@ -425,18 +425,18 @@ void check_label(Checker *c, AstNode *label) { } ast_node(l, Label, label); if (l->name->kind != AstNode_Ident) { - error_node(l->name, "A label's name must be an identifier"); + error(l->name, "A label's name must be an identifier"); return; } String name = l->name->Ident.string; if (name == "_") { - error_node(l->name, "A label's name cannot be a blank identifier"); + error(l->name, "A label's name cannot be a blank identifier"); return; } if (c->proc_stack.count == 0) { - error_node(l->name, "A label is only allowed within a procedure"); + error(l->name, "A label is only allowed within a procedure"); return; } GB_ASSERT(c->context.decl != NULL); @@ -445,7 +445,7 @@ void check_label(Checker *c, AstNode *label) { for_array(i, c->context.decl->labels) { BlockLabel bl = c->context.decl->labels[i]; if (bl.name == name) { - error_node(label, "Duplicate label with the name `%.*s`", LIT(name)); + error(label, "Duplicate label with the name `%.*s`", LIT(name)); ok = false; break; } @@ -594,7 +594,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { switch (operand.mode) { case Addressing_Type: { gbString str = type_to_string(operand.type); - error_node(node, "`%s` is not an expression", str); + error(node, "`%s` is not an expression", str); gb_string_free(str); } break; case Addressing_NoValue: @@ -609,14 +609,14 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (is_type_proc(t)) { if (t->Proc.require_results) { gbString expr_str = expr_to_string(ce->proc); - error_node(node, "`%s` requires that its results must be handled", expr_str); + error(node, "`%s` requires that its results must be handled", expr_str); gb_string_free(expr_str); } } return; } gbString expr_str = expr_to_string(operand.expr); - error_node(node, "Expression is not used: `%s`", expr_str); + error(node, "Expression is not used: `%s`", expr_str); gb_string_free(expr_str); } break; } @@ -624,7 +624,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { case_ast_node(ts, TagStmt, node); // TODO(bill): Tag Statements - error_node(node, "Tag statements are not supported yet"); + error(node, "Tag statements are not supported yet"); check_stmt(c, ts->stmt, flags); case_end; @@ -634,7 +634,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { case Token_Inc: op = Token_Add; break; case Token_Dec: op = Token_Sub; break; default: - error_node(node, "Invalid inc/dec operation"); + error(node, "Invalid inc/dec operation"); return; } @@ -646,7 +646,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (!is_type_integer(x.type) && !is_type_float(x.type)) { gbString e = expr_to_string(s->expr); gbString t = type_to_string(x.type); - error_node(node, "%s%.*s used on non-numeric type %s", e, LIT(s->op.string), t); + error(node, "%s%.*s used on non-numeric type %s", e, LIT(s->op.string), t); gb_string_free(t); gb_string_free(e); return; @@ -702,7 +702,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { check_assignment_variable(c, &operands[i], as->lhs[i]); } if (lhs_count != rhs_count) { - error_node(as->lhs[0], "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count); + error(as->lhs[0], "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count); } gb_temp_arena_memory_end(tmp); @@ -754,7 +754,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { Operand operand = {Addressing_Invalid}; check_expr(c, &operand, is->cond); if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) { - error_node(is->cond, "Non-boolean condition in `if` statement"); + error(is->cond, "Non-boolean condition in `if` statement"); } check_stmt(c, is->body, mod_flags); @@ -766,7 +766,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { check_stmt(c, is->else_stmt, mod_flags); break; default: - error_node(is->else_stmt, "Invalid `else` statement in `if` statement"); + error(is->else_stmt, "Invalid `else` statement in `if` statement"); break; } } @@ -800,7 +800,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { variables = tuple->variables; } if (rs->results.count == 0) { - error_node(node, "Expected %td return values, got 0", result_count); + error(node, "Expected %td return values, got 0", result_count); } else { // TokenPos pos = rs->token.pos; // if (pos.line == 10) { @@ -815,7 +815,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { // } } } else if (rs->results.count > 0) { - error_node(rs->results[0], "No return values expected"); + error(rs->results[0], "No return values expected"); } case_end; @@ -832,7 +832,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { Operand o = {Addressing_Invalid}; check_expr(c, &o, fs->cond); if (o.mode != Addressing_Invalid && !is_type_boolean(o.type)) { - error_node(fs->cond, "Non-boolean condition in `for` statement"); + error(fs->cond, "Non-boolean condition in `for` statement"); } } if (fs->post != NULL) { @@ -840,7 +840,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (fs->post->kind != AstNode_AssignStmt && fs->post->kind != AstNode_IncDecStmt) { - error_node(fs->post, "`for` statement post statement must be a simple statement"); + error(fs->post, "`for` statement post statement must be a simple statement"); } } check_stmt(c, fs->body, new_flags); @@ -954,7 +954,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (operand.mode == Addressing_Type) { if (!is_type_enum(operand.type)) { gbString t = type_to_string(operand.type); - error_node(operand.expr, "Cannot iterate over the type `%s`", t); + error(operand.expr, "Cannot iterate over the type `%s`", t); gb_string_free(t); goto skip_expr; } else { @@ -1002,7 +1002,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (val == NULL) { gbString s = expr_to_string(operand.expr); gbString t = type_to_string(operand.type); - error_node(operand.expr, "Cannot iterate over `%s` of type `%s`", s, t); + error(operand.expr, "Cannot iterate over `%s` of type `%s`", s, t); gb_string_free(t); gb_string_free(s); } @@ -1040,7 +1040,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { entity = found; } } else { - error_node(name, "A variable declaration must be an identifier"); + error(name, "A variable declaration must be an identifier"); } if (entity == NULL) { @@ -1089,7 +1089,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { } if (is_type_vector(x.type)) { gbString str = type_to_string(x.type); - error_node(x.expr, "Invalid match expression type: %s", str); + error(x.expr, "Invalid match expression type: %s", str); gb_string_free(str); break; } @@ -1107,13 +1107,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { default_stmt = stmt; } } else { - error_node(stmt, "Invalid AST - expected case clause"); + error(stmt, "Invalid AST - expected case clause"); } if (default_stmt != NULL) { if (first_default != NULL) { TokenPos pos = ast_node_token(first_default).pos; - error_node(stmt, + error(stmt, "multiple `default` clauses\n" "\tfirst at %.*s(%td:%td)", LIT(pos.file), pos.line, pos.column); @@ -1155,7 +1155,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (!is_type_ordered(x.type)) { gbString str = type_to_string(x.type); - error_node(x.expr, "Unordered type `%s`, is invalid for an interval expression", str); + error(x.expr, "Unordered type `%s`, is invalid for an interval expression", str); gb_string_free(str); continue; } @@ -1229,7 +1229,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (are_types_identical(y.type, tap.type)) { TokenPos pos = tap.token.pos; gbString expr_str = expr_to_string(y.expr); - error_node(y.expr, + error(y.expr, "Duplicate case `%s`\n" "\tprevious case at %.*s(%td:%td)", expr_str, @@ -1276,7 +1276,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { MatchTypeKind match_type_kind = MatchType_Invalid; if (ms->tag->kind != AstNode_AssignStmt) { - error_node(ms->tag, "Expected an `in` assignment for this type match statement"); + error(ms->tag, "Expected an `in` assignment for this type match statement"); break; } @@ -1298,7 +1298,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { match_type_kind = check_valid_type_match_type(x.type); if (check_valid_type_match_type(x.type) == MatchType_Invalid) { gbString str = type_to_string(x.type); - error_node(x.expr, "Invalid type for this type match expression, got `%s`", str); + error(x.expr, "Invalid type for this type match expression, got `%s`", str); gb_string_free(str); break; } @@ -1317,13 +1317,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { default_stmt = stmt; } } else { - error_node(stmt, "Invalid AST - expected case clause"); + error(stmt, "Invalid AST - expected case clause"); } if (default_stmt != NULL) { if (first_default != NULL) { TokenPos pos = ast_node_token(first_default).pos; - error_node(stmt, + error(stmt, "Multiple `default` clauses\n" "\tfirst at %.*s(%td:%td)", LIT(pos.file), pos.line, pos.column); } else { @@ -1334,7 +1334,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (lhs->kind != AstNode_Ident) { - error_node(rhs, "Expected an identifier, got `%.*s`", LIT(ast_node_strings[rhs->kind])); + error(rhs, "Expected an identifier, got `%.*s`", LIT(ast_node_strings[rhs->kind])); break; } @@ -1372,7 +1372,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { } if (!tag_type_found) { gbString type_str = type_to_string(y.type); - error_node(y.expr, "Unknown tag type, got `%s`", type_str); + error(y.expr, "Unknown tag type, got `%s`", type_str); gb_string_free(type_str); continue; } @@ -1388,7 +1388,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (found) { TokenPos pos = cc->token.pos; gbString expr_str = expr_to_string(y.expr); - error_node(y.expr, + error(y.expr, "Duplicate type case `%s`\n" "\tprevious type case at %.*s(%td:%td)", expr_str, @@ -1469,7 +1469,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (bs->label != NULL) { if (bs->label->kind != AstNode_Ident) { - error_node(bs->label, "A branch statement's label name must be an identifier"); + error(bs->label, "A branch statement's label name must be an identifier"); return; } AstNode *ident = bs->label; @@ -1477,12 +1477,12 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { Operand o = {}; Entity *e = check_ident(c, &o, ident, NULL, NULL, false); if (e == NULL) { - error_node(ident, "Undeclared label name: %.*s", LIT(name)); + error(ident, "Undeclared label name: %.*s", LIT(name)); return; } add_entity_use(c, ident, e); if (e->kind != Entity_Label) { - error_node(ident, "`%.*s` is not a label", LIT(name)); + error(ident, "`%.*s` is not a label", LIT(name)); return; } } @@ -1537,7 +1537,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { AstNode *foreign_library = fb->foreign_library; bool ok = true; if (foreign_library->kind != AstNode_Ident) { - error_node(foreign_library, "foreign library name must be an identifier"); + error(foreign_library, "foreign library name must be an identifier"); ok = false; } @@ -1576,14 +1576,14 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (gd->flags & VarDeclFlag_thread_local) { gd->flags &= ~VarDeclFlag_thread_local; - error_node(node, "`thread_local` may only be applied to a variable declaration"); + error(node, "`thread_local` may only be applied to a variable declaration"); } for_array(i, vd->names) { AstNode *name = vd->names[i]; Entity *entity = NULL; if (name->kind != AstNode_Ident) { - error_node(name, "A variable declaration must be an identifier"); + error(name, "A variable declaration must be an identifier"); } else { Token token = name->Ident; String str = token.string; diff --git a/src/checker.cpp b/src/checker.cpp index ba8f7b35a..21265f9dd 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1438,23 +1438,23 @@ bool check_arity_match(Checker *c, AstNodeValueSpec *spec) { if (rhs == 0) { if (spec->type == NULL) { - error_node(spec->names[0], "Missing type or initial expression"); + error(spec->names[0], "Missing type or initial expression"); return false; } } else if (lhs < rhs) { if (lhs < spec->values.count) { AstNode *n = spec->values[lhs]; gbString str = expr_to_string(n); - error_node(n, "Extra initial expression `%s`", str); + error(n, "Extra initial expression `%s`", str); gb_string_free(str); } else { - error_node(spec->names[0], "Extra initial expression"); + error(spec->names[0], "Extra initial expression"); } return false; } else if (lhs > rhs && rhs != 1) { AstNode *n = spec->names[rhs]; gbString str = expr_to_string(n); - error_node(n, "Missing expression for `%s`", str); + error(n, "Missing expression for `%s`", str); gb_string_free(str); return false; } @@ -1466,13 +1466,13 @@ void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws, bool Operand operand = {Addressing_Invalid}; check_expr(c, &operand, ws->cond); if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) { - error_node(ws->cond, "Non-boolean condition in `when` statement"); + error(ws->cond, "Non-boolean condition in `when` statement"); } if (operand.mode != Addressing_Constant) { - error_node(ws->cond, "Non-constant condition in `when` statement"); + error(ws->cond, "Non-constant condition in `when` statement"); } if (ws->body == NULL || ws->body->kind != AstNode_BlockStmt) { - error_node(ws->cond, "Invalid body for `when` statement"); + error(ws->cond, "Invalid body for `when` statement"); } else { if (operand.value.kind == ExactValue_Bool && operand.value.value_bool) { @@ -1486,7 +1486,7 @@ void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws, bool check_collect_entities_from_when_stmt(c, &ws->else_stmt->WhenStmt, is_file_scope); break; default: - error_node(ws->else_stmt, "Invalid `else` statement in `when` statement"); + error(ws->else_stmt, "Invalid `else` statement in `when` statement"); break; } } @@ -1514,7 +1514,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco case_ast_node(ws, WhenStmt, decl); if (c->context.scope->is_file) { - error_node(decl, "`when` statements are not allowed at file scope"); + error(decl, "`when` statements are not allowed at file scope"); } else { // Will be handled later } @@ -1538,7 +1538,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco for_array(i, vs->names) { AstNode *name = vs->names[i]; if (name->kind != AstNode_Ident) { - error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); + error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); continue; } @@ -1580,7 +1580,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco if (gd->flags & VarDeclFlag_thread_local) { - error_node(decl, "#thread_local variable declarations cannot have initialization values"); + error(decl, "#thread_local variable declarations cannot have initialization values"); } } @@ -1592,7 +1592,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco value = vs->values[i]; } if (name->kind != AstNode_Ident) { - error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); + error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); continue; } Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident, NULL, gd->token.kind == Token_let); @@ -1601,7 +1601,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco if (gd->flags & VarDeclFlag_using) { gd->flags &= ~VarDeclFlag_using; // NOTE(bill): This error will be only caught once - error_node(name, "`using` is not allowed at the file scope"); + error(name, "`using` is not allowed at the file scope"); } AstNode *fl = c->context.curr_foreign_library; @@ -1636,7 +1636,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco AstNode *name = ts->name; if (name->kind != AstNode_Ident) { - error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); + error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); break; } @@ -1658,9 +1658,9 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco ast_node(ts, ImportSpec, spec); if (!c->context.scope->is_file) { if (ts->is_import) { - error_node(decl, "import declarations are only allowed in the file scope"); + error(decl, "import declarations are only allowed in the file scope"); } else { - error_node(decl, "import_load declarations are only allowed in the file scope"); + error(decl, "import_load declarations are only allowed in the file scope"); } // NOTE(bill): _Should_ be caught by the parser // TODO(bill): Better error handling if it isn't @@ -1675,9 +1675,9 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco ast_node(fl, ForeignLibrarySpec, spec); if (!c->context.scope->is_file) { if (fl->is_system) { - error_node(spec, "foreign_system_library declarations are only allowed in the file scope"); + error(spec, "foreign_system_library declarations are only allowed in the file scope"); } else { - error_node(spec, "foreign_library declarations are only allowed in the file scope"); + error(spec, "foreign_library declarations are only allowed in the file scope"); } // NOTE(bill): _Should_ be caught by the parser // TODO(bill): Better error handling if it isn't @@ -1688,7 +1688,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco Operand operand = {Addressing_Invalid}; check_expr(c, &operand, fl->cond); if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) { - error_node(fl->cond, "Non-constant boolean `when` condition"); + error(fl->cond, "Non-constant boolean `when` condition"); continue; } if (operand.value.kind == ExactValue_Bool && @@ -1707,7 +1707,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco case_ast_node(fb, ForeignBlockDecl, decl); AstNode *foreign_library = fb->foreign_library; if (foreign_library->kind != AstNode_Ident) { - error_node(foreign_library, "foreign library name must be an identifier"); + error(foreign_library, "foreign library name must be an identifier"); foreign_library = NULL; } @@ -1720,7 +1720,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco case_ast_node(pd, ProcDecl, decl); AstNode *name = pd->name; if (name->kind != AstNode_Ident) { - error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); + error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); break; } @@ -1743,7 +1743,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco default: if (c->context.scope->is_file) { - error_node(decl, "Only declarations are allowed at file scope"); + error(decl, "Only declarations are allowed at file scope"); } break; } @@ -2011,7 +2011,7 @@ void check_import_entities(Checker *c, Map *file_scopes) { Operand operand = {Addressing_Invalid}; check_expr(c, &operand, id->cond); if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) { - error_node(id->cond, "Non-constant boolean `when` condition"); + error(id->cond, "Non-constant boolean `when` condition"); continue; } if (operand.value.kind == ExactValue_Bool && @@ -2104,7 +2104,7 @@ void check_import_entities(Checker *c, Map *file_scopes) { Operand operand = {Addressing_Invalid}; check_expr(c, &operand, fl->cond); if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) { - error_node(fl->cond, "Non-constant boolean `when` condition"); + error(fl->cond, "Non-constant boolean `when` condition"); continue; } if (operand.value.kind == ExactValue_Bool && @@ -2116,7 +2116,7 @@ void check_import_entities(Checker *c, Map *file_scopes) { String library_name = path_to_entity_name(fl->library_name.string, file_str); if (library_name == "_") { - error_node(spec, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string)); + error(spec, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string)); } else { GB_ASSERT(fl->library_name.pos.line != 0); fl->library_name.string = library_name; diff --git a/src/ir.cpp b/src/ir.cpp index 7e4858c44..85fd98147 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -2262,6 +2262,17 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal left = ir_emit_conv(proc, left, ir_type(right)); } else if (right->kind == irValue_Constant || right->kind == irValue_Nil) { right = ir_emit_conv(proc, right, ir_type(left)); + } else { + gbAllocator a = proc->module->allocator; + i64 ls = type_size_of(a, ir_type(left)); + i64 rs = type_size_of(a, ir_type(right)); + if (ls < rs) { + left = ir_emit_conv(proc, left, ir_type(right)); + } else if (ls > rs) { + right = ir_emit_conv(proc, right, ir_type(left)); + } else { + right = ir_emit_conv(proc, right, ir_type(left)); + } } Type *result = t_bool; diff --git a/src/main.cpp b/src/main.cpp index eb72817db..cc6472561 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -305,166 +305,166 @@ int main(int argc, char **argv) { #endif #if defined(GB_SYSTEM_WINDOWS) - timings_start_section(&timings, str_lit("llvm-llc")); - // For more arguments: http://llvm.org/docs/CommandGuide/llc.html - exit_code = system_exec_command_line_app("llvm-llc", false, - "\"%.*sbin/llc\" \"%.*s.bc\" -filetype=obj -O%d " - "%.*s " - // "-debug-pass=Arguments " - "", - LIT(build_context.ODIN_ROOT), - LIT(output_base), - optimization_level, - LIT(build_context.llc_flags)); - if (exit_code != 0) { - return exit_code; - } + timings_start_section(&timings, str_lit("llvm-llc")); + // For more arguments: http://llvm.org/docs/CommandGuide/llc.html + exit_code = system_exec_command_line_app("llvm-llc", false, + "\"%.*sbin/llc\" \"%.*s.bc\" -filetype=obj -O%d " + "%.*s " + // "-debug-pass=Arguments " + "", + LIT(build_context.ODIN_ROOT), + LIT(output_base), + optimization_level, + LIT(build_context.llc_flags)); + if (exit_code != 0) { + return exit_code; + } - timings_start_section(&timings, str_lit("msvc-link")); + timings_start_section(&timings, str_lit("msvc-link")); - gbString lib_str = gb_string_make(heap_allocator(), ""); - // defer (gb_string_free(lib_str)); - char lib_str_buf[1024] = {0}; - for_array(i, ir_gen.module.foreign_library_paths) { - String lib = ir_gen.module.foreign_library_paths[i]; - // gb_printf_err("Linking lib: %.*s\n", LIT(lib)); - isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), - " \"%.*s\"", LIT(lib)); - lib_str = gb_string_appendc(lib_str, lib_str_buf); - } - - char *output_ext = "exe"; - char *link_settings = ""; - if (build_context.is_dll) { - output_ext = "dll"; - link_settings = "/DLL"; - } else { - link_settings = "/ENTRY:mainCRTStartup"; - } - - exit_code = system_exec_command_line_app("msvc-link", true, - "link \"%.*s\".obj -OUT:\"%.*s.%s\" %s " - "/defaultlib:libcmt " - "/nologo /incremental:no /opt:ref /subsystem:CONSOLE " - " %.*s " - " %s " - "", - LIT(output_base), LIT(output_base), output_ext, - lib_str, LIT(build_context.link_flags), - link_settings - ); - if (exit_code != 0) { - return exit_code; - } - - // timings_print_all(&timings); - - if (run_output) { - system_exec_command_line_app("odin run", false, "%.*s.exe", LIT(output_base)); - } - - #else - - // NOTE(zangent): Linux / Unix is unfinished and not tested very well. - - - timings_start_section(&timings, str_lit("llvm-llc")); - // For more arguments: http://llvm.org/docs/CommandGuide/llc.html - exit_code = system_exec_command_line_app("llc", false, - "llc \"%.*s.bc\" -filetype=obj -relocation-model=pic -O%d " - "%.*s " - // "-debug-pass=Arguments " - "", - LIT(output_base), - optimization_level, - LIT(build_context.llc_flags)); - if (exit_code != 0) { - return exit_code; - } - - timings_start_section(&timings, str_lit("ld-link")); - - gbString lib_str = gb_string_make(heap_allocator(), ""); - // defer (gb_string_free(lib_str)); - char lib_str_buf[1024] = {0}; - for_array(i, ir_gen.module.foreign_library_paths) { - String lib = ir_gen.module.foreign_library_paths[i]; - - // NOTE(zangent): Sometimes, you have to use -framework on MacOS. - // This allows you to specify '-f' in a #foreign_system_library, - // without having to implement any new syntax specifically for MacOS. - #if defined(GB_SYSTEM_OSX) - isize len; - if(lib.len > 2 && lib[0] == '-' && lib[1] == 'f') { - len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), - " -framework %.*s ", (int)(lib.len) - 2, lib.text + 2); - } else { - len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), - " -l%.*s ", LIT(lib)); - } - #else + gbString lib_str = gb_string_make(heap_allocator(), ""); + // defer (gb_string_free(lib_str)); + char lib_str_buf[1024] = {0}; + for_array(i, ir_gen.module.foreign_library_paths) { + String lib = ir_gen.module.foreign_library_paths[i]; + // gb_printf_err("Linking lib: %.*s\n", LIT(lib)); isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), - " -l%.*s ", LIT(lib)); - #endif - lib_str = gb_string_appendc(lib_str, lib_str_buf); - } + " \"%.*s\"", LIT(lib)); + lib_str = gb_string_appendc(lib_str, lib_str_buf); + } - // Unlike the Win32 linker code, the output_ext includes the dot, because - // typically executable files on *NIX systems don't have extensions. - char *output_ext = ""; - char *link_settings = ""; - char *linker; - if (build_context.is_dll) { - // Shared libraries are .dylib on MacOS and .so on Linux. - // TODO(zangent): Is that statement entirely truthful? - #if defined(GB_SYSTEM_OSX) - output_ext = ".dylib"; - #else - output_ext = ".so"; - #endif + char *output_ext = "exe"; + char *link_settings = ""; + if (build_context.is_dll) { + output_ext = "dll"; + link_settings = "/DLL"; + } else { + link_settings = "/ENTRY:mainCRTStartup"; + } - link_settings = "-shared"; - } else { - // TODO: Do I need anything here? - link_settings = ""; - } + exit_code = system_exec_command_line_app("msvc-link", true, + "link \"%.*s\".obj -OUT:\"%.*s.%s\" %s " + "/defaultlib:libcmt " + "/nologo /incremental:no /opt:ref /subsystem:CONSOLE " + " %.*s " + " %s " + "", + LIT(output_base), LIT(output_base), output_ext, + lib_str, LIT(build_context.link_flags), + link_settings + ); + if (exit_code != 0) { + return exit_code; + } + + // timings_print_all(&timings); + + if (run_output) { + system_exec_command_line_app("odin run", false, "%.*s.exe", LIT(output_base)); + } - #if defined(GB_SYSTEM_OSX) - linker = "ld"; #else - // TODO(zangent): Figure out how to make ld work on Linux. - // It probably has to do with including the entire CRT, but - // that's quite a complicated issue to solve while remaining distro-agnostic. - // Clang can figure out linker flags for us, and that's good enough _for now_. - linker = "clang -Wno-unused-command-line-argument"; - #endif - exit_code = system_exec_command_line_app("ld-link", true, - "%s \"%.*s\".o -o \"%.*s%s\" %s " - "-lc -lm " - " %.*s " - " %s " + // NOTE(zangent): Linux / Unix is unfinished and not tested very well. + + + timings_start_section(&timings, str_lit("llvm-llc")); + // For more arguments: http://llvm.org/docs/CommandGuide/llc.html + exit_code = system_exec_command_line_app("llc", false, + "llc \"%.*s.bc\" -filetype=obj -relocation-model=pic -O%d " + "%.*s " + // "-debug-pass=Arguments " + "", + LIT(output_base), + optimization_level, + LIT(build_context.llc_flags)); + if (exit_code != 0) { + return exit_code; + } + + timings_start_section(&timings, str_lit("ld-link")); + + gbString lib_str = gb_string_make(heap_allocator(), ""); + // defer (gb_string_free(lib_str)); + char lib_str_buf[1024] = {0}; + for_array(i, ir_gen.module.foreign_library_paths) { + String lib = ir_gen.module.foreign_library_paths[i]; + + // NOTE(zangent): Sometimes, you have to use -framework on MacOS. + // This allows you to specify '-f' in a #foreign_system_library, + // without having to implement any new syntax specifically for MacOS. + #if defined(GB_SYSTEM_OSX) + isize len; + if(lib.len > 2 && lib[0] == '-' && lib[1] == 'f') { + len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), + " -framework %.*s ", (int)(lib.len) - 2, lib.text + 2); + } else { + len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), + " -l%.*s ", LIT(lib)); + } + #else + isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), + " -l%.*s ", LIT(lib)); + #endif + lib_str = gb_string_appendc(lib_str, lib_str_buf); + } + + // Unlike the Win32 linker code, the output_ext includes the dot, because + // typically executable files on *NIX systems don't have extensions. + char *output_ext = ""; + char *link_settings = ""; + char *linker; + if (build_context.is_dll) { + // Shared libraries are .dylib on MacOS and .so on Linux. + // TODO(zangent): Is that statement entirely truthful? + #if defined(GB_SYSTEM_OSX) + output_ext = ".dylib"; + #else + output_ext = ".so"; + #endif + + link_settings = "-shared"; + } else { + // TODO: Do I need anything here? + link_settings = ""; + } + #if defined(GB_SYSTEM_OSX) - // This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit. - // NOTE: If you change this (although this minimum is as low as you can go with Odin working) - // make sure to also change the `mtriple` param passed to `opt` - " -macosx_version_min 10.8.0 " - // This points the linker to where the entry point is - " -e _main " + linker = "ld"; + #else + // TODO(zangent): Figure out how to make ld work on Linux. + // It probably has to do with including the entire CRT, but + // that's quite a complicated issue to solve while remaining distro-agnostic. + // Clang can figure out linker flags for us, and that's good enough _for now_. + linker = "clang -Wno-unused-command-line-argument"; #endif - , linker, LIT(output_base), LIT(output_base), output_ext, - lib_str, LIT(build_context.link_flags), - link_settings - ); - if (exit_code != 0) { - return exit_code; - } - // timings_print_all(&timings); + exit_code = system_exec_command_line_app("ld-link", true, + "%s \"%.*s\".o -o \"%.*s%s\" %s " + "-lc -lm " + " %.*s " + " %s " + #if defined(GB_SYSTEM_OSX) + // This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit. + // NOTE: If you change this (although this minimum is as low as you can go with Odin working) + // make sure to also change the `mtriple` param passed to `opt` + " -macosx_version_min 10.8.0 " + // This points the linker to where the entry point is + " -e _main " + #endif + , linker, LIT(output_base), LIT(output_base), output_ext, + lib_str, LIT(build_context.link_flags), + link_settings + ); + if (exit_code != 0) { + return exit_code; + } - if (run_output) { - system_exec_command_line_app("odin run", false, "%.*s", LIT(output_base)); - } + // timings_print_all(&timings); + + if (run_output) { + system_exec_command_line_app("odin run", false, "%.*s", LIT(output_base)); + } #endif #endif diff --git a/src/parser.cpp b/src/parser.cpp index 04788522c..d09db81d2 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -34,6 +34,7 @@ struct AstFile { // NOTE(bill): Used to prevent type literals in control clauses isize expr_level; bool allow_range; // NOTE(bill): Ranges are only allowed in certain cases + bool in_foreign_block; Array decls; bool is_global_scope; @@ -90,12 +91,11 @@ enum ProcTag { }; enum ProcCallingConvention { - ProcCC_Odin = 0, - ProcCC_C = 1, - ProcCC_Std = 2, - ProcCC_Fast = 3, - - ProcCC_Invalid, + ProcCC_Invalid = 0, + ProcCC_Odin = 1, + ProcCC_C = 2, + ProcCC_Std = 3, + ProcCC_Fast = 4, }; enum VarDeclFlag { @@ -861,21 +861,21 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) { } -void error_node(AstNode *node, char *fmt, ...) { +void error(AstNode *node, char *fmt, ...) { va_list va; va_start(va, fmt); error_va(ast_node_token(node), fmt, va); va_end(va); } -void warning_node(AstNode *node, char *fmt, ...) { +void warning(AstNode *node, char *fmt, ...) { va_list va; va_start(va, fmt); warning_va(ast_node_token(node), fmt, va); va_end(va); } -void syntax_error_node(AstNode *node, char *fmt, ...) { +void syntax_error(AstNode *node, char *fmt, ...) { va_list va; va_start(va, fmt); syntax_error_va(ast_node_token(node), fmt, va); @@ -885,7 +885,7 @@ void syntax_error_node(AstNode *node, char *fmt, ...) { bool ast_node_expect(AstNode *node, AstNodeKind kind) { if (node->kind != kind) { - error_node(node, "Expected %.*s, got %.*s", LIT(ast_node_strings[node->kind])); + error(node, "Expected %.*s, got %.*s", LIT(ast_node_strings[node->kind])); return false; } return true; @@ -1980,7 +1980,7 @@ AstNode *parse_type_or_ident(AstFile *f); void check_proc_add_tag(AstFile *f, AstNode *tag_expr, u64 *tags, ProcTag tag, String tag_name) { if (*tags & tag) { - syntax_error_node(tag_expr, "Procedure tag already used: %.*s", LIT(tag_name)); + syntax_error(tag_expr, "Procedure tag already used: %.*s", LIT(tag_name)); } *tags |= tag; } @@ -2056,7 +2056,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven *link_name = f->curr_token.string; // TODO(bill): Check if valid string if (!is_foreign_name_valid(*link_name)) { - syntax_error_node(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*link_name)); + syntax_error(tag_expr, "Invalid alternative link procedure name `%.*s`", LIT(*link_name)); } next_token(f); @@ -2076,35 +2076,35 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven if (cc == ProcCC_Invalid) { cc = ProcCC_Odin; } else { - syntax_error_node(tag_expr, "Multiple calling conventions for procedure type"); + syntax_error(tag_expr, "Multiple calling conventions for procedure type"); } } else if (tag_name == "cc_c") { if (cc == ProcCC_Invalid) { cc = ProcCC_C; } else { - syntax_error_node(tag_expr, "Multiple calling conventions for procedure type"); + syntax_error(tag_expr, "Multiple calling conventions for procedure type"); } } else if (tag_name == "cc_std") { if (cc == ProcCC_Invalid) { cc = ProcCC_Std; } else { - syntax_error_node(tag_expr, "Multiple calling conventions for procedure type"); + syntax_error(tag_expr, "Multiple calling conventions for procedure type"); } } else if (tag_name == "cc_fast") { if (cc == ProcCC_Invalid) { cc = ProcCC_Fast; } else { - syntax_error_node(tag_expr, "Multiple calling conventions for procedure type"); + syntax_error(tag_expr, "Multiple calling conventions for procedure type"); } } else { - syntax_error_node(tag_expr, "Unknown procedure tag #%.*s\n", LIT(tag_name)); + syntax_error(tag_expr, "Unknown procedure tag #%.*s\n", LIT(tag_name)); } #undef ELSE_IF_ADD_TAG } if (cc == ProcCC_Invalid) { - if ((*tags) & ProcTag_foreign) { + if ((*tags) & ProcTag_foreign || f->in_foreign_block) { cc = ProcCC_C; } else { cc = ProcCC_Odin; @@ -2116,7 +2116,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven } if ((*tags & ProcTag_foreign) && (*tags & ProcTag_export)) { - syntax_error(f->curr_token, "You cannot apply both #foreign and #export to a procedure"); + syntax_error(f->curr_token, "A foreign procedure cannot have #export"); } if ((*tags & ProcTag_inline) && (*tags & ProcTag_no_inline)) { @@ -2221,7 +2221,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) { AstNode *expr = parse_expr(f, false); operand = ast_run_expr(f, token, name, expr); if (unparen_expr(expr)->kind != AstNode_CallExpr) { - error_node(expr, "#run can only be applied to procedure calls"); + error(expr, "#run can only be applied to procedure calls"); operand = ast_bad_expr(f, token, f->curr_token); } warning(token, "#run is not yet implemented"); @@ -2943,7 +2943,7 @@ void parse_foreign_block_decl(AstFile *f, Array *decls) { /* fallthrough */ default: - error_node(decl, "Foreign blocks only allow procedure and variable declarations"); + error(decl, "Foreign blocks only allow procedure and variable declarations"); return; } } @@ -2979,6 +2979,10 @@ AstNode *parse_decl(AstFile *f) { Token close = {}; Array decls = make_ast_node_array(f); + bool prev_in_foreign_block = f->in_foreign_block; + defer (f->in_foreign_block = prev_in_foreign_block); + f->in_foreign_block = true; + if (f->curr_token.kind != Token_OpenBrace) { parse_foreign_block_decl(f, &decls); } else { @@ -3161,8 +3165,7 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) { u64 tags = 0; String link_name = {}; - ProcCallingConvention cc = ProcCC_Odin; - + ProcCallingConvention cc = ProcCC_Invalid; parse_proc_tags(f, &tags, &link_name, &cc); if (link_name_) *link_name_ = link_name; @@ -3293,7 +3296,7 @@ Array convert_to_ident_list(AstFile *f, Array list, if (!ignore_flags) { if (i != 0) { - error_node(ident, "Illegal use of prefixes in parameter list"); + error(ident, "Illegal use of prefixes in parameter list"); } } @@ -3302,7 +3305,7 @@ Array convert_to_ident_list(AstFile *f, Array list, case AstNode_BadExpr: break; default: - error_node(ident, "Expected an identifier"); + error(ident, "Expected an identifier"); ident = ast_ident(f, blank_token); break; } @@ -3951,7 +3954,7 @@ AstNode *parse_for_stmt(AstFile *f) { index = cond->AssignStmt.lhs[1]; break; default: - error_node(cond, "Expected at 1 or 2 identifiers"); + error(cond, "Expected at 1 or 2 identifiers"); return ast_bad_stmt(f, token, f->curr_token); } @@ -4301,7 +4304,7 @@ Array parse_stmt_list(AstFile *f) { if (stmt->kind == AstNode_ExprStmt && stmt->ExprStmt.expr != NULL && stmt->ExprStmt.expr->kind == AstNode_ProcLit) { - syntax_error_node(stmt, "Procedure literal evaluated but not used"); + syntax_error(stmt, "Procedure literal evaluated but not used"); } } } @@ -4466,7 +4469,7 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Arraykind != AstNode_BadStmt && node->kind != AstNode_EmptyStmt) { // NOTE(bill): Sanity check - syntax_error_node(node, "Only declarations are allowed at file scope %.*s", LIT(ast_node_strings[node->kind])); + syntax_error(node, "Only declarations are allowed at file scope %.*s", LIT(ast_node_strings[node->kind])); } else if (node->kind == AstNode_GenDecl) { ast_node(gd, GenDecl, node); if (gd->token.kind == Token_import || @@ -4482,9 +4485,9 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Arrayis_import) { - syntax_error_node(node, "Invalid import path: `%.*s`", LIT(file_str)); + syntax_error(node, "Invalid import path: `%.*s`", LIT(file_str)); } else { - syntax_error_node(node, "Invalid include path: `%.*s`", LIT(file_str)); + syntax_error(node, "Invalid include path: `%.*s`", LIT(file_str)); } // NOTE(bill): It's a naughty name decls[i] = ast_bad_decl(f, id->relpath, id->relpath); @@ -4513,9 +4516,9 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Arrayis_system) { - syntax_error_node(node, "Invalid `foreign_system_library` path"); + syntax_error(node, "Invalid `foreign_system_library` path"); } else { - syntax_error_node(node, "Invalid `foreign_library` path"); + syntax_error(node, "Invalid `foreign_library` path"); } // NOTE(bill): It's a naughty name gd->specs[spec_index] = ast_bad_decl(f, fl->filepath, fl->filepath);