| ... | ... | @@ -877,63 +877,115 @@ pub fn structInitExpr( |
| 877 | 877 | } |
| 878 | 878 | } |
| 879 | 879 | switch (rl) { |
| 880 | | .discard => return astgen.failNode(node, "TODO implement structInitExpr discard", .{}), |
| 881 | | .none, .none_or_ref => return astgen.failNode(node, "TODO implement structInitExpr none", .{}), |
| 882 | | .ref => unreachable, // struct literal not valid as l-value |
| 883 | | .ty => |ty_inst| { |
| 884 | | const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len); |
| 880 | .discard => { |
| 881 | for (struct_init.ast.fields) |field_init| { |
| 882 | _ = try expr(gz, scope, .discard, field_init); |
| 883 | } |
| 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 | 892 | defer gpa.free(fields_list); |
| 886 | 893 | |
| 887 | 894 | for (struct_init.ast.fields) |field_init, i| { |
| 888 | 895 | const name_token = tree.firstToken(field_init) - 2; |
| 889 | 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 | 898 | fields_list[i] = .{ |
| 896 | | .field_type = gz.refToIndex(field_ty_inst).?, |
| 897 | | .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init), |
| 899 | .field_name = str_index, |
| 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 | 904 | .fields_len = @intCast(u32, fields_list.len), |
| 902 | 905 | }); |
| 903 | 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 | 908 | for (fields_list) |field| { |
| 906 | 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| { |
| 911 | | const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len); |
| 912 | | defer gpa.free(field_ptr_list); |
| 913 | .ref => unreachable, // struct literal not valid as l-value |
| 914 | .ty => |ty_inst| return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst), |
| 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| { |
| 915 | | const name_token = tree.firstToken(field_init) - 2; |
| 916 | | const str_index = try gz.identAsString(name_token); |
| 917 | | const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{ |
| 918 | | .lhs = ptr_inst, |
| 919 | | .field_name_start = str_index, |
| 920 | | }); |
| 921 | | field_ptr_list[i] = gz.refToIndex(field_ptr).?; |
| 922 | | _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init); |
| 923 | | } |
| 924 | | const validate_inst = try gz.addPlNode(.validate_struct_init_ptr, node, Zir.Inst.Block{ |
| 925 | | .body_len = @intCast(u32, field_ptr_list.len), |
| 926 | | }); |
| 927 | | try astgen.extra.appendSlice(gpa, field_ptr_list); |
| 928 | | return validate_inst; |
| 929 | | }, |
| 930 | | .inferred_ptr => |ptr_inst| { |
| 931 | | return astgen.failNode(node, "TODO implement structInitExpr inferred_ptr", .{}); |
| 932 | | }, |
| 933 | | .block_ptr => |block_gz| { |
| 934 | | return astgen.failNode(node, "TODO implement structInitExpr block", .{}); |
| 935 | | }, |
| 920 | pub fn structInitExprRlPtr( |
| 921 | gz: *GenZir, |
| 922 | scope: *Scope, |
| 923 | rl: ResultLoc, |
| 924 | node: ast.Node.Index, |
| 925 | struct_init: ast.full.StructInit, |
| 926 | result_ptr: Zir.Inst.Ref, |
| 927 | ) InnerError!Zir.Inst.Ref { |
| 928 | const astgen = gz.astgen; |
| 929 | const gpa = astgen.gpa; |
| 930 | const tree = &astgen.file.tree; |
| 931 | |
| 932 | const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len); |
| 933 | defer gpa.free(field_ptr_list); |
| 934 | |
| 935 | for (struct_init.ast.fields) |field_init, i| { |
| 936 | const name_token = tree.firstToken(field_init) - 2; |
| 937 | const str_index = try gz.identAsString(name_token); |
| 938 | const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{ |
| 939 | .lhs = result_ptr, |
| 940 | .field_name_start = str_index, |
| 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 | 991 | pub fn comptimeExpr( |
| ... | ... | @@ -1318,7 +1370,6 @@ fn blockExprStmts( |
| 1318 | 1370 | .elem_val, |
| 1319 | 1371 | .elem_ptr_node, |
| 1320 | 1372 | .elem_val_node, |
| 1321 | | .floatcast, |
| 1322 | 1373 | .field_ptr, |
| 1323 | 1374 | .field_val, |
| 1324 | 1375 | .field_ptr_named, |
| ... | ... | @@ -1403,8 +1454,10 @@ fn blockExprStmts( |
| 1403 | 1454 | .switch_capture_else_ref, |
| 1404 | 1455 | .struct_init_empty, |
| 1405 | 1456 | .struct_init, |
| 1457 | .struct_init_anon, |
| 1406 | 1458 | .union_init_ptr, |
| 1407 | 1459 | .field_type, |
| 1460 | .field_type_ref, |
| 1408 | 1461 | .struct_decl, |
| 1409 | 1462 | .struct_decl_packed, |
| 1410 | 1463 | .struct_decl_extern, |
| ... | ... | @@ -4706,21 +4759,61 @@ fn as( |
| 4706 | 4759 | const result = try expr(gz, scope, .{ .ty = dest_type }, rhs); |
| 4707 | 4760 | return rvalue(gz, scope, rl, result, node); |
| 4708 | 4761 | }, |
| 4709 | | |
| 4710 | | .ptr => |result_ptr| { |
| 4762 | .ptr, .inferred_ptr => |result_ptr| { |
| 4711 | 4763 | return asRlPtr(gz, scope, rl, result_ptr, rhs, dest_type); |
| 4712 | 4764 | }, |
| 4713 | 4765 | .block_ptr => |block_scope| { |
| 4714 | 4766 | return asRlPtr(gz, scope, rl, block_scope.rl_ptr, rhs, dest_type); |
| 4715 | 4767 | }, |
| 4768 | } |
| 4769 | } |
| 4716 | 4770 | |
| 4717 | | .inferred_ptr => |result_alloc| { |
| 4718 | | // TODO here we should be able to resolve the inference; we now have a type for the result. |
| 4719 | | return gz.astgen.failNode(node, "TODO implement @as with inferred-type result location pointer", .{}); |
| 4771 | fn unionInit( |
| 4772 | gz: *GenZir, |
| 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 | 4817 | fn asRlPtr( |
| 4725 | 4818 | parent_gz: *GenZir, |
| 4726 | 4819 | scope: *Scope, |
| ... | ... | @@ -4750,8 +4843,7 @@ fn asRlPtr( |
| 4750 | 4843 | // Busted! This expression didn't actually need a pointer. |
| 4751 | 4844 | const zir_tags = astgen.instructions.items(.tag); |
| 4752 | 4845 | const zir_datas = astgen.instructions.items(.data); |
| 4753 | | const expected_len = parent_zir.items.len + as_scope.instructions.items.len - 2; |
| 4754 | | try parent_zir.ensureCapacity(astgen.gpa, expected_len); |
| 4846 | try parent_zir.ensureUnusedCapacity(astgen.gpa, as_scope.instructions.items.len); |
| 4755 | 4847 | for (as_scope.instructions.items) |src_inst| { |
| 4756 | 4848 | if (parent_gz.indexToRef(src_inst) == as_scope.rl_ptr) continue; |
| 4757 | 4849 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| ... | ... | @@ -4759,7 +4851,6 @@ fn asRlPtr( |
| 4759 | 4851 | } |
| 4760 | 4852 | parent_zir.appendAssumeCapacity(src_inst); |
| 4761 | 4853 | } |
| 4762 | | assert(parent_zir.items.len == expected_len); |
| 4763 | 4854 | const casted_result = try parent_gz.addBin(.as, dest_type, result); |
| 4764 | 4855 | return rvalue(parent_gz, scope, rl, casted_result, operand_node); |
| 4765 | 4856 | } else { |
| ... | ... | @@ -5445,24 +5536,6 @@ fn cImport( |
| 5445 | 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 | 5539 | fn overflowArithmetic( |
| 5467 | 5540 | gz: *GenZir, |
| 5468 | 5541 | scope: *Scope, |