Commit 3cbe827464
Changed files (4)
src/all_types.hpp
@@ -2651,7 +2651,7 @@ struct IrInstructionContainerInitList {
IrInstruction *elem_type;
size_t item_count;
IrInstruction **items;
- ResultLoc *result_loc;
+ IrInstruction *result_loc;
};
struct IrInstructionContainerInitFieldsField {
@@ -2667,7 +2667,7 @@ struct IrInstructionContainerInitFields {
IrInstruction *container_type;
size_t field_count;
IrInstructionContainerInitFieldsField *fields;
- ResultLoc *result_loc;
+ IrInstruction *result_loc;
};
struct IrInstructionUnreachable {
src/ir.cpp
@@ -1507,7 +1507,7 @@ 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, ResultLoc *result_loc)
+ IrInstruction *container_type, size_t item_count, IrInstruction **items, IrInstruction *result_loc)
{
IrInstructionContainerInitList *container_init_list_instruction =
ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);
@@ -1520,13 +1520,14 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
for (size_t i = 0; i < item_count; i += 1) {
ir_ref_instruction(items[i], irb->current_basic_block);
}
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
return &container_init_list_instruction->base;
}
static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields,
- ResultLoc *result_loc)
+ IrInstruction *result_loc)
{
IrInstructionContainerInitFields *container_init_fields_instruction =
ir_build_instruction<IrInstructionContainerInitFields>(irb, scope, source_node);
@@ -1539,6 +1540,7 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scop
for (size_t i = 0; i < field_count; i += 1) {
ir_ref_instruction(fields[i].value, irb->current_basic_block);
}
+ if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
return &container_init_fields_instruction->base;
}
@@ -5667,14 +5669,10 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
}
static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
- ResultLoc *result_loc)
+ ResultLoc *parent_result_loc)
{
assert(node->type == NodeTypeContainerInitExpr);
- if (ir_should_inline(irb->exec, scope)) {
- result_loc = nullptr;
- }
-
AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
ContainerInitKind kind = container_init_expr->kind;
@@ -5699,13 +5697,13 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
}
IrInstruction *container_ptr = nullptr;
- if (result_loc != nullptr) {
- src_assert(result_loc->scope_elide == nullptr, node);
- result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
+ if (!ir_should_inline(irb->exec, scope)) {
+ src_assert(parent_result_loc->scope_elide == nullptr, node);
+ parent_result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
- src_assert(result_loc != nullptr, node);
- container_ptr = ir_build_resolve_result(irb, &result_loc->scope_elide->base,
- node, result_loc, container_type);
+ src_assert(parent_result_loc != nullptr, node);
+ container_ptr = ir_build_resolve_result(irb, &parent_result_loc->scope_elide->base,
+ node, parent_result_loc, container_type);
}
size_t field_count = container_init_expr->entries.length;
@@ -5720,14 +5718,14 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
Scope *val_scope = scope;
ResultLoc *child_result_loc = nullptr;
if (container_ptr != nullptr) {
- IrInstruction *field_ptr = ir_build_field_ptr(irb, &result_loc->scope_elide->base, expr_node,
- container_ptr, name, true);
+ IrInstruction *field_ptr = ir_build_field_ptr(irb, &parent_result_loc->scope_elide->base,
+ expr_node, container_ptr, name, true);
ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
result_loc_inst->base.id = ResultLocIdInstruction;
result_loc_inst->base.source_instruction = field_ptr;
ir_ref_instruction(field_ptr, irb->current_basic_block);
child_result_loc = &result_loc_inst->base;
- val_scope = &result_loc->scope_elide->base;
+ val_scope = &parent_result_loc->scope_elide->base;
}
IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone,
@@ -5740,9 +5738,9 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
fields[i].source_node = entry_node;
}
IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type,
- field_count, fields, result_loc);
+ field_count, fields, container_ptr);
- return ir_lval_wrap(irb, scope, init_fields, lval, result_loc);
+ return ir_lval_wrap(irb, scope, init_fields, lval, parent_result_loc);
}
case ContainerInitKindArray: {
size_t item_count = container_init_expr->entries.length;
@@ -5753,12 +5751,12 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
}
IrInstruction *container_ptr = nullptr;
- if (result_loc != nullptr) {
- src_assert(result_loc->scope_elide == nullptr, node);
- result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
+ if (!ir_should_inline(irb->exec, scope)) {
+ src_assert(parent_result_loc->scope_elide == nullptr, node);
+ parent_result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
- container_ptr = ir_build_resolve_result(irb, &result_loc->scope_elide->base,
- node, result_loc, container_type);
+ container_ptr = ir_build_resolve_result(irb, &parent_result_loc->scope_elide->base,
+ node, parent_result_loc, container_type);
}
IrInstruction **values = allocate<IrInstruction *>(item_count);
@@ -5768,15 +5766,16 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
ResultLoc *child_result_loc = nullptr;
Scope *val_scope = scope;
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, true);
+ IrInstruction *elem_index = ir_build_const_usize(irb, &parent_result_loc->scope_elide->base,
+ expr_node, i);
+ IrInstruction *elem_ptr = ir_build_elem_ptr(irb, &parent_result_loc->scope_elide->base,
+ expr_node, container_ptr, elem_index, false, PtrLenSingle, true);
ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
result_loc_inst->base.id = ResultLocIdInstruction;
result_loc_inst->base.source_instruction = elem_ptr;
ir_ref_instruction(elem_ptr, irb->current_basic_block);
child_result_loc = &result_loc_inst->base;
- val_scope = &result_loc->scope_elide->base;
+ val_scope = &parent_result_loc->scope_elide->base;
}
IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone,
@@ -5787,8 +5786,8 @@ 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, result_loc);
- return ir_lval_wrap(irb, scope, init_list, lval, result_loc);
+ item_count, values, container_ptr);
+ return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc);
}
}
zig_unreachable();
@@ -16900,6 +16899,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
}
}
+ if (is_slice(array_type) && elem_ptr_instruction->initializing) {
+ // we need a pointer to an element inside a slice. but we're initializing an array.
+ // this means that the slice isn't actually pointing at anything.
+ ir_add_error(ira, &elem_ptr_instruction->base,
+ buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'",
+ buf_ptr(&array_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
} else {
// runtime known element index
switch (type_requires_comptime(ira->codegen, return_type)) {
@@ -18729,7 +18736,8 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe
}
static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
- ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields)
+ ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
+ IrInstruction *old_result_loc)
{
Error err;
assert(container_type->id == ZigTypeIdUnion);
@@ -18785,20 +18793,21 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
return result;
}
- // this instruction should not get to codegen
- IrInstruction *new_instruction = ir_const(ira, instruction, container_type);
- // this is how we signal to EndExpr the value is not comptime known
- new_instruction->value.special = ConstValSpecialRuntime;
- return new_instruction;
+ ir_assert(old_result_loc != nullptr, instruction);
+ IrInstruction *result_loc = old_result_loc->child;
+ if (type_is_invalid(result_loc->value.type))
+ return result_loc;
+ return ir_get_deref(ira, instruction, result_loc, nullptr);
}
static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
- ResultLoc *result_loc_pass1)
+ IrInstruction *old_result_loc)
{
Error err;
if (container_type->id == ZigTypeIdUnion) {
- return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count, fields);
+ return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count,
+ fields, old_result_loc);
}
if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {
ir_add_error(ira, instruction,
@@ -18929,9 +18938,10 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
return ira->codegen->invalid_instruction;
}
- 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))
+
+ ir_assert(old_result_loc != nullptr, instruction);
+ IrInstruction *result_loc = old_result_loc->child;
+ if (type_is_invalid(result_loc->value.type))
return result_loc;
return ir_get_deref(ira, instruction, result_loc, nullptr);
}
@@ -19039,9 +19049,9 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
return ira->codegen->invalid_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))
+ ir_assert(instruction->result_loc != nullptr, &instruction->base);
+ IrInstruction *result_loc = instruction->result_loc->child;
+ if (type_is_invalid(result_loc->value.type))
return result_loc;
return ir_get_deref(ira, &instruction->base, result_loc, nullptr);
} else if (container_type->id == ZigTypeIdVoid) {
test/stage1/behavior/array.zig
@@ -174,103 +174,103 @@ fn plusOne(x: u32) u32 {
test "runtime initialize array elem and then implicit cast to slice" {
var two: i32 = 2;
- const x: []const i32 = [_]i32{two};
+ const x: []const i32 = [_]i32{two};
expect(x[0] == 2);
}
-//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 "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);
-//}
+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 "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);
+}
BRANCH_TODO
@@ -10,3 +10,9 @@ get an empty file compiling successfully (with no panic fn override)
uncomment all the behavior tests
+better behavior for implicit casts. for example these introduce an extra allocation/memcpy:
+ var x: [1]i32 = [_]i32{1};
+ var x = ([1]i32)([_]i32{1});
+whereas this one does not:
+ var x = [_]i32{1};
+but all 3 should be semantically identical