From efb064449f4db63c1e841f6f0e434f26fcd487ab Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 13 Jun 2019 13:31:15 -0400 Subject: [PATCH] fix runtime initialize array elem and then implicit cast to slice --- src/all_types.hpp | 4 +- src/ir.cpp | 64 ++++++----- test/stage1/behavior.zig | 2 +- test/stage1/behavior/array.zig | 192 +++++++++++++++++---------------- 4 files changed, 140 insertions(+), 122 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index b0147694b4..7cd0bd27eb 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2555,8 +2555,8 @@ struct IrInstructionElemPtr { IrInstruction *array_ptr; IrInstruction *elem_index; PtrLen ptr_len; - bool is_const; bool safety_check_on; + bool initializing; }; struct IrInstructionVarPtr { @@ -2651,6 +2651,7 @@ struct IrInstructionContainerInitList { IrInstruction *elem_type; size_t item_count; IrInstruction **items; + ResultLoc *result_loc; }; struct IrInstructionContainerInitFieldsField { @@ -2666,6 +2667,7 @@ struct IrInstructionContainerInitFields { IrInstruction *container_type; size_t field_count; IrInstructionContainerInitFieldsField *fields; + ResultLoc *result_loc; }; struct IrInstructionUnreachable { diff --git a/src/ir.cpp b/src/ir.cpp index 45424a0939..2dca881d2c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1298,14 +1298,16 @@ static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, IrInstruction *source_ return &instruction->base; } -static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *array_ptr, - IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len) +static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *array_ptr, IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len, + bool initializing) { IrInstructionElemPtr *instruction = ir_build_instruction(irb, scope, source_node); instruction->array_ptr = array_ptr; instruction->elem_index = elem_index; instruction->safety_check_on = safety_check_on; instruction->ptr_len = ptr_len; + instruction->initializing = initializing; ir_ref_instruction(array_ptr, irb->current_basic_block); ir_ref_instruction(elem_index, irb->current_basic_block); @@ -1505,13 +1507,14 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour } static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container_type, size_t item_count, IrInstruction **items) + IrInstruction *container_type, size_t item_count, IrInstruction **items, ResultLoc *result_loc) { IrInstructionContainerInitList *container_init_list_instruction = ir_build_instruction(irb, scope, source_node); container_init_list_instruction->container_type = container_type; container_init_list_instruction->item_count = item_count; container_init_list_instruction->items = items; + container_init_list_instruction->result_loc = result_loc; ir_ref_instruction(container_type, irb->current_basic_block); for (size_t i = 0; i < item_count; i += 1) { @@ -1522,13 +1525,15 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, } static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields) + IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields, + ResultLoc *result_loc) { IrInstructionContainerInitFields *container_init_fields_instruction = ir_build_instruction(irb, scope, source_node); container_init_fields_instruction->container_type = container_type; container_init_fields_instruction->field_count = field_count; container_init_fields_instruction->fields = fields; + container_init_fields_instruction->result_loc = result_loc; ir_ref_instruction(container_type, irb->current_basic_block); for (size_t i = 0; i < field_count; i += 1) { @@ -4202,7 +4207,7 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode return subscript_instruction; IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, - subscript_instruction, true, PtrLenSingle); + subscript_instruction, true, PtrLenSingle, false); if (lval == LValPtr) return ptr_instruction; @@ -5734,7 +5739,8 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A fields[i].value = expr_value; fields[i].source_node = entry_node; } - IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type, field_count, fields); + IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type, + field_count, fields, result_loc); return ir_lval_wrap(irb, scope, init_fields, lval, result_loc); } @@ -5764,7 +5770,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A if (container_ptr != nullptr) { IrInstruction *elem_index = ir_build_const_usize(irb, &result_loc->scope_elide->base, expr_node, i); IrInstruction *elem_ptr = ir_build_elem_ptr(irb, &result_loc->scope_elide->base, expr_node, - container_ptr, elem_index, false, PtrLenSingle); + container_ptr, elem_index, false, PtrLenSingle, true); ResultLocInstruction *result_loc_inst = allocate(1); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = elem_ptr; @@ -5781,7 +5787,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A values[i] = expr_value; } IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type, - item_count, values); + item_count, values, result_loc); return ir_lval_wrap(irb, scope, init_list, lval, result_loc); } } @@ -6264,7 +6270,8 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo is_comptime); ir_set_cursor_at_end_and_append_block(irb, body_block); - IrInstruction *elem_ptr = ir_build_elem_ptr(irb, parent_scope, node, array_val_ptr, index_val, false, PtrLenSingle); + IrInstruction *elem_ptr = ir_build_elem_ptr(irb, parent_scope, node, array_val_ptr, index_val, false, + PtrLenSingle, false); // TODO make it an error to write to element variable or i variable. Buf *elem_var_name = elem_node->data.symbol_expr.symbol; ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime); @@ -16825,8 +16832,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } else if (is_slice(array_type)) { ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index]; if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { - IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node, - array_ptr, casted_elem_index, false, elem_ptr_instruction->ptr_len); + IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, + elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, false, + elem_ptr_instruction->ptr_len, true); result->value.type = return_type; return result; } @@ -16917,8 +16925,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } } - IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node, - array_ptr, casted_elem_index, safety_check_on, elem_ptr_instruction->ptr_len); + IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, + elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, safety_check_on, + elem_ptr_instruction->ptr_len, elem_ptr_instruction->initializing); result->value.type = return_type; return result; } @@ -18784,7 +18793,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI } static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction, - ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields) + ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields, + ResultLoc *result_loc_pass1) { Error err; if (container_type->id == ZigTypeIdUnion) { @@ -18919,11 +18929,11 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc return ira->codegen->invalid_instruction; } - // this instruction should not get to codegen - IrInstruction *result = ir_const(ira, instruction, container_type); - // this is how we signal to EndExpr the value is not comptime known - result->value.special = ConstValSpecialRuntime; - return result; + IrInstruction *result_loc = ir_resolve_result(ira, instruction, result_loc_pass1, + container_type, nullptr); + if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) + return result_loc; + return ir_get_deref(ira, instruction, result_loc, nullptr); } static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, @@ -18942,8 +18952,8 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, buf_sprintf("expected array type or [_], found slice")); return ira->codegen->invalid_instruction; } else if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) { - return ir_analyze_container_init_fields(ira, &instruction->base, container_type, - 0, nullptr); + return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, + instruction->result_loc); } else if (container_type->id == ZigTypeIdArray) { // array is same as slice init but we make a compile error if the length is wrong ZigType *child_type; @@ -19029,11 +19039,11 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, return ira->codegen->invalid_instruction; } - // this instruction should not get to codegen - IrInstruction *new_instruction = ir_const(ira, &instruction->base, fixed_size_array_type); - // this is how we signal to EndExpr the value is not comptime known - new_instruction->value.special = ConstValSpecialRuntime; - return new_instruction; + IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, + fixed_size_array_type, nullptr); + if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) + return result_loc; + return ir_get_deref(ira, &instruction->base, result_loc, nullptr); } else if (container_type->id == ZigTypeIdVoid) { if (elem_count != 0) { ir_add_error_node(ira, instruction->base.source_node, @@ -19058,7 +19068,7 @@ static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ir return ira->codegen->invalid_instruction; return ir_analyze_container_init_fields(ira, &instruction->base, container_type, - instruction->field_count, instruction->fields); + instruction->field_count, instruction->fields, instruction->result_loc); } static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira, diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index 308c7cd4e4..8c179f6d24 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -1,7 +1,7 @@ comptime { _ = @import("behavior/align.zig"); _ = @import("behavior/alignof.zig"); - //_ = @import("behavior/array.zig"); + _ = @import("behavior/array.zig"); _ = @import("behavior/asm.zig"); //_ = @import("behavior/atomics.zig"); _ = @import("behavior/bit_shifting.zig"); diff --git a/test/stage1/behavior/array.zig b/test/stage1/behavior/array.zig index 21d07f75f5..96f7a12cd1 100644 --- a/test/stage1/behavior/array.zig +++ b/test/stage1/behavior/array.zig @@ -172,99 +172,105 @@ fn plusOne(x: u32) u32 { return x + 1; } -test "array literal as argument to function" { - const S = struct { - fn entry(two: i32) void { - foo([_]i32{ - 1, - 2, - 3, - }); - foo([_]i32{ - 1, - two, - 3, - }); - foo2(true, [_]i32{ - 1, - 2, - 3, - }); - foo2(true, [_]i32{ - 1, - two, - 3, - }); - } - fn foo(x: []const i32) void { - expect(x[0] == 1); - expect(x[1] == 2); - expect(x[2] == 3); - } - fn foo2(trash: bool, x: []const i32) void { - expect(trash); - expect(x[0] == 1); - expect(x[1] == 2); - expect(x[2] == 3); - } - }; - S.entry(2); - comptime S.entry(2); +test "runtime initialize array elem and then implicit cast to slice" { + var two: i32 = 2; + const x: []const i32 = [_]i32{two}; + expect(x[0] == 2); } -test "double nested array to const slice cast in array literal" { - const S = struct { - fn entry(two: i32) void { - const cases = [_][]const []const i32{ - [_][]const i32{[_]i32{1}}, - [_][]const i32{[_]i32{ 2, 3 }}, - [_][]const i32{ - [_]i32{4}, - [_]i32{ 5, 6, 7 }, - }, - }; - check(cases); +//test "array literal as argument to function" { +// const S = struct { +// fn entry(two: i32) void { +// foo([_]i32{ +// 1, +// 2, +// 3, +// }); +// foo([_]i32{ +// 1, +// two, +// 3, +// }); +// foo2(true, [_]i32{ +// 1, +// 2, +// 3, +// }); +// foo2(true, [_]i32{ +// 1, +// two, +// 3, +// }); +// } +// fn foo(x: []const i32) void { +// expect(x[0] == 1); +// expect(x[1] == 2); +// expect(x[2] == 3); +// } +// fn foo2(trash: bool, x: []const i32) void { +// expect(trash); +// expect(x[0] == 1); +// expect(x[1] == 2); +// expect(x[2] == 3); +// } +// }; +// S.entry(2); +// comptime S.entry(2); +//} - const cases2 = [_][]const i32{ - [_]i32{1}, - [_]i32{ two, 3 }, - }; - expect(cases2.len == 2); - expect(cases2[0].len == 1); - expect(cases2[0][0] == 1); - expect(cases2[1].len == 2); - expect(cases2[1][0] == 2); - expect(cases2[1][1] == 3); - - const cases3 = [_][]const []const i32{ - [_][]const i32{[_]i32{1}}, - [_][]const i32{[_]i32{ two, 3 }}, - [_][]const i32{ - [_]i32{4}, - [_]i32{ 5, 6, 7 }, - }, - }; - check(cases3); - } - - fn check(cases: []const []const []const i32) void { - expect(cases.len == 3); - expect(cases[0].len == 1); - expect(cases[0][0].len == 1); - expect(cases[0][0][0] == 1); - expect(cases[1].len == 1); - expect(cases[1][0].len == 2); - expect(cases[1][0][0] == 2); - expect(cases[1][0][1] == 3); - expect(cases[2].len == 2); - expect(cases[2][0].len == 1); - expect(cases[2][0][0] == 4); - expect(cases[2][1].len == 3); - expect(cases[2][1][0] == 5); - expect(cases[2][1][1] == 6); - expect(cases[2][1][2] == 7); - } - }; - S.entry(2); - comptime S.entry(2); -} +//test "double nested array to const slice cast in array literal" { +// const S = struct { +// fn entry(two: i32) void { +// const cases = [_][]const []const i32{ +// [_][]const i32{[_]i32{1}}, +// [_][]const i32{[_]i32{ 2, 3 }}, +// [_][]const i32{ +// [_]i32{4}, +// [_]i32{ 5, 6, 7 }, +// }, +// }; +// check(cases); +// +// const cases2 = [_][]const i32{ +// [_]i32{1}, +// [_]i32{ two, 3 }, +// }; +// expect(cases2.len == 2); +// expect(cases2[0].len == 1); +// expect(cases2[0][0] == 1); +// expect(cases2[1].len == 2); +// expect(cases2[1][0] == 2); +// expect(cases2[1][1] == 3); +// +// const cases3 = [_][]const []const i32{ +// [_][]const i32{[_]i32{1}}, +// [_][]const i32{[_]i32{ two, 3 }}, +// [_][]const i32{ +// [_]i32{4}, +// [_]i32{ 5, 6, 7 }, +// }, +// }; +// check(cases3); +// } +// +// fn check(cases: []const []const []const i32) void { +// expect(cases.len == 3); +// expect(cases[0].len == 1); +// expect(cases[0][0].len == 1); +// expect(cases[0][0][0] == 1); +// expect(cases[1].len == 1); +// expect(cases[1][0].len == 2); +// expect(cases[1][0][0] == 2); +// expect(cases[1][0][1] == 3); +// expect(cases[2].len == 2); +// expect(cases[2][0].len == 1); +// expect(cases[2][0][0] == 4); +// expect(cases[2][1].len == 3); +// expect(cases[2][1][0] == 5); +// expect(cases[2][1][1] == 6); +// expect(cases[2][1][2] == 7); +// } +// }; +// S.entry(2); +// comptime S.entry(2); +//}