From a9b20c29b1ade46d82ab6c62dfcf9148d86daae0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 30 Mar 2019 10:17:31 +0000 Subject: [PATCH 1/8] Fix slicing issue; Change path of math/bits in package json #363 --- core/encoding/json/marshal.odin | 2 +- core/runtime/internal.odin | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/encoding/json/marshal.odin b/core/encoding/json/marshal.odin index d25758275..4f5ee6880 100644 --- a/core/encoding/json/marshal.odin +++ b/core/encoding/json/marshal.odin @@ -1,7 +1,7 @@ package json import "core:mem" -import "core:bits" +import "core:math/bits" import "core:runtime" import "core:strconv" import "core:strings" diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 82cd4cb72..60110be15 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -303,7 +303,7 @@ slice_expr_error_hi :: proc "contextless" (file: string, line, column: int, hi: } slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { - if 0 <= lo && lo < len && lo <= hi && hi <= len do return; + if 0 <= lo && lo <= len && lo <= hi && hi <= len do return; handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { fd := os.stderr; print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); From 7580ec494b144d85bf96af114d32fc60f0f8c0ad Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 30 Mar 2019 10:43:53 +0000 Subject: [PATCH 2/8] Disallow ambiguous singularly variadic polymorphic parameters #361 --- src/check_expr.cpp | 32 ++++++++++++++++++++++++++++++-- src/check_type.cpp | 6 ++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index af3ef01b4..d10dd33c7 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5,6 +5,7 @@ enum CallArgumentError { CallArgumentError_NonVariadicExpand, CallArgumentError_VariadicTuple, CallArgumentError_MultipleVariadicExpand, + CallArgumentError_AmbiguousPolymorphicVariadic, CallArgumentError_ArgumentCount, CallArgumentError_TooFewArguments, CallArgumentError_TooManyArguments, @@ -4492,6 +4493,15 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { err = CallArgumentError_NonVariadicExpand; } else if (operands.count == 0 && param_count_excluding_defaults == 0) { err = CallArgumentError_None; + + if (variadic) { + GB_ASSERT(param_tuple != nullptr && param_tuple->variables.count > 0); + Type *t = param_tuple->variables[0]->type; + if (is_type_polymorphic(t)) { + error(call, "Ambiguous call to a polymorphic variadic procedure with no variadic input"); + err = CallArgumentError_AmbiguousPolymorphicVariadic; + } + } } else { i32 error_code = 0; if (operands.count < param_count_excluding_defaults) { @@ -4583,6 +4593,12 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { GB_ASSERT(is_type_slice(slice)); Type *elem = base_type(slice)->Slice.elem; Type *t = elem; + + if (is_type_polymorphic(t)) { + error(call, "Ambiguous call to a polymorphic variadic procedure with no variadic input"); + err = CallArgumentError_AmbiguousPolymorphicVariadic; + } + for (; operand_index < operands.count; operand_index++) { Operand o = operands[operand_index]; if (vari_expand) { @@ -4761,11 +4777,24 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { for (isize i = 0; i < param_count; i++) { + Entity *e = pt->params->Tuple.variables[i]; Operand *o = &ordered_operands[i]; + bool param_is_variadic = pt->variadic && pt->variadic_index == i; + + if (o->mode == Addressing_Invalid) { + if (param_is_variadic) { + Type *slice = e->type; + GB_ASSERT(is_type_slice(slice)); + Type *elem = base_type(slice)->Slice.elem; + if (is_type_polymorphic(elem)) { + error(call, "Ambiguous call to a polymorphic variadic procedure with no variadic input"); + err = CallArgumentError_AmbiguousPolymorphicVariadic; + return err; + } + } continue; } - Entity *e = pt->params->Tuple.variables[i]; if (e->kind == Entity_TypeName) { GB_ASSERT(pt->is_polymorphic); @@ -4782,7 +4811,6 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) { } } else { i64 s = 0; - bool param_is_variadic = pt->variadic && pt->variadic_index == i; if (!check_is_assignable_to_with_score(c, o, e->type, &s, param_is_variadic)) { bool ok = false; if (e->flags & EntityFlag_AutoCast) { diff --git a/src/check_type.cpp b/src/check_type.cpp index 1721ed881..22cd409ee 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1570,6 +1570,12 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is if (operands != nullptr && variables.count < operands->count) { Operand op = (*operands)[variables.count]; + if (op.expr == nullptr) { + // NOTE(bill): 2019-03-30 + // This is just to add the error message to determine_type_from_polymorphic which + // depends on valid position information + op.expr = _params; + } if (is_type_polymorphic_type) { type = determine_type_from_polymorphic(ctx, type, op); if (type == t_invalid) { From a019059975736fa099958b00f3927f57a6240613 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 30 Mar 2019 10:52:53 +0000 Subject: [PATCH 3/8] Fix -vet for demo.odin --- core/dynlib/lib_windows.odin | 2 +- core/os/os_osx.odin | 12 ++++++------ core/strconv/strconv.odin | 4 ++-- examples/demo/demo.odin | 1 - 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/core/dynlib/lib_windows.odin b/core/dynlib/lib_windows.odin index 67ce47cc1..16167f425 100644 --- a/core/dynlib/lib_windows.odin +++ b/core/dynlib/lib_windows.odin @@ -17,7 +17,7 @@ unload_library :: proc(library: Library) -> bool { } symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) { - c_str := strings.new_cstring(symbol, context.temp_allocator); + c_str := strings.clone_to_cstring(symbol, context.temp_allocator); ptr = win32.get_proc_address(cast(win32.Hmodule)library, c_str); found == ptr != nil; return; diff --git a/core/os/os_osx.odin b/core/os/os_osx.odin index 1914ca0c3..302cba76a 100644 --- a/core/os/os_osx.odin +++ b/core/os/os_osx.odin @@ -153,7 +153,7 @@ foreign dl { } open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) { - cstr := strings.new_cstring(path); + cstr := strings.clone_to_cstring(path); handle := _unix_open(cstr, flags, mode); delete(cstr); if handle == -1 { @@ -221,14 +221,14 @@ is_path_separator :: proc(r: rune) -> bool { stat :: inline proc(path: string) -> (Stat, bool) { s: Stat; - cstr := strings.new_cstring(path); + cstr := strings.clone_to_cstring(path); defer delete(cstr); ret_int := _unix_stat(cstr, &s); return s, ret_int==0; } access :: inline proc(path: string, mask: int) -> bool { - cstr := strings.new_cstring(path); + cstr := strings.clone_to_cstring(path); defer delete(cstr); return _unix_access(cstr, mask) == 0; } @@ -245,7 +245,7 @@ heap_free :: inline proc(ptr: rawptr) { } getenv :: proc(name: string) -> (string, bool) { - path_str := strings.new_cstring(name); + path_str := strings.clone_to_cstring(name); defer delete(path_str); cstr := _unix_getenv(path_str); if cstr == nil { @@ -265,14 +265,14 @@ current_thread_id :: proc "contextless" () -> int { } dlopen :: inline proc(filename: string, flags: int) -> rawptr { - cstr := strings.new_cstring(filename); + cstr := strings.clone_to_cstring(filename); defer delete(cstr); handle := _unix_dlopen(cstr, flags); return handle; } dlsym :: inline proc(handle: rawptr, symbol: string) -> rawptr { assert(handle != nil); - cstr := strings.new_cstring(symbol); + cstr := strings.clone_to_cstring(symbol); defer delete(cstr); proc_handle := _unix_dlsym(handle, cstr); return proc_handle; diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index 2b87c7c72..dd1eea0cb 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -236,8 +236,8 @@ quote :: proc(buf: []byte, s: string) -> string { write_byte(buf, &i, digits[s[0]&0xf]); } if i < len(buf) { - s := quote_rune(buf[i:], r); - i += len(s); + x := quote_rune(buf[i:], r); + i += len(x); } } write_byte(buf, &i, c); diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index efce9299a..dd7590d01 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -5,7 +5,6 @@ import "core:mem" import "core:os" when os.OS == "windows" { - import "core:runtime" import "core:thread" } From 68d4bde82fe58150871feb91e7c3dbc0de4e7662 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 30 Mar 2019 14:51:42 +0000 Subject: [PATCH 4/8] Overrideable stdin, stdout, stderr at the `context` level --- core/fmt/fmt.odin | 12 ++++++------ core/log/file_console_logger.odin | 2 +- core/runtime/core.odin | 8 ++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index c1d21c00d..c75cbba27 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -59,12 +59,12 @@ fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int { // print* procedures return the number of bytes written -print :: proc(args: ..any) -> int { return fprint(os.stdout, ..args); } -print_err :: proc(args: ..any) -> int { return fprint(os.stderr, ..args); } -println :: proc(args: ..any) -> int { return fprintln(os.stdout, ..args); } -println_err :: proc(args: ..any) -> int { return fprintln(os.stderr, ..args); } -printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args); } -printf_err :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args); } +print :: proc(args: ..any) -> int { return fprint(context.stdout, ..args); } +print_err :: proc(args: ..any) -> int { return fprint(context.stderr, ..args); } +println :: proc(args: ..any) -> int { return fprintln(context.stdout, ..args); } +println_err :: proc(args: ..any) -> int { return fprintln(context.stderr, ..args); } +printf :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stdout, fmt, ..args); } +printf_err :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stderr, fmt, ..args); } // aprint* procedures return a string that was allocated with the current context diff --git a/core/log/file_console_logger.odin b/core/log/file_console_logger.odin index 1a961f910..3778d3e53 100644 --- a/core/log/file_console_logger.odin +++ b/core/log/file_console_logger.odin @@ -69,7 +69,7 @@ file_console_logger_proc :: proc(logger_data: rawptr, level: Level, text: string h : os.Handle; if(data.file_handle != os.INVALID_HANDLE) do h = data.file_handle; - else do h = level <= Level.Error ? os.stdout : os.stderr; + else do h = level <= Level.Error ? context.stdout : context.stderr; backing: [1024]byte; //NOTE(Hoej): 1024 might be too much for a header backing, unless somebody has really long paths. buf := strings.builder_from_slice(backing[:]); diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 187573557..5932d57c5 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -213,6 +213,10 @@ Context :: struct { assertion_failure_proc: Assertion_Failure_Proc, logger: log.Logger, + stdin: os.Handle, + stdout: os.Handle, + stderr: os.Handle, + thread_id: int, user_data: any, @@ -350,6 +354,10 @@ __init_context :: proc "contextless" (c: ^Context) { c.logger.procedure = log.nil_logger_proc; c.logger.data = nil; + + c.stdin = os.stdin; + c.stdout = os.stdout; + c.stderr = os.stderr; } @builtin From ef04d13337131f6be0c04da5b0b40c7697fe7251 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 30 Mar 2019 15:10:40 +0000 Subject: [PATCH 5/8] Use `context` for assert-based things. --- core/runtime/core.odin | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 5932d57c5..a01ad4cf8 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -366,7 +366,7 @@ init_global_temporary_allocator :: proc(data: []byte, backup_allocator := contex } default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) { - fd := os.stderr; + fd := context.stderr; print_caller_location(fd, loc); os.write_string(fd, " "); os.write_string(fd, prefix); @@ -661,7 +661,7 @@ card :: proc(s: $S/bit_set[$E; $U]) -> int { @builtin -assert :: proc "contextless" (condition: bool, message := "", loc := #caller_location) -> bool { +assert :: proc(condition: bool, message := "", loc := #caller_location) -> bool { if !condition { p := context.assertion_failure_proc; if p == nil { @@ -673,7 +673,7 @@ assert :: proc "contextless" (condition: bool, message := "", loc := #caller_loc } @builtin -panic :: proc "contextless" (message: string, loc := #caller_location) -> ! { +panic :: proc(message: string, loc := #caller_location) -> ! { p := context.assertion_failure_proc; if p == nil { p = default_assertion_failure_proc; @@ -682,7 +682,7 @@ panic :: proc "contextless" (message: string, loc := #caller_location) -> ! { } @builtin -unimplemented :: proc "contextless" (message := "", loc := #caller_location) -> ! { +unimplemented :: proc(message := "", loc := #caller_location) -> ! { p := context.assertion_failure_proc; if p == nil { p = default_assertion_failure_proc; @@ -691,7 +691,7 @@ unimplemented :: proc "contextless" (message := "", loc := #caller_location) -> } @builtin -unreachable :: proc "contextless" (message := "", loc := #caller_location) -> ! { +unreachable :: proc(message := "", loc := #caller_location) -> ! { p := context.assertion_failure_proc; if p == nil { p = default_assertion_failure_proc; From 564e85ee29eb2e4cd7d03d01ccc12ee797d93382 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 31 Mar 2019 11:22:27 +0100 Subject: [PATCH 6/8] Modify ir_generate_array name logic slightly --- src/ir.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index b5ff56b93..b486a6309 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1433,11 +1433,13 @@ irValue *ir_value_procedure(irModule *m, Entity *entity, Type *type, Ast *type_e irValue *ir_generate_array(irModule *m, Type *elem_type, i64 count, String prefix, i64 id) { gbAllocator a = ir_allocator(); Token token = {Token_Ident}; - isize name_len = prefix.len + 10; + isize name_len = prefix.len + 1 + 20; - char *text = gb_alloc_array(a, char, name_len); + auto suffix_id = cast(unsigned long long)id; + char *text = gb_alloc_array(a, char, name_len+1); gb_snprintf(text, name_len, - "%.*s-%llx", LIT(prefix), cast(unsigned long long)id); + "%.*s-%llu", LIT(prefix), suffix_id); + text[name_len] = 0; String s = make_string_c(text); From 1354f53d02840959b3f70bc8386a188920108d98 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 31 Mar 2019 11:58:54 +0100 Subject: [PATCH 7/8] Remove `derived` from `context`; Fix parsing issue for `typeid` specializations in record parameters; Fix runtime printing of types --- core/odin/parser/parser.odin | 4 ++- core/runtime/core.odin | 1 + core/runtime/internal.odin | 56 +++++++++++++++++++----------------- src/parser.cpp | 5 ++-- 4 files changed, 37 insertions(+), 29 deletions(-) diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index ccae59a7c..2f933a341 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -1528,6 +1528,8 @@ parse_field_list :: proc(p: ^Parser, follow: token.Kind, allowed_flags: ast.Fiel return ok; } + is_signature := (allowed_flags & Field_Flags_Signature_Params) == Field_Flags_Signature_Params; + any_polymorphic_names := check_procedure_name_list(p, names); set_flags = check_field_flag_prefixes(p, len(names), allowed_flags, set_flags); @@ -1538,7 +1540,7 @@ parse_field_list :: proc(p: ^Parser, follow: token.Kind, allowed_flags: ast.Fiel if p.curr_tok.kind != token.Eq { type = parse_var_type(p, allowed_flags); tt := ast.unparen_expr(type); - if !any_polymorphic_names { + if is_signature && !any_polymorphic_names { if ti, ok := tt.derived.(ast.Typeid_Type); ok && ti.specialization != nil { error(p, tt.pos, "specialization of typeid is not allowed without polymorphic names"); } diff --git a/core/runtime/core.odin b/core/runtime/core.odin index a01ad4cf8..8b6fc7319 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -220,6 +220,7 @@ Context :: struct { thread_id: int, user_data: any, + user_ptr: rawptr, user_index: int, derived: any, // May be used for derived data types diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 60110be15..d3ef1f94d 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -223,6 +223,21 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) { print_type(fd, info.underlying); } os.write_byte(fd, ']'); + + case Type_Info_Opaque: + os.write_string(fd, "opaque "); + print_type(fd, info.elem); + + case Type_Info_Simd_Vector: + if info.is_x86_mmx { + os.write_string(fd, "intrinsics.x86_mmx"); + } else { + os.write_string(fd, "intrinsics.vector("); + print_u64(fd, u64(info.count)); + os.write_string(fd, ", "); + print_type(fd, info.elem); + os.write_byte(fd, ')'); + } } } @@ -285,38 +300,27 @@ bounds_check_error :: proc "contextless" (file: string, line, column: int, index handle_error(file, line, column, index, count); } +slice_handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { + fd := os.stderr; + print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); + os.write_string(fd, " Invalid slice indices: "); + print_i64(fd, i64(lo)); + os.write_string(fd, ":"); + print_i64(fd, i64(hi)); + os.write_string(fd, ":"); + print_i64(fd, i64(len)); + os.write_byte(fd, '\n'); + debug_trap(); +} + slice_expr_error_hi :: proc "contextless" (file: string, line, column: int, hi: int, len: int) { if 0 <= hi && hi <= len do return; - handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { - fd := os.stderr; - print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); - os.write_string(fd, " Invalid slice indices: "); - print_i64(fd, i64(lo)); - os.write_string(fd, ":"); - print_i64(fd, i64(hi)); - os.write_string(fd, ":"); - print_i64(fd, i64(len)); - os.write_byte(fd, '\n'); - debug_trap(); - } - handle_error(file, line, column, 0, hi, len); + slice_handle_error(file, line, column, 0, hi, len); } slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { if 0 <= lo && lo <= len && lo <= hi && hi <= len do return; - handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { - fd := os.stderr; - print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); - os.write_string(fd, " Invalid slice indices: "); - print_i64(fd, i64(lo)); - os.write_string(fd, ":"); - print_i64(fd, i64(hi)); - os.write_string(fd, ":"); - print_i64(fd, i64(len)); - os.write_byte(fd, '\n'); - debug_trap(); - } - handle_error(file, line, column, lo, hi, len); + slice_handle_error(file, line, column, lo, hi, len); } dynamic_array_expr_error :: proc "contextless" (file: string, line, column: int, low, high, max: int) { diff --git a/src/parser.cpp b/src/parser.cpp index 2eee82e22..12b7edb01 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3024,6 +3024,7 @@ Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKi isize total_name_count = 0; bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis; bool seen_ellipsis = false; + bool is_signature = (allowed_flags & FieldFlag_Signature) == FieldFlag_Signature; while (f->curr_token.kind != follow && f->curr_token.kind != Token_Colon && @@ -3064,7 +3065,7 @@ Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKi if (f->curr_token.kind != Token_Eq) { type = parse_var_type(f, allow_ellipsis, allow_typeid_token); Ast *tt = unparen_expr(type); - if (!any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { + if (is_signature && !any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { syntax_error(type, "Specialization of typeid is not allowed without polymorphic names"); } } @@ -3121,7 +3122,7 @@ Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKi if (f->curr_token.kind != Token_Eq) { type = parse_var_type(f, allow_ellipsis, allow_typeid_token); Ast *tt = unparen_expr(type); - if (!any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { + if (is_signature && !any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) { syntax_error(type, "Specialization of typeid is not allowed without polymorphic names"); } } From dd9113786c4e7b18e894bd3ceee94cdf08ac6037 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 31 Mar 2019 13:06:01 +0100 Subject: [PATCH 8/8] Remove -keep-temp-files from the build.bat --- build.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.bat b/build.bat index 58ae69f93..6e5450c2b 100644 --- a/build.bat +++ b/build.bat @@ -42,7 +42,7 @@ del *.ilk > NUL 2> NUL cl %compiler_settings% "src\main.cpp" ^ /link %linker_settings% -OUT:%exe_name% ^ - && odin run examples/demo/demo.odin -keep-temp-files + && odin run examples/demo/demo.odin del *.obj > NUL 2> NUL