| ... | ... | @@ -560,7 +560,7 @@ pub const DeclGen = struct { |
| 560 | 560 | // them). The analysis until now should ensure that the C function |
| 561 | 561 | // pointers are compatible. If they are not, then there is a bug |
| 562 | 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 | 564 | if (need_typecast) { |
| 565 | 565 | try writer.writeAll("(("); |
| 566 | 566 | try dg.renderType(writer, ty); |
| ... | ... | @@ -581,6 +581,7 @@ pub const DeclGen = struct { |
| 581 | 581 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 582 | 582 | const mod = dg.module; |
| 583 | 583 | const ptr_ty = mod.intern_pool.typeOf(ptr_val).toType(); |
| 584 | const ptr_cty = try dg.typeToIndex(ptr_ty, .complete); |
| 584 | 585 | const ptr = mod.intern_pool.indexToKey(ptr_val).ptr; |
| 585 | 586 | switch (ptr.addr) { |
| 586 | 587 | .decl, .mut_decl => try dg.renderDeclValue( |
| ... | ... | @@ -598,22 +599,66 @@ pub const DeclGen = struct { |
| 598 | 599 | try dg.fmtIntLiteral(Type.usize, int.toValue(), .Other), |
| 599 | 600 | }), |
| 600 | 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 | 604 | // Ensure complete type definition is visible before accessing fields. |
| 603 | 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 | 618 | try writer.writeAll("&("); |
| 605 | 619 | try dg.renderParentPtr(writer, base, location); |
| 606 | 620 | try writer.writeAll(")->payload"); |
| 607 | 621 | }, |
| 608 | 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 | 632 | try writer.writeAll("&("); |
| 633 | if (mod.intern_pool.indexToKey(ptr_base_ty.toIntern()).ptr_type.size == .One) |
| 634 | try writer.writeByte('*'); |
| 610 | 635 | try dg.renderParentPtr(writer, elem.base, location); |
| 611 | 636 | try writer.print(")[{d}]", .{elem.index}); |
| 612 | 637 | }, |
| 613 | 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 | 641 | // Ensure complete type definition is visible before accessing fields. |
| 616 | 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 | 662 | switch (fieldLocation(base_ty, ptr_ty, @intCast(u32, field.index), mod)) { |
| 618 | 663 | .begin => try dg.renderParentPtr(writer, field.base, location), |
| 619 | 664 | .field => |name| { |
| ... | ... | @@ -861,234 +906,6 @@ pub const DeclGen = struct { |
| 861 | 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 | 909 | switch (mod.intern_pool.indexToKey(val.ip_index)) { |
| 1093 | 910 | // types, not values |
| 1094 | 911 | .int_type, |
| ... | ... | @@ -1144,10 +961,24 @@ pub const DeclGen = struct { |
| 1144 | 961 | .error_union => |error_union| { |
| 1145 | 962 | const payload_ty = ty.errorUnionPayload(mod); |
| 1146 | 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 | 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 | 984 | if (!location.isInitializer()) { |
| ... | ... | @@ -1156,15 +987,34 @@ pub const DeclGen = struct { |
| 1156 | 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 | 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 | 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 | 1018 | try writer.writeAll(" }"); |
| 1169 | 1019 | }, |
| 1170 | 1020 | .enum_tag => { |
| ... | ... | @@ -1272,30 +1122,42 @@ pub const DeclGen = struct { |
| 1272 | 1122 | } |
| 1273 | 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 | 1137 | switch (ptr.addr) { |
| 1276 | 1138 | .decl, .mut_decl => try dg.renderDeclValue( |
| 1277 | 1139 | writer, |
| 1278 | | ty, |
| 1279 | | val, |
| 1140 | ptr_ty, |
| 1141 | ptr_val, |
| 1280 | 1142 | switch (ptr.addr) { |
| 1281 | 1143 | .decl => |decl| decl, |
| 1282 | 1144 | .mut_decl => |mut_decl| mut_decl.decl, |
| 1283 | 1145 | else => unreachable, |
| 1284 | 1146 | }, |
| 1285 | | location, |
| 1147 | ptr_location, |
| 1286 | 1148 | ), |
| 1287 | 1149 | .int => |int| { |
| 1288 | 1150 | try writer.writeAll("(("); |
| 1289 | | try dg.renderType(writer, ty); |
| 1151 | try dg.renderType(writer, ptr_ty); |
| 1290 | 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 | 1156 | .eu_payload, |
| 1295 | 1157 | .opt_payload, |
| 1296 | 1158 | .elem, |
| 1297 | 1159 | .field, |
| 1298 | | => try dg.renderParentPtr(writer, val.ip_index, location), |
| 1160 | => try dg.renderParentPtr(writer, ptr_val.ip_index, ptr_location), |
| 1299 | 1161 | .comptime_field => unreachable, |
| 1300 | 1162 | } |
| 1301 | 1163 | if (ptr.len != .none) { |
| ... | ... | @@ -1311,10 +1173,19 @@ pub const DeclGen = struct { |
| 1311 | 1173 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 1312 | 1174 | return dg.renderValue(writer, Type.bool, is_null_val, location); |
| 1313 | 1175 | |
| 1314 | | if (ty.optionalReprIsPayload(mod)) switch (opt.val) { |
| 1315 | | .none => return writer.writeByte('0'), |
| 1316 | | else => |payload| return dg.renderValue(writer, payload_ty, payload.toValue(), location), |
| 1317 | | }; |
| 1176 | if (ty.optionalReprIsPayload(mod)) return dg.renderValue( |
| 1177 | writer, |
| 1178 | payload_ty, |
| 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 | 1190 | if (!location.isInitializer()) { |
| 1320 | 1191 | try writer.writeByte('('); |
| ... | ... | @@ -2535,7 +2406,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 2535 | 2406 | try writer.writeAll("enum {\n"); |
| 2536 | 2407 | o.indent_writer.pushIndent(); |
| 2537 | 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 | 2410 | max_name_len = std.math.max(name.len, max_name_len); |
| 2540 | 2411 | const err_val = try mod.intern(.{ .err = .{ |
| 2541 | 2412 | .ty = .anyerror_type, |
| ... | ... | @@ -2562,21 +2433,21 @@ pub fn genErrDecls(o: *Object) !void { |
| 2562 | 2433 | .child = .u8_type, |
| 2563 | 2434 | .sentinel = .zero_u8, |
| 2564 | 2435 | }); |
| 2565 | | |
| 2566 | | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name }; |
| 2567 | | const name_val = Value.initPayload(&name_pl.base); |
| 2436 | const name_val = try mod.intern(.{ .aggregate = .{ |
| 2437 | .ty = name_ty.toIntern(), |
| 2438 | .storage = .{ .bytes = name }, |
| 2439 | } }); |
| 2568 | 2440 | |
| 2569 | 2441 | try writer.writeAll("static "); |
| 2570 | 2442 | try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, Const, 0, .complete); |
| 2571 | 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 | 2445 | try writer.writeAll(";\n"); |
| 2574 | 2446 | } |
| 2575 | 2447 | |
| 2576 | 2448 | const name_array_ty = try mod.arrayType(.{ |
| 2577 | 2449 | .len = mod.error_name_list.items.len, |
| 2578 | 2450 | .child = .slice_const_u8_sentinel_0_type, |
| 2579 | | .sentinel = .zero_u8, |
| 2580 | 2451 | }); |
| 2581 | 2452 | |
| 2582 | 2453 | try writer.writeAll("static "); |
| ... | ... | @@ -2588,7 +2459,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 2588 | 2459 | const len_val = try mod.intValue(Type.usize, name.len); |
| 2589 | 2460 | |
| 2590 | 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 | 2465 | try writer.writeAll("};\n"); |
| ... | ... | @@ -2642,10 +2513,10 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2642 | 2513 | .child = .u8_type, |
| 2643 | 2514 | .sentinel = .zero_u8, |
| 2644 | 2515 | }); |
| 2645 | | |
| 2646 | | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name }; |
| 2647 | | const name_val = Value.initPayload(&name_pl.base); |
| 2648 | | |
| 2516 | const name_val = try mod.intern(.{ .aggregate = .{ |
| 2517 | .ty = name_ty.toIntern(), |
| 2518 | .storage = .{ .bytes = name }, |
| 2519 | } }); |
| 2649 | 2520 | const len_val = try mod.intValue(Type.usize, name.len); |
| 2650 | 2521 | |
| 2651 | 2522 | try w.print(" case {}: {{\n static ", .{ |
| ... | ... | @@ -2653,7 +2524,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2653 | 2524 | }); |
| 2654 | 2525 | try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete); |
| 2655 | 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 | 2528 | try w.writeAll(";\n return ("); |
| 2658 | 2529 | try o.dg.renderType(w, name_slice_ty); |
| 2659 | 2530 | try w.print("){{{}, {}}};\n", .{ |
| ... | ... | @@ -2789,7 +2660,7 @@ pub fn genDecl(o: *Object) !void { |
| 2789 | 2660 | const mod = o.dg.module; |
| 2790 | 2661 | const decl = o.dg.decl.?; |
| 2791 | 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 | 2665 | if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; |
| 2795 | 2666 | if (tv.val.getExternFunc(mod)) |_| { |
| ... | ... | @@ -4771,6 +4642,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4771 | 4642 | try writer.writeAll(") "); |
| 4772 | 4643 | |
| 4773 | 4644 | try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false); |
| 4645 | try writer.writeByte('\n'); |
| 4774 | 4646 | |
| 4775 | 4647 | // We don't need to use `genBodyResolveState` for the else block, because this instruction is |
| 4776 | 4648 | // noreturn so must terminate a body, therefore we don't need to leave `value_map` or |
| ... | ... | @@ -5165,7 +5037,7 @@ fn airIsNull( |
| 5165 | 5037 | TypedValue{ .ty = Type.bool, .val = Value.true } |
| 5166 | 5038 | else if (optional_ty.isPtrLikeOptional(mod)) |
| 5167 | 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 | 5041 | else if (payload_ty.zigTypeTag(mod) == .ErrorSet) |
| 5170 | 5042 | TypedValue{ .ty = Type.err_int, .val = try mod.intValue(Type.err_int, 0) } |
| 5171 | 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 | 5650 | try reap(f, inst, &.{ty_op.operand}); |
| 5779 | 5651 | try f.writeCValueDeref(writer, operand); |
| 5780 | 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 | 5654 | try writer.writeAll(";\n"); |
| 5783 | 5655 | |
| 5784 | 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 | 6632 | try writer.writeAll(" = "); |
| 6761 | 6633 | |
| 6762 | 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 | 6640 | .And => switch (scalar_ty.zigTypeTag(mod)) { |
| 6765 | | .Bool => try mod.intValue(Type.comptime_int, 1), |
| 6766 | | else => switch (scalar_ty.intInfo(mod).signedness) { |
| 6641 | .Bool => Value.true, |
| 6642 | .Int => switch (scalar_ty.intInfo(mod).signedness) { |
| 6767 | 6643 | .unsigned => try scalar_ty.maxIntScalar(mod, scalar_ty), |
| 6768 | 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 | 6658 | .Min => switch (scalar_ty.zigTypeTag(mod)) { |
| 6772 | | .Bool => Value.one_comptime_int, |
| 6659 | .Bool => Value.true, |
| 6773 | 6660 | .Int => try scalar_ty.maxIntScalar(mod, scalar_ty), |
| 6774 | 6661 | .Float => try mod.floatValue(scalar_ty, std.math.nan_f128), |
| 6775 | 6662 | else => unreachable, |
| 6776 | 6663 | }, |
| 6777 | 6664 | .Max => switch (scalar_ty.zigTypeTag(mod)) { |
| 6778 | | .Bool => try mod.intValue(scalar_ty, 0), |
| 6779 | | .Int => try scalar_ty.minInt(mod, scalar_ty), |
| 6665 | .Bool => Value.false, |
| 6666 | .Int => try scalar_ty.minIntScalar(mod, scalar_ty), |
| 6780 | 6667 | .Float => try mod.floatValue(scalar_ty, std.math.nan_f128), |
| 6781 | 6668 | else => unreachable, |
| 6782 | 6669 | }, |
| 6783 | | .Mul => try mod.intValue(Type.comptime_int, 1), |
| 6784 | 6670 | }, .Initializer); |
| 6785 | 6671 | try writer.writeAll(";\n"); |
| 6786 | 6672 | |