| ... | @@ -560,7 +560,7 @@ pub const DeclGen = struct { | ... | @@ -560,7 +560,7 @@ pub const DeclGen = struct { |
| 560 | // them). The analysis until now should ensure that the C function | 560 | // them). The analysis until now should ensure that the C function |
| 561 | // pointers are compatible. If they are not, then there is a bug | 561 | // pointers are compatible. If they are not, then there is a bug |
| 562 | // somewhere and we should let the C compiler tell us about it. | 562 | // somewhere and we should let the C compiler tell us about it. |
| 563 | const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.eql(decl.ty, mod); | 563 | const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.childType(mod).eql(decl.ty, mod); |
| 564 | if (need_typecast) { | 564 | if (need_typecast) { |
| 565 | try writer.writeAll("(("); | 565 | try writer.writeAll("(("); |
| 566 | try dg.renderType(writer, ty); | 566 | try dg.renderType(writer, ty); |
| ... | @@ -581,6 +581,7 @@ pub const DeclGen = struct { | ... | @@ -581,6 +581,7 @@ pub const DeclGen = struct { |
| 581 | ) error{ OutOfMemory, AnalysisFail }!void { | 581 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 582 | const mod = dg.module; | 582 | const mod = dg.module; |
| 583 | const ptr_ty = mod.intern_pool.typeOf(ptr_val).toType(); | 583 | const ptr_ty = mod.intern_pool.typeOf(ptr_val).toType(); |
| | 584 | const ptr_cty = try dg.typeToIndex(ptr_ty, .complete); |
| 584 | const ptr = mod.intern_pool.indexToKey(ptr_val).ptr; | 585 | const ptr = mod.intern_pool.indexToKey(ptr_val).ptr; |
| 585 | switch (ptr.addr) { | 586 | switch (ptr.addr) { |
| 586 | .decl, .mut_decl => try dg.renderDeclValue( | 587 | .decl, .mut_decl => try dg.renderDeclValue( |
| ... | @@ -598,22 +599,66 @@ pub const DeclGen = struct { | ... | @@ -598,22 +599,66 @@ pub const DeclGen = struct { |
| 598 | try dg.fmtIntLiteral(Type.usize, int.toValue(), .Other), | 599 | try dg.fmtIntLiteral(Type.usize, int.toValue(), .Other), |
| 599 | }), | 600 | }), |
| 600 | .eu_payload, .opt_payload => |base| { | 601 | .eu_payload, .opt_payload => |base| { |
| 601 | const base_ty = mod.intern_pool.typeOf(base).toType().childType(mod); | 602 | const ptr_base_ty = mod.intern_pool.typeOf(base).toType(); |
| | 603 | const base_ty = ptr_base_ty.childType(mod); |
| 602 | // Ensure complete type definition is visible before accessing fields. | 604 | // Ensure complete type definition is visible before accessing fields. |
| 603 | _ = try dg.typeToIndex(base_ty, .complete); | 605 | _ = try dg.typeToIndex(base_ty, .complete); |
| | 606 | const payload_ty = switch (ptr.addr) { |
| | 607 | .eu_payload => base_ty.errorUnionPayload(mod), |
| | 608 | .opt_payload => base_ty.optionalChild(mod), |
| | 609 | else => unreachable, |
| | 610 | }; |
| | 611 | const ptr_payload_ty = try mod.adjustPtrTypeChild(ptr_base_ty, payload_ty); |
| | 612 | const ptr_payload_cty = try dg.typeToIndex(ptr_payload_ty, .complete); |
| | 613 | if (ptr_cty != ptr_payload_cty) { |
| | 614 | try writer.writeByte('('); |
| | 615 | try dg.renderCType(writer, ptr_cty); |
| | 616 | try writer.writeByte(')'); |
| | 617 | } |
| 604 | try writer.writeAll("&("); | 618 | try writer.writeAll("&("); |
| 605 | try dg.renderParentPtr(writer, base, location); | 619 | try dg.renderParentPtr(writer, base, location); |
| 606 | try writer.writeAll(")->payload"); | 620 | try writer.writeAll(")->payload"); |
| 607 | }, | 621 | }, |
| 608 | .elem => |elem| { | 622 | .elem => |elem| { |
| | 623 | const ptr_base_ty = mod.intern_pool.typeOf(elem.base).toType(); |
| | 624 | const elem_ty = ptr_base_ty.elemType2(mod); |
| | 625 | const ptr_elem_ty = try mod.adjustPtrTypeChild(ptr_base_ty, elem_ty); |
| | 626 | const ptr_elem_cty = try dg.typeToIndex(ptr_elem_ty, .complete); |
| | 627 | if (ptr_cty != ptr_elem_cty) { |
| | 628 | try writer.writeByte('('); |
| | 629 | try dg.renderCType(writer, ptr_cty); |
| | 630 | try writer.writeByte(')'); |
| | 631 | } |
| 609 | try writer.writeAll("&("); | 632 | try writer.writeAll("&("); |
| | 633 | if (mod.intern_pool.indexToKey(ptr_base_ty.toIntern()).ptr_type.size == .One) |
| | 634 | try writer.writeByte('*'); |
| 610 | try dg.renderParentPtr(writer, elem.base, location); | 635 | try dg.renderParentPtr(writer, elem.base, location); |
| 611 | try writer.print(")[{d}]", .{elem.index}); | 636 | try writer.print(")[{d}]", .{elem.index}); |
| 612 | }, | 637 | }, |
| 613 | .field => |field| { | 638 | .field => |field| { |
| 614 | const base_ty = mod.intern_pool.typeOf(field.base).toType().childType(mod); | 639 | const ptr_base_ty = mod.intern_pool.typeOf(field.base).toType(); |
| | 640 | const base_ty = ptr_base_ty.childType(mod); |
| 615 | // Ensure complete type definition is visible before accessing fields. | 641 | // Ensure complete type definition is visible before accessing fields. |
| 616 | _ = try dg.typeToIndex(base_ty, .complete); | 642 | _ = try dg.typeToIndex(base_ty, .complete); |
| | 643 | const field_ty = switch (mod.intern_pool.indexToKey(base_ty.toIntern())) { |
| | 644 | .anon_struct_type, .struct_type, .union_type => base_ty.structFieldType(field.index, mod), |
| | 645 | .ptr_type => |ptr_type| switch (ptr_type.size) { |
| | 646 | .One, .Many, .C => unreachable, |
| | 647 | .Slice => switch (field.index) { |
| | 648 | Value.slice_ptr_index => base_ty.slicePtrFieldType(mod), |
| | 649 | Value.slice_len_index => Type.usize, |
| | 650 | else => unreachable, |
| | 651 | }, |
| | 652 | }, |
| | 653 | else => unreachable, |
| | 654 | }; |
| | 655 | const ptr_field_ty = try mod.adjustPtrTypeChild(ptr_base_ty, field_ty); |
| | 656 | const ptr_field_cty = try dg.typeToIndex(ptr_field_ty, .complete); |
| | 657 | if (ptr_cty != ptr_field_cty) { |
| | 658 | try writer.writeByte('('); |
| | 659 | try dg.renderCType(writer, ptr_cty); |
| | 660 | try writer.writeByte(')'); |
| | 661 | } |
| 617 | switch (fieldLocation(base_ty, ptr_ty, @intCast(u32, field.index), mod)) { | 662 | switch (fieldLocation(base_ty, ptr_ty, @intCast(u32, field.index), mod)) { |
| 618 | .begin => try dg.renderParentPtr(writer, field.base, location), | 663 | .begin => try dg.renderParentPtr(writer, field.base, location), |
| 619 | .field => |name| { | 664 | .field => |name| { |
| ... | @@ -861,234 +906,6 @@ pub const DeclGen = struct { | ... | @@ -861,234 +906,6 @@ pub const DeclGen = struct { |
| 861 | unreachable; | 906 | unreachable; |
| 862 | } | 907 | } |
| 863 | | 908 | |
| 864 | if (val.ip_index == .none) switch (ty.zigTypeTag(mod)) { | | |
| 865 | .Array, .Vector => { | | |
| 866 | if (location == .FunctionArgument) { | | |
| 867 | try writer.writeByte('('); | | |
| 868 | try dg.renderType(writer, ty); | | |
| 869 | try writer.writeByte(')'); | | |
| 870 | } | | |
| 871 | | | |
| 872 | // First try specific tag representations for more efficiency. | | |
| 873 | switch (val.toIntern()) { | | |
| 874 | .undef => { | | |
| 875 | const ai = ty.arrayInfo(mod); | | |
| 876 | try writer.writeByte('{'); | | |
| 877 | if (ai.sentinel) |s| { | | |
| 878 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); | | |
| 879 | } else { | | |
| 880 | try writer.writeByte('0'); | | |
| 881 | } | | |
| 882 | try writer.writeByte('}'); | | |
| 883 | return; | | |
| 884 | }, | | |
| 885 | .empty_struct => { | | |
| 886 | const ai = ty.arrayInfo(mod); | | |
| 887 | try writer.writeByte('{'); | | |
| 888 | if (ai.sentinel) |s| { | | |
| 889 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); | | |
| 890 | } else { | | |
| 891 | try writer.writeByte('0'); | | |
| 892 | } | | |
| 893 | try writer.writeByte('}'); | | |
| 894 | return; | | |
| 895 | }, | | |
| 896 | else => {}, | | |
| 897 | } | | |
| 898 | // Fall back to generic implementation. | | |
| 899 | | | |
| 900 | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal | | |
| 901 | const max_string_initializer_len = 65535; | | |
| 902 | | | |
| 903 | const ai = ty.arrayInfo(mod); | | |
| 904 | if (ai.elem_type.eql(Type.u8, mod)) { | | |
| 905 | if (ai.len <= max_string_initializer_len) { | | |
| 906 | var literal = stringLiteral(writer); | | |
| 907 | try literal.start(); | | |
| 908 | var index: usize = 0; | | |
| 909 | while (index < ai.len) : (index += 1) { | | |
| 910 | const elem_val = try val.elemValue(mod, index); | | |
| 911 | const elem_val_u8 = if (elem_val.isUndef(mod)) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); | | |
| 912 | try literal.writeChar(elem_val_u8); | | |
| 913 | } | | |
| 914 | if (ai.sentinel) |s| { | | |
| 915 | const s_u8 = @intCast(u8, s.toUnsignedInt(mod)); | | |
| 916 | if (s_u8 != 0) try literal.writeChar(s_u8); | | |
| 917 | } | | |
| 918 | try literal.end(); | | |
| 919 | } else { | | |
| 920 | try writer.writeByte('{'); | | |
| 921 | var index: usize = 0; | | |
| 922 | while (index < ai.len) : (index += 1) { | | |
| 923 | if (index != 0) try writer.writeByte(','); | | |
| 924 | const elem_val = try val.elemValue(mod, index); | | |
| 925 | const elem_val_u8 = if (elem_val.isUndef(mod)) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); | | |
| 926 | try writer.print("'\\x{x}'", .{elem_val_u8}); | | |
| 927 | } | | |
| 928 | if (ai.sentinel) |s| { | | |
| 929 | if (index != 0) try writer.writeByte(','); | | |
| 930 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); | | |
| 931 | } | | |
| 932 | try writer.writeByte('}'); | | |
| 933 | } | | |
| 934 | } else { | | |
| 935 | try writer.writeByte('{'); | | |
| 936 | var index: usize = 0; | | |
| 937 | while (index < ai.len) : (index += 1) { | | |
| 938 | if (index != 0) try writer.writeByte(','); | | |
| 939 | const elem_val = try val.elemValue(mod, index); | | |
| 940 | try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type); | | |
| 941 | } | | |
| 942 | if (ai.sentinel) |s| { | | |
| 943 | if (index != 0) try writer.writeByte(','); | | |
| 944 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); | | |
| 945 | } | | |
| 946 | try writer.writeByte('}'); | | |
| 947 | } | | |
| 948 | }, | | |
| 949 | .Struct => switch (ty.containerLayout(mod)) { | | |
| 950 | .Auto, .Extern => { | | |
| 951 | const field_vals = val.castTag(.aggregate).?.data; | | |
| 952 | | | |
| 953 | if (!location.isInitializer()) { | | |
| 954 | try writer.writeByte('('); | | |
| 955 | try dg.renderType(writer, ty); | | |
| 956 | try writer.writeByte(')'); | | |
| 957 | } | | |
| 958 | | | |
| 959 | try writer.writeByte('{'); | | |
| 960 | var empty = true; | | |
| 961 | for (field_vals, 0..) |field_val, field_i| { | | |
| 962 | if (ty.structFieldIsComptime(field_i, mod)) continue; | | |
| 963 | const field_ty = ty.structFieldType(field_i, mod); | | |
| 964 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | | |
| 965 | | | |
| 966 | if (!empty) try writer.writeByte(','); | | |
| 967 | try dg.renderValue(writer, field_ty, field_val, initializer_type); | | |
| 968 | | | |
| 969 | empty = false; | | |
| 970 | } | | |
| 971 | try writer.writeByte('}'); | | |
| 972 | }, | | |
| 973 | .Packed => { | | |
| 974 | const field_vals = val.castTag(.aggregate).?.data; | | |
| 975 | const int_info = ty.intInfo(mod); | | |
| 976 | | | |
| 977 | const bits = Type.smallestUnsignedBits(int_info.bits - 1); | | |
| 978 | const bit_offset_ty = try mod.intType(.unsigned, bits); | | |
| 979 | | | |
| 980 | var bit_offset: u64 = 0; | | |
| 981 | | | |
| 982 | var eff_num_fields: usize = 0; | | |
| 983 | for (0..field_vals.len) |field_i| { | | |
| 984 | if (ty.structFieldIsComptime(field_i, mod)) continue; | | |
| 985 | const field_ty = ty.structFieldType(field_i, mod); | | |
| 986 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | | |
| 987 | | | |
| 988 | eff_num_fields += 1; | | |
| 989 | } | | |
| 990 | | | |
| 991 | if (eff_num_fields == 0) { | | |
| 992 | try writer.writeByte('('); | | |
| 993 | try dg.renderValue(writer, ty, Value.undef, initializer_type); | | |
| 994 | try writer.writeByte(')'); | | |
| 995 | } else if (ty.bitSize(mod) > 64) { | | |
| 996 | // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) | | |
| 997 | var num_or = eff_num_fields - 1; | | |
| 998 | while (num_or > 0) : (num_or -= 1) { | | |
| 999 | try writer.writeAll("zig_or_"); | | |
| 1000 | try dg.renderTypeForBuiltinFnName(writer, ty); | | |
| 1001 | try writer.writeByte('('); | | |
| 1002 | } | | |
| 1003 | | | |
| 1004 | var eff_index: usize = 0; | | |
| 1005 | var needs_closing_paren = false; | | |
| 1006 | for (field_vals, 0..) |field_val, field_i| { | | |
| 1007 | if (ty.structFieldIsComptime(field_i, mod)) continue; | | |
| 1008 | const field_ty = ty.structFieldType(field_i, mod); | | |
| 1009 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | | |
| 1010 | | | |
| 1011 | const cast_context = IntCastContext{ .value = .{ .value = field_val } }; | | |
| 1012 | if (bit_offset != 0) { | | |
| 1013 | try writer.writeAll("zig_shl_"); | | |
| 1014 | try dg.renderTypeForBuiltinFnName(writer, ty); | | |
| 1015 | try writer.writeByte('('); | | |
| 1016 | try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); | | |
| 1017 | try writer.writeAll(", "); | | |
| 1018 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | | |
| 1019 | try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | | |
| 1020 | try writer.writeByte(')'); | | |
| 1021 | } else { | | |
| 1022 | try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); | | |
| 1023 | } | | |
| 1024 | | | |
| 1025 | if (needs_closing_paren) try writer.writeByte(')'); | | |
| 1026 | if (eff_index != eff_num_fields - 1) try writer.writeAll(", "); | | |
| 1027 | | | |
| 1028 | bit_offset += field_ty.bitSize(mod); | | |
| 1029 | needs_closing_paren = true; | | |
| 1030 | eff_index += 1; | | |
| 1031 | } | | |
| 1032 | } else { | | |
| 1033 | try writer.writeByte('('); | | |
| 1034 | // a << a_off | b << b_off | c << c_off | | |
| 1035 | var empty = true; | | |
| 1036 | for (field_vals, 0..) |field_val, field_i| { | | |
| 1037 | if (ty.structFieldIsComptime(field_i, mod)) continue; | | |
| 1038 | const field_ty = ty.structFieldType(field_i, mod); | | |
| 1039 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | | |
| 1040 | | | |
| 1041 | if (!empty) try writer.writeAll(" | "); | | |
| 1042 | try writer.writeByte('('); | | |
| 1043 | try dg.renderType(writer, ty); | | |
| 1044 | try writer.writeByte(')'); | | |
| 1045 | | | |
| 1046 | if (bit_offset != 0) { | | |
| 1047 | try dg.renderValue(writer, field_ty, field_val, .Other); | | |
| 1048 | try writer.writeAll(" << "); | | |
| 1049 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | | |
| 1050 | try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | | |
| 1051 | } else { | | |
| 1052 | try dg.renderValue(writer, field_ty, field_val, .Other); | | |
| 1053 | } | | |
| 1054 | | | |
| 1055 | bit_offset += field_ty.bitSize(mod); | | |
| 1056 | empty = false; | | |
| 1057 | } | | |
| 1058 | try writer.writeByte(')'); | | |
| 1059 | } | | |
| 1060 | }, | | |
| 1061 | }, | | |
| 1062 | | | |
| 1063 | .Frame, | | |
| 1064 | .AnyFrame, | | |
| 1065 | => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{ | | |
| 1066 | @tagName(tag), | | |
| 1067 | }), | | |
| 1068 | | | |
| 1069 | .Float, | | |
| 1070 | .Union, | | |
| 1071 | .Optional, | | |
| 1072 | .ErrorUnion, | | |
| 1073 | .ErrorSet, | | |
| 1074 | .Int, | | |
| 1075 | .Enum, | | |
| 1076 | .Bool, | | |
| 1077 | .Pointer, | | |
| 1078 | => unreachable, // handled below | | |
| 1079 | .Type, | | |
| 1080 | .Void, | | |
| 1081 | .NoReturn, | | |
| 1082 | .ComptimeFloat, | | |
| 1083 | .ComptimeInt, | | |
| 1084 | .Undefined, | | |
| 1085 | .Null, | | |
| 1086 | .Opaque, | | |
| 1087 | .EnumLiteral, | | |
| 1088 | .Fn, | | |
| 1089 | => unreachable, // comptime-only types | | |
| 1090 | }; | | |
| 1091 | | | |
| 1092 | switch (mod.intern_pool.indexToKey(val.ip_index)) { | 909 | switch (mod.intern_pool.indexToKey(val.ip_index)) { |
| 1093 | // types, not values | 910 | // types, not values |
| 1094 | .int_type, | 911 | .int_type, |
| ... | @@ -1144,10 +961,24 @@ pub const DeclGen = struct { | ... | @@ -1144,10 +961,24 @@ pub const DeclGen = struct { |
| 1144 | .error_union => |error_union| { | 961 | .error_union => |error_union| { |
| 1145 | const payload_ty = ty.errorUnionPayload(mod); | 962 | const payload_ty = ty.errorUnionPayload(mod); |
| 1146 | const error_ty = ty.errorUnionSet(mod); | 963 | const error_ty = ty.errorUnionSet(mod); |
| 1147 | const error_val = if (val.errorUnionIsPayload(mod)) try mod.intValue(Type.err_int, 0) else val; | | |
| 1148 | | | |
| 1149 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 964 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1150 | return dg.renderValue(writer, Type.err_int, error_val, location); | 965 | switch (error_union.val) { |
| | 966 | .err_name => |err_name| return dg.renderValue( |
| | 967 | writer, |
| | 968 | error_ty, |
| | 969 | (try mod.intern(.{ .err = .{ |
| | 970 | .ty = error_ty.toIntern(), |
| | 971 | .name = err_name, |
| | 972 | } })).toValue(), |
| | 973 | location, |
| | 974 | ), |
| | 975 | .payload => return dg.renderValue( |
| | 976 | writer, |
| | 977 | Type.err_int, |
| | 978 | try mod.intValue(Type.err_int, 0), |
| | 979 | location, |
| | 980 | ), |
| | 981 | } |
| 1151 | } | 982 | } |
| 1152 | | 983 | |
| 1153 | if (!location.isInitializer()) { | 984 | if (!location.isInitializer()) { |
| ... | @@ -1156,15 +987,34 @@ pub const DeclGen = struct { | ... | @@ -1156,15 +987,34 @@ pub const DeclGen = struct { |
| 1156 | try writer.writeByte(')'); | 987 | try writer.writeByte(')'); |
| 1157 | } | 988 | } |
| 1158 | | 989 | |
| 1159 | const payload_val = switch (error_union.val) { | | |
| 1160 | .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }), | | |
| 1161 | .payload => |payload| payload, | | |
| 1162 | }.toValue(); | | |
| 1163 | | | |
| 1164 | try writer.writeAll("{ .payload = "); | 990 | try writer.writeAll("{ .payload = "); |
| 1165 | try dg.renderValue(writer, payload_ty, payload_val, initializer_type); | 991 | try dg.renderValue( |
| | 992 | writer, |
| | 993 | payload_ty, |
| | 994 | switch (error_union.val) { |
| | 995 | .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }), |
| | 996 | .payload => |payload| payload, |
| | 997 | }.toValue(), |
| | 998 | initializer_type, |
| | 999 | ); |
| 1166 | try writer.writeAll(", .error = "); | 1000 | try writer.writeAll(", .error = "); |
| 1167 | try dg.renderValue(writer, error_ty, error_val, initializer_type); | 1001 | switch (error_union.val) { |
| | 1002 | .err_name => |err_name| try dg.renderValue( |
| | 1003 | writer, |
| | 1004 | error_ty, |
| | 1005 | (try mod.intern(.{ .err = .{ |
| | 1006 | .ty = error_ty.toIntern(), |
| | 1007 | .name = err_name, |
| | 1008 | } })).toValue(), |
| | 1009 | location, |
| | 1010 | ), |
| | 1011 | .payload => try dg.renderValue( |
| | 1012 | writer, |
| | 1013 | Type.err_int, |
| | 1014 | try mod.intValue(Type.err_int, 0), |
| | 1015 | location, |
| | 1016 | ), |
| | 1017 | } |
| 1168 | try writer.writeAll(" }"); | 1018 | try writer.writeAll(" }"); |
| 1169 | }, | 1019 | }, |
| 1170 | .enum_tag => { | 1020 | .enum_tag => { |
| ... | @@ -1272,30 +1122,42 @@ pub const DeclGen = struct { | ... | @@ -1272,30 +1122,42 @@ pub const DeclGen = struct { |
| 1272 | } | 1122 | } |
| 1273 | try writer.writeByte('{'); | 1123 | try writer.writeByte('{'); |
| 1274 | } | 1124 | } |
| | 1125 | const ptr_location = switch (ptr.len) { |
| | 1126 | .none => location, |
| | 1127 | else => initializer_type, |
| | 1128 | }; |
| | 1129 | const ptr_ty = switch (ptr.len) { |
| | 1130 | .none => ty, |
| | 1131 | else => ty.slicePtrFieldType(mod), |
| | 1132 | }; |
| | 1133 | const ptr_val = switch (ptr.len) { |
| | 1134 | .none => val, |
| | 1135 | else => val.slicePtr(mod), |
| | 1136 | }; |
| 1275 | switch (ptr.addr) { | 1137 | switch (ptr.addr) { |
| 1276 | .decl, .mut_decl => try dg.renderDeclValue( | 1138 | .decl, .mut_decl => try dg.renderDeclValue( |
| 1277 | writer, | 1139 | writer, |
| 1278 | ty, | 1140 | ptr_ty, |
| 1279 | val, | 1141 | ptr_val, |
| 1280 | switch (ptr.addr) { | 1142 | switch (ptr.addr) { |
| 1281 | .decl => |decl| decl, | 1143 | .decl => |decl| decl, |
| 1282 | .mut_decl => |mut_decl| mut_decl.decl, | 1144 | .mut_decl => |mut_decl| mut_decl.decl, |
| 1283 | else => unreachable, | 1145 | else => unreachable, |
| 1284 | }, | 1146 | }, |
| 1285 | location, | 1147 | ptr_location, |
| 1286 | ), | 1148 | ), |
| 1287 | .int => |int| { | 1149 | .int => |int| { |
| 1288 | try writer.writeAll("(("); | 1150 | try writer.writeAll("(("); |
| 1289 | try dg.renderType(writer, ty); | 1151 | try dg.renderType(writer, ptr_ty); |
| 1290 | try writer.print("){x})", .{ | 1152 | try writer.print("){x})", .{ |
| 1291 | try dg.fmtIntLiteral(Type.usize, int.toValue(), .Other), | 1153 | try dg.fmtIntLiteral(Type.usize, int.toValue(), ptr_location), |
| 1292 | }); | 1154 | }); |
| 1293 | }, | 1155 | }, |
| 1294 | .eu_payload, | 1156 | .eu_payload, |
| 1295 | .opt_payload, | 1157 | .opt_payload, |
| 1296 | .elem, | 1158 | .elem, |
| 1297 | .field, | 1159 | .field, |
| 1298 | => try dg.renderParentPtr(writer, val.ip_index, location), | 1160 | => try dg.renderParentPtr(writer, ptr_val.ip_index, ptr_location), |
| 1299 | .comptime_field => unreachable, | 1161 | .comptime_field => unreachable, |
| 1300 | } | 1162 | } |
| 1301 | if (ptr.len != .none) { | 1163 | if (ptr.len != .none) { |
| ... | @@ -1311,10 +1173,19 @@ pub const DeclGen = struct { | ... | @@ -1311,10 +1173,19 @@ pub const DeclGen = struct { |
| 1311 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) | 1173 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 1312 | return dg.renderValue(writer, Type.bool, is_null_val, location); | 1174 | return dg.renderValue(writer, Type.bool, is_null_val, location); |
| 1313 | | 1175 | |
| 1314 | if (ty.optionalReprIsPayload(mod)) switch (opt.val) { | 1176 | if (ty.optionalReprIsPayload(mod)) return dg.renderValue( |
| 1315 | .none => return writer.writeByte('0'), | 1177 | writer, |
| 1316 | else => |payload| return dg.renderValue(writer, payload_ty, payload.toValue(), location), | 1178 | payload_ty, |
| 1317 | }; | 1179 | switch (opt.val) { |
| | 1180 | .none => switch (payload_ty.zigTypeTag(mod)) { |
| | 1181 | .ErrorSet => try mod.intValue(Type.err_int, 0), |
| | 1182 | .Pointer => try mod.getCoerced(val, payload_ty), |
| | 1183 | else => unreachable, |
| | 1184 | }, |
| | 1185 | else => |payload| payload.toValue(), |
| | 1186 | }, |
| | 1187 | location, |
| | 1188 | ); |
| 1318 | | 1189 | |
| 1319 | if (!location.isInitializer()) { | 1190 | if (!location.isInitializer()) { |
| 1320 | try writer.writeByte('('); | 1191 | try writer.writeByte('('); |
| ... | @@ -2535,7 +2406,7 @@ pub fn genErrDecls(o: *Object) !void { | ... | @@ -2535,7 +2406,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 2535 | try writer.writeAll("enum {\n"); | 2406 | try writer.writeAll("enum {\n"); |
| 2536 | o.indent_writer.pushIndent(); | 2407 | o.indent_writer.pushIndent(); |
| 2537 | var max_name_len: usize = 0; | 2408 | var max_name_len: usize = 0; |
| 2538 | for (mod.error_name_list.items, 0..) |name, value| { | 2409 | for (mod.error_name_list.items[1..], 1..) |name, value| { |
| 2539 | max_name_len = std.math.max(name.len, max_name_len); | 2410 | max_name_len = std.math.max(name.len, max_name_len); |
| 2540 | const err_val = try mod.intern(.{ .err = .{ | 2411 | const err_val = try mod.intern(.{ .err = .{ |
| 2541 | .ty = .anyerror_type, | 2412 | .ty = .anyerror_type, |
| ... | @@ -2562,21 +2433,21 @@ pub fn genErrDecls(o: *Object) !void { | ... | @@ -2562,21 +2433,21 @@ pub fn genErrDecls(o: *Object) !void { |
| 2562 | .child = .u8_type, | 2433 | .child = .u8_type, |
| 2563 | .sentinel = .zero_u8, | 2434 | .sentinel = .zero_u8, |
| 2564 | }); | 2435 | }); |
| 2565 | | 2436 | const name_val = try mod.intern(.{ .aggregate = .{ |
| 2566 | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name }; | 2437 | .ty = name_ty.toIntern(), |
| 2567 | const name_val = Value.initPayload(&name_pl.base); | 2438 | .storage = .{ .bytes = name }, |
| | 2439 | } }); |
| 2568 | | 2440 | |
| 2569 | try writer.writeAll("static "); | 2441 | try writer.writeAll("static "); |
| 2570 | try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, Const, 0, .complete); | 2442 | try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, Const, 0, .complete); |
| 2571 | try writer.writeAll(" = "); | 2443 | try writer.writeAll(" = "); |
| 2572 | try o.dg.renderValue(writer, name_ty, name_val, .StaticInitializer); | 2444 | try o.dg.renderValue(writer, name_ty, name_val.toValue(), .StaticInitializer); |
| 2573 | try writer.writeAll(";\n"); | 2445 | try writer.writeAll(";\n"); |
| 2574 | } | 2446 | } |
| 2575 | | 2447 | |
| 2576 | const name_array_ty = try mod.arrayType(.{ | 2448 | const name_array_ty = try mod.arrayType(.{ |
| 2577 | .len = mod.error_name_list.items.len, | 2449 | .len = mod.error_name_list.items.len, |
| 2578 | .child = .slice_const_u8_sentinel_0_type, | 2450 | .child = .slice_const_u8_sentinel_0_type, |
| 2579 | .sentinel = .zero_u8, | | |
| 2580 | }); | 2451 | }); |
| 2581 | | 2452 | |
| 2582 | try writer.writeAll("static "); | 2453 | try writer.writeAll("static "); |
| ... | @@ -2588,7 +2459,7 @@ pub fn genErrDecls(o: *Object) !void { | ... | @@ -2588,7 +2459,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 2588 | const len_val = try mod.intValue(Type.usize, name.len); | 2459 | const len_val = try mod.intValue(Type.usize, name.len); |
| 2589 | | 2460 | |
| 2590 | try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{ | 2461 | try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{ |
| 2591 | fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val, .Other), | 2462 | fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val, .StaticInitializer), |
| 2592 | }); | 2463 | }); |
| 2593 | } | 2464 | } |
| 2594 | try writer.writeAll("};\n"); | 2465 | try writer.writeAll("};\n"); |
| ... | @@ -2642,10 +2513,10 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | ... | @@ -2642,10 +2513,10 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2642 | .child = .u8_type, | 2513 | .child = .u8_type, |
| 2643 | .sentinel = .zero_u8, | 2514 | .sentinel = .zero_u8, |
| 2644 | }); | 2515 | }); |
| 2645 | | 2516 | const name_val = try mod.intern(.{ .aggregate = .{ |
| 2646 | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name }; | 2517 | .ty = name_ty.toIntern(), |
| 2647 | const name_val = Value.initPayload(&name_pl.base); | 2518 | .storage = .{ .bytes = name }, |
| 2648 | | 2519 | } }); |
| 2649 | const len_val = try mod.intValue(Type.usize, name.len); | 2520 | const len_val = try mod.intValue(Type.usize, name.len); |
| 2650 | | 2521 | |
| 2651 | try w.print(" case {}: {{\n static ", .{ | 2522 | try w.print(" case {}: {{\n static ", .{ |
| ... | @@ -2653,7 +2524,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | ... | @@ -2653,7 +2524,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2653 | }); | 2524 | }); |
| 2654 | try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete); | 2525 | try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete); |
| 2655 | try w.writeAll(" = "); | 2526 | try w.writeAll(" = "); |
| 2656 | try o.dg.renderValue(w, name_ty, name_val, .Initializer); | 2527 | try o.dg.renderValue(w, name_ty, name_val.toValue(), .Initializer); |
| 2657 | try w.writeAll(";\n return ("); | 2528 | try w.writeAll(";\n return ("); |
| 2658 | try o.dg.renderType(w, name_slice_ty); | 2529 | try o.dg.renderType(w, name_slice_ty); |
| 2659 | try w.print("){{{}, {}}};\n", .{ | 2530 | try w.print("){{{}, {}}};\n", .{ |
| ... | @@ -2789,7 +2660,7 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2789,7 +2660,7 @@ pub fn genDecl(o: *Object) !void { |
| 2789 | const mod = o.dg.module; | 2660 | const mod = o.dg.module; |
| 2790 | const decl = o.dg.decl.?; | 2661 | const decl = o.dg.decl.?; |
| 2791 | const decl_c_value = .{ .decl = o.dg.decl_index.unwrap().? }; | 2662 | const decl_c_value = .{ .decl = o.dg.decl_index.unwrap().? }; |
| 2792 | const tv: TypedValue = .{ .ty = decl.ty, .val = decl.val }; | 2663 | const tv: TypedValue = .{ .ty = decl.ty, .val = (try decl.internValue(mod)).toValue() }; |
| 2793 | | 2664 | |
| 2794 | if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; | 2665 | if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; |
| 2795 | if (tv.val.getExternFunc(mod)) |_| { | 2666 | if (tv.val.getExternFunc(mod)) |_| { |
| ... | @@ -4771,6 +4642,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4771,6 +4642,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4771 | try writer.writeAll(") "); | 4642 | try writer.writeAll(") "); |
| 4772 | | 4643 | |
| 4773 | try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false); | 4644 | try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false); |
| | 4645 | try writer.writeByte('\n'); |
| 4774 | | 4646 | |
| 4775 | // We don't need to use `genBodyResolveState` for the else block, because this instruction is | 4647 | // We don't need to use `genBodyResolveState` for the else block, because this instruction is |
| 4776 | // noreturn so must terminate a body, therefore we don't need to leave `value_map` or | 4648 | // noreturn so must terminate a body, therefore we don't need to leave `value_map` or |
| ... | @@ -5165,7 +5037,7 @@ fn airIsNull( | ... | @@ -5165,7 +5037,7 @@ fn airIsNull( |
| 5165 | TypedValue{ .ty = Type.bool, .val = Value.true } | 5037 | TypedValue{ .ty = Type.bool, .val = Value.true } |
| 5166 | else if (optional_ty.isPtrLikeOptional(mod)) | 5038 | else if (optional_ty.isPtrLikeOptional(mod)) |
| 5167 | // operand is a regular pointer, test `operand !=/== NULL` | 5039 | // operand is a regular pointer, test `operand !=/== NULL` |
| 5168 | TypedValue{ .ty = optional_ty, .val = try mod.nullValue(optional_ty) } | 5040 | TypedValue{ .ty = optional_ty, .val = try mod.getCoerced(Value.null, optional_ty) } |
| 5169 | else if (payload_ty.zigTypeTag(mod) == .ErrorSet) | 5041 | else if (payload_ty.zigTypeTag(mod) == .ErrorSet) |
| 5170 | TypedValue{ .ty = Type.err_int, .val = try mod.intValue(Type.err_int, 0) } | 5042 | TypedValue{ .ty = Type.err_int, .val = try mod.intValue(Type.err_int, 0) } |
| 5171 | else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: { | 5043 | else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: { |
| ... | @@ -5778,7 +5650,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5778,7 +5650,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5778 | try reap(f, inst, &.{ty_op.operand}); | 5650 | try reap(f, inst, &.{ty_op.operand}); |
| 5779 | try f.writeCValueDeref(writer, operand); | 5651 | try f.writeCValueDeref(writer, operand); |
| 5780 | try writer.writeAll(".error = "); | 5652 | try writer.writeAll(".error = "); |
| 5781 | try f.object.dg.renderValue(writer, error_ty, try mod.intValue(error_ty, 0), .Other); | 5653 | try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other); |
| 5782 | try writer.writeAll(";\n"); | 5654 | try writer.writeAll(";\n"); |
| 5783 | | 5655 | |
| 5784 | // Then return the payload pointer (only if it is used) | 5656 | // Then return the payload pointer (only if it is used) |
| ... | @@ -6760,27 +6632,41 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6760,27 +6632,41 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6760 | try writer.writeAll(" = "); | 6632 | try writer.writeAll(" = "); |
| 6761 | | 6633 | |
| 6762 | try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) { | 6634 | try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) { |
| 6763 | .Or, .Xor, .Add => try mod.intValue(scalar_ty, 0), | 6635 | .Or, .Xor => switch (scalar_ty.zigTypeTag(mod)) { |
| | 6636 | .Bool => Value.false, |
| | 6637 | .Int => try mod.intValue(scalar_ty, 0), |
| | 6638 | else => unreachable, |
| | 6639 | }, |
| 6764 | .And => switch (scalar_ty.zigTypeTag(mod)) { | 6640 | .And => switch (scalar_ty.zigTypeTag(mod)) { |
| 6765 | .Bool => try mod.intValue(Type.comptime_int, 1), | 6641 | .Bool => Value.true, |
| 6766 | else => switch (scalar_ty.intInfo(mod).signedness) { | 6642 | .Int => switch (scalar_ty.intInfo(mod).signedness) { |
| 6767 | .unsigned => try scalar_ty.maxIntScalar(mod, scalar_ty), | 6643 | .unsigned => try scalar_ty.maxIntScalar(mod, scalar_ty), |
| 6768 | .signed => try mod.intValue(scalar_ty, -1), | 6644 | .signed => try mod.intValue(scalar_ty, -1), |
| 6769 | }, | 6645 | }, |
| | 6646 | else => unreachable, |
| | 6647 | }, |
| | 6648 | .Add => switch (scalar_ty.zigTypeTag(mod)) { |
| | 6649 | .Int => try mod.intValue(scalar_ty, 0), |
| | 6650 | .Float => try mod.floatValue(scalar_ty, 0.0), |
| | 6651 | else => unreachable, |
| | 6652 | }, |
| | 6653 | .Mul => switch (scalar_ty.zigTypeTag(mod)) { |
| | 6654 | .Int => try mod.intValue(scalar_ty, 1), |
| | 6655 | .Float => try mod.floatValue(scalar_ty, 1.0), |
| | 6656 | else => unreachable, |
| 6770 | }, | 6657 | }, |
| 6771 | .Min => switch (scalar_ty.zigTypeTag(mod)) { | 6658 | .Min => switch (scalar_ty.zigTypeTag(mod)) { |
| 6772 | .Bool => Value.one_comptime_int, | 6659 | .Bool => Value.true, |
| 6773 | .Int => try scalar_ty.maxIntScalar(mod, scalar_ty), | 6660 | .Int => try scalar_ty.maxIntScalar(mod, scalar_ty), |
| 6774 | .Float => try mod.floatValue(scalar_ty, std.math.nan_f128), | 6661 | .Float => try mod.floatValue(scalar_ty, std.math.nan_f128), |
| 6775 | else => unreachable, | 6662 | else => unreachable, |
| 6776 | }, | 6663 | }, |
| 6777 | .Max => switch (scalar_ty.zigTypeTag(mod)) { | 6664 | .Max => switch (scalar_ty.zigTypeTag(mod)) { |
| 6778 | .Bool => try mod.intValue(scalar_ty, 0), | 6665 | .Bool => Value.false, |
| 6779 | .Int => try scalar_ty.minInt(mod, scalar_ty), | 6666 | .Int => try scalar_ty.minIntScalar(mod, scalar_ty), |
| 6780 | .Float => try mod.floatValue(scalar_ty, std.math.nan_f128), | 6667 | .Float => try mod.floatValue(scalar_ty, std.math.nan_f128), |
| 6781 | else => unreachable, | 6668 | else => unreachable, |
| 6782 | }, | 6669 | }, |
| 6783 | .Mul => try mod.intValue(Type.comptime_int, 1), | | |
| 6784 | }, .Initializer); | 6670 | }, .Initializer); |
| 6785 | try writer.writeAll(";\n"); | 6671 | try writer.writeAll(";\n"); |
| 6786 | | 6672 | |