From 807256dea4d22550ee5da48e806b4e773670fbfc Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Thu, 15 Sep 2016 18:58:29 +0100 Subject: [PATCH] ssa - alloca all variables at the very start --- code/demo.odin | 20 ++--- code/runtime.odin | 2 +- code/win32.odin | 156 ++++++++++++++++++++++++------------- src/checker/stmt.cpp | 14 ++-- src/codegen/print_llvm.cpp | 48 +++++++++--- src/codegen/ssa.cpp | 46 +++++++++-- src/main.cpp | 11 +-- src/parser.cpp | 50 ++++++++---- 8 files changed, 240 insertions(+), 107 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index 8ac345de6..4fca39f63 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,14 +1,16 @@ -#import "fmt.odin" as fmt -// #import "game.odin" as game +#import "runtime.odin" as _ +#import "punity.odin" as punity -test_proc :: proc() { - fmt.println("Hello?") -} main :: proc() { - x := 0 - // fmt.println("% % % %", "Hellope", true, 6.28, {4}int{1, 2, 3, 4}) - fmt.println("%(%)", #file, #line) - // game.run() + init :: proc() { + + } + + step :: proc() { + + } + + punity.run(init, step) } diff --git a/code/runtime.odin b/code/runtime.odin index 4a440dc89..1d293b5f7 100644 --- a/code/runtime.odin +++ b/code/runtime.odin @@ -171,7 +171,7 @@ __string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > __assert :: proc(msg: string) { - os.write(os.get_standard_file(os.File_Standard.ERROR), msg as []byte) + _ = os.write(os.get_standard_file(os.File_Standard.ERROR), msg as []byte) __debug_trap() } diff --git a/code/win32.odin b/code/win32.odin index aa80e4002..de67784d3 100644 --- a/code/win32.odin +++ b/code/win32.odin @@ -9,18 +9,19 @@ HICON :: type HANDLE HCURSOR :: type HANDLE HMENU :: type HANDLE HBRUSH :: type HANDLE +HGDIOBJ :: type HANDLE WPARAM :: type uint LPARAM :: type int LRESULT :: type int ATOM :: type i16 BOOL :: type i32 -POINT :: type struct { x, y: i32 } WNDPROC :: type proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE -CS_VREDRAW :: 1 -CS_HREDRAW :: 2 +CS_VREDRAW :: 0x0001 +CS_HREDRAW :: 0x0002 +CS_OWNDC :: 0x0020 CW_USEDEFAULT :: 0x80000000 WS_OVERLAPPED :: 0 @@ -32,13 +33,25 @@ WS_CAPTION :: 0x00C00000 WS_VISIBLE :: 0x10000000 WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX -WM_DESTROY :: 0x02 -WM_CLOSE :: 0x10 -WM_QUIT :: 0x12 +WM_DESTROY :: 0x0002 +WM_CLOSE :: 0x0010 +WM_QUIT :: 0x0012 +WM_KEYDOWN :: 0x0100 +WM_KEYUP :: 0x0101 PM_REMOVE :: 1 COLOR_BACKGROUND :: 1 as HBRUSH +BLACK_BRUSH :: 4 + +SM_CXSCREEN :: 0 +SM_CYSCREEN :: 1 + +SW_SHOW :: 5 + +POINT :: struct #ordered { + x, y: i32 +} WNDCLASSEXA :: struct #ordered { @@ -62,45 +75,49 @@ MSG :: struct #ordered { pt: POINT } - - -GetLastError :: proc() -> i32 #foreign -ExitProcess :: proc(exit_code: u32) #foreign -GetDesktopWindow :: proc() -> HWND #foreign -GetCursorPos :: proc(p: ^POINT) -> i32 #foreign -ScreenToClient :: proc(h: HWND, p: ^POINT) -> i32 #foreign - -GetModuleHandleA :: proc(module_name: ^u8) -> HINSTANCE #foreign - -QueryPerformanceFrequency :: proc(result: ^i64) -> i32 #foreign -QueryPerformanceCounter :: proc(result: ^i64) -> i32 #foreign - -sleep_ms :: proc(ms: i32) { - Sleep :: proc(ms: i32) -> i32 #foreign - Sleep(ms) +RECT :: struct #ordered { + left: i32 + top: i32 + right: i32 + bottom: i32 } -OutputDebugStringA :: proc(c_str: ^u8) #foreign + +GetLastError :: proc() -> i32 #foreign #dll_import +ExitProcess :: proc(exit_code: u32) #foreign #dll_import +GetDesktopWindow :: proc() -> HWND #foreign #dll_import +GetCursorPos :: proc(p: ^POINT) -> i32 #foreign #dll_import +ScreenToClient :: proc(h: HWND, p: ^POINT) -> i32 #foreign #dll_import +GetModuleHandleA :: proc(module_name: ^u8) -> HINSTANCE #foreign #dll_import +GetStockObject :: proc(fn_object: i32) -> HGDIOBJ #foreign #dll_import +PostQuitMessage :: proc(exit_code: i32) #foreign #dll_import + +QueryPerformanceFrequency :: proc(result: ^i64) -> i32 #foreign #dll_import +QueryPerformanceCounter :: proc(result: ^i64) -> i32 #foreign #dll_import + +Sleep :: proc(ms: i32) -> i32 #foreign + +OutputDebugStringA :: proc(c_str: ^u8) #foreign #dll_import -RegisterClassExA :: proc(wc: ^WNDCLASSEXA) -> ATOM #foreign +RegisterClassExA :: proc(wc: ^WNDCLASSEXA) -> ATOM #foreign #dll_import CreateWindowExA :: proc(ex_style: u32, class_name, title: ^u8, style: u32, - x, y: u32, - w, h: i32, + x, y, w, h: i32, parent: HWND, menu: HMENU, instance: HINSTANCE, - param: rawptr) -> HWND #foreign + param: rawptr) -> HWND #foreign #dll_import -ShowWindow :: proc(hwnd: HWND, cmd_show: i32) -> BOOL #foreign -TranslateMessage :: proc(msg: ^MSG) -> BOOL #foreign -DispatchMessageA :: proc(msg: ^MSG) -> LRESULT #foreign -UpdateWindow :: proc(hwnd: HWND) -> BOOL #foreign +ShowWindow :: proc(hwnd: HWND, cmd_show: i32) -> BOOL #foreign #dll_import +TranslateMessage :: proc(msg: ^MSG) -> BOOL #foreign #dll_import +DispatchMessageA :: proc(msg: ^MSG) -> LRESULT #foreign #dll_import +UpdateWindow :: proc(hwnd: HWND) -> BOOL #foreign #dll_import PeekMessageA :: proc(msg: ^MSG, hwnd: HWND, - msg_filter_min, msg_filter_max, remove_msg: u32) -> BOOL #foreign + msg_filter_min, msg_filter_max, remove_msg: u32) -> BOOL #foreign #dll_import -DefWindowProcA :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #foreign +DefWindowProcA :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #foreign #dll_import +AdjustWindowRect :: proc(rect: ^RECT, style: u32, menu: BOOL) -> BOOL #foreign #dll_import GetQueryPerformanceFrequency :: proc() -> i64 { @@ -109,21 +126,21 @@ GetQueryPerformanceFrequency :: proc() -> i64 { return r } -GetCommandLineA :: proc() -> ^u8 #foreign - -GetCurrentThreadId :: proc() -> u32 #foreign +GetCommandLineA :: proc() -> ^u8 #foreign #dll_import +GetSystemMetrics :: proc(index: i32) -> i32 #foreign #dll_import +GetCurrentThreadId :: proc() -> u32 #foreign #dll_import // File Stuff -CloseHandle :: proc(h: HANDLE) -> i32 #foreign -GetStdHandle :: proc(h: i32) -> HANDLE #foreign +CloseHandle :: proc(h: HANDLE) -> i32 #foreign #dll_import +GetStdHandle :: proc(h: i32) -> HANDLE #foreign #dll_import CreateFileA :: proc(filename: ^u8, desired_access, share_mode: u32, security: rawptr, - creation, flags_and_attribs: u32, template_file: HANDLE) -> HANDLE #foreign -ReadFile :: proc(h: HANDLE, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> BOOL #foreign -WriteFile :: proc(h: HANDLE, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> i32 #foreign + creation, flags_and_attribs: u32, template_file: HANDLE) -> HANDLE #foreign #dll_import +ReadFile :: proc(h: HANDLE, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> BOOL #foreign #dll_import +WriteFile :: proc(h: HANDLE, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> i32 #foreign #dll_import -GetFileSizeEx :: proc(file_handle: HANDLE, file_size: ^i64) -> BOOL #foreign +GetFileSizeEx :: proc(file_handle: HANDLE, file_size: ^i64) -> BOOL #foreign #dll_import FILE_SHARE_READ :: 0x00000001 FILE_SHARE_WRITE :: 0x00000002 @@ -144,17 +161,48 @@ OPEN_ALWAYS :: 4 TRUNCATE_EXISTING :: 5 -HeapAlloc :: proc(h: HANDLE, flags: u32, bytes: int) -> rawptr #foreign -HeapFree :: proc(h: HANDLE, flags: u32, memory: rawptr) -> BOOL #foreign -GetProcessHeap :: proc() -> HANDLE #foreign +HeapAlloc :: proc(h: HANDLE, flags: u32, bytes: int) -> rawptr #foreign #dll_import +HeapFree :: proc(h: HANDLE, flags: u32, memory: rawptr) -> BOOL #foreign #dll_import +GetProcessHeap :: proc() -> HANDLE #foreign #dll_import + HEAP_ZERO_MEMORY :: 0x00000008 +// GDI + +BITMAPINFO :: struct #ordered { + HEADER :: struct #ordered { + size: u32 + width, height: i32 + planes, bit_count: i16 + compression: u32 + size_image: u32 + x_pels_per_meter: i32 + y_pels_per_meter: i32 + clr_used: u32 + clr_important: u32 + } + using header: HEADER + colors: [1]RGBQUAD +} +RGBQUAD :: struct #ordered { + blue, green, red, reserved: byte +} +BI_RGB :: 0 +DIB_RGB_COLORS :: 0x00 +SRCCOPY : u32 : 0x00cc0020 + +StretchDIBits :: proc(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 #foreign #dll_import @@ -222,24 +270,24 @@ PIXELFORMATDESCRIPTOR :: struct #ordered { } GetDC :: proc(h: HANDLE) -> HDC #foreign -SetPixelFormat :: proc(hdc: HDC, pixel_format: i32, pfd: ^PIXELFORMATDESCRIPTOR ) -> BOOL #foreign -ChoosePixelFormat :: proc(hdc: HDC, pfd: ^PIXELFORMATDESCRIPTOR) -> i32 #foreign -SwapBuffers :: proc(hdc: HDC) -> BOOL #foreign - +SetPixelFormat :: proc(hdc: HDC, pixel_format: i32, pfd: ^PIXELFORMATDESCRIPTOR ) -> BOOL #foreign #dll_import +ChoosePixelFormat :: proc(hdc: HDC, pfd: ^PIXELFORMATDESCRIPTOR) -> i32 #foreign #dll_import +SwapBuffers :: proc(hdc: HDC) -> BOOL #foreign #dll_import +ReleaseDC :: proc(wnd: HWND, hdc: HDC) -> i32 #foreign #dll_import WGL_CONTEXT_MAJOR_VERSION_ARB :: 0x2091 WGL_CONTEXT_MINOR_VERSION_ARB :: 0x2092 WGL_CONTEXT_PROFILE_MASK_ARB :: 0x9126 WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x0002 -wglCreateContext :: proc(hdc: HDC) -> HGLRC #foreign -wglMakeCurrent :: proc(hdc: HDC, hglrc: HGLRC) -> BOOL #foreign -wglGetProcAddress :: proc(c_str: ^u8) -> PROC #foreign -wglDeleteContext :: proc(hglrc: HGLRC) -> BOOL #foreign +wglCreateContext :: proc(hdc: HDC) -> HGLRC #foreign #dll_import +wglMakeCurrent :: proc(hdc: HDC, hglrc: HGLRC) -> BOOL #foreign #dll_import +wglGetProcAddress :: proc(c_str: ^u8) -> PROC #foreign #dll_import +wglDeleteContext :: proc(hglrc: HGLRC) -> BOOL #foreign #dll_import -GetAsyncKeyState :: proc(v_key: i32) -> i16 #foreign +GetAsyncKeyState :: proc(v_key: i32) -> i16 #foreign #dll_import is_key_down :: proc(key: Key_Code) -> bool { return GetAsyncKeyState(key as i32) < 0 diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index fa29456c2..1f57519e0 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -754,12 +754,14 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { case Addressing_Type: error(&c->error_collector, ast_node_token(node), "Is not an expression"); break; - default: - if (kind == Expr_Stmt) { - return; - } - error(&c->error_collector, ast_node_token(node), "Expression is not used"); - break; + case Addressing_NoValue: + return; + default: { + gbString expr_str = expr_to_string(operand.expr); + defer (gb_string_free(expr_str)); + + error(&c->error_collector, ast_node_token(node), "Expression is not used: `%s`", expr_str); + } break; } case_end; diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index 1015207c4..d0debf173 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -387,13 +387,22 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) { ssa_fprintf(f, "%%%d = alloca ", value->id); ssa_print_type(f, m->sizes, type); ssa_fprintf(f, ", align %lld\n", type_align_of(m->sizes, m->allocator, type)); - if (instr->Local.zero_initialized) { - ssa_fprintf(f, "\tstore "); - ssa_print_type(f, m->sizes, type); - ssa_fprintf(f, " zeroinitializer, "); - ssa_print_type(f, m->sizes, type); - ssa_fprintf(f, "* %%%d\n", value->id); - } + // if (instr->Local.zero_initialized) { + // ssa_fprintf(f, "\tstore "); + // ssa_print_type(f, m->sizes, type); + // ssa_fprintf(f, " zeroinitializer, "); + // ssa_print_type(f, m->sizes, type); + // ssa_fprintf(f, "* %%%d\n", value->id); + // } + } break; + + case ssaInstr_ZeroInit: { + Type *type = type_deref(ssa_type(instr->ZeroInit.address)); + ssa_fprintf(f, "\tstore "); + ssa_print_type(f, m->sizes, type); + ssa_fprintf(f, " zeroinitializer, "); + ssa_print_type(f, m->sizes, type); + ssa_fprintf(f, "* %%%d\n", instr->ZeroInit.address->id); } break; case ssaInstr_Store: { @@ -745,10 +754,23 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) { void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { if (proc->body == NULL) { ssa_fprintf(f, "declare "); + if (proc->tags & ProcTag_dll_import) { + ssa_fprintf(f, "dllimport "); + } + if (proc->tags & ProcTag_dll_export) { + ssa_fprintf(f, "dllexport "); + } } else { ssa_fprintf(f, "\ndefine "); } + if (proc->tags & ProcTag_stdcall) { + ssa_fprintf(f, "cc 64 "); + } + if (proc->tags & ProcTag_fastcall) { + ssa_fprintf(f, "cc 65 "); + } + auto *proc_type = &proc->type->Proc; if (proc_type->result_count == 0) { @@ -773,7 +795,9 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { ssa_fprintf(f, ", "); } ssa_print_type(f, m->sizes, e->type); - ssa_fprintf(f, " %%%.*s", LIT(e->token.string)); + if (proc->body != NULL) { + ssa_fprintf(f, " %%%.*s", LIT(e->token.string)); + } } } @@ -787,14 +811,20 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { ssa_fprintf(f, "noinline "); } + // if (proc->tags & ProcTag_stdcall) { + // ssa_fprintf(f, "\"cc\"=\"64\" "); + // } + // if (proc->tags & ProcTag_fastcall) { + // ssa_fprintf(f, "\"cc\"=\"65\" "); + // } if (proc->tags & ProcTag_foreign) { - // TODO(bill): Set calling convention ssa_fprintf(f, "; foreign\n"); } } if (proc->body != NULL) { + // ssa_fprintf(f, "nounwind uwtable {\n"); ssa_fprintf(f, "{\n"); gb_for_array(i, proc->blocks) { ssaBlock *block = proc->blocks[i]; diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index 268778493..bcbe35634 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -65,6 +65,8 @@ struct ssaProcedure { isize scope_index; gbArray(ssaDefer) defer_stmts; gbArray(ssaBlock *) blocks; + ssaBlock * decl_block; + ssaBlock * entry_block; ssaBlock * curr_block; ssaTargetList * target_list; }; @@ -78,6 +80,7 @@ struct ssaProcedure { SSA_INSTR_KIND(Invalid), \ SSA_INSTR_KIND(Comment), \ SSA_INSTR_KIND(Local), \ + SSA_INSTR_KIND(ZeroInit), \ SSA_INSTR_KIND(Store), \ SSA_INSTR_KIND(Load), \ SSA_INSTR_KIND(GetElementPtr), \ @@ -151,6 +154,9 @@ struct ssaInstr { Type * type; b32 zero_initialized; } Local; + struct { + ssaValue *address; + } ZeroInit; struct { ssaValue *address; ssaValue *value; @@ -509,6 +515,13 @@ ssaValue *ssa_make_instr_store(ssaProcedure *p, ssaValue *address, ssaValue *val return v; } +ssaValue *ssa_make_instr_zero_init(ssaProcedure *p, ssaValue *address) { + ssaValue *v = ssa_alloc_instr(p, ssaInstr_ZeroInit); + ssaInstr *i = &v->Instr; + i->ZeroInit.address = address; + return v; +} + ssaValue *ssa_make_instr_load(ssaProcedure *p, ssaValue *address) { ssaValue *v = ssa_alloc_instr(p, ssaInstr_Load); ssaInstr *i = &v->Instr; @@ -743,13 +756,26 @@ ssaValue *ssa_emit_select(ssaProcedure *p, ssaValue *cond, ssaValue *t, ssaValue return ssa_emit(p, ssa_make_instr_select(p, cond, t, f)); } +ssaValue *ssa_emit_zero_init(ssaProcedure *p, ssaValue *address) { + return ssa_emit(p, ssa_make_instr_zero_init(p, address)); +} + ssaValue *ssa_emit_comment(ssaProcedure *p, String text) { return ssa_emit(p, ssa_make_instr_comment(p, text)); } ssaValue *ssa_add_local(ssaProcedure *proc, Entity *e, b32 zero_initialized = true) { - return ssa_emit(proc, ssa_make_instr_local(proc, e, zero_initialized)); + ssaBlock *b = proc->decl_block; // all variables must be in the first block + ssaValue *instr = ssa_make_instr_local(proc, e, zero_initialized); + instr->Instr.parent = b; + gb_array_append(b->instrs, instr); + + if (zero_initialized) { + ssa_emit_zero_init(proc, instr); + } + + return instr; } ssaValue *ssa_add_local_for_identifier(ssaProcedure *proc, AstNode *name, b32 zero_initialized) { @@ -769,11 +795,11 @@ ssaValue *ssa_add_local_generated(ssaProcedure *proc, Type *type) { if (proc->curr_block) { scope = proc->curr_block->scope; } - Entity *entity = make_entity_variable(proc->module->allocator, - scope, - empty_token, - type); - return ssa_emit(proc, ssa_make_instr_local(proc, entity, true)); + Entity *e = make_entity_variable(proc->module->allocator, + scope, + empty_token, + type); + return ssa_add_local(proc, e, true); } ssaValue *ssa_add_param(ssaProcedure *proc, Entity *e) { @@ -944,7 +970,9 @@ ssaValue *ssa_lvalue_load(ssaProcedure *proc, ssaAddr lval) { void ssa_begin_procedure_body(ssaProcedure *proc) { gb_array_init(proc->blocks, gb_heap_allocator()); gb_array_init(proc->defer_stmts, gb_heap_allocator()); - proc->curr_block = ssa_add_block(proc, proc->type_expr, make_string("entry")); + proc->decl_block = ssa_add_block(proc, proc->type_expr, make_string("decls")); + proc->entry_block = ssa_add_block(proc, proc->type_expr, make_string("entry")); + proc->curr_block = proc->entry_block; if (proc->type->Proc.params != NULL) { auto *params = &proc->type->Proc.params->Tuple; @@ -960,6 +988,9 @@ void ssa_end_procedure_body(ssaProcedure *proc) { ssa_emit_ret(proc, NULL); } + proc->curr_block = proc->decl_block; + ssa_emit_jump(proc, proc->entry_block); + // Number blocks and registers i32 reg_id = 0; @@ -973,6 +1004,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) { // NOTE(bill): Ignore non-returning instructions switch (instr->kind) { case ssaInstr_Comment: + case ssaInstr_ZeroInit: case ssaInstr_Store: case ssaInstr_Br: case ssaInstr_Ret: diff --git a/src/main.cpp b/src/main.cpp index e3d819ffb..a0984cbd7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -128,10 +128,10 @@ int main(int argc, char **argv) { exit_code = win32_exec_command_line_app( // "../misc/llvm-bin/opt %s -o %.*s.bc " "opt %s -o %.*s.bc " - "-memcpyopt " - "-mem2reg " - "-die -dse " - "-dce " + // "-memcpyopt " + // "-mem2reg " + // "-die -dse " + // "-dce " // "-S " // "-debug-pass=Arguments " "", @@ -148,13 +148,14 @@ int main(int argc, char **argv) { gb_for_array(i, parser.system_libraries) { String lib = parser.system_libraries[i]; isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), - " -l%.*s.lib", LIT(lib)); + " -l%.*s", LIT(lib)); lib_str = gb_string_appendc(lib_str, lib_str_buf); } exit_code = win32_exec_command_line_app( "clang %.*s.bc -o %.*s.exe " "-O0 " + // "-O2 " "-Wno-override-module " "%s", cast(int)base_name_len, output_name, diff --git a/src/parser.cpp b/src/parser.cpp index 3190698fd..9ecce6778 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -65,12 +65,19 @@ enum DeclKind { Declaration_Count, }; -enum ProcTag { +enum ProcTag : u64 { ProcTag_bounds_check = GB_BIT(0), ProcTag_no_bounds_check = GB_BIT(1), - ProcTag_foreign = GB_BIT(2), - ProcTag_inline = GB_BIT(3), - ProcTag_no_inline = GB_BIT(4), + + ProcTag_foreign = GB_BIT(10), + ProcTag_inline = GB_BIT(11), + ProcTag_no_inline = GB_BIT(12), + ProcTag_dll_import = GB_BIT(13), + ProcTag_dll_export = GB_BIT(14), + + ProcTag_stdcall = GB_BIT(15), + ProcTag_fastcall = GB_BIT(16), + // ProcTag_cdecl = GB_BIT(17), }; enum VarDeclTag { @@ -220,7 +227,7 @@ AST_NODE_KIND(_DeclBegin, "", struct{}) \ AST_NODE_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \ AST_NODE_KIND(VarDecl, "variable declaration", struct { \ DeclKind kind; \ - u32 tags; \ + u64 tags; \ b32 is_using; \ AstNodeArray names; \ AstNode *type; \ @@ -1171,10 +1178,19 @@ b32 is_foreign_name_valid(String name) { void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) { // TODO(bill): Add this to procedure literals too + + + while (f->cursor[0].kind == Token_Hash) { AstNode *tag_expr = parse_tag_expr(f, NULL); ast_node(te, TagExpr, tag_expr); String tag_name = te->name.string; + + #define ELSE_IF_ADD_TAG(name) \ + else if (are_strings_equal(tag_name, make_string(#name))) { \ + check_proc_add_tag(f, tag_expr, tags, ProcTag_##name, tag_name); \ + } + if (are_strings_equal(tag_name, make_string("foreign"))) { check_proc_add_tag(f, tag_expr, tags, ProcTag_foreign, tag_name); if (f->cursor[0].kind == Token_String) { @@ -1186,19 +1202,21 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) { next_token(f); } - } else if (are_strings_equal(tag_name, make_string("bounds_check"))) { - check_proc_add_tag(f, tag_expr, tags, ProcTag_bounds_check, tag_name); - } else if (are_strings_equal(tag_name, make_string("no_bounds_check"))) { - check_proc_add_tag(f, tag_expr, tags, ProcTag_no_bounds_check, tag_name); - } else if (are_strings_equal(tag_name, make_string("inline"))) { - check_proc_add_tag(f, tag_expr, tags, ProcTag_inline, tag_name); - } else if (are_strings_equal(tag_name, make_string("no_inline"))) { - check_proc_add_tag(f, tag_expr, tags, ProcTag_no_inline, tag_name); - // } else if (are_strings_equal(tag_name, make_string("no_context"))) { - // check_proc_add_tag(f, tag_expr, tags, ProcTag_no_context, tag_name); - } else { + } + ELSE_IF_ADD_TAG(bounds_check) + ELSE_IF_ADD_TAG(no_bounds_check) + ELSE_IF_ADD_TAG(inline) + ELSE_IF_ADD_TAG(no_inline) + ELSE_IF_ADD_TAG(dll_import) + ELSE_IF_ADD_TAG(dll_export) + ELSE_IF_ADD_TAG(stdcall) + ELSE_IF_ADD_TAG(fastcall) + // ELSE_IF_ADD_TAG(cdecl) + else { ast_file_err(f, ast_node_token(tag_expr), "Unknown procedure tag"); } + + #undef ELSE_IF_ADD_TAG } if ((*tags & ProcTag_inline) && (*tags & ProcTag_no_inline)) {