| ... | @@ -877,63 +877,115 @@ pub fn structInitExpr( | ... | @@ -877,63 +877,115 @@ pub fn structInitExpr( |
| 877 | } | 877 | } |
| 878 | } | 878 | } |
| 879 | switch (rl) { | 879 | switch (rl) { |
| 880 | .discard => return astgen.failNode(node, "TODO implement structInitExpr discard", .{}), | 880 | .discard => { |
| 881 | .none, .none_or_ref => return astgen.failNode(node, "TODO implement structInitExpr none", .{}), | 881 | for (struct_init.ast.fields) |field_init| { |
| 882 | .ref => unreachable, // struct literal not valid as l-value | 882 | _ = try expr(gz, scope, .discard, field_init); |
| 883 | .ty => |ty_inst| { | 883 | } |
| 884 | const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len); | 884 | return Zir.Inst.Ref.void_value; |
| | 885 | }, |
| | 886 | .none, .none_or_ref => { |
| | 887 | if (struct_init.ast.type_expr != 0) { |
| | 888 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); |
| | 889 | return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst); |
| | 890 | } |
| | 891 | const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len); |
| 885 | defer gpa.free(fields_list); | 892 | defer gpa.free(fields_list); |
| 886 | | 893 | |
| 887 | for (struct_init.ast.fields) |field_init, i| { | 894 | for (struct_init.ast.fields) |field_init, i| { |
| 888 | const name_token = tree.firstToken(field_init) - 2; | 895 | const name_token = tree.firstToken(field_init) - 2; |
| 889 | const str_index = try gz.identAsString(name_token); | 896 | const str_index = try gz.identAsString(name_token); |
| 890 | | 897 | |
| 891 | const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{ | | |
| 892 | .container_type = ty_inst, | | |
| 893 | .name_start = str_index, | | |
| 894 | }); | | |
| 895 | fields_list[i] = .{ | 898 | fields_list[i] = .{ |
| 896 | .field_type = gz.refToIndex(field_ty_inst).?, | 899 | .field_name = str_index, |
| 897 | .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init), | 900 | .init = try expr(gz, scope, .none, field_init), |
| 898 | }; | 901 | }; |
| 899 | } | 902 | } |
| 900 | const init_inst = try gz.addPlNode(.struct_init, node, Zir.Inst.StructInit{ | 903 | const init_inst = try gz.addPlNode(.struct_init_anon, node, Zir.Inst.StructInitAnon{ |
| 901 | .fields_len = @intCast(u32, fields_list.len), | 904 | .fields_len = @intCast(u32, fields_list.len), |
| 902 | }); | 905 | }); |
| 903 | try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + | 906 | try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + |
| 904 | fields_list.len * @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len); | 907 | fields_list.len * @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len); |
| 905 | for (fields_list) |field| { | 908 | for (fields_list) |field| { |
| 906 | _ = gz.astgen.addExtraAssumeCapacity(field); | 909 | _ = gz.astgen.addExtraAssumeCapacity(field); |
| 907 | } | 910 | } |
| 908 | return rvalue(gz, scope, rl, init_inst, node); | 911 | return init_inst; |
| 909 | }, | 912 | }, |
| 910 | .ptr => |ptr_inst| { | 913 | .ref => unreachable, // struct literal not valid as l-value |
| 911 | const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len); | 914 | .ty => |ty_inst| return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst), |
| 912 | defer gpa.free(field_ptr_list); | 915 | .ptr, .inferred_ptr => |ptr_inst| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst), |
| | 916 | .block_ptr => |block_gz| return structInitExprRlPtr(gz, scope, rl, node, struct_init, block_gz.rl_ptr), |
| | 917 | } |
| | 918 | } |
| 913 | | 919 | |
| 914 | for (struct_init.ast.fields) |field_init, i| { | 920 | pub fn structInitExprRlPtr( |
| 915 | const name_token = tree.firstToken(field_init) - 2; | 921 | gz: *GenZir, |
| 916 | const str_index = try gz.identAsString(name_token); | 922 | scope: *Scope, |
| 917 | const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{ | 923 | rl: ResultLoc, |
| 918 | .lhs = ptr_inst, | 924 | node: ast.Node.Index, |
| 919 | .field_name_start = str_index, | 925 | struct_init: ast.full.StructInit, |
| 920 | }); | 926 | result_ptr: Zir.Inst.Ref, |
| 921 | field_ptr_list[i] = gz.refToIndex(field_ptr).?; | 927 | ) InnerError!Zir.Inst.Ref { |
| 922 | _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init); | 928 | const astgen = gz.astgen; |
| 923 | } | 929 | const gpa = astgen.gpa; |
| 924 | const validate_inst = try gz.addPlNode(.validate_struct_init_ptr, node, Zir.Inst.Block{ | 930 | const tree = &astgen.file.tree; |
| 925 | .body_len = @intCast(u32, field_ptr_list.len), | 931 | |
| 926 | }); | 932 | const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len); |
| 927 | try astgen.extra.appendSlice(gpa, field_ptr_list); | 933 | defer gpa.free(field_ptr_list); |
| 928 | return validate_inst; | 934 | |
| 929 | }, | 935 | for (struct_init.ast.fields) |field_init, i| { |
| 930 | .inferred_ptr => |ptr_inst| { | 936 | const name_token = tree.firstToken(field_init) - 2; |
| 931 | return astgen.failNode(node, "TODO implement structInitExpr inferred_ptr", .{}); | 937 | const str_index = try gz.identAsString(name_token); |
| 932 | }, | 938 | const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{ |
| 933 | .block_ptr => |block_gz| { | 939 | .lhs = result_ptr, |
| 934 | return astgen.failNode(node, "TODO implement structInitExpr block", .{}); | 940 | .field_name_start = str_index, |
| 935 | }, | 941 | }); |
| | 942 | field_ptr_list[i] = gz.refToIndex(field_ptr).?; |
| | 943 | _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init); |
| | 944 | } |
| | 945 | const validate_inst = try gz.addPlNode(.validate_struct_init_ptr, node, Zir.Inst.Block{ |
| | 946 | .body_len = @intCast(u32, field_ptr_list.len), |
| | 947 | }); |
| | 948 | try astgen.extra.appendSlice(gpa, field_ptr_list); |
| | 949 | return validate_inst; |
| | 950 | } |
| | 951 | |
| | 952 | pub fn structInitExprRlTy( |
| | 953 | gz: *GenZir, |
| | 954 | scope: *Scope, |
| | 955 | rl: ResultLoc, |
| | 956 | node: ast.Node.Index, |
| | 957 | struct_init: ast.full.StructInit, |
| | 958 | ty_inst: Zir.Inst.Ref, |
| | 959 | ) InnerError!Zir.Inst.Ref { |
| | 960 | const astgen = gz.astgen; |
| | 961 | const gpa = astgen.gpa; |
| | 962 | const tree = &astgen.file.tree; |
| | 963 | |
| | 964 | const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len); |
| | 965 | defer gpa.free(fields_list); |
| | 966 | |
| | 967 | for (struct_init.ast.fields) |field_init, i| { |
| | 968 | const name_token = tree.firstToken(field_init) - 2; |
| | 969 | const str_index = try gz.identAsString(name_token); |
| | 970 | |
| | 971 | const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{ |
| | 972 | .container_type = ty_inst, |
| | 973 | .name_start = str_index, |
| | 974 | }); |
| | 975 | fields_list[i] = .{ |
| | 976 | .field_type = gz.refToIndex(field_ty_inst).?, |
| | 977 | .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init), |
| | 978 | }; |
| 936 | } | 979 | } |
| | 980 | const init_inst = try gz.addPlNode(.struct_init, node, Zir.Inst.StructInit{ |
| | 981 | .fields_len = @intCast(u32, fields_list.len), |
| | 982 | }); |
| | 983 | try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + |
| | 984 | fields_list.len * @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len); |
| | 985 | for (fields_list) |field| { |
| | 986 | _ = gz.astgen.addExtraAssumeCapacity(field); |
| | 987 | } |
| | 988 | return init_inst; |
| 937 | } | 989 | } |
| 938 | | 990 | |
| 939 | pub fn comptimeExpr( | 991 | pub fn comptimeExpr( |
| ... | @@ -1318,7 +1370,6 @@ fn blockExprStmts( | ... | @@ -1318,7 +1370,6 @@ fn blockExprStmts( |
| 1318 | .elem_val, | 1370 | .elem_val, |
| 1319 | .elem_ptr_node, | 1371 | .elem_ptr_node, |
| 1320 | .elem_val_node, | 1372 | .elem_val_node, |
| 1321 | .floatcast, | | |
| 1322 | .field_ptr, | 1373 | .field_ptr, |
| 1323 | .field_val, | 1374 | .field_val, |
| 1324 | .field_ptr_named, | 1375 | .field_ptr_named, |
| ... | @@ -1403,8 +1454,10 @@ fn blockExprStmts( | ... | @@ -1403,8 +1454,10 @@ fn blockExprStmts( |
| 1403 | .switch_capture_else_ref, | 1454 | .switch_capture_else_ref, |
| 1404 | .struct_init_empty, | 1455 | .struct_init_empty, |
| 1405 | .struct_init, | 1456 | .struct_init, |
| | 1457 | .struct_init_anon, |
| 1406 | .union_init_ptr, | 1458 | .union_init_ptr, |
| 1407 | .field_type, | 1459 | .field_type, |
| | 1460 | .field_type_ref, |
| 1408 | .struct_decl, | 1461 | .struct_decl, |
| 1409 | .struct_decl_packed, | 1462 | .struct_decl_packed, |
| 1410 | .struct_decl_extern, | 1463 | .struct_decl_extern, |
| ... | @@ -4706,21 +4759,61 @@ fn as( | ... | @@ -4706,21 +4759,61 @@ fn as( |
| 4706 | const result = try expr(gz, scope, .{ .ty = dest_type }, rhs); | 4759 | const result = try expr(gz, scope, .{ .ty = dest_type }, rhs); |
| 4707 | return rvalue(gz, scope, rl, result, node); | 4760 | return rvalue(gz, scope, rl, result, node); |
| 4708 | }, | 4761 | }, |
| 4709 | | 4762 | .ptr, .inferred_ptr => |result_ptr| { |
| 4710 | .ptr => |result_ptr| { | | |
| 4711 | return asRlPtr(gz, scope, rl, result_ptr, rhs, dest_type); | 4763 | return asRlPtr(gz, scope, rl, result_ptr, rhs, dest_type); |
| 4712 | }, | 4764 | }, |
| 4713 | .block_ptr => |block_scope| { | 4765 | .block_ptr => |block_scope| { |
| 4714 | return asRlPtr(gz, scope, rl, block_scope.rl_ptr, rhs, dest_type); | 4766 | return asRlPtr(gz, scope, rl, block_scope.rl_ptr, rhs, dest_type); |
| 4715 | }, | 4767 | }, |
| | 4768 | } |
| | 4769 | } |
| 4716 | | 4770 | |
| 4717 | .inferred_ptr => |result_alloc| { | 4771 | fn unionInit( |
| 4718 | // TODO here we should be able to resolve the inference; we now have a type for the result. | 4772 | gz: *GenZir, |
| 4719 | return gz.astgen.failNode(node, "TODO implement @as with inferred-type result location pointer", .{}); | 4773 | scope: *Scope, |
| | 4774 | rl: ResultLoc, |
| | 4775 | node: ast.Node.Index, |
| | 4776 | params: []const ast.Node.Index, |
| | 4777 | ) InnerError!Zir.Inst.Ref { |
| | 4778 | const union_type = try typeExpr(gz, scope, params[0]); |
| | 4779 | const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); |
| | 4780 | switch (rl) { |
| | 4781 | .none, .none_or_ref, .discard, .ref, .ty, .inferred_ptr => { |
| | 4782 | const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{ |
| | 4783 | .container_type = union_type, |
| | 4784 | .field_name = field_name, |
| | 4785 | }); |
| | 4786 | const result = try expr(gz, scope, .{ .ty = union_type }, params[2]); |
| | 4787 | return rvalue(gz, scope, rl, result, node); |
| | 4788 | }, |
| | 4789 | .ptr => |result_ptr| { |
| | 4790 | return unionInitRlPtr(gz, scope, rl, node, result_ptr, params[2], union_type, field_name); |
| | 4791 | }, |
| | 4792 | .block_ptr => |block_scope| { |
| | 4793 | return unionInitRlPtr(gz, scope, rl, node, block_scope.rl_ptr, params[2], union_type, field_name); |
| 4720 | }, | 4794 | }, |
| 4721 | } | 4795 | } |
| 4722 | } | 4796 | } |
| 4723 | | 4797 | |
| | 4798 | fn unionInitRlPtr( |
| | 4799 | parent_gz: *GenZir, |
| | 4800 | scope: *Scope, |
| | 4801 | rl: ResultLoc, |
| | 4802 | node: ast.Node.Index, |
| | 4803 | result_ptr: Zir.Inst.Ref, |
| | 4804 | expr_node: ast.Node.Index, |
| | 4805 | union_type: Zir.Inst.Ref, |
| | 4806 | field_name: Zir.Inst.Ref, |
| | 4807 | ) InnerError!Zir.Inst.Ref { |
| | 4808 | const union_init_ptr = try parent_gz.addPlNode(.union_init_ptr, node, Zir.Inst.UnionInitPtr{ |
| | 4809 | .result_ptr = result_ptr, |
| | 4810 | .union_type = union_type, |
| | 4811 | .field_name = field_name, |
| | 4812 | }); |
| | 4813 | // TODO check if we need to do the elision like below in asRlPtr |
| | 4814 | return expr(parent_gz, scope, .{ .ptr = union_init_ptr }, expr_node); |
| | 4815 | } |
| | 4816 | |
| 4724 | fn asRlPtr( | 4817 | fn asRlPtr( |
| 4725 | parent_gz: *GenZir, | 4818 | parent_gz: *GenZir, |
| 4726 | scope: *Scope, | 4819 | scope: *Scope, |
| ... | @@ -4750,8 +4843,7 @@ fn asRlPtr( | ... | @@ -4750,8 +4843,7 @@ fn asRlPtr( |
| 4750 | // Busted! This expression didn't actually need a pointer. | 4843 | // Busted! This expression didn't actually need a pointer. |
| 4751 | const zir_tags = astgen.instructions.items(.tag); | 4844 | const zir_tags = astgen.instructions.items(.tag); |
| 4752 | const zir_datas = astgen.instructions.items(.data); | 4845 | const zir_datas = astgen.instructions.items(.data); |
| 4753 | const expected_len = parent_zir.items.len + as_scope.instructions.items.len - 2; | 4846 | try parent_zir.ensureUnusedCapacity(astgen.gpa, as_scope.instructions.items.len); |
| 4754 | try parent_zir.ensureCapacity(astgen.gpa, expected_len); | | |
| 4755 | for (as_scope.instructions.items) |src_inst| { | 4847 | for (as_scope.instructions.items) |src_inst| { |
| 4756 | if (parent_gz.indexToRef(src_inst) == as_scope.rl_ptr) continue; | 4848 | if (parent_gz.indexToRef(src_inst) == as_scope.rl_ptr) continue; |
| 4757 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 4849 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| ... | @@ -4759,7 +4851,6 @@ fn asRlPtr( | ... | @@ -4759,7 +4851,6 @@ fn asRlPtr( |
| 4759 | } | 4851 | } |
| 4760 | parent_zir.appendAssumeCapacity(src_inst); | 4852 | parent_zir.appendAssumeCapacity(src_inst); |
| 4761 | } | 4853 | } |
| 4762 | assert(parent_zir.items.len == expected_len); | | |
| 4763 | const casted_result = try parent_gz.addBin(.as, dest_type, result); | 4854 | const casted_result = try parent_gz.addBin(.as, dest_type, result); |
| 4764 | return rvalue(parent_gz, scope, rl, casted_result, operand_node); | 4855 | return rvalue(parent_gz, scope, rl, casted_result, operand_node); |
| 4765 | } else { | 4856 | } else { |
| ... | @@ -5445,24 +5536,6 @@ fn cImport( | ... | @@ -5445,24 +5536,6 @@ fn cImport( |
| 5445 | return rvalue(gz, scope, rl, .void_value, node); | 5536 | return rvalue(gz, scope, rl, .void_value, node); |
| 5446 | } | 5537 | } |
| 5447 | | 5538 | |
| 5448 | fn unionInit( | | |
| 5449 | gz: *GenZir, | | |
| 5450 | scope: *Scope, | | |
| 5451 | rl: ResultLoc, | | |
| 5452 | node: ast.Node.Index, | | |
| 5453 | params: []const ast.Node.Index, | | |
| 5454 | ) InnerError!Zir.Inst.Ref { | | |
| 5455 | const union_type = try typeExpr(gz, scope, params[0]); | | |
| 5456 | const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); | | |
| 5457 | const union_init_ptr = try gz.addPlNode(.union_init_ptr, node, Zir.Inst.UnionInitPtr{ | | |
| 5458 | .union_type = union_type, | | |
| 5459 | .field_name = field_name, | | |
| 5460 | }); | | |
| 5461 | // TODO: set up a store_to_block_ptr elision thing here | | |
| 5462 | const result = try expr(gz, scope, .{ .ptr = union_init_ptr }, params[2]); | | |
| 5463 | return rvalue(gz, scope, rl, result, node); | | |
| 5464 | } | | |
| 5465 | | | |
| 5466 | fn overflowArithmetic( | 5539 | fn overflowArithmetic( |
| 5467 | gz: *GenZir, | 5540 | gz: *GenZir, |
| 5468 | scope: *Scope, | 5541 | scope: *Scope, |