From 2f740fa19ff88981d028289162b3eb469b7f5315 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 4 Nov 2019 09:54:13 +0100 Subject: [PATCH 1/6] Fix cmpxchg trying to execute at CT Fixes #3582 --- src/ir.cpp | 3 ++- test/stage1/behavior/atomics.zig | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index a53367a324..ce0e204e63 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -21798,7 +21798,8 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi return ira->codegen->invalid_instruction; } - if (instr_is_comptime(casted_ptr) && instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) { + if (instr_is_comptime(casted_ptr) && casted_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar && + instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) { zig_panic("TODO compile-time execution of cmpxchg"); } diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig index 1a941cf21c..8c4a186032 100644 --- a/test/stage1/behavior/atomics.zig +++ b/test/stage1/behavior/atomics.zig @@ -100,3 +100,10 @@ test "cmpxchg with ignored result" { expectEqual(i32(5678), x); } + +var a_global_variable = u32(1234); + +test "cmpxchg on a global variable" { + _ = @cmpxchgWeak(u32, &a_global_variable, 1234, 42, .Acquire, .Monotonic); + expectEqual(u32(42), a_global_variable); +} From c8b6e552991136e3a45095007ae4c3594be02ef9 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 4 Nov 2019 09:58:02 +0100 Subject: [PATCH 2/6] Make the `leb` module available to non-std code --- lib/std/debug.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 5e5a886d4e..61b492c20d 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -17,7 +17,7 @@ const maxInt = std.math.maxInt; const File = std.fs.File; const windows = std.os.windows; -const leb = @import("debug/leb128.zig"); +pub const leb = @import("debug/leb128.zig"); pub const FailingAllocator = @import("debug/failing_allocator.zig").FailingAllocator; pub const failing_allocator = &FailingAllocator.init(global_allocator, 0).allocator; From 61825062aadd68e6cd2e864c717b3a8ce482258d Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 4 Nov 2019 10:11:33 +0100 Subject: [PATCH 3/6] Correctly process errors for invalid types in fn call Fixes #3544 --- src/analyze.cpp | 15 ++++++++++++--- test/compile_errors.zig | 12 ++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index e38470f7f9..9c7ee3ca53 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4238,7 +4238,8 @@ AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index) { return nullptr; } -static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { +static Error define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { + Error err; ZigType *fn_type = fn_table_entry->type_entry; assert(!fn_type->data.fn.is_generic); FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; @@ -4257,8 +4258,11 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { } ZigType *param_type = param_info->type; - bool is_noalias = param_info->is_noalias; + if ((err = type_resolve(g, param_type, ResolveStatusSizeKnown))) { + return err; + } + bool is_noalias = param_info->is_noalias; if (is_noalias && get_codegen_ptr_type(param_type) == nullptr) { add_node_error(g, param_decl_node, buf_sprintf("noalias on non-pointer parameter")); } @@ -4273,6 +4277,8 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { fn_table_entry->variable_list.append(var); } } + + return ErrorNone; } bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node) { @@ -4596,7 +4602,10 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { if (!fn_table_entry->child_scope) fn_table_entry->child_scope = &fn_table_entry->fndef_scope->base; - define_local_param_variables(g, fn_table_entry); + if (define_local_param_variables(g, fn_table_entry) != ErrorNone) { + fn_table_entry->anal_state = FnAnalStateInvalid; + return; + } ZigType *fn_type = fn_table_entry->type_entry; assert(!fn_type->data.fn.is_generic); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 440545de8f..a49ad8c117 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,18 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "using invalid types in function call raises an error", + \\const MenuEffect = enum {}; + \\fn func(effect: MenuEffect) void {} + \\export fn entry() void { + \\ func(MenuEffect.ThisDoesNotExist); + \\} + , + "tmp.zig:1:20: error: enums must have 1 or more fields", + "tmp.zig:4:20: note: referenced here", + ); + cases.add( "using an unknown len ptr type instead of array", \\const resolutions = [*][*]const u8{ From 2b4bf1e7ced151482ce741788eadcb39f6d60f72 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 4 Nov 2019 10:38:48 +0100 Subject: [PATCH 4/6] Fix crash in #3483 The bytesToSlice is still not evaluated at comptime but at least it doesn't crash anymore. --- src/ir.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index ce0e204e63..ea87999454 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1668,7 +1668,7 @@ static IrInstruction *ir_build_resize_slice(IrAnalyze *ira, IrInstruction *sourc instruction->result_loc = result_loc; ir_ref_instruction(operand, ira->new_irb.current_basic_block); - ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); return &instruction->base; } From c47211cc60a826837191fbb87b32f0baacb167cb Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 4 Nov 2019 15:09:11 +0100 Subject: [PATCH 5/6] Prevent crash when slicing undefined ptr to slice Fixes #3534 --- src/ir.cpp | 18 +++++++++++++----- test/compile_errors.zig | 10 ++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index ea87999454..211af9a758 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -22949,12 +22949,20 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction if (parent_ptr == nullptr) return ira->codegen->invalid_instruction; - array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.source_node); - if (array_val == nullptr) - return ira->codegen->invalid_instruction; - rel_end = child_array_type->data.array.len; - abs_offset = 0; + if (parent_ptr->special == ConstValSpecialUndef) { + array_val = nullptr; + abs_offset = 0; + rel_end = SIZE_MAX; + ptr_is_undef = true; + } else { + array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.source_node); + if (array_val == nullptr) + return ira->codegen->invalid_instruction; + + rel_end = child_array_type->data.array.len; + abs_offset = 0; + } } else { array_val = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node); if (array_val == nullptr) diff --git a/test/compile_errors.zig b/test/compile_errors.zig index a49ad8c117..a9d93dd882 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,16 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "slicing of global undefined pointer", + \\var buf: *[1]u8 = undefined; + \\export fn entry() void { + \\ _ = buf[0..1]; + \\} + , + "tmp.zig:3:12: error: non-zero length slice of undefined pointer", + ); + cases.add( "using invalid types in function call raises an error", \\const MenuEffect = enum {}; From 9170dcb73f7b654cdf8447452240c3bf8d3de838 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 4 Nov 2019 15:32:51 +0100 Subject: [PATCH 6/6] Fix #3558 Finding a suitable test case is left as an exercise to the reader. --- src/ir.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 211af9a758..35ef2b98e2 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11297,7 +11297,10 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { if (!const_val) return nullptr; - assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction); + // May be a ConstPtrSpecialHardCodedAddr + if (const_val->data.x_ptr.special != ConstPtrSpecialFunction) + return nullptr; + return const_val->data.x_ptr.data.fn.fn_entry; } @@ -16737,9 +16740,8 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC return ir_finish_anal(ira, cast_instruction); } else if (fn_ref->value.type->id == ZigTypeIdFn) { ZigFn *fn_table_entry = ir_resolve_fn(ira, fn_ref); - if (fn_table_entry == nullptr) - return ira->codegen->invalid_instruction; - return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry, + ZigType *fn_type = fn_table_entry ? fn_table_entry->type_entry : fn_ref->value.type; + return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_type, fn_ref, nullptr, is_comptime, call_instruction->fn_inline); } else if (fn_ref->value.type->id == ZigTypeIdBoundFn) { assert(fn_ref->value.special == ConstValSpecialStatic); @@ -16756,7 +16758,7 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC if (fn_ref->value.type->id == ZigTypeIdFn) { return ir_analyze_fn_call(ira, call_instruction, nullptr, fn_ref->value.type, - fn_ref, nullptr, false, FnInlineAuto); + fn_ref, nullptr, false, call_instruction->fn_inline); } else { ir_add_error_node(ira, fn_ref->source_node, buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value.type->name)));