From a9ea22d4f9816998cccfca4df2ef56d5069e1814 Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Fri, 27 Jul 2018 19:17:38 +0900 Subject: src/ir.cpp: wire-up IR for handle builtin; Tracking Issue #1296 ; --- src/ir.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index 699baa152e..50c8c70290 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -580,6 +580,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *) return IrInstructionIdFrameAddress; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionHandle *) { + return IrInstructionIdHandle; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) { return IrInstructionIdAlignOf; } @@ -2240,6 +2244,17 @@ static IrInstruction *ir_build_frame_address_from(IrBuilder *irb, IrInstruction return new_instruction; } +static IrInstruction *ir_build_handle(IrBuilder *irb, Scope *scope, AstNode *source_node) { + IrInstructionHandle *instruction = ir_build_instruction(irb, scope, source_node); + return &instruction->base; +} + +static IrInstruction *ir_build_handle_from(IrBuilder *irb, IrInstruction *old_instruction) { + IrInstruction *new_instruction = ir_build_handle(irb, old_instruction->scope, old_instruction->source_node); + ir_link_new_instruction(new_instruction, old_instruction); + return new_instruction; +} + static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2, IrInstruction *result_ptr, TypeTableEntry *result_ptr_type) @@ -4475,6 +4490,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval); case BuiltinFnIdFrameAddress: return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval); + case BuiltinFnIdHandle: + return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval); case BuiltinFnIdAlignOf: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -19007,6 +19024,13 @@ static TypeTableEntry *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrIn return u8_ptr_const; } +static TypeTableEntry *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructionHandle *instruction) { + ir_build_handle_from(&ira->new_irb, &instruction->base); + + TypeTableEntry *promise_type = get_promise_type(ira->codegen, nullptr); + return promise_type; +} + static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) { IrInstruction *type_value = instruction->type_value->other; if (type_is_invalid(type_value->value.type)) @@ -20982,6 +21006,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction); case IrInstructionIdFrameAddress: return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction); + case IrInstructionIdHandle: + return ir_analyze_instruction_handle(ira, (IrInstructionHandle *)instruction); case IrInstructionIdAlignOf: return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction); case IrInstructionIdOverflowOp: @@ -21274,6 +21300,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdAlignOf: case IrInstructionIdReturnAddress: case IrInstructionIdFrameAddress: + case IrInstructionIdHandle: case IrInstructionIdTestErr: case IrInstructionIdUnwrapErrCode: case IrInstructionIdOptionalWrap: -- cgit v1.2.3 From c1a3b0cb0af3c0639ce09b2a17a3cc90977346fe Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sat, 28 Jul 2018 15:23:09 +0900 Subject: src/ir.cpp: add/throw error for @handle() in a non async context; Tracking Issue #1296 ; Thanks @andrewrk ; --- src/ir.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index 50c8c70290..1e9d1bdb7e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -3858,6 +3858,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return irb->codegen->invalid_instruction; } + bool is_async = exec_is_async(irb->exec); + switch (builtin_fn->id) { case BuiltinFnIdInvalid: zig_unreachable(); @@ -4491,6 +4493,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo case BuiltinFnIdFrameAddress: return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval); case BuiltinFnIdHandle: + if (!is_async) { + add_node_error(irb->codegen, node, buf_sprintf("@handle() in non-async function")); + return irb->codegen->invalid_instruction; + } return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval); case BuiltinFnIdAlignOf: { -- cgit v1.2.3 From fcf53b31fc2899cba682c4c9a8cade40c6e0ab9e Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sat, 28 Jul 2018 15:38:22 +0900 Subject: src/ir.cpp: return promise->T instead of promise; Tracking Issue #1296 ; Thanks @andrewrk ; --- src/ir.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index 1e9d1bdb7e..9712cb0bc2 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -19033,8 +19033,9 @@ static TypeTableEntry *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrIn static TypeTableEntry *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructionHandle *instruction) { ir_build_handle_from(&ira->new_irb, &instruction->base); - TypeTableEntry *promise_type = get_promise_type(ira->codegen, nullptr); - return promise_type; + FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); + assert(fn_entry != nullptr); + return get_promise_type(ira->codegen, fn_entry->type_entry->data.fn.fn_type_id.return_type); } static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) { -- cgit v1.2.3 From a8ea2360958354ba8310c7cea388351299e72e44 Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sat, 28 Jul 2018 17:35:50 +0900 Subject: src/ir.cpp: don't allow `@handle()` outside of a function; Tracking Issue #1296 ; --- src/ir.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index 9712cb0bc2..966d8e9f33 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4493,6 +4493,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo case BuiltinFnIdFrameAddress: return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval); case BuiltinFnIdHandle: + if (!irb->exec->fn_entry) { + add_node_error(irb->codegen, node, buf_sprintf("@handle() called outside of function definition")); + return irb->codegen->invalid_instruction; + } if (!is_async) { add_node_error(irb->codegen, node, buf_sprintf("@handle() in non-async function")); return irb->codegen->invalid_instruction; -- cgit v1.2.3 From b3cd65d56e2efc3e0f67461dbad75747b2db3aa7 Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sun, 29 Jul 2018 17:10:48 +0900 Subject: src/ir.cpp: remove promise_symbol from suspend; Tracking Issue #1296 ; --- src/ir.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index 966d8e9f33..7d2881744d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -7096,19 +7096,8 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod if (node->data.suspend.block == nullptr) { suspend_code = ir_build_coro_suspend(irb, parent_scope, node, nullptr, const_bool_false); } else { - assert(node->data.suspend.promise_symbol != nullptr); - assert(node->data.suspend.promise_symbol->type == NodeTypeSymbol); - Buf *promise_symbol_name = node->data.suspend.promise_symbol->data.symbol_expr.symbol; Scope *child_scope; - if (!buf_eql_str(promise_symbol_name, "_")) { - VariableTableEntry *promise_var = ir_create_var(irb, node, parent_scope, promise_symbol_name, - true, true, false, const_bool_false); - ir_build_var_decl(irb, parent_scope, node, promise_var, nullptr, nullptr, irb->exec->coro_handle); - child_scope = promise_var->child_scope; - } else { - child_scope = parent_scope; - } - ScopeSuspend *suspend_scope = create_suspend_scope(node, child_scope); + ScopeSuspend *suspend_scope = create_suspend_scope(node, parent_scope); suspend_scope->resume_block = resume_block; child_scope = &suspend_scope->base; IrInstruction *save_token = ir_build_coro_save(irb, child_scope, node, irb->exec->coro_handle); -- cgit v1.2.3 From 298abbcff86629273f24891d243fb6e503392e8f Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Fri, 3 Aug 2018 02:55:31 +0900 Subject: better support for `_` identifier * disallow variable declaration of `_` * prevent `_` from shadowing itself * prevent read access of `_` closes #1204 closes #1320 --- src/ir.cpp | 16 ++++++++++++- test/behavior.zig | 1 + test/cases/underscore.zig | 28 +++++++++++++++++++++++ test/compile_errors.zig | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 test/cases/underscore.zig (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index 7d2881744d..8dd4bb41db 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -3332,7 +3332,15 @@ static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Sco static VariableTableEntry *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime) { - VariableTableEntry *var = create_local_var(irb->codegen, node, scope, name, src_is_const, gen_is_const, is_shadowable, is_comptime); + bool is_underscored = name ? buf_eql_str(name, "_") : false; + VariableTableEntry *var = create_local_var( irb->codegen + , node + , scope + , (is_underscored ? nullptr : name) + , src_is_const + , gen_is_const + , (is_underscored ? true : is_shadowable) + , is_comptime ); if (is_comptime != nullptr || gen_is_const) { var->mem_slot_index = exec_next_mem_slot(irb->exec); var->owner_exec = irb->exec; @@ -5186,6 +5194,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; + if (buf_eql_str(variable_declaration->symbol, "_")) { + add_node_error(irb->codegen, node, buf_sprintf("`_` is not a declarable symbol")); + return irb->codegen->invalid_instruction; + } + IrInstruction *type_instruction; if (variable_declaration->type != nullptr) { type_instruction = ir_gen_node(irb, variable_declaration->type, scope); @@ -5198,6 +5211,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod bool is_shadowable = false; bool is_const = variable_declaration->is_const; bool is_extern = variable_declaration->is_extern; + IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime); VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol, diff --git a/test/behavior.zig b/test/behavior.zig index b03336eb71..e993d7e0dc 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -60,6 +60,7 @@ comptime { _ = @import("cases/try.zig"); _ = @import("cases/type_info.zig"); _ = @import("cases/undefined.zig"); + _ = @import("cases/underscore.zig"); _ = @import("cases/union.zig"); _ = @import("cases/var_args.zig"); _ = @import("cases/void.zig"); diff --git a/test/cases/underscore.zig b/test/cases/underscore.zig new file mode 100644 index 0000000000..44451e3723 --- /dev/null +++ b/test/cases/underscore.zig @@ -0,0 +1,28 @@ +const std = @import("std"); +const assert = std.debug.assert; + +test "ignore lval with underscore" { + _ = false; +} + +test "ignore lval with underscore (for loop)" { + for ([]void{}) |_, i| { + for ([]void{}) |_, j| { + break; + } + break; + } +} + +test "ignore lval with underscore (while loop)" { + while (optionalReturnError()) |_| { + while (optionalReturnError()) |_| { + break; + } else |_| { } + break; + } else |_| { } +} + +fn optionalReturnError() !?u32 { + return error.optionalReturnError; +} diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 948d212e58..56b2c51d74 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -22,6 +22,64 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { ".tmp_source.zig:3:28: error: @handle() in non-async function", ); + cases.add( + "`_` is not a declarable symbol", + \\export fn f1() usize { + \\ var _: usize = 2; + \\ return _; + \\} + , + ".tmp_source.zig:2:5: error: `_` is not a declarable symbol", + ".tmp_source.zig:3:12: error: use of undeclared identifier '_'", + ); + + cases.add( + "`_` should not be usable inside for", + \\export fn returns() void { + \\ for ([]void{}) |_, i| { + \\ for ([]void{}) |_, j| { + \\ return _; + \\ } + \\ } + \\} + , + ".tmp_source.zig:4:20: error: use of undeclared identifier '_'", + ); + + cases.add( + "`_` should not be usable inside while", + \\export fn returns() void { + \\ while (optionalReturn()) |_| { + \\ while (optionalReturn()) |_| { + \\ return _; + \\ } + \\ } + \\} + \\fn optionalReturn() ?u32 { + \\ return 1; + \\} + , + ".tmp_source.zig:4:20: error: use of undeclared identifier '_'", + ); + + cases.add( + "`_` should not be usable inside while else", + \\export fn returns() void { + \\ while (optionalReturnError()) |_| { + \\ while (optionalReturnError()) |_| { + \\ return; + \\ } else |_| { + \\ if (_ == error.optionalReturnError) return; + \\ } + \\ } + \\} + \\fn optionalReturnError() !?u32 { + \\ return error.optionalReturnError; + \\} + , + ".tmp_source.zig:6:17: error: use of undeclared identifier '_'", + ); + cases.add( "while loop body expression ignored", \\fn returns() usize { -- cgit v1.2.3 From 9bd8b01650f9cf21e601117951711b21aa5fd216 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 3 Aug 2018 15:21:08 -0400 Subject: fix tagged union initialization with a runtime void closes #1328 --- src/ir.cpp | 11 ++++++++++- test/cases/union.zig | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index 8dd4bb41db..3e423487aa 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -9628,6 +9628,9 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un case ConstValSpecialStatic: return &value->value; case ConstValSpecialRuntime: + if (!type_has_bits(value->value.type)) { + return &value->value; + } ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression")); return nullptr; case ConstValSpecialUndef: @@ -16129,8 +16132,14 @@ static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, Ir if (casted_field_value == ira->codegen->invalid_instruction) return ira->codegen->builtin_types.entry_invalid; + type_ensure_zero_bits_known(ira->codegen, casted_field_value->value.type); + if (type_is_invalid(casted_field_value->value.type)) + return ira->codegen->builtin_types.entry_invalid; + bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope); - if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) { + if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime || + !type_has_bits(casted_field_value->value.type)) + { ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk); if (!field_val) return ira->codegen->builtin_types.entry_invalid; diff --git a/test/cases/union.zig b/test/cases/union.zig index 78b2dc8dd7..08969e64fe 100644 --- a/test/cases/union.zig +++ b/test/cases/union.zig @@ -297,3 +297,17 @@ test "access a member of tagged union with conflicting enum tag name" { comptime assert(Bar.A == u8); } + +test "tagged union initialization with runtime void" { + assert(testTaggedUnionInit({})); +} + +const TaggedUnionWithAVoid = union(enum) { + A, + B: i32, +}; + +fn testTaggedUnionInit(x: var) bool { + const y = TaggedUnionWithAVoid{ .A = x }; + return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A; +} -- cgit v1.2.3