From 22e982c8fbec797f2fb48a7df5ab28efc0ee16c9 Mon Sep 17 00:00:00 2001 From: nakst Date: Mon, 2 Sep 2019 16:46:50 +0100 Subject: New Essence OS layer; cross-compiling improvements --- src/main.cpp | 92 +++++++++++++++++++++++++++--------------------------------- 1 file changed, 42 insertions(+), 50 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 05fa6c366..539480bf4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -75,7 +75,7 @@ i32 system_exec_command_line_app(char *name, char *fmt, ...) { va_end(va); cmd = make_string(cast(u8 *)&cmd_line, cmd_len-1); - //printf("do: %s\n", cmd_line); + // printf("do: %s\n", cmd_line); exit_code = system(&cmd_line[0]); // pid_t pid = fork(); @@ -210,9 +210,8 @@ enum BuildFlagKind { BuildFlag_Collection, BuildFlag_Define, BuildFlag_BuildMode, + BuildFlag_Target, BuildFlag_Debug, - BuildFlag_CrossCompile, - BuildFlag_CrossLibDir, BuildFlag_NoBoundsCheck, BuildFlag_NoCRT, BuildFlag_UseLLD, @@ -298,9 +297,8 @@ bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Collection, str_lit("collection"), BuildFlagParam_String); add_flag(&build_flags, BuildFlag_Define, str_lit("define"), BuildFlagParam_String); add_flag(&build_flags, BuildFlag_BuildMode, str_lit("build-mode"), BuildFlagParam_String); + add_flag(&build_flags, BuildFlag_Target, str_lit("target"), BuildFlagParam_String); add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None); - add_flag(&build_flags, BuildFlag_CrossCompile, str_lit("cross-compile"), BuildFlagParam_String); - add_flag(&build_flags, BuildFlag_CrossLibDir, str_lit("cross-lib-dir"), BuildFlagParam_String); add_flag(&build_flags, BuildFlag_NoBoundsCheck, str_lit("no-bounds-check"), BuildFlagParam_None); add_flag(&build_flags, BuildFlag_NoCRT, str_lit("no-crt"), BuildFlagParam_None); add_flag(&build_flags, BuildFlag_UseLLD, str_lit("lld"), BuildFlagParam_None); @@ -478,33 +476,6 @@ bool parse_build_flags(Array args) { build_context.keep_temp_files = true; break; - case BuildFlag_CrossCompile: { - GB_ASSERT(value.kind == ExactValue_String); - cross_compile_target = value.value_string; - #if defined(GB_SYSTEM_UNIX) && defined(GB_ARCH_64_BIT) - if (str_eq_ignore_case(cross_compile_target, str_lit("Essence"))) { - - } else - #endif - { - gb_printf_err("Unsupported cross compilation target '%.*s'\n", LIT(cross_compile_target)); - gb_printf_err("Currently supported targets: Essence (from 64-bit Unixes only)\n"); - bad_flags = true; - } - break; - } - - case BuildFlag_CrossLibDir: { - GB_ASSERT(value.kind == ExactValue_String); - if (cross_compile_lib_dir.len) { - gb_printf_err("Multiple cross compilation library directories\n"); - bad_flags = true; - } else { - cross_compile_lib_dir = concatenate_strings(heap_allocator(), str_lit("-L"), value.value_string); - } - break; - } - case BuildFlag_Collection: { GB_ASSERT(value.kind == ExactValue_String); String str = value.value_string; @@ -623,7 +594,25 @@ bool parse_build_flags(Array args) { break; } + case BuildFlag_Target: { + String str = value.value_string; + bool found = false; + + for (int i = 0; i < sizeof(named_targets) / sizeof(named_targets[0]); i++) { + if (str_eq_ignore_case(str, named_targets[i].name)) { + found = true; + selected_target_metrics = named_targets + i; + break; + } + } + + if (!found) { + gb_printf_err("Unknown target '%.*s'\n", LIT(str)); + bad_flags = true; + } + break; + } case BuildFlag_BuildMode: { GB_ASSERT(value.kind == ExactValue_String); @@ -889,8 +878,8 @@ i32 exec_llvm_opt(String output_base) { } i32 exec_llvm_llc(String output_base) { -#if defined(GB_SYSTEM_WINDOWS) // For more arguments: http://llvm.org/docs/CommandGuide/llc.html +#if defined(GB_SYSTEM_WINDOWS) return system_exec_command_line_app("llvm-llc", "\"%.*sbin\\llc\" \"%.*s.bc\" -filetype=obj -O%d " "-o \"%.*s.obj\" " @@ -903,21 +892,19 @@ i32 exec_llvm_llc(String output_base) { LIT(build_context.llc_flags)); #else // NOTE(zangent): Linux / Unix is unfinished and not tested very well. - // For more arguments: http://llvm.org/docs/CommandGuide/llc.html return system_exec_command_line_app("llc", "llc \"%.*s.bc\" -filetype=obj -relocation-model=pic -O%d " "%.*s " - "%s" - "", + "%s%.*s", LIT(output_base), build_context.optimization_level, LIT(build_context.llc_flags), - str_eq_ignore_case(cross_compile_target, str_lit("Essence")) ? "-mtriple=x86_64-pc-none-elf" : ""); + build_context.cross_compiling ? "-mtriple=" : "", + (int) (build_context.cross_compiling ? build_context.target_triplet.len : 0), + build_context.target_triplet.text); #endif } - - int main(int arg_count, char **arg_ptr) { if (arg_count < 2) { usage(make_string_c(arg_ptr[0])); @@ -1026,7 +1013,7 @@ int main(int arg_count, char **arg_ptr) { } - init_build_context(); + init_build_context(selected_target_metrics ? selected_target_metrics->metrics : nullptr); if (build_context.word_size == 4) { print_usage_line(0, "%s 32-bit is not yet supported", args[0]); return 1; @@ -1121,6 +1108,17 @@ int main(int arg_count, char **arg_ptr) { return exit_code; } + if (build_context.cross_compiling) { + if (0) { +#ifdef GB_SYSTEM_UNIX + } else if (selected_target_metrics->metrics == &target_essence_amd64) { + system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s", + LIT(output_base), LIT(output_base), LIT(build_context.link_flags)); +#endif + } else { + gb_printf_err("Don't know how to cross compile to selected target.\n"); + } + } else { #if defined(GB_SYSTEM_WINDOWS) timings_start_section(&timings, str_lit("msvc-link")); @@ -1309,11 +1307,7 @@ int main(int arg_count, char **arg_ptr) { // 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_. - if (str_eq_ignore_case(cross_compile_target, str_lit("Essence"))) { - linker = "x86_64-elf-gcc -T core/sys/essence_linker_userland64.ld -ffreestanding -nostdlib -lgcc -g -z max-page-size=0x1000 -Wno-unused-command-line-argument"; - } else { - linker = "clang -Wno-unused-command-line-argument"; - } + linker = "clang -Wno-unused-command-line-argument"; #endif exit_code = system_exec_command_line_app("ld-link", @@ -1321,7 +1315,6 @@ int main(int arg_count, char **arg_ptr) { " %s " " %.*s " " %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) @@ -1332,11 +1325,9 @@ int main(int arg_count, char **arg_ptr) { #endif , linker, LIT(output_base), LIT(output_base), LIT(output_ext), lib_str, - str_eq_ignore_case(cross_compile_target, str_lit("Essence")) ? "-lfreetype -lglue" : "-lc -lm", + "-lc -lm", LIT(build_context.link_flags), - link_settings, - LIT(cross_compile_lib_dir) - ); + link_settings); if (exit_code != 0) { return exit_code; } @@ -1369,6 +1360,7 @@ int main(int arg_count, char **arg_ptr) { system_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(complete_path), LIT(run_args_string)); } #endif + } return 0; } -- cgit v1.2.3 From 08dd8414c1f7c97e91f082cdace0bcea56603df4 Mon Sep 17 00:00:00 2001 From: Mikkel Hjortshøj Date: Sun, 8 Sep 2019 01:09:04 +0200 Subject: Make `odin run` return the process exit code --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 05fa6c366..00490bce7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1219,7 +1219,7 @@ int main(int arg_count, char **arg_ptr) { remove_temp_files(output_base); if (run_output) { - system_exec_command_line_app("odin run", "%.*s.exe %.*s", LIT(output_base), LIT(run_args_string)); + return system_exec_command_line_app("odin run", "%.*s.exe %.*s", LIT(output_base), LIT(run_args_string)); } #else timings_start_section(&timings, str_lit("ld-link")); -- cgit v1.2.3 From bc34083c9c60397b88da0f594364791b5571ba61 Mon Sep 17 00:00:00 2001 From: Mikkel Hjortshøj Date: Sun, 8 Sep 2019 01:10:54 +0200 Subject: Also return on unix --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 00490bce7..a75b711f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1366,7 +1366,7 @@ int main(int arg_count, char **arg_ptr) { //NOTE(thebirk): This whole thing is a little leaky String complete_path = concatenate_strings(heap_allocator(), output_base, output_ext); complete_path = path_to_full_path(heap_allocator(), complete_path); - system_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(complete_path), LIT(run_args_string)); + return system_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(complete_path), LIT(run_args_string)); } #endif -- cgit v1.2.3 From 218d1131e84c4c45da8b9796f46d52094df2962e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 29 Sep 2019 09:25:33 +0100 Subject: Change how foreign imports work for mac --- src/main.cpp | 8 +++++++- src/unicode.cpp | 1 - src/utf8proc/utf8proc.c | 1 - 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index e6af04a3a..b294e7f96 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1242,12 +1242,18 @@ int main(int arg_count, char **arg_ptr) { if (lib.len > 2 && lib[0] == '-' && lib[1] == 'f') { // framework thingie lib_str = gb_string_append_fmt(lib_str, " -framework %.*s ", (int)(lib.len) - 2, lib.text + 2); + } else if (string_ends_with(lib, str_lit(".framework"))) { + // framework thingie + String lib_name = lib; + lib_name = remove_extension_from_path(lib_name); + lib_str = gb_string_append_fmt(lib_str, " -framework %.*s ", LIT(lib_name)); } else if (string_ends_with(lib, str_lit(".a"))) { // static libs, absolute full path relative to the file in which the lib was imported from lib_str = gb_string_append_fmt(lib_str, " %.*s ", LIT(lib)); } else if (string_ends_with(lib, str_lit(".dylib"))) { // dynamic lib, relative path to executable - lib_str = gb_string_append_fmt(lib_str, " -l:%s/%.*s ", cwd, LIT(lib)); + // lib_str = gb_string_append_fmt(lib_str, " -l:%s/%.*s ", cwd, LIT(lib)); + lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib)); } else { // dynamic or static system lib, just link regularly searching system library paths lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib)); diff --git a/src/unicode.cpp b/src/unicode.cpp index 0ad658806..679d56365 100644 --- a/src/unicode.cpp +++ b/src/unicode.cpp @@ -2,7 +2,6 @@ #pragma warning(disable: 4245) extern "C" { -#include "utf8proc/utf8proc.h" #include "utf8proc/utf8proc.c" } #pragma warning(pop) diff --git a/src/utf8proc/utf8proc.c b/src/utf8proc/utf8proc.c index e821889c6..29fc250fc 100644 --- a/src/utf8proc/utf8proc.c +++ b/src/utf8proc/utf8proc.c @@ -40,7 +40,6 @@ * Implementation of libutf8proc. */ - #include "utf8proc.h" #include "utf8proc_data.c" -- cgit v1.2.3 From 2a6d9e8927ad1eb1e5f3a79fc9ed068a02cbfdfc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 13 Oct 2019 12:38:23 +0100 Subject: `#panic`; Minor change to demo.odin; Fix `#assert` bug at file scope --- core/odin/parser/parser.odin | 2 +- core/runtime/core.odin | 54 +++++++++++++++++++----------------- examples/demo/demo.odin | 20 +++++++------- src/check_expr.cpp | 22 +++++++++++++-- src/check_type.cpp | 37 ++++++++++++++++++++----- src/checker.cpp | 13 +++++++-- src/checker.hpp | 1 + src/main.cpp | 14 ++++------ src/parser.cpp | 38 +++---------------------- src/types.cpp | 66 ++++++++++++++++++++++++-------------------- 10 files changed, 145 insertions(+), 122 deletions(-) (limited to 'src/main.cpp') diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 213041924..fee9b7bdc 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -1091,7 +1091,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { case: error(p, stmt.pos, "#complete can only be applied to a switch statement"); } return stmt; - case "assert": + case "assert", "panic": bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(tag)); bd.tok = tok; bd.name = name; diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 729932781..9ad5d3d8a 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -6,6 +6,7 @@ package runtime import "core:os" import "core:mem" import "core:log" +import "intrinsics" // Naming Conventions: // In general, Ada_Case for types and snake_case for values @@ -187,12 +188,13 @@ Typeid_Kind :: enum u8 { #assert(len(Typeid_Kind) < 32); Typeid_Bit_Field :: bit_field #align align_of(uintptr) { - index: 8*size_of(align_of(uintptr)) - 8, + index: 8*size_of(uintptr) - 8, kind: 5, // Typeid_Kind named: 1, special: 1, // signed, cstring, etc reserved: 1, } +#assert(size_of(Typeid_Bit_Field) == size_of(uintptr)); // NOTE(bill): only the ones that are needed (not all types) // This will be set by the compiler @@ -678,7 +680,7 @@ assert :: proc(condition: bool, message := "", loc := #caller_location) -> bool if p == nil { p = default_assertion_failure_proc; } - p("Runtime assertion", message, loc); + p("runtime assertion", message, loc); }(message, loc); } return condition; @@ -690,7 +692,7 @@ panic :: proc(message: string, loc := #caller_location) -> ! { if p == nil { p = default_assertion_failure_proc; } - p("Panic", message, loc); + p("panic", message, loc); } @builtin @@ -816,8 +818,7 @@ __get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> Map_Header { value: V, }; - _, is_string := type_info_base(type_info_of(K)).variant.(Type_Info_String); - header.is_key_string = is_string; + header.is_key_string = intrinsics.type_is_string(K); header.entry_size = int(size_of(Entry)); header.entry_align = int(align_of(Entry)); header.value_offset = uintptr(offset_of(Entry, value)); @@ -828,33 +829,34 @@ __get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> Map_Header { __get_map_key :: proc "contextless" (k: $K) -> Map_Key { key := k; map_key: Map_Key; - ti := type_info_base_without_enum(type_info_of(K)); - switch _ in ti.variant { - case Type_Info_Integer: - switch 8*size_of(key) { - case 8: map_key.hash = u64(( ^u8)(&key)^); - case 16: map_key.hash = u64(( ^u16)(&key)^); - case 32: map_key.hash = u64(( ^u32)(&key)^); - case 64: map_key.hash = u64(( ^u64)(&key)^); - case: panic("Unhandled integer size"); - } - case Type_Info_Rune: + + T :: intrinsics.type_core_type(K); + + when intrinsics.type_is_integer(T) { + sz :: 8*size_of(T); + when sz == 8 do map_key.hash = u64(( ^u8)(&key)^); + else when sz == 16 do map_key.hash = u64((^u16)(&key)^); + else when sz == 32 do map_key.hash = u64((^u32)(&key)^); + else when sz == 64 do map_key.hash = u64((^u64)(&key)^); + else do #assert(false, "Unhandled integer size"); + } else when intrinsics.type_is_rune(T) { map_key.hash = u64((^rune)(&key)^); - case Type_Info_Pointer: + } else when intrinsics.type_is_pointer(T) { map_key.hash = u64(uintptr((^rawptr)(&key)^)); - case Type_Info_Float: - switch 8*size_of(key) { - case 32: map_key.hash = u64((^u32)(&key)^); - case 64: map_key.hash = u64((^u64)(&key)^); - case: panic("Unhandled float size"); - } - case Type_Info_String: + } else when intrinsics.type_is_float(T) { + sz :: 8*size_of(T); + when sz == 32 do map_key.hash = u64((^u32)(&key)^); + else when sz == 64 do map_key.hash = u64((^u64)(&key)^); + else do #assert(false, "Unhandled float size"); + } else when intrinsics.type_is_string(T) { + #assert(T == string); str := (^string)(&key)^; map_key.hash = default_hash_string(str); map_key.str = str; - case: - panic("Unhandled map key type"); + } else { + #assert(false, "Unhandled map key type"); } + return map_key; } diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index ff861b1de..5ee9ded84 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -28,9 +28,9 @@ when os.OS == "windows" { Answers to common questions about Odin. */ -@(link_name="general_stuff") -general_stuff :: proc() { - fmt.println("# general_stuff"); +@(link_name="extra_general_stuff") +extra_general_stuff :: proc() { + fmt.println("# extra_general_stuff"); { // `do` for inline statements rather than block foo :: proc() do fmt.println("Foo!"); if false do foo(); @@ -209,8 +209,8 @@ union_type :: proc() { } } - Vector3 :: struct {x, y, z: f32}; - Quaternion :: struct {x, y, z, w: f32}; + Vector3 :: distinct [3]f32; + Quaternion :: distinct quaternion128; // More realistic examples { @@ -320,17 +320,17 @@ union_type :: proc() { /* Entity :: struct { - .. + ... derived: union{^Frog, ^Monster}, } Frog :: struct { using entity: Entity, - .. + ... } Monster :: struct { using entity: Entity, - .. + ... } new_entity :: proc(T: type) -> ^Entity { @@ -539,7 +539,7 @@ parametric_polymorphism :: proc() { fmt.println(r); r = 123; fmt.println(r); - r = Error.Foo0; + r = Error.Foo0; // r = .Foo0; is allow too, see implicit selector expressions below fmt.println(r); } @@ -1190,7 +1190,7 @@ where_clauses :: proc() { main :: proc() { when true { - general_stuff(); + extra_general_stuff(); union_type(); parametric_polymorphism(); threading_example(); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 6a0d8221f..7c418c4f0 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3071,7 +3071,6 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ } if (selector->kind != Ast_Ident) { - // if (selector->kind != Ast_Ident) { error(selector, "Illegal selector kind: '%.*s'", LIT(ast_strings[selector->kind])); operand->mode = Addressing_Invalid; operand->expr = node; @@ -3544,6 +3543,25 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 operand->type = t_untyped_bool; operand->mode = Addressing_Constant; + } else if (name == "panic") { + if (ce->args.count != 1) { + error(call, "'#panic' expects 1 argument, got %td", ce->args.count); + return false; + } + if (!is_type_string(operand->type) && operand->mode != Addressing_Constant) { + gbString str = expr_to_string(ce->args[0]); + error(call, "'%s' is not a constant string", str); + gb_string_free(str); + return false; + } + error(call, "Compile time panic: %.*s", LIT(operand->value.value_string)); + if (c->proc_name != "") { + gbString str = type_to_string(c->curr_proc_sig); + error_line("\tCalled within '%.*s' :: %s\n", LIT(c->proc_name), str); + gb_string_free(str); + } + operand->type = t_invalid; + operand->mode = Addressing_NoValue; } else if (name == "defined") { if (ce->args.count != 1) { error(call, "'#defined' expects 1 argument, got %td", ce->args.count); @@ -6349,7 +6367,7 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call) { ce->proc->kind == Ast_BasicDirective) { ast_node(bd, BasicDirective, ce->proc); String name = bd->name; - if (name == "location" || name == "assert" || name == "defined" || name == "load") { + if (name == "location" || name == "assert" || name == "panic" || name == "defined" || name == "load") { operand->mode = Addressing_Builtin; operand->builtin_id = BuiltinProc_DIRECTIVE; operand->expr = ce->proc; diff --git a/src/check_type.cpp b/src/check_type.cpp index 329755ea5..4d107a9ac 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1847,7 +1847,7 @@ Array systemv_distribute_struct_fields(Type *t) { } auto distributed = array_make(heap_allocator(), 0, distributed_cap); - + i64 sz = type_size_of(bt); switch (bt->kind) { case Type_Basic: switch (bt->Basic.kind){ @@ -1925,9 +1925,9 @@ Array systemv_distribute_struct_fields(Type *t) { array_add(&distributed, t_int); break; + case Type_Union: case Type_DynamicArray: case Type_Map: - case Type_Union: case Type_BitField: // TODO(bill): Ignore? // NOTE(bill, 2019-10-10): Odin specific, don't worry about C calling convention yet goto DEFAULT; @@ -1937,7 +1937,7 @@ Array systemv_distribute_struct_fields(Type *t) { case Type_SimdVector: // TODO(bill): Is this correct logic? default: DEFAULT:; - if (type_size_of(bt) > 0) { + if (sz > 0) { array_add(&distributed, bt); } break; @@ -1959,13 +1959,22 @@ Type *handle_single_distributed_type_parameter(Array const &types, bool if (types.count == 1) { if (offset) *offset = 1; + + i64 sz = type_size_of(types[0]); + if (is_type_float(types[0])) { return types[0]; - } else if (type_size_of(types[0]) == 8) { + } + switch (sz) { + case 0: + GB_PANIC("Zero sized type found!"); + case 1: + case 2: + case 4: + case 8: return types[0]; - } else { - return t_u64; } + return t_u64; } else if (types.count >= 2) { if (types[0] == t_f32 && types[1] == t_f32) { if (offset) *offset = 2; @@ -2050,7 +2059,7 @@ Type *handle_struct_system_v_amd64_abi_type(Type *t) { Type *final_type = nullptr; if (field_types.count == 0) { - return t; + final_type = t; } else if (field_types.count == 1) { final_type = field_types[0]; } else { @@ -2072,8 +2081,22 @@ Type *handle_struct_system_v_amd64_abi_type(Type *t) { variables[1] = alloc_entity_param(nullptr, empty_token, two_types[1], false, false); final_type = alloc_type_tuple(); final_type->Tuple.variables = variables; + if (t->kind == Type_Struct) { + // NOTE(bill): Make this packed + final_type->Tuple.is_packed = t->Struct.is_packed; + } } } + + + GB_ASSERT(final_type != nullptr); + i64 ftsz = type_size_of(final_type); + i64 otsz = type_size_of(original_type); + if (ftsz != otsz) { + // TODO(bill): Handle this case which will be caused by #packed most likely + GB_PANIC("Incorrectly handled case for handle_struct_system_v_amd64_abi_type, %lld vs %lld", ftsz, otsz); + } + return final_type; } } diff --git a/src/checker.cpp b/src/checker.cpp index f30273439..8ce9d8ec2 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3367,8 +3367,9 @@ bool collect_file_decls(CheckerContext *ctx, Array const &decls) { if (es->expr->kind == Ast_CallExpr) { ast_node(ce, CallExpr, es->expr); if (ce->proc->kind == Ast_BasicDirective) { - Operand o = {}; - check_expr(ctx, &o, es->expr); + if (ctx->collect_delayed_decls) { + array_add(&ctx->scope->delayed_directives, es->expr); + } } } case_end; @@ -3525,12 +3526,18 @@ void check_import_entities(Checker *c) { for_array(i, pkg->files) { AstFile *f = pkg->files[i]; CheckerContext ctx = c->init_ctx; - add_curr_ast_file(&ctx, f); + for_array(j, f->scope->delayed_imports) { Ast *decl = f->scope->delayed_imports[j]; check_add_import_decl(&ctx, decl); } + } + for_array(i, pkg->files) { + AstFile *f = pkg->files[i]; + CheckerContext ctx = c->init_ctx; + add_curr_ast_file(&ctx, f); + for_array(j, f->scope->delayed_directives) { Ast *expr = f->scope->delayed_directives[j]; Operand o = {}; diff --git a/src/checker.hpp b/src/checker.hpp index 58cb01a82..f86acce5c 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -222,6 +222,7 @@ struct ForeignContext { typedef Array CheckerTypePath; typedef Array CheckerPolyPath; + // CheckerInfo stores all the symbol information for a type-checked program struct CheckerInfo { Map untyped; // Key: Ast * | Expression -> ExprInfo diff --git a/src/main.cpp b/src/main.cpp index b294e7f96..78859e04e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -445,7 +445,7 @@ bool parse_build_flags(Array args) { path = substring(path, 0, string_extension_position(path)); } #endif - build_context.out_filepath = path; + build_context.out_filepath = path_to_full_path(heap_allocator(), path); } else { gb_printf_err("Invalid -out path, got %.*s\n", LIT(path)); bad_flags = true; @@ -624,7 +624,7 @@ bool parse_build_flags(Array args) { break; } - if (str == "dll") { + if (str == "dll" || str == "shared") { build_context.is_dll = true; } else if (str == "exe") { build_context.is_dll = false; @@ -1112,7 +1112,7 @@ int main(int arg_count, char **arg_ptr) { if (0) { #ifdef GB_SYSTEM_UNIX } else if (selected_target_metrics->metrics == &target_essence_amd64) { - system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s", + system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s", LIT(output_base), LIT(output_base), LIT(build_context.link_flags)); #endif } else { @@ -1239,10 +1239,7 @@ int main(int arg_count, char **arg_ptr) { // 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) - if (lib.len > 2 && lib[0] == '-' && lib[1] == 'f') { - // framework thingie - lib_str = gb_string_append_fmt(lib_str, " -framework %.*s ", (int)(lib.len) - 2, lib.text + 2); - } else if (string_ends_with(lib, str_lit(".framework"))) { + if (string_ends_with(lib, str_lit(".framework"))) { // framework thingie String lib_name = lib; lib_name = remove_extension_from_path(lib_name); @@ -1251,8 +1248,7 @@ int main(int arg_count, char **arg_ptr) { // static libs, absolute full path relative to the file in which the lib was imported from lib_str = gb_string_append_fmt(lib_str, " %.*s ", LIT(lib)); } else if (string_ends_with(lib, str_lit(".dylib"))) { - // dynamic lib, relative path to executable - // lib_str = gb_string_append_fmt(lib_str, " -l:%s/%.*s ", cwd, LIT(lib)); + // dynamic lib lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib)); } else { // dynamic or static system lib, just link regularly searching system library paths diff --git a/src/parser.cpp b/src/parser.cpp index 025a181ba..f69efc0ce 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3970,34 +3970,6 @@ Ast *parse_stmt(AstFile *f) { return s; } - // case Token_static: { - // CommentGroup *docs = f->lead_comment; - // Token token = expect_token(f, Token_static); - - // Ast *decl = nullptr; - // Array list = parse_lhs_expr_list(f); - // if (list.count == 0) { - // syntax_error(token, "Illegal use of 'static' statement"); - // expect_semicolon(f, nullptr); - // return ast_bad_stmt(f, token, f->curr_token); - // } - - // expect_token_after(f, Token_Colon, "identifier list"); - // decl = parse_value_decl(f, list, docs); - - // if (decl != nullptr && decl->kind == Ast_ValueDecl) { - // if (decl->ValueDecl.is_mutable) { - // decl->ValueDecl.is_static = true; - // } else { - // error(token, "'static' may only be currently used with variable declaration"); - // } - // return decl; - // } - - // syntax_error(token, "Illegal use of 'static' statement"); - // return ast_bad_stmt(f, token, f->curr_token); - // } break; - case Token_using: { CommentGroup *docs = f->lead_comment; Token token = expect_token(f, Token_using); @@ -4071,12 +4043,10 @@ Ast *parse_stmt(AstFile *f) { } else if (tag == "assert") { Ast *t = ast_basic_directive(f, hash_token, tag); return ast_expr_stmt(f, parse_call_expr(f, t)); - } /* else if (name.string == "no_deferred") { - s = parse_stmt(f); - s->stmt_state_flags |= StmtStateFlag_no_deferred; - } */ - - if (tag == "include") { + } else if (tag == "panic") { + Ast *t = ast_basic_directive(f, hash_token, tag); + return ast_expr_stmt(f, parse_call_expr(f, t)); + } else if (tag == "include") { syntax_error(token, "#include is not a valid import declaration kind. Did you mean 'import'?"); s = ast_bad_stmt(f, token, f->curr_token); } else { diff --git a/src/types.cpp b/src/types.cpp index d8a579510..8ad352f62 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -113,21 +113,22 @@ struct BasicType { struct TypeStruct { Array fields; Array tags; - Ast *node; - Scope * scope; - - Array offsets; - bool are_offsets_set; - bool are_offsets_being_processed; - bool is_packed; - bool is_raw_union; - bool is_polymorphic; - bool is_poly_specialized; + Array offsets; + Ast * node; + Scope * scope; + Type * polymorphic_params; // Type_Tuple Type * polymorphic_parent; - i64 custom_align; // NOTE(bill): Only used in structs at the moment + i64 custom_align; Entity * names; + + bool are_offsets_set; + bool are_offsets_being_processed; + bool is_packed; + bool is_raw_union; + bool is_polymorphic; + bool is_poly_specialized; }; struct TypeUnion { @@ -137,12 +138,11 @@ struct TypeUnion { i64 variant_block_size; i64 custom_align; i64 tag_size; + Type * polymorphic_params; // Type_Tuple + Type * polymorphic_parent; bool no_nil; - - bool is_polymorphic; - bool is_poly_specialized; - Type * polymorphic_params; // Type_Tuple - Type * polymorphic_parent; + bool is_polymorphic; + bool is_poly_specialized; }; #define TYPE_KINDS \ @@ -190,7 +190,9 @@ struct TypeUnion { TYPE_KIND(Tuple, struct { \ Array variables; /* Entity_Variable */ \ Array offsets; \ + bool are_offsets_being_processed; \ bool are_offsets_set; \ + bool is_packed; \ }) \ TYPE_KIND(Proc, struct { \ Ast *node; \ @@ -201,9 +203,8 @@ struct TypeUnion { i32 result_count; \ Array abi_compat_params; \ Type * abi_compat_result_type; \ - bool return_by_pointer; \ - bool variadic; \ i32 variadic_index; \ + bool variadic; \ bool require_results; \ bool c_vararg; \ bool is_polymorphic; \ @@ -211,6 +212,7 @@ struct TypeUnion { bool has_proc_default_values; \ bool has_named_results; \ bool diverging; /* no return */ \ + bool return_by_pointer; \ u64 tags; \ isize specialization_count; \ ProcCallingConvention calling_convention; \ @@ -1782,7 +1784,8 @@ bool are_types_identical(Type *x, Type *y) { case Type_Tuple: if (y->kind == Type_Tuple) { - if (x->Tuple.variables.count == y->Tuple.variables.count) { + if (x->Tuple.variables.count == y->Tuple.variables.count && + x->Tuple.is_packed == y->Tuple.is_packed) { for_array(i, x->Tuple.variables) { Entity *xe = x->Tuple.variables[i]; Entity *ye = y->Tuple.variables[i]; @@ -2231,19 +2234,22 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty if (type->Array.count <= 4) { // HACK(bill): Memory leak switch (type->Array.count) { - #define _ARRAY_FIELD_CASE(_length, _name) \ - case (_length): \ - if (field_name == _name) { \ + #define _ARRAY_FIELD_CASE_IF(_length, _name) \ + if (field_name == (_name)) { \ selection_add_index(&sel, (_length)-1); \ sel.entity = alloc_entity_array_elem(nullptr, make_token_ident(str_lit(_name)), type->Array.elem, (_length)-1); \ return sel; \ - } \ + } + #define _ARRAY_FIELD_CASE(_length, _name0, _name1) \ + case (_length): \ + _ARRAY_FIELD_CASE_IF(_length, _name0); \ + _ARRAY_FIELD_CASE_IF(_length, _name1); \ /*fallthrough*/ - _ARRAY_FIELD_CASE(4, "w"); - _ARRAY_FIELD_CASE(3, "z"); - _ARRAY_FIELD_CASE(2, "y"); - _ARRAY_FIELD_CASE(1, "x"); + _ARRAY_FIELD_CASE(4, "w", "a"); + _ARRAY_FIELD_CASE(3, "z", "b"); + _ARRAY_FIELD_CASE(2, "y", "g"); + _ARRAY_FIELD_CASE(1, "x", "r"); default: break; #undef _ARRAY_FIELD_CASE @@ -2590,9 +2596,9 @@ bool type_set_offsets(Type *t) { } } else if (is_type_tuple(t)) { if (!t->Tuple.are_offsets_set) { - t->Struct.are_offsets_being_processed = true; - t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, false, false); - t->Struct.are_offsets_being_processed = false; + t->Tuple.are_offsets_being_processed = true; + t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, t->Tuple.is_packed, false); + t->Tuple.are_offsets_being_processed = false; t->Tuple.are_offsets_set = true; return true; } -- cgit v1.2.3 From 10b109e25f05862f478ba4c82f18ba22c8289017 Mon Sep 17 00:00:00 2001 From: Tetralux Date: Sat, 19 Oct 2019 17:55:05 +0100 Subject: Clarify that you can pass a directory to `odin build` Changes the usage information to this: ``` D:\Software\odin\odin.exe is a tool for managing Odin source code Usage: D:\Software\odin\odin.exe command [arguments] Commands: build compile .odin file, or directory of .odin files, as an executable. one must contain the program's entry point, all must be in the same package. run same as 'build', but also then runs the newly compiled executable. check parse and type check .odin file query parse, type check, and output a .json file containing information about the program docs generate documentation for a .odin file version print version ``` --- src/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 78859e04e..acb580ca2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -160,8 +160,9 @@ void usage(String argv0) { print_usage_line(0, "Usage:"); print_usage_line(1, "%.*s command [arguments]", LIT(argv0)); print_usage_line(0, "Commands:"); - print_usage_line(1, "build compile .odin file as executable"); - print_usage_line(1, "run compile and run .odin file"); + print_usage_line(1, "build compile .odin file, or directory of .odin files, as an executable."); + print_usage_line(1, " one must contain the program's entry point, all must be in the same package."); + print_usage_line(1, "run same as 'build', but also then runs the newly compiled executable."); print_usage_line(1, "check parse and type check .odin file"); print_usage_line(1, "query parse, type check, and output a .json file containing information about the program"); print_usage_line(1, "docs generate documentation for a .odin file"); -- cgit v1.2.3