| author | |
| committer | |
| log | 9aec2758cc29d27c31dcb0b4bb040484a885ef23 |
| tree | c171c40656f3b8f70375b4afca94a87784bb2dda |
| parent | 1e7dcaa3ae57294ab5998b44a8c13ccc5019e7ea |
Instead of doing everything at once which is a hopelessly large task,
this introduces a piecemeal transition that can be done in small
increments at a time.
This is a minimal changeset that keeps the compiler compiling. It only
uses the InternPool for a small set of types.
Behavior tests are not passing.
Air.Inst.Ref and Zir.Inst.Ref are separated into different enums but
compile-time verified to have the same fields in the same order.
The large set of changes is mainly to deal with the fact that most Type
and Value methods now require a Module to be passed in, so that the
InternPool object can be accessed.38 files changed, 6473 insertions(+), 5784 deletions(-)
src/Air.zig+104-21| ... | @@ -5,10 +5,12 @@ | ... | @@ -5,10 +5,12 @@ |
| 5 | 5 | ||
| 6 | const std = @import("std"); | 6 | const std = @import("std"); |
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const Value = @import("value.zig").Value; | ||
| 9 | const Type = @import("type.zig").Type; | ||
| 10 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
| 9 | |||
| 11 | const Air = @This(); | 10 | const Air = @This(); |
| 11 | const Value = @import("value.zig").Value; | ||
| 12 | const Type = @import("type.zig").Type; | ||
| 13 | const InternPool = @import("InternPool.zig"); | ||
| 12 | 14 | ||
| 13 | instructions: std.MultiArrayList(Inst).Slice, | 15 | instructions: std.MultiArrayList(Inst).Slice, |
| 14 | /// The meaning of this data is determined by `Inst.Tag` value. | 16 | /// The meaning of this data is determined by `Inst.Tag` value. |
| ... | @@ -837,7 +839,88 @@ pub const Inst = struct { | ... | @@ -837,7 +839,88 @@ pub const Inst = struct { |
| 837 | /// The position of an AIR instruction within the `Air` instructions array. | 839 | /// The position of an AIR instruction within the `Air` instructions array. |
| 838 | pub const Index = u32; | 840 | pub const Index = u32; |
| 839 | 841 | ||
| 840 | pub const Ref = @import("Zir.zig").Inst.Ref; | 842 | pub const Ref = enum(u32) { |
| 843 | u1_type = @enumToInt(InternPool.Index.u1_type), | ||
| 844 | u8_type = @enumToInt(InternPool.Index.u8_type), | ||
| 845 | i8_type = @enumToInt(InternPool.Index.i8_type), | ||
| 846 | u16_type = @enumToInt(InternPool.Index.u16_type), | ||
| 847 | i16_type = @enumToInt(InternPool.Index.i16_type), | ||
| 848 | u29_type = @enumToInt(InternPool.Index.u29_type), | ||
| 849 | u32_type = @enumToInt(InternPool.Index.u32_type), | ||
| 850 | i32_type = @enumToInt(InternPool.Index.i32_type), | ||
| 851 | u64_type = @enumToInt(InternPool.Index.u64_type), | ||
| 852 | i64_type = @enumToInt(InternPool.Index.i64_type), | ||
| 853 | u80_type = @enumToInt(InternPool.Index.u80_type), | ||
| 854 | u128_type = @enumToInt(InternPool.Index.u128_type), | ||
| 855 | i128_type = @enumToInt(InternPool.Index.i128_type), | ||
| 856 | usize_type = @enumToInt(InternPool.Index.usize_type), | ||
| 857 | isize_type = @enumToInt(InternPool.Index.isize_type), | ||
| 858 | c_char_type = @enumToInt(InternPool.Index.c_char_type), | ||
| 859 | c_short_type = @enumToInt(InternPool.Index.c_short_type), | ||
| 860 | c_ushort_type = @enumToInt(InternPool.Index.c_ushort_type), | ||
| 861 | c_int_type = @enumToInt(InternPool.Index.c_int_type), | ||
| 862 | c_uint_type = @enumToInt(InternPool.Index.c_uint_type), | ||
| 863 | c_long_type = @enumToInt(InternPool.Index.c_long_type), | ||
| 864 | c_ulong_type = @enumToInt(InternPool.Index.c_ulong_type), | ||
| 865 | c_longlong_type = @enumToInt(InternPool.Index.c_longlong_type), | ||
| 866 | c_ulonglong_type = @enumToInt(InternPool.Index.c_ulonglong_type), | ||
| 867 | c_longdouble_type = @enumToInt(InternPool.Index.c_longdouble_type), | ||
| 868 | f16_type = @enumToInt(InternPool.Index.f16_type), | ||
| 869 | f32_type = @enumToInt(InternPool.Index.f32_type), | ||
| 870 | f64_type = @enumToInt(InternPool.Index.f64_type), | ||
| 871 | f80_type = @enumToInt(InternPool.Index.f80_type), | ||
| 872 | f128_type = @enumToInt(InternPool.Index.f128_type), | ||
| 873 | anyopaque_type = @enumToInt(InternPool.Index.anyopaque_type), | ||
| 874 | bool_type = @enumToInt(InternPool.Index.bool_type), | ||
| 875 | void_type = @enumToInt(InternPool.Index.void_type), | ||
| 876 | type_type = @enumToInt(InternPool.Index.type_type), | ||
| 877 | anyerror_type = @enumToInt(InternPool.Index.anyerror_type), | ||
| 878 | comptime_int_type = @enumToInt(InternPool.Index.comptime_int_type), | ||
| 879 | comptime_float_type = @enumToInt(InternPool.Index.comptime_float_type), | ||
| 880 | noreturn_type = @enumToInt(InternPool.Index.noreturn_type), | ||
| 881 | anyframe_type = @enumToInt(InternPool.Index.anyframe_type), | ||
| 882 | null_type = @enumToInt(InternPool.Index.null_type), | ||
| 883 | undefined_type = @enumToInt(InternPool.Index.undefined_type), | ||
| 884 | enum_literal_type = @enumToInt(InternPool.Index.enum_literal_type), | ||
| 885 | atomic_order_type = @enumToInt(InternPool.Index.atomic_order_type), | ||
| 886 | atomic_rmw_op_type = @enumToInt(InternPool.Index.atomic_rmw_op_type), | ||
| 887 | calling_convention_type = @enumToInt(InternPool.Index.calling_convention_type), | ||
| 888 | address_space_type = @enumToInt(InternPool.Index.address_space_type), | ||
| 889 | float_mode_type = @enumToInt(InternPool.Index.float_mode_type), | ||
| 890 | reduce_op_type = @enumToInt(InternPool.Index.reduce_op_type), | ||
| 891 | call_modifier_type = @enumToInt(InternPool.Index.call_modifier_type), | ||
| 892 | prefetch_options_type = @enumToInt(InternPool.Index.prefetch_options_type), | ||
| 893 | export_options_type = @enumToInt(InternPool.Index.export_options_type), | ||
| 894 | extern_options_type = @enumToInt(InternPool.Index.extern_options_type), | ||
| 895 | type_info_type = @enumToInt(InternPool.Index.type_info_type), | ||
| 896 | manyptr_u8_type = @enumToInt(InternPool.Index.manyptr_u8_type), | ||
| 897 | manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type), | ||
| 898 | single_const_pointer_to_comptime_int_type = @enumToInt(InternPool.Index.single_const_pointer_to_comptime_int_type), | ||
| 899 | const_slice_u8_type = @enumToInt(InternPool.Index.const_slice_u8_type), | ||
| 900 | anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type), | ||
| 901 | generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type), | ||
| 902 | var_args_param_type = @enumToInt(InternPool.Index.var_args_param_type), | ||
| 903 | empty_struct_type = @enumToInt(InternPool.Index.empty_struct_type), | ||
| 904 | undef = @enumToInt(InternPool.Index.undef), | ||
| 905 | zero = @enumToInt(InternPool.Index.zero), | ||
| 906 | zero_usize = @enumToInt(InternPool.Index.zero_usize), | ||
| 907 | one = @enumToInt(InternPool.Index.one), | ||
| 908 | one_usize = @enumToInt(InternPool.Index.one_usize), | ||
| 909 | calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c), | ||
| 910 | calling_convention_inline = @enumToInt(InternPool.Index.calling_convention_inline), | ||
| 911 | void_value = @enumToInt(InternPool.Index.void_value), | ||
| 912 | unreachable_value = @enumToInt(InternPool.Index.unreachable_value), | ||
| 913 | null_value = @enumToInt(InternPool.Index.null_value), | ||
| 914 | bool_true = @enumToInt(InternPool.Index.bool_true), | ||
| 915 | bool_false = @enumToInt(InternPool.Index.bool_false), | ||
| 916 | empty_struct = @enumToInt(InternPool.Index.empty_struct), | ||
| 917 | generic_poison = @enumToInt(InternPool.Index.generic_poison), | ||
| 918 | |||
| 919 | /// This Ref does not correspond to any AIR instruction or constant | ||
| 920 | /// value and may instead be used as a sentinel to indicate null. | ||
| 921 | none = std.math.maxInt(u32), | ||
| 922 | _, | ||
| 923 | }; | ||
| 841 | 924 | ||
| 842 | /// All instructions have an 8-byte payload, which is contained within | 925 | /// All instructions have an 8-byte payload, which is contained within |
| 843 | /// this union. `Tag` determines which union field is active, as well as | 926 | /// this union. `Tag` determines which union field is active, as well as |
| ... | @@ -1066,10 +1149,13 @@ pub fn getMainBody(air: Air) []const Air.Inst.Index { | ... | @@ -1066,10 +1149,13 @@ pub fn getMainBody(air: Air) []const Air.Inst.Index { |
| 1066 | 1149 | ||
| 1067 | pub fn typeOf(air: Air, inst: Air.Inst.Ref) Type { | 1150 | pub fn typeOf(air: Air, inst: Air.Inst.Ref) Type { |
| 1068 | const ref_int = @enumToInt(inst); | 1151 | const ref_int = @enumToInt(inst); |
| 1069 | if (ref_int < Air.Inst.Ref.typed_value_map.len) { | 1152 | if (ref_int < InternPool.static_keys.len) { |
| 1070 | return Air.Inst.Ref.typed_value_map[ref_int].ty; | 1153 | return .{ |
| 1154 | .ip_index = InternPool.static_keys[ref_int].typeOf(), | ||
| 1155 | .legacy = undefined, | ||
| 1156 | }; | ||
| 1071 | } | 1157 | } |
| 1072 | return air.typeOfIndex(@intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len)); | 1158 | return air.typeOfIndex(ref_int - ref_start_index); |
| 1073 | } | 1159 | } |
| 1074 | 1160 | ||
| 1075 | pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | 1161 | pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| ... | @@ -1286,11 +1372,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -1286,11 +1372,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 1286 | 1372 | ||
| 1287 | .call, .call_always_tail, .call_never_tail, .call_never_inline => { | 1373 | .call, .call_always_tail, .call_never_tail, .call_never_inline => { |
| 1288 | const callee_ty = air.typeOf(datas[inst].pl_op.operand); | 1374 | const callee_ty = air.typeOf(datas[inst].pl_op.operand); |
| 1289 | switch (callee_ty.zigTypeTag()) { | 1375 | return callee_ty.fnReturnType(); |
| 1290 | .Fn => return callee_ty.fnReturnType(), | ||
| 1291 | .Pointer => return callee_ty.childType().fnReturnType(), | ||
| 1292 | else => unreachable, | ||
| 1293 | } | ||
| 1294 | }, | 1376 | }, |
| 1295 | 1377 | ||
| 1296 | .slice_elem_val, .ptr_elem_val, .array_elem_val => { | 1378 | .slice_elem_val, .ptr_elem_val, .array_elem_val => { |
| ... | @@ -1328,11 +1410,11 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -1328,11 +1410,11 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 1328 | 1410 | ||
| 1329 | pub fn getRefType(air: Air, ref: Air.Inst.Ref) Type { | 1411 | pub fn getRefType(air: Air, ref: Air.Inst.Ref) Type { |
| 1330 | const ref_int = @enumToInt(ref); | 1412 | const ref_int = @enumToInt(ref); |
| 1331 | if (ref_int < Air.Inst.Ref.typed_value_map.len) { | 1413 | if (ref_int < ref_start_index) { |
| 1332 | var buffer: Value.ToTypeBuffer = undefined; | 1414 | const ip_index = @intToEnum(InternPool.Index, ref_int); |
| 1333 | return Air.Inst.Ref.typed_value_map[ref_int].val.toType(&buffer); | 1415 | return ip_index.toType(); |
| 1334 | } | 1416 | } |
| 1335 | const inst_index = ref_int - Air.Inst.Ref.typed_value_map.len; | 1417 | const inst_index = ref_int - ref_start_index; |
| 1336 | const air_tags = air.instructions.items(.tag); | 1418 | const air_tags = air.instructions.items(.tag); |
| 1337 | const air_datas = air.instructions.items(.data); | 1419 | const air_datas = air.instructions.items(.data); |
| 1338 | assert(air_tags[inst_index] == .const_ty); | 1420 | assert(air_tags[inst_index] == .const_ty); |
| ... | @@ -1367,7 +1449,7 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void { | ... | @@ -1367,7 +1449,7 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void { |
| 1367 | air.* = undefined; | 1449 | air.* = undefined; |
| 1368 | } | 1450 | } |
| 1369 | 1451 | ||
| 1370 | const ref_start_index: u32 = Air.Inst.Ref.typed_value_map.len; | 1452 | pub const ref_start_index: u32 = InternPool.static_len; |
| 1371 | 1453 | ||
| 1372 | pub fn indexToRef(inst: Air.Inst.Index) Air.Inst.Ref { | 1454 | pub fn indexToRef(inst: Air.Inst.Index) Air.Inst.Ref { |
| 1373 | return @intToEnum(Air.Inst.Ref, ref_start_index + inst); | 1455 | return @intToEnum(Air.Inst.Ref, ref_start_index + inst); |
| ... | @@ -1383,17 +1465,18 @@ pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index { | ... | @@ -1383,17 +1465,18 @@ pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index { |
| 1383 | } | 1465 | } |
| 1384 | 1466 | ||
| 1385 | /// Returns `null` if runtime-known. | 1467 | /// Returns `null` if runtime-known. |
| 1386 | pub fn value(air: Air, inst: Air.Inst.Ref) ?Value { | 1468 | pub fn value(air: Air, inst: Air.Inst.Ref, mod: *const @import("Module.zig")) ?Value { |
| 1387 | const ref_int = @enumToInt(inst); | 1469 | const ref_int = @enumToInt(inst); |
| 1388 | if (ref_int < Air.Inst.Ref.typed_value_map.len) { | 1470 | if (ref_int < ref_start_index) { |
| 1389 | return Air.Inst.Ref.typed_value_map[ref_int].val; | 1471 | const ip_index = @intToEnum(InternPool.Index, ref_int); |
| 1472 | return ip_index.toValue(); | ||
| 1390 | } | 1473 | } |
| 1391 | const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len); | 1474 | const inst_index = @intCast(Air.Inst.Index, ref_int - ref_start_index); |
| 1392 | const air_datas = air.instructions.items(.data); | 1475 | const air_datas = air.instructions.items(.data); |
| 1393 | switch (air.instructions.items(.tag)[inst_index]) { | 1476 | switch (air.instructions.items(.tag)[inst_index]) { |
| 1394 | .constant => return air.values[air_datas[inst_index].ty_pl.payload], | 1477 | .constant => return air.values[air_datas[inst_index].ty_pl.payload], |
| 1395 | .const_ty => unreachable, | 1478 | .const_ty => unreachable, |
| 1396 | else => return air.typeOfIndex(inst_index).onePossibleValue(), | 1479 | else => return air.typeOfIndex(inst_index).onePossibleValue(mod), |
| 1397 | } | 1480 | } |
| 1398 | } | 1481 | } |
| 1399 | 1482 |
src/AstGen.zig+1-5| ... | @@ -8530,7 +8530,7 @@ fn builtinCall( | ... | @@ -8530,7 +8530,7 @@ fn builtinCall( |
| 8530 | return rvalue(gz, ri, result, node); | 8530 | return rvalue(gz, ri, result, node); |
| 8531 | }, | 8531 | }, |
| 8532 | .call => { | 8532 | .call => { |
| 8533 | const modifier = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .modifier_type } }, params[0]); | 8533 | const modifier = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .call_modifier_type } }, params[0]); |
| 8534 | const callee = try expr(gz, scope, .{ .rl = .none }, params[1]); | 8534 | const callee = try expr(gz, scope, .{ .rl = .none }, params[1]); |
| 8535 | const args = try expr(gz, scope, .{ .rl = .none }, params[2]); | 8535 | const args = try expr(gz, scope, .{ .rl = .none }, params[2]); |
| 8536 | const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{ | 8536 | const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{ |
| ... | @@ -10298,10 +10298,6 @@ fn rvalue( | ... | @@ -10298,10 +10298,6 @@ fn rvalue( |
| 10298 | as_ty | @enumToInt(Zir.Inst.Ref.noreturn_type), | 10298 | as_ty | @enumToInt(Zir.Inst.Ref.noreturn_type), |
| 10299 | as_ty | @enumToInt(Zir.Inst.Ref.null_type), | 10299 | as_ty | @enumToInt(Zir.Inst.Ref.null_type), |
| 10300 | as_ty | @enumToInt(Zir.Inst.Ref.undefined_type), | 10300 | as_ty | @enumToInt(Zir.Inst.Ref.undefined_type), |
| 10301 | as_ty | @enumToInt(Zir.Inst.Ref.fn_noreturn_no_args_type), | ||
| 10302 | as_ty | @enumToInt(Zir.Inst.Ref.fn_void_no_args_type), | ||
| 10303 | as_ty | @enumToInt(Zir.Inst.Ref.fn_naked_noreturn_no_args_type), | ||
| 10304 | as_ty | @enumToInt(Zir.Inst.Ref.fn_ccc_void_no_args_type), | ||
| 10305 | as_ty | @enumToInt(Zir.Inst.Ref.single_const_pointer_to_comptime_int_type), | 10301 | as_ty | @enumToInt(Zir.Inst.Ref.single_const_pointer_to_comptime_int_type), |
| 10306 | as_ty | @enumToInt(Zir.Inst.Ref.const_slice_u8_type), | 10302 | as_ty | @enumToInt(Zir.Inst.Ref.const_slice_u8_type), |
| 10307 | as_ty | @enumToInt(Zir.Inst.Ref.enum_literal_type), | 10303 | as_ty | @enumToInt(Zir.Inst.Ref.enum_literal_type), |
src/Autodoc.zig-2| ... | @@ -95,8 +95,6 @@ pub fn generateZirData(self: *Autodoc) !void { | ... | @@ -95,8 +95,6 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 95 | } | 95 | } |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | log.debug("Ref map size: {}", .{Ref.typed_value_map.len}); | ||
| 99 | |||
| 100 | const root_src_dir = self.comp_module.main_pkg.root_src_directory; | 98 | const root_src_dir = self.comp_module.main_pkg.root_src_directory; |
| 101 | const root_src_path = self.comp_module.main_pkg.root_src_path; | 99 | const root_src_path = self.comp_module.main_pkg.root_src_path; |
| 102 | const joined_src_path = try root_src_dir.join(self.arena, &.{root_src_path}); | 100 | const joined_src_path = try root_src_dir.join(self.arena, &.{root_src_path}); |
src/Compilation.zig+2-1| ... | @@ -1317,7 +1317,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { | ... | @@ -1317,7 +1317,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1317 | .emit_h = emit_h, | 1317 | .emit_h = emit_h, |
| 1318 | .error_name_list = .{}, | 1318 | .error_name_list = .{}, |
| 1319 | }; | 1319 | }; |
| 1320 | try module.error_name_list.append(gpa, "(no error)"); | 1320 | try module.init(); |
| 1321 | 1321 | ||
| 1322 | break :blk module; | 1322 | break :blk module; |
| 1323 | } else blk: { | 1323 | } else blk: { |
| ... | @@ -2064,6 +2064,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void | ... | @@ -2064,6 +2064,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void |
| 2064 | if (!build_options.only_c and !build_options.only_core_functionality) { | 2064 | if (!build_options.only_c and !build_options.only_core_functionality) { |
| 2065 | if (comp.emit_docs) |doc_location| { | 2065 | if (comp.emit_docs) |doc_location| { |
| 2066 | if (comp.bin_file.options.module) |module| { | 2066 | if (comp.bin_file.options.module) |module| { |
| 2067 | if (true) @panic("TODO: get autodoc working again in this branch"); | ||
| 2067 | var autodoc = Autodoc.init(module, doc_location); | 2068 | var autodoc = Autodoc.init(module, doc_location); |
| 2068 | defer autodoc.deinit(); | 2069 | defer autodoc.deinit(); |
| 2069 | try autodoc.generateZirData(); | 2070 | try autodoc.generateZirData(); |
src/InternPool.zig+488-30| ... | @@ -1,11 +1,16 @@ | ... | @@ -1,11 +1,16 @@ |
| 1 | //! All interned objects have both a value and a type. | ||
| 2 | |||
| 1 | map: std.AutoArrayHashMapUnmanaged(void, void) = .{}, | 3 | map: std.AutoArrayHashMapUnmanaged(void, void) = .{}, |
| 2 | items: std.MultiArrayList(Item) = .{}, | 4 | items: std.MultiArrayList(Item) = .{}, |
| 3 | extra: std.ArrayListUnmanaged(u32) = .{}, | 5 | extra: std.ArrayListUnmanaged(u32) = .{}, |
| 4 | 6 | ||
| 5 | const InternPool = @This(); | ||
| 6 | const std = @import("std"); | 7 | const std = @import("std"); |
| 7 | const Allocator = std.mem.Allocator; | 8 | const Allocator = std.mem.Allocator; |
| 8 | const assert = std.debug.assert; | 9 | const assert = std.debug.assert; |
| 10 | const BigIntConst = std.math.big.int.Const; | ||
| 11 | |||
| 12 | const InternPool = @This(); | ||
| 13 | const DeclIndex = enum(u32) { _ }; | ||
| 9 | 14 | ||
| 10 | const KeyAdapter = struct { | 15 | const KeyAdapter = struct { |
| 11 | intern_pool: *const InternPool, | 16 | intern_pool: *const InternPool, |
| ... | @@ -17,24 +22,21 @@ const KeyAdapter = struct { | ... | @@ -17,24 +22,21 @@ const KeyAdapter = struct { |
| 17 | 22 | ||
| 18 | pub fn hash(ctx: @This(), a: Key) u32 { | 23 | pub fn hash(ctx: @This(), a: Key) u32 { |
| 19 | _ = ctx; | 24 | _ = ctx; |
| 20 | return a.hash(); | 25 | return a.hash32(); |
| 21 | } | 26 | } |
| 22 | }; | 27 | }; |
| 23 | 28 | ||
| 24 | pub const Key = union(enum) { | 29 | pub const Key = union(enum) { |
| 25 | int_type: struct { | 30 | int_type: IntType, |
| 26 | signedness: std.builtin.Signedness, | ||
| 27 | bits: u16, | ||
| 28 | }, | ||
| 29 | ptr_type: struct { | 31 | ptr_type: struct { |
| 30 | elem_type: Index, | 32 | elem_type: Index, |
| 31 | sentinel: Index, | 33 | sentinel: Index = .none, |
| 32 | alignment: u16, | 34 | alignment: u16 = 0, |
| 33 | size: std.builtin.Type.Pointer.Size, | 35 | size: std.builtin.Type.Pointer.Size, |
| 34 | is_const: bool, | 36 | is_const: bool = false, |
| 35 | is_volatile: bool, | 37 | is_volatile: bool = false, |
| 36 | is_allowzero: bool, | 38 | is_allowzero: bool = false, |
| 37 | address_space: std.builtin.AddressSpace, | 39 | address_space: std.builtin.AddressSpace = .generic, |
| 38 | }, | 40 | }, |
| 39 | array_type: struct { | 41 | array_type: struct { |
| 40 | len: u64, | 42 | len: u64, |
| ... | @@ -52,20 +54,52 @@ pub const Key = union(enum) { | ... | @@ -52,20 +54,52 @@ pub const Key = union(enum) { |
| 52 | error_set_type: Index, | 54 | error_set_type: Index, |
| 53 | payload_type: Index, | 55 | payload_type: Index, |
| 54 | }, | 56 | }, |
| 55 | simple: Simple, | 57 | simple_type: SimpleType, |
| 58 | simple_value: SimpleValue, | ||
| 59 | extern_func: struct { | ||
| 60 | ty: Index, | ||
| 61 | /// The Decl that corresponds to the function itself. | ||
| 62 | owner_decl: DeclIndex, | ||
| 63 | /// Library name if specified. | ||
| 64 | /// For example `extern "c" fn write(...) usize` would have 'c' as library name. | ||
| 65 | /// Index into the string table bytes. | ||
| 66 | lib_name: u32, | ||
| 67 | }, | ||
| 68 | int: struct { | ||
| 69 | ty: Index, | ||
| 70 | big_int: BigIntConst, | ||
| 71 | }, | ||
| 72 | enum_tag: struct { | ||
| 73 | ty: Index, | ||
| 74 | tag: BigIntConst, | ||
| 75 | }, | ||
| 76 | struct_type: struct { | ||
| 77 | fields_len: u32, | ||
| 78 | // TODO move Module.Struct data to here | ||
| 79 | }, | ||
| 80 | |||
| 81 | pub const IntType = std.builtin.Type.Int; | ||
| 56 | 82 | ||
| 57 | pub fn hash(key: Key) u32 { | 83 | pub fn hash32(key: Key) u32 { |
| 84 | return @truncate(u32, key.hash64()); | ||
| 85 | } | ||
| 86 | |||
| 87 | pub fn hash64(key: Key) u64 { | ||
| 58 | var hasher = std.hash.Wyhash.init(0); | 88 | var hasher = std.hash.Wyhash.init(0); |
| 89 | key.hashWithHasher(&hasher); | ||
| 90 | return hasher.final(); | ||
| 91 | } | ||
| 92 | |||
| 93 | pub fn hashWithHasher(key: Key, hasher: *std.hash.Wyhash) void { | ||
| 59 | switch (key) { | 94 | switch (key) { |
| 60 | .int_type => |int_type| { | 95 | .int_type => |int_type| { |
| 61 | std.hash.autoHash(&hasher, int_type); | 96 | std.hash.autoHash(hasher, int_type); |
| 62 | }, | 97 | }, |
| 63 | .array_type => |array_type| { | 98 | .array_type => |array_type| { |
| 64 | std.hash.autoHash(&hasher, array_type); | 99 | std.hash.autoHash(hasher, array_type); |
| 65 | }, | 100 | }, |
| 66 | else => @panic("TODO"), | 101 | else => @panic("TODO"), |
| 67 | } | 102 | } |
| 68 | return @truncate(u32, hasher.final()); | ||
| 69 | } | 103 | } |
| 70 | 104 | ||
| 71 | pub fn eql(a: Key, b: Key) bool { | 105 | pub fn eql(a: Key, b: Key) bool { |
| ... | @@ -85,6 +119,34 @@ pub const Key = union(enum) { | ... | @@ -85,6 +119,34 @@ pub const Key = union(enum) { |
| 85 | else => @panic("TODO"), | 119 | else => @panic("TODO"), |
| 86 | } | 120 | } |
| 87 | } | 121 | } |
| 122 | |||
| 123 | pub fn typeOf(key: Key) Index { | ||
| 124 | switch (key) { | ||
| 125 | .int_type, | ||
| 126 | .ptr_type, | ||
| 127 | .array_type, | ||
| 128 | .vector_type, | ||
| 129 | .optional_type, | ||
| 130 | .error_union_type, | ||
| 131 | .simple_type, | ||
| 132 | .struct_type, | ||
| 133 | => return .type_type, | ||
| 134 | |||
| 135 | .int => |x| return x.ty, | ||
| 136 | .extern_func => |x| return x.ty, | ||
| 137 | .enum_tag => |x| return x.ty, | ||
| 138 | |||
| 139 | .simple_value => |s| switch (s) { | ||
| 140 | .undefined => return .undefined_type, | ||
| 141 | .void => return .void_type, | ||
| 142 | .null => return .null_type, | ||
| 143 | .false, .true => return .bool_type, | ||
| 144 | .empty_struct => return .empty_struct_type, | ||
| 145 | .@"unreachable" => return .noreturn_type, | ||
| 146 | .generic_poison => unreachable, | ||
| 147 | }, | ||
| 148 | } | ||
| 149 | } | ||
| 88 | }; | 150 | }; |
| 89 | 151 | ||
| 90 | pub const Item = struct { | 152 | pub const Item = struct { |
| ... | @@ -98,11 +160,330 @@ pub const Item = struct { | ... | @@ -98,11 +160,330 @@ pub const Item = struct { |
| 98 | /// Two values which have the same type can be equality compared simply | 160 | /// Two values which have the same type can be equality compared simply |
| 99 | /// by checking if their indexes are equal, provided they are both in | 161 | /// by checking if their indexes are equal, provided they are both in |
| 100 | /// the same `InternPool`. | 162 | /// the same `InternPool`. |
| 163 | /// When adding a tag to this enum, consider adding a corresponding entry to | ||
| 164 | /// `primitives` in AstGen.zig. | ||
| 101 | pub const Index = enum(u32) { | 165 | pub const Index = enum(u32) { |
| 166 | u1_type, | ||
| 167 | u8_type, | ||
| 168 | i8_type, | ||
| 169 | u16_type, | ||
| 170 | i16_type, | ||
| 171 | u29_type, | ||
| 172 | u32_type, | ||
| 173 | i32_type, | ||
| 174 | u64_type, | ||
| 175 | i64_type, | ||
| 176 | u80_type, | ||
| 177 | u128_type, | ||
| 178 | i128_type, | ||
| 179 | usize_type, | ||
| 180 | isize_type, | ||
| 181 | c_char_type, | ||
| 182 | c_short_type, | ||
| 183 | c_ushort_type, | ||
| 184 | c_int_type, | ||
| 185 | c_uint_type, | ||
| 186 | c_long_type, | ||
| 187 | c_ulong_type, | ||
| 188 | c_longlong_type, | ||
| 189 | c_ulonglong_type, | ||
| 190 | c_longdouble_type, | ||
| 191 | f16_type, | ||
| 192 | f32_type, | ||
| 193 | f64_type, | ||
| 194 | f80_type, | ||
| 195 | f128_type, | ||
| 196 | anyopaque_type, | ||
| 197 | bool_type, | ||
| 198 | void_type, | ||
| 199 | type_type, | ||
| 200 | anyerror_type, | ||
| 201 | comptime_int_type, | ||
| 202 | comptime_float_type, | ||
| 203 | noreturn_type, | ||
| 204 | anyframe_type, | ||
| 205 | null_type, | ||
| 206 | undefined_type, | ||
| 207 | enum_literal_type, | ||
| 208 | atomic_order_type, | ||
| 209 | atomic_rmw_op_type, | ||
| 210 | calling_convention_type, | ||
| 211 | address_space_type, | ||
| 212 | float_mode_type, | ||
| 213 | reduce_op_type, | ||
| 214 | call_modifier_type, | ||
| 215 | prefetch_options_type, | ||
| 216 | export_options_type, | ||
| 217 | extern_options_type, | ||
| 218 | type_info_type, | ||
| 219 | manyptr_u8_type, | ||
| 220 | manyptr_const_u8_type, | ||
| 221 | single_const_pointer_to_comptime_int_type, | ||
| 222 | const_slice_u8_type, | ||
| 223 | anyerror_void_error_union_type, | ||
| 224 | generic_poison_type, | ||
| 225 | var_args_param_type, | ||
| 226 | empty_struct_type, | ||
| 227 | |||
| 228 | /// `undefined` (untyped) | ||
| 229 | undef, | ||
| 230 | /// `0` (comptime_int) | ||
| 231 | zero, | ||
| 232 | /// `0` (usize) | ||
| 233 | zero_usize, | ||
| 234 | /// `1` (comptime_int) | ||
| 235 | one, | ||
| 236 | /// `1` (usize) | ||
| 237 | one_usize, | ||
| 238 | /// `std.builtin.CallingConvention.C` | ||
| 239 | calling_convention_c, | ||
| 240 | /// `std.builtin.CallingConvention.Inline` | ||
| 241 | calling_convention_inline, | ||
| 242 | /// `{}` | ||
| 243 | void_value, | ||
| 244 | /// `unreachable` (noreturn type) | ||
| 245 | unreachable_value, | ||
| 246 | /// `null` (untyped) | ||
| 247 | null_value, | ||
| 248 | /// `true` | ||
| 249 | bool_true, | ||
| 250 | /// `false` | ||
| 251 | bool_false, | ||
| 252 | /// `.{}` (untyped) | ||
| 253 | empty_struct, | ||
| 254 | /// Used for generic parameters where the type and value | ||
| 255 | /// is not known until generic function instantiation. | ||
| 256 | generic_poison, | ||
| 257 | |||
| 102 | none = std.math.maxInt(u32), | 258 | none = std.math.maxInt(u32), |
| 259 | |||
| 103 | _, | 260 | _, |
| 261 | |||
| 262 | pub fn toType(i: Index) @import("type.zig").Type { | ||
| 263 | assert(i != .none); | ||
| 264 | return .{ | ||
| 265 | .ip_index = i, | ||
| 266 | .legacy = undefined, | ||
| 267 | }; | ||
| 268 | } | ||
| 269 | |||
| 270 | pub fn toValue(i: Index) @import("value.zig").Value { | ||
| 271 | assert(i != .none); | ||
| 272 | return .{ | ||
| 273 | .ip_index = i, | ||
| 274 | .legacy = undefined, | ||
| 275 | }; | ||
| 276 | } | ||
| 277 | }; | ||
| 278 | |||
| 279 | pub const static_keys = [_]Key{ | ||
| 280 | .{ .int_type = .{ | ||
| 281 | .signedness = .unsigned, | ||
| 282 | .bits = 1, | ||
| 283 | } }, | ||
| 284 | |||
| 285 | .{ .int_type = .{ | ||
| 286 | .signedness = .unsigned, | ||
| 287 | .bits = 8, | ||
| 288 | } }, | ||
| 289 | |||
| 290 | .{ .int_type = .{ | ||
| 291 | .signedness = .signed, | ||
| 292 | .bits = 8, | ||
| 293 | } }, | ||
| 294 | |||
| 295 | .{ .int_type = .{ | ||
| 296 | .signedness = .unsigned, | ||
| 297 | .bits = 16, | ||
| 298 | } }, | ||
| 299 | |||
| 300 | .{ .int_type = .{ | ||
| 301 | .signedness = .signed, | ||
| 302 | .bits = 16, | ||
| 303 | } }, | ||
| 304 | |||
| 305 | .{ .int_type = .{ | ||
| 306 | .signedness = .unsigned, | ||
| 307 | .bits = 29, | ||
| 308 | } }, | ||
| 309 | |||
| 310 | .{ .int_type = .{ | ||
| 311 | .signedness = .unsigned, | ||
| 312 | .bits = 32, | ||
| 313 | } }, | ||
| 314 | |||
| 315 | .{ .int_type = .{ | ||
| 316 | .signedness = .signed, | ||
| 317 | .bits = 32, | ||
| 318 | } }, | ||
| 319 | |||
| 320 | .{ .int_type = .{ | ||
| 321 | .signedness = .unsigned, | ||
| 322 | .bits = 64, | ||
| 323 | } }, | ||
| 324 | |||
| 325 | .{ .int_type = .{ | ||
| 326 | .signedness = .signed, | ||
| 327 | .bits = 64, | ||
| 328 | } }, | ||
| 329 | |||
| 330 | .{ .int_type = .{ | ||
| 331 | .signedness = .unsigned, | ||
| 332 | .bits = 80, | ||
| 333 | } }, | ||
| 334 | |||
| 335 | .{ .int_type = .{ | ||
| 336 | .signedness = .unsigned, | ||
| 337 | .bits = 128, | ||
| 338 | } }, | ||
| 339 | |||
| 340 | .{ .int_type = .{ | ||
| 341 | .signedness = .signed, | ||
| 342 | .bits = 128, | ||
| 343 | } }, | ||
| 344 | |||
| 345 | .{ .simple_type = .usize }, | ||
| 346 | .{ .simple_type = .isize }, | ||
| 347 | .{ .simple_type = .c_char }, | ||
| 348 | .{ .simple_type = .c_short }, | ||
| 349 | .{ .simple_type = .c_ushort }, | ||
| 350 | .{ .simple_type = .c_int }, | ||
| 351 | .{ .simple_type = .c_uint }, | ||
| 352 | .{ .simple_type = .c_long }, | ||
| 353 | .{ .simple_type = .c_ulong }, | ||
| 354 | .{ .simple_type = .c_longlong }, | ||
| 355 | .{ .simple_type = .c_ulonglong }, | ||
| 356 | .{ .simple_type = .c_longdouble }, | ||
| 357 | .{ .simple_type = .f16 }, | ||
| 358 | .{ .simple_type = .f32 }, | ||
| 359 | .{ .simple_type = .f64 }, | ||
| 360 | .{ .simple_type = .f80 }, | ||
| 361 | .{ .simple_type = .f128 }, | ||
| 362 | .{ .simple_type = .anyopaque }, | ||
| 363 | .{ .simple_type = .bool }, | ||
| 364 | .{ .simple_type = .void }, | ||
| 365 | .{ .simple_type = .type }, | ||
| 366 | .{ .simple_type = .anyerror }, | ||
| 367 | .{ .simple_type = .comptime_int }, | ||
| 368 | .{ .simple_type = .comptime_float }, | ||
| 369 | .{ .simple_type = .noreturn }, | ||
| 370 | .{ .simple_type = .@"anyframe" }, | ||
| 371 | .{ .simple_type = .null }, | ||
| 372 | .{ .simple_type = .undefined }, | ||
| 373 | .{ .simple_type = .enum_literal }, | ||
| 374 | .{ .simple_type = .atomic_order }, | ||
| 375 | .{ .simple_type = .atomic_rmw_op }, | ||
| 376 | .{ .simple_type = .calling_convention }, | ||
| 377 | .{ .simple_type = .address_space }, | ||
| 378 | .{ .simple_type = .float_mode }, | ||
| 379 | .{ .simple_type = .reduce_op }, | ||
| 380 | .{ .simple_type = .call_modifier }, | ||
| 381 | .{ .simple_type = .prefetch_options }, | ||
| 382 | .{ .simple_type = .export_options }, | ||
| 383 | .{ .simple_type = .extern_options }, | ||
| 384 | .{ .simple_type = .type_info }, | ||
| 385 | |||
| 386 | .{ .ptr_type = .{ | ||
| 387 | .elem_type = .u8_type, | ||
| 388 | .size = .Many, | ||
| 389 | } }, | ||
| 390 | |||
| 391 | .{ .ptr_type = .{ | ||
| 392 | .elem_type = .u8_type, | ||
| 393 | .size = .Many, | ||
| 394 | .is_const = true, | ||
| 395 | } }, | ||
| 396 | |||
| 397 | .{ .ptr_type = .{ | ||
| 398 | .elem_type = .comptime_int_type, | ||
| 399 | .size = .One, | ||
| 400 | .is_const = true, | ||
| 401 | } }, | ||
| 402 | |||
| 403 | .{ .ptr_type = .{ | ||
| 404 | .elem_type = .u8_type, | ||
| 405 | .size = .Slice, | ||
| 406 | .is_const = true, | ||
| 407 | } }, | ||
| 408 | |||
| 409 | .{ .error_union_type = .{ | ||
| 410 | .error_set_type = .anyerror_type, | ||
| 411 | .payload_type = .void_type, | ||
| 412 | } }, | ||
| 413 | |||
| 414 | // generic_poison_type | ||
| 415 | .{ .simple_type = .generic_poison }, | ||
| 416 | |||
| 417 | // var_args_param_type | ||
| 418 | .{ .simple_type = .var_args_param }, | ||
| 419 | |||
| 420 | // empty_struct_type | ||
| 421 | .{ .struct_type = .{ | ||
| 422 | .fields_len = 0, | ||
| 423 | } }, | ||
| 424 | |||
| 425 | .{ .simple_value = .undefined }, | ||
| 426 | |||
| 427 | .{ .int = .{ | ||
| 428 | .ty = .comptime_int_type, | ||
| 429 | .big_int = .{ | ||
| 430 | .limbs = &.{0}, | ||
| 431 | .positive = true, | ||
| 432 | }, | ||
| 433 | } }, | ||
| 434 | |||
| 435 | .{ .int = .{ | ||
| 436 | .ty = .usize_type, | ||
| 437 | .big_int = .{ | ||
| 438 | .limbs = &.{0}, | ||
| 439 | .positive = true, | ||
| 440 | }, | ||
| 441 | } }, | ||
| 442 | |||
| 443 | .{ .int = .{ | ||
| 444 | .ty = .comptime_int_type, | ||
| 445 | .big_int = .{ | ||
| 446 | .limbs = &.{1}, | ||
| 447 | .positive = true, | ||
| 448 | }, | ||
| 449 | } }, | ||
| 450 | |||
| 451 | .{ .int = .{ | ||
| 452 | .ty = .usize_type, | ||
| 453 | .big_int = .{ | ||
| 454 | .limbs = &.{1}, | ||
| 455 | .positive = true, | ||
| 456 | }, | ||
| 457 | } }, | ||
| 458 | |||
| 459 | .{ .enum_tag = .{ | ||
| 460 | .ty = .calling_convention_type, | ||
| 461 | .tag = .{ | ||
| 462 | .limbs = &.{@enumToInt(std.builtin.CallingConvention.C)}, | ||
| 463 | .positive = true, | ||
| 464 | }, | ||
| 465 | } }, | ||
| 466 | |||
| 467 | .{ .enum_tag = .{ | ||
| 468 | .ty = .calling_convention_type, | ||
| 469 | .tag = .{ | ||
| 470 | .limbs = &.{@enumToInt(std.builtin.CallingConvention.Inline)}, | ||
| 471 | .positive = true, | ||
| 472 | }, | ||
| 473 | } }, | ||
| 474 | |||
| 475 | .{ .simple_value = .void }, | ||
| 476 | .{ .simple_value = .@"unreachable" }, | ||
| 477 | .{ .simple_value = .null }, | ||
| 478 | .{ .simple_value = .true }, | ||
| 479 | .{ .simple_value = .false }, | ||
| 480 | .{ .simple_value = .empty_struct }, | ||
| 481 | .{ .simple_value = .generic_poison }, | ||
| 104 | }; | 482 | }; |
| 105 | 483 | ||
| 484 | /// How many items in the InternPool are statically known. | ||
| 485 | pub const static_len: u32 = static_keys.len; | ||
| 486 | |||
| 106 | pub const Tag = enum(u8) { | 487 | pub const Tag = enum(u8) { |
| 107 | /// An integer type. | 488 | /// An integer type. |
| 108 | /// data is number of bits | 489 | /// data is number of bits |
| ... | @@ -113,9 +494,12 @@ pub const Tag = enum(u8) { | ... | @@ -113,9 +494,12 @@ pub const Tag = enum(u8) { |
| 113 | /// An array type. | 494 | /// An array type. |
| 114 | /// data is payload to Array. | 495 | /// data is payload to Array. |
| 115 | type_array, | 496 | type_array, |
| 116 | /// A type or value that can be represented with only an enum tag. | 497 | /// A type that can be represented with only an enum tag. |
| 117 | /// data is Simple enum value | 498 | /// data is SimpleType enum value. |
| 118 | simple, | 499 | simple_type, |
| 500 | /// A value that can be represented with only an enum tag. | ||
| 501 | /// data is SimpleValue enum value. | ||
| 502 | simple_value, | ||
| 119 | /// An unsigned integer value that can be represented by u32. | 503 | /// An unsigned integer value that can be represented by u32. |
| 120 | /// data is integer value | 504 | /// data is integer value |
| 121 | int_u32, | 505 | int_u32, |
| ... | @@ -137,9 +521,20 @@ pub const Tag = enum(u8) { | ... | @@ -137,9 +521,20 @@ pub const Tag = enum(u8) { |
| 137 | /// A float value that can be represented by f128. | 521 | /// A float value that can be represented by f128. |
| 138 | /// data is payload index to Float128. | 522 | /// data is payload index to Float128. |
| 139 | float_f128, | 523 | float_f128, |
| 524 | /// An extern function. | ||
| 525 | extern_func, | ||
| 526 | /// A regular function. | ||
| 527 | func, | ||
| 528 | /// Represents the data that an enum declaration provides, when the fields | ||
| 529 | /// are auto-numbered, and there are no declarations. | ||
| 530 | /// data is payload index to `EnumSimple`. | ||
| 531 | enum_simple, | ||
| 140 | }; | 532 | }; |
| 141 | 533 | ||
| 142 | pub const Simple = enum(u32) { | 534 | /// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to |
| 535 | /// implement logic that only wants to deal with types because the logic can | ||
| 536 | /// ignore all simple values. Note that technically, types are values. | ||
| 537 | pub const SimpleType = enum(u32) { | ||
| 143 | f16, | 538 | f16, |
| 144 | f32, | 539 | f32, |
| 145 | f64, | 540 | f64, |
| ... | @@ -147,6 +542,7 @@ pub const Simple = enum(u32) { | ... | @@ -147,6 +542,7 @@ pub const Simple = enum(u32) { |
| 147 | f128, | 542 | f128, |
| 148 | usize, | 543 | usize, |
| 149 | isize, | 544 | isize, |
| 545 | c_char, | ||
| 150 | c_short, | 546 | c_short, |
| 151 | c_ushort, | 547 | c_ushort, |
| 152 | c_int, | 548 | c_int, |
| ... | @@ -165,14 +561,36 @@ pub const Simple = enum(u32) { | ... | @@ -165,14 +561,36 @@ pub const Simple = enum(u32) { |
| 165 | comptime_float, | 561 | comptime_float, |
| 166 | noreturn, | 562 | noreturn, |
| 167 | @"anyframe", | 563 | @"anyframe", |
| 168 | null_type, | 564 | null, |
| 169 | undefined_type, | ||
| 170 | enum_literal_type, | ||
| 171 | undefined, | 565 | undefined, |
| 172 | void_value, | 566 | enum_literal, |
| 567 | |||
| 568 | atomic_order, | ||
| 569 | atomic_rmw_op, | ||
| 570 | calling_convention, | ||
| 571 | address_space, | ||
| 572 | float_mode, | ||
| 573 | reduce_op, | ||
| 574 | call_modifier, | ||
| 575 | prefetch_options, | ||
| 576 | export_options, | ||
| 577 | extern_options, | ||
| 578 | type_info, | ||
| 579 | |||
| 580 | generic_poison, | ||
| 581 | var_args_param, | ||
| 582 | }; | ||
| 583 | |||
| 584 | pub const SimpleValue = enum(u32) { | ||
| 585 | undefined, | ||
| 586 | void, | ||
| 173 | null, | 587 | null, |
| 174 | bool_true, | 588 | empty_struct, |
| 175 | bool_false, | 589 | true, |
| 590 | false, | ||
| 591 | @"unreachable", | ||
| 592 | |||
| 593 | generic_poison, | ||
| 176 | }; | 594 | }; |
| 177 | 595 | ||
| 178 | pub const Array = struct { | 596 | pub const Array = struct { |
| ... | @@ -180,10 +598,44 @@ pub const Array = struct { | ... | @@ -180,10 +598,44 @@ pub const Array = struct { |
| 180 | child: Index, | 598 | child: Index, |
| 181 | }; | 599 | }; |
| 182 | 600 | ||
| 601 | /// Trailing: | ||
| 602 | /// 0. field name: null-terminated string index for each fields_len; declaration order | ||
| 603 | pub const EnumSimple = struct { | ||
| 604 | /// The Decl that corresponds to the enum itself. | ||
| 605 | owner_decl: DeclIndex, | ||
| 606 | /// An integer type which is used for the numerical value of the enum. This | ||
| 607 | /// is inferred by Zig to be the smallest power of two unsigned int that | ||
| 608 | /// fits the number of fields. It is stored here to avoid unnecessary | ||
| 609 | /// calculations and possibly allocation failure when querying the tag type | ||
| 610 | /// of enums. | ||
| 611 | int_tag_ty: Index, | ||
| 612 | fields_len: u32, | ||
| 613 | }; | ||
| 614 | |||
| 615 | pub fn init(ip: *InternPool, gpa: Allocator) !void { | ||
| 616 | assert(ip.items.len == 0); | ||
| 617 | |||
| 618 | // So that we can use `catch unreachable` below. | ||
| 619 | try ip.items.ensureUnusedCapacity(gpa, static_keys.len); | ||
| 620 | try ip.map.ensureUnusedCapacity(gpa, static_keys.len); | ||
| 621 | try ip.extra.ensureUnusedCapacity(gpa, static_keys.len); | ||
| 622 | |||
| 623 | // This inserts all the statically-known values into the intern pool in the | ||
| 624 | // order expected. | ||
| 625 | for (static_keys) |key| _ = ip.get(gpa, key) catch unreachable; | ||
| 626 | |||
| 627 | // Sanity check. | ||
| 628 | assert(ip.indexToKey(.bool_true).simple_value == .true); | ||
| 629 | assert(ip.indexToKey(.bool_false).simple_value == .false); | ||
| 630 | |||
| 631 | assert(ip.items.len == static_keys.len); | ||
| 632 | } | ||
| 633 | |||
| 183 | pub fn deinit(ip: *InternPool, gpa: Allocator) void { | 634 | pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 184 | ip.map.deinit(gpa); | 635 | ip.map.deinit(gpa); |
| 185 | ip.items.deinit(gpa); | 636 | ip.items.deinit(gpa); |
| 186 | ip.extra.deinit(gpa); | 637 | ip.extra.deinit(gpa); |
| 638 | ip.* = undefined; | ||
| 187 | } | 639 | } |
| 188 | 640 | ||
| 189 | pub fn indexToKey(ip: InternPool, index: Index) Key { | 641 | pub fn indexToKey(ip: InternPool, index: Index) Key { |
| ... | @@ -210,7 +662,8 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { | ... | @@ -210,7 +662,8 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 210 | .sentinel = .none, | 662 | .sentinel = .none, |
| 211 | } }; | 663 | } }; |
| 212 | }, | 664 | }, |
| 213 | .simple => .{ .simple = @intToEnum(Simple, data) }, | 665 | .simple_type => .{ .simple_type = @intToEnum(SimpleType, data) }, |
| 666 | .simple_value => .{ .simple_value = @intToEnum(SimpleValue, data) }, | ||
| 214 | 667 | ||
| 215 | else => @panic("TODO"), | 668 | else => @panic("TODO"), |
| 216 | }; | 669 | }; |
| ... | @@ -224,12 +677,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -224,12 +677,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 224 | } | 677 | } |
| 225 | switch (key) { | 678 | switch (key) { |
| 226 | .int_type => |int_type| { | 679 | .int_type => |int_type| { |
| 227 | const tag: Tag = switch (int_type.signedness) { | 680 | const t: Tag = switch (int_type.signedness) { |
| 228 | .signed => .type_int_signed, | 681 | .signed => .type_int_signed, |
| 229 | .unsigned => .type_int_unsigned, | 682 | .unsigned => .type_int_unsigned, |
| 230 | }; | 683 | }; |
| 231 | try ip.items.append(gpa, .{ | 684 | try ip.items.append(gpa, .{ |
| 232 | .tag = tag, | 685 | .tag = t, |
| 233 | .data = int_type.bits, | 686 | .data = int_type.bits, |
| 234 | }); | 687 | }); |
| 235 | }, | 688 | }, |
| ... | @@ -249,6 +702,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -249,6 +702,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 249 | return @intToEnum(Index, ip.items.len - 1); | 702 | return @intToEnum(Index, ip.items.len - 1); |
| 250 | } | 703 | } |
| 251 | 704 | ||
| 705 | pub fn tag(ip: InternPool, index: Index) Tag { | ||
| 706 | const tags = ip.items.items(.tag); | ||
| 707 | return tags[@enumToInt(index)]; | ||
| 708 | } | ||
| 709 | |||
| 252 | fn addExtra(ip: *InternPool, gpa: Allocator, extra: anytype) Allocator.Error!u32 { | 710 | fn addExtra(ip: *InternPool, gpa: Allocator, extra: anytype) Allocator.Error!u32 { |
| 253 | const fields = std.meta.fields(@TypeOf(extra)); | 711 | const fields = std.meta.fields(@TypeOf(extra)); |
| 254 | try ip.extra.ensureUnusedCapacity(gpa, fields.len); | 712 | try ip.extra.ensureUnusedCapacity(gpa, fields.len); |
src/Liveness.zig+5-3| ... | @@ -5,15 +5,17 @@ | ... | @@ -5,15 +5,17 @@ |
| 5 | //! Some instructions are special, such as: | 5 | //! Some instructions are special, such as: |
| 6 | //! * Conditional Branches | 6 | //! * Conditional Branches |
| 7 | //! * Switch Branches | 7 | //! * Switch Branches |
| 8 | const Liveness = @This(); | ||
| 9 | const std = @import("std"); | 8 | const std = @import("std"); |
| 10 | const trace = @import("tracy.zig").trace; | ||
| 11 | const log = std.log.scoped(.liveness); | 9 | const log = std.log.scoped(.liveness); |
| 12 | const assert = std.debug.assert; | 10 | const assert = std.debug.assert; |
| 13 | const Allocator = std.mem.Allocator; | 11 | const Allocator = std.mem.Allocator; |
| 14 | const Air = @import("Air.zig"); | ||
| 15 | const Log2Int = std.math.Log2Int; | 12 | const Log2Int = std.math.Log2Int; |
| 16 | 13 | ||
| 14 | const Liveness = @This(); | ||
| 15 | const trace = @import("tracy.zig").trace; | ||
| 16 | const Air = @import("Air.zig"); | ||
| 17 | const InternPool = @import("InternPool.zig"); | ||
| 18 | |||
| 17 | pub const Verify = @import("Liveness/Verify.zig"); | 19 | pub const Verify = @import("Liveness/Verify.zig"); |
| 18 | 20 | ||
| 19 | /// This array is split into sets of 4 bits per AIR instruction. | 21 | /// This array is split into sets of 4 bits per AIR instruction. |
src/Module.zig+276-59| ... | @@ -32,6 +32,19 @@ const build_options = @import("build_options"); | ... | @@ -32,6 +32,19 @@ const build_options = @import("build_options"); |
| 32 | const Liveness = @import("Liveness.zig"); | 32 | const Liveness = @import("Liveness.zig"); |
| 33 | const isUpDir = @import("introspect.zig").isUpDir; | 33 | const isUpDir = @import("introspect.zig").isUpDir; |
| 34 | const clang = @import("clang.zig"); | 34 | const clang = @import("clang.zig"); |
| 35 | const InternPool = @import("InternPool.zig"); | ||
| 36 | |||
| 37 | comptime { | ||
| 38 | @setEvalBranchQuota(4000); | ||
| 39 | for ( | ||
| 40 | @typeInfo(Zir.Inst.Ref).Enum.fields, | ||
| 41 | @typeInfo(Air.Inst.Ref).Enum.fields, | ||
| 42 | @typeInfo(InternPool.Index).Enum.fields, | ||
| 43 | ) |zir_field, air_field, ip_field| { | ||
| 44 | assert(mem.eql(u8, zir_field.name, ip_field.name)); | ||
| 45 | assert(mem.eql(u8, air_field.name, ip_field.name)); | ||
| 46 | } | ||
| 47 | } | ||
| 35 | 48 | ||
| 36 | /// General-purpose allocator. Used for both temporary and long-term storage. | 49 | /// General-purpose allocator. Used for both temporary and long-term storage. |
| 37 | gpa: Allocator, | 50 | gpa: Allocator, |
| ... | @@ -83,6 +96,9 @@ embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{}, | ... | @@ -83,6 +96,9 @@ embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{}, |
| 83 | string_literal_table: std.HashMapUnmanaged(StringLiteralContext.Key, Decl.OptionalIndex, StringLiteralContext, std.hash_map.default_max_load_percentage) = .{}, | 96 | string_literal_table: std.HashMapUnmanaged(StringLiteralContext.Key, Decl.OptionalIndex, StringLiteralContext, std.hash_map.default_max_load_percentage) = .{}, |
| 84 | string_literal_bytes: ArrayListUnmanaged(u8) = .{}, | 97 | string_literal_bytes: ArrayListUnmanaged(u8) = .{}, |
| 85 | 98 | ||
| 99 | /// Stores all Type and Value objects; periodically garbage collected. | ||
| 100 | intern_pool: InternPool = .{}, | ||
| 101 | |||
| 86 | /// The set of all the generic function instantiations. This is used so that when a generic | 102 | /// The set of all the generic function instantiations. This is used so that when a generic |
| 87 | /// function is called twice with the same comptime parameter arguments, both calls dispatch | 103 | /// function is called twice with the same comptime parameter arguments, both calls dispatch |
| 88 | /// to the same function. | 104 | /// to the same function. |
| ... | @@ -807,9 +823,9 @@ pub const Decl = struct { | ... | @@ -807,9 +823,9 @@ pub const Decl = struct { |
| 807 | return (try decl.typedValue()).val; | 823 | return (try decl.typedValue()).val; |
| 808 | } | 824 | } |
| 809 | 825 | ||
| 810 | pub fn isFunction(decl: Decl) !bool { | 826 | pub fn isFunction(decl: Decl, mod: *const Module) !bool { |
| 811 | const tv = try decl.typedValue(); | 827 | const tv = try decl.typedValue(); |
| 812 | return tv.ty.zigTypeTag() == .Fn; | 828 | return tv.ty.zigTypeTag(mod) == .Fn; |
| 813 | } | 829 | } |
| 814 | 830 | ||
| 815 | /// If the Decl has a value and it is a struct, return it, | 831 | /// If the Decl has a value and it is a struct, return it, |
| ... | @@ -921,14 +937,14 @@ pub const Decl = struct { | ... | @@ -921,14 +937,14 @@ pub const Decl = struct { |
| 921 | }; | 937 | }; |
| 922 | } | 938 | } |
| 923 | 939 | ||
| 924 | pub fn getAlignment(decl: Decl, target: Target) u32 { | 940 | pub fn getAlignment(decl: Decl, mod: *const Module) u32 { |
| 925 | assert(decl.has_tv); | 941 | assert(decl.has_tv); |
| 926 | if (decl.@"align" != 0) { | 942 | if (decl.@"align" != 0) { |
| 927 | // Explicit alignment. | 943 | // Explicit alignment. |
| 928 | return decl.@"align"; | 944 | return decl.@"align"; |
| 929 | } else { | 945 | } else { |
| 930 | // Natural alignment. | 946 | // Natural alignment. |
| 931 | return decl.ty.abiAlignment(target); | 947 | return decl.ty.abiAlignment(mod); |
| 932 | } | 948 | } |
| 933 | } | 949 | } |
| 934 | }; | 950 | }; |
| ... | @@ -1030,7 +1046,7 @@ pub const Struct = struct { | ... | @@ -1030,7 +1046,7 @@ pub const Struct = struct { |
| 1030 | /// Returns the field alignment. If the struct is packed, returns 0. | 1046 | /// Returns the field alignment. If the struct is packed, returns 0. |
| 1031 | pub fn alignment( | 1047 | pub fn alignment( |
| 1032 | field: Field, | 1048 | field: Field, |
| 1033 | target: Target, | 1049 | mod: *const Module, |
| 1034 | layout: std.builtin.Type.ContainerLayout, | 1050 | layout: std.builtin.Type.ContainerLayout, |
| 1035 | ) u32 { | 1051 | ) u32 { |
| 1036 | if (field.abi_align != 0) { | 1052 | if (field.abi_align != 0) { |
| ... | @@ -1038,24 +1054,26 @@ pub const Struct = struct { | ... | @@ -1038,24 +1054,26 @@ pub const Struct = struct { |
| 1038 | return field.abi_align; | 1054 | return field.abi_align; |
| 1039 | } | 1055 | } |
| 1040 | 1056 | ||
| 1057 | const target = mod.getTarget(); | ||
| 1058 | |||
| 1041 | switch (layout) { | 1059 | switch (layout) { |
| 1042 | .Packed => return 0, | 1060 | .Packed => return 0, |
| 1043 | .Auto => { | 1061 | .Auto => { |
| 1044 | if (target.ofmt == .c) { | 1062 | if (target.ofmt == .c) { |
| 1045 | return alignmentExtern(field, target); | 1063 | return alignmentExtern(field, mod); |
| 1046 | } else { | 1064 | } else { |
| 1047 | return field.ty.abiAlignment(target); | 1065 | return field.ty.abiAlignment(mod); |
| 1048 | } | 1066 | } |
| 1049 | }, | 1067 | }, |
| 1050 | .Extern => return alignmentExtern(field, target), | 1068 | .Extern => return alignmentExtern(field, mod), |
| 1051 | } | 1069 | } |
| 1052 | } | 1070 | } |
| 1053 | 1071 | ||
| 1054 | pub fn alignmentExtern(field: Field, target: Target) u32 { | 1072 | pub fn alignmentExtern(field: Field, mod: *const Module) u32 { |
| 1055 | // This logic is duplicated in Type.abiAlignmentAdvanced. | 1073 | // This logic is duplicated in Type.abiAlignmentAdvanced. |
| 1056 | const ty_abi_align = field.ty.abiAlignment(target); | 1074 | const ty_abi_align = field.ty.abiAlignment(mod); |
| 1057 | 1075 | ||
| 1058 | if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) { | 1076 | if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) { |
| 1059 | // The C ABI requires 128 bit integer fields of structs | 1077 | // The C ABI requires 128 bit integer fields of structs |
| 1060 | // to be 16-bytes aligned. | 1078 | // to be 16-bytes aligned. |
| 1061 | return @max(ty_abi_align, 16); | 1079 | return @max(ty_abi_align, 16); |
| ... | @@ -1132,7 +1150,7 @@ pub const Struct = struct { | ... | @@ -1132,7 +1150,7 @@ pub const Struct = struct { |
| 1132 | }; | 1150 | }; |
| 1133 | } | 1151 | } |
| 1134 | 1152 | ||
| 1135 | pub fn packedFieldBitOffset(s: Struct, target: Target, index: usize) u16 { | 1153 | pub fn packedFieldBitOffset(s: Struct, mod: *const Module, index: usize) u16 { |
| 1136 | assert(s.layout == .Packed); | 1154 | assert(s.layout == .Packed); |
| 1137 | assert(s.haveLayout()); | 1155 | assert(s.haveLayout()); |
| 1138 | var bit_sum: u64 = 0; | 1156 | var bit_sum: u64 = 0; |
| ... | @@ -1140,12 +1158,13 @@ pub const Struct = struct { | ... | @@ -1140,12 +1158,13 @@ pub const Struct = struct { |
| 1140 | if (i == index) { | 1158 | if (i == index) { |
| 1141 | return @intCast(u16, bit_sum); | 1159 | return @intCast(u16, bit_sum); |
| 1142 | } | 1160 | } |
| 1143 | bit_sum += field.ty.bitSize(target); | 1161 | bit_sum += field.ty.bitSize(mod); |
| 1144 | } | 1162 | } |
| 1145 | unreachable; // index out of bounds | 1163 | unreachable; // index out of bounds |
| 1146 | } | 1164 | } |
| 1147 | 1165 | ||
| 1148 | pub const RuntimeFieldIterator = struct { | 1166 | pub const RuntimeFieldIterator = struct { |
| 1167 | module: *const Module, | ||
| 1149 | struct_obj: *const Struct, | 1168 | struct_obj: *const Struct, |
| 1150 | index: u32 = 0, | 1169 | index: u32 = 0, |
| 1151 | 1170 | ||
| ... | @@ -1155,6 +1174,7 @@ pub const Struct = struct { | ... | @@ -1155,6 +1174,7 @@ pub const Struct = struct { |
| 1155 | }; | 1174 | }; |
| 1156 | 1175 | ||
| 1157 | pub fn next(it: *RuntimeFieldIterator) ?FieldAndIndex { | 1176 | pub fn next(it: *RuntimeFieldIterator) ?FieldAndIndex { |
| 1177 | const mod = it.module; | ||
| 1158 | while (true) { | 1178 | while (true) { |
| 1159 | var i = it.index; | 1179 | var i = it.index; |
| 1160 | it.index += 1; | 1180 | it.index += 1; |
| ... | @@ -1167,15 +1187,18 @@ pub const Struct = struct { | ... | @@ -1167,15 +1187,18 @@ pub const Struct = struct { |
| 1167 | } | 1187 | } |
| 1168 | const field = it.struct_obj.fields.values()[i]; | 1188 | const field = it.struct_obj.fields.values()[i]; |
| 1169 | 1189 | ||
| 1170 | if (!field.is_comptime and field.ty.hasRuntimeBits()) { | 1190 | if (!field.is_comptime and field.ty.hasRuntimeBits(mod)) { |
| 1171 | return FieldAndIndex{ .index = i, .field = field }; | 1191 | return FieldAndIndex{ .index = i, .field = field }; |
| 1172 | } | 1192 | } |
| 1173 | } | 1193 | } |
| 1174 | } | 1194 | } |
| 1175 | }; | 1195 | }; |
| 1176 | 1196 | ||
| 1177 | pub fn runtimeFieldIterator(s: *const Struct) RuntimeFieldIterator { | 1197 | pub fn runtimeFieldIterator(s: *const Struct, module: *const Module) RuntimeFieldIterator { |
| 1178 | return .{ .struct_obj = s }; | 1198 | return .{ |
| 1199 | .struct_obj = s, | ||
| 1200 | .module = module, | ||
| 1201 | }; | ||
| 1179 | } | 1202 | } |
| 1180 | }; | 1203 | }; |
| 1181 | 1204 | ||
| ... | @@ -1323,9 +1346,9 @@ pub const Union = struct { | ... | @@ -1323,9 +1346,9 @@ pub const Union = struct { |
| 1323 | /// Returns the field alignment, assuming the union is not packed. | 1346 | /// Returns the field alignment, assuming the union is not packed. |
| 1324 | /// Keep implementation in sync with `Sema.unionFieldAlignment`. | 1347 | /// Keep implementation in sync with `Sema.unionFieldAlignment`. |
| 1325 | /// Prefer to call that function instead of this one during Sema. | 1348 | /// Prefer to call that function instead of this one during Sema. |
| 1326 | pub fn normalAlignment(field: Field, target: Target) u32 { | 1349 | pub fn normalAlignment(field: Field, mod: *const Module) u32 { |
| 1327 | if (field.abi_align == 0) { | 1350 | if (field.abi_align == 0) { |
| 1328 | return field.ty.abiAlignment(target); | 1351 | return field.ty.abiAlignment(mod); |
| 1329 | } else { | 1352 | } else { |
| 1330 | return field.abi_align; | 1353 | return field.abi_align; |
| 1331 | } | 1354 | } |
| ... | @@ -1383,22 +1406,22 @@ pub const Union = struct { | ... | @@ -1383,22 +1406,22 @@ pub const Union = struct { |
| 1383 | }; | 1406 | }; |
| 1384 | } | 1407 | } |
| 1385 | 1408 | ||
| 1386 | pub fn hasAllZeroBitFieldTypes(u: Union) bool { | 1409 | pub fn hasAllZeroBitFieldTypes(u: Union, mod: *const Module) bool { |
| 1387 | assert(u.haveFieldTypes()); | 1410 | assert(u.haveFieldTypes()); |
| 1388 | for (u.fields.values()) |field| { | 1411 | for (u.fields.values()) |field| { |
| 1389 | if (field.ty.hasRuntimeBits()) return false; | 1412 | if (field.ty.hasRuntimeBits(mod)) return false; |
| 1390 | } | 1413 | } |
| 1391 | return true; | 1414 | return true; |
| 1392 | } | 1415 | } |
| 1393 | 1416 | ||
| 1394 | pub fn mostAlignedField(u: Union, target: Target) u32 { | 1417 | pub fn mostAlignedField(u: Union, mod: *const Module) u32 { |
| 1395 | assert(u.haveFieldTypes()); | 1418 | assert(u.haveFieldTypes()); |
| 1396 | var most_alignment: u32 = 0; | 1419 | var most_alignment: u32 = 0; |
| 1397 | var most_index: usize = undefined; | 1420 | var most_index: usize = undefined; |
| 1398 | for (u.fields.values(), 0..) |field, i| { | 1421 | for (u.fields.values(), 0..) |field, i| { |
| 1399 | if (!field.ty.hasRuntimeBits()) continue; | 1422 | if (!field.ty.hasRuntimeBits(mod)) continue; |
| 1400 | 1423 | ||
| 1401 | const field_align = field.normalAlignment(target); | 1424 | const field_align = field.normalAlignment(mod); |
| 1402 | if (field_align > most_alignment) { | 1425 | if (field_align > most_alignment) { |
| 1403 | most_alignment = field_align; | 1426 | most_alignment = field_align; |
| 1404 | most_index = i; | 1427 | most_index = i; |
| ... | @@ -1408,20 +1431,20 @@ pub const Union = struct { | ... | @@ -1408,20 +1431,20 @@ pub const Union = struct { |
| 1408 | } | 1431 | } |
| 1409 | 1432 | ||
| 1410 | /// Returns 0 if the union is represented with 0 bits at runtime. | 1433 | /// Returns 0 if the union is represented with 0 bits at runtime. |
| 1411 | pub fn abiAlignment(u: Union, target: Target, have_tag: bool) u32 { | 1434 | pub fn abiAlignment(u: Union, mod: *const Module, have_tag: bool) u32 { |
| 1412 | var max_align: u32 = 0; | 1435 | var max_align: u32 = 0; |
| 1413 | if (have_tag) max_align = u.tag_ty.abiAlignment(target); | 1436 | if (have_tag) max_align = u.tag_ty.abiAlignment(mod); |
| 1414 | for (u.fields.values()) |field| { | 1437 | for (u.fields.values()) |field| { |
| 1415 | if (!field.ty.hasRuntimeBits()) continue; | 1438 | if (!field.ty.hasRuntimeBits(mod)) continue; |
| 1416 | 1439 | ||
| 1417 | const field_align = field.normalAlignment(target); | 1440 | const field_align = field.normalAlignment(mod); |
| 1418 | max_align = @max(max_align, field_align); | 1441 | max_align = @max(max_align, field_align); |
| 1419 | } | 1442 | } |
| 1420 | return max_align; | 1443 | return max_align; |
| 1421 | } | 1444 | } |
| 1422 | 1445 | ||
| 1423 | pub fn abiSize(u: Union, target: Target, have_tag: bool) u64 { | 1446 | pub fn abiSize(u: Union, mod: *const Module, have_tag: bool) u64 { |
| 1424 | return u.getLayout(target, have_tag).abi_size; | 1447 | return u.getLayout(mod, have_tag).abi_size; |
| 1425 | } | 1448 | } |
| 1426 | 1449 | ||
| 1427 | pub const Layout = struct { | 1450 | pub const Layout = struct { |
| ... | @@ -1451,7 +1474,7 @@ pub const Union = struct { | ... | @@ -1451,7 +1474,7 @@ pub const Union = struct { |
| 1451 | }; | 1474 | }; |
| 1452 | } | 1475 | } |
| 1453 | 1476 | ||
| 1454 | pub fn getLayout(u: Union, target: Target, have_tag: bool) Layout { | 1477 | pub fn getLayout(u: Union, mod: *const Module, have_tag: bool) Layout { |
| 1455 | assert(u.haveLayout()); | 1478 | assert(u.haveLayout()); |
| 1456 | var most_aligned_field: u32 = undefined; | 1479 | var most_aligned_field: u32 = undefined; |
| 1457 | var most_aligned_field_size: u64 = undefined; | 1480 | var most_aligned_field_size: u64 = undefined; |
| ... | @@ -1460,16 +1483,16 @@ pub const Union = struct { | ... | @@ -1460,16 +1483,16 @@ pub const Union = struct { |
| 1460 | var payload_align: u32 = 0; | 1483 | var payload_align: u32 = 0; |
| 1461 | const fields = u.fields.values(); | 1484 | const fields = u.fields.values(); |
| 1462 | for (fields, 0..) |field, i| { | 1485 | for (fields, 0..) |field, i| { |
| 1463 | if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue; | 1486 | if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1464 | 1487 | ||
| 1465 | const field_align = a: { | 1488 | const field_align = a: { |
| 1466 | if (field.abi_align == 0) { | 1489 | if (field.abi_align == 0) { |
| 1467 | break :a field.ty.abiAlignment(target); | 1490 | break :a field.ty.abiAlignment(mod); |
| 1468 | } else { | 1491 | } else { |
| 1469 | break :a field.abi_align; | 1492 | break :a field.abi_align; |
| 1470 | } | 1493 | } |
| 1471 | }; | 1494 | }; |
| 1472 | const field_size = field.ty.abiSize(target); | 1495 | const field_size = field.ty.abiSize(mod); |
| 1473 | if (field_size > payload_size) { | 1496 | if (field_size > payload_size) { |
| 1474 | payload_size = field_size; | 1497 | payload_size = field_size; |
| 1475 | biggest_field = @intCast(u32, i); | 1498 | biggest_field = @intCast(u32, i); |
| ... | @@ -1481,7 +1504,7 @@ pub const Union = struct { | ... | @@ -1481,7 +1504,7 @@ pub const Union = struct { |
| 1481 | } | 1504 | } |
| 1482 | } | 1505 | } |
| 1483 | payload_align = @max(payload_align, 1); | 1506 | payload_align = @max(payload_align, 1); |
| 1484 | if (!have_tag or !u.tag_ty.hasRuntimeBits()) { | 1507 | if (!have_tag or !u.tag_ty.hasRuntimeBits(mod)) { |
| 1485 | return .{ | 1508 | return .{ |
| 1486 | .abi_size = std.mem.alignForwardGeneric(u64, payload_size, payload_align), | 1509 | .abi_size = std.mem.alignForwardGeneric(u64, payload_size, payload_align), |
| 1487 | .abi_align = payload_align, | 1510 | .abi_align = payload_align, |
| ... | @@ -1497,8 +1520,8 @@ pub const Union = struct { | ... | @@ -1497,8 +1520,8 @@ pub const Union = struct { |
| 1497 | } | 1520 | } |
| 1498 | // Put the tag before or after the payload depending on which one's | 1521 | // Put the tag before or after the payload depending on which one's |
| 1499 | // alignment is greater. | 1522 | // alignment is greater. |
| 1500 | const tag_size = u.tag_ty.abiSize(target); | 1523 | const tag_size = u.tag_ty.abiSize(mod); |
| 1501 | const tag_align = @max(1, u.tag_ty.abiAlignment(target)); | 1524 | const tag_align = @max(1, u.tag_ty.abiAlignment(mod)); |
| 1502 | var size: u64 = 0; | 1525 | var size: u64 = 0; |
| 1503 | var padding: u32 = undefined; | 1526 | var padding: u32 = undefined; |
| 1504 | if (tag_align >= payload_align) { | 1527 | if (tag_align >= payload_align) { |
| ... | @@ -2281,7 +2304,7 @@ pub const ErrorMsg = struct { | ... | @@ -2281,7 +2304,7 @@ pub const ErrorMsg = struct { |
| 2281 | ) !*ErrorMsg { | 2304 | ) !*ErrorMsg { |
| 2282 | const err_msg = try gpa.create(ErrorMsg); | 2305 | const err_msg = try gpa.create(ErrorMsg); |
| 2283 | errdefer gpa.destroy(err_msg); | 2306 | errdefer gpa.destroy(err_msg); |
| 2284 | err_msg.* = try init(gpa, src_loc, format, args); | 2307 | err_msg.* = try ErrorMsg.init(gpa, src_loc, format, args); |
| 2285 | return err_msg; | 2308 | return err_msg; |
| 2286 | } | 2309 | } |
| 2287 | 2310 | ||
| ... | @@ -3391,6 +3414,12 @@ pub const CompileError = error{ | ... | @@ -3391,6 +3414,12 @@ pub const CompileError = error{ |
| 3391 | ComptimeBreak, | 3414 | ComptimeBreak, |
| 3392 | }; | 3415 | }; |
| 3393 | 3416 | ||
| 3417 | pub fn init(mod: *Module) !void { | ||
| 3418 | const gpa = mod.gpa; | ||
| 3419 | try mod.error_name_list.append(gpa, "(no error)"); | ||
| 3420 | try mod.intern_pool.init(gpa); | ||
| 3421 | } | ||
| 3422 | |||
| 3394 | pub fn deinit(mod: *Module) void { | 3423 | pub fn deinit(mod: *Module) void { |
| 3395 | const gpa = mod.gpa; | 3424 | const gpa = mod.gpa; |
| 3396 | 3425 | ||
| ... | @@ -3518,6 +3547,8 @@ pub fn deinit(mod: *Module) void { | ... | @@ -3518,6 +3547,8 @@ pub fn deinit(mod: *Module) void { |
| 3518 | 3547 | ||
| 3519 | mod.string_literal_table.deinit(gpa); | 3548 | mod.string_literal_table.deinit(gpa); |
| 3520 | mod.string_literal_bytes.deinit(gpa); | 3549 | mod.string_literal_bytes.deinit(gpa); |
| 3550 | |||
| 3551 | mod.intern_pool.deinit(gpa); | ||
| 3521 | } | 3552 | } |
| 3522 | 3553 | ||
| 3523 | pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { | 3554 | pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { |
| ... | @@ -4277,7 +4308,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { | ... | @@ -4277,7 +4308,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 4277 | // Update all dependents which have at least this level of dependency. | 4308 | // Update all dependents which have at least this level of dependency. |
| 4278 | // If our type remained the same and we're a function, only update | 4309 | // If our type remained the same and we're a function, only update |
| 4279 | // decls which depend on our body; otherwise, update all dependents. | 4310 | // decls which depend on our body; otherwise, update all dependents. |
| 4280 | const update_level: Decl.DepType = if (!type_changed and decl.ty.zigTypeTag() == .Fn) .function_body else .normal; | 4311 | const update_level: Decl.DepType = if (!type_changed and decl.ty.zigTypeTag(mod) == .Fn) .function_body else .normal; |
| 4281 | 4312 | ||
| 4282 | for (decl.dependants.keys(), decl.dependants.values()) |dep_index, dep_type| { | 4313 | for (decl.dependants.keys(), decl.dependants.values()) |dep_index, dep_type| { |
| 4283 | if (@enumToInt(dep_type) < @enumToInt(update_level)) continue; | 4314 | if (@enumToInt(dep_type) < @enumToInt(update_level)) continue; |
| ... | @@ -4748,8 +4779,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4748,8 +4779,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4748 | decl_tv.ty.fmt(mod), | 4779 | decl_tv.ty.fmt(mod), |
| 4749 | }); | 4780 | }); |
| 4750 | } | 4781 | } |
| 4751 | var buffer: Value.ToTypeBuffer = undefined; | 4782 | const ty = try decl_tv.val.toType().copy(decl_arena_allocator); |
| 4752 | const ty = try decl_tv.val.toType(&buffer).copy(decl_arena_allocator); | ||
| 4753 | if (ty.getNamespace() == null) { | 4783 | if (ty.getNamespace() == null) { |
| 4754 | return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)}); | 4784 | return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)}); |
| 4755 | } | 4785 | } |
| ... | @@ -4775,7 +4805,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4775,7 +4805,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4775 | var type_changed = true; | 4805 | var type_changed = true; |
| 4776 | 4806 | ||
| 4777 | if (decl.has_tv) { | 4807 | if (decl.has_tv) { |
| 4778 | prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(); | 4808 | prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod); |
| 4779 | type_changed = !decl.ty.eql(decl_tv.ty, mod); | 4809 | type_changed = !decl.ty.eql(decl_tv.ty, mod); |
| 4780 | if (decl.getFunction()) |prev_func| { | 4810 | if (decl.getFunction()) |prev_func| { |
| 4781 | prev_is_inline = prev_func.state == .inline_only; | 4811 | prev_is_inline = prev_func.state == .inline_only; |
| ... | @@ -5510,7 +5540,7 @@ pub fn clearDecl( | ... | @@ -5510,7 +5540,7 @@ pub fn clearDecl( |
| 5510 | try mod.deleteDeclExports(decl_index); | 5540 | try mod.deleteDeclExports(decl_index); |
| 5511 | 5541 | ||
| 5512 | if (decl.has_tv) { | 5542 | if (decl.has_tv) { |
| 5513 | if (decl.ty.isFnOrHasRuntimeBits()) { | 5543 | if (decl.ty.isFnOrHasRuntimeBits(mod)) { |
| 5514 | mod.comp.bin_file.freeDecl(decl_index); | 5544 | mod.comp.bin_file.freeDecl(decl_index); |
| 5515 | } | 5545 | } |
| 5516 | if (decl.getInnerNamespace()) |namespace| { | 5546 | if (decl.getInnerNamespace()) |namespace| { |
| ... | @@ -5699,7 +5729,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air { | ... | @@ -5699,7 +5729,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air { |
| 5699 | 5729 | ||
| 5700 | const arg_val = if (arg_tv.val.tag() != .generic_poison) | 5730 | const arg_val = if (arg_tv.val.tag() != .generic_poison) |
| 5701 | arg_tv.val | 5731 | arg_tv.val |
| 5702 | else if (arg_tv.ty.onePossibleValue()) |opv| | 5732 | else if (arg_tv.ty.onePossibleValue(mod)) |opv| |
| 5703 | opv | 5733 | opv |
| 5704 | else | 5734 | else |
| 5705 | break :t arg_tv.ty; | 5735 | break :t arg_tv.ty; |
| ... | @@ -5773,7 +5803,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air { | ... | @@ -5773,7 +5803,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air { |
| 5773 | // If we don't get an error return trace from a caller, create our own. | 5803 | // If we don't get an error return trace from a caller, create our own. |
| 5774 | if (func.calls_or_awaits_errorable_fn and | 5804 | if (func.calls_or_awaits_errorable_fn and |
| 5775 | mod.comp.bin_file.options.error_return_tracing and | 5805 | mod.comp.bin_file.options.error_return_tracing and |
| 5776 | !sema.fn_ret_ty.isError()) | 5806 | !sema.fn_ret_ty.isError(mod)) |
| 5777 | { | 5807 | { |
| 5778 | sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) { | 5808 | sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) { |
| 5779 | // TODO make these unreachable instead of @panic | 5809 | // TODO make these unreachable instead of @panic |
| ... | @@ -5995,25 +6025,11 @@ pub fn initNewAnonDecl( | ... | @@ -5995,25 +6025,11 @@ pub fn initNewAnonDecl( |
| 5995 | // if the Decl is referenced by an instruction or another constant. Otherwise, | 6025 | // if the Decl is referenced by an instruction or another constant. Otherwise, |
| 5996 | // the Decl will be garbage collected by the `codegen_decl` task instead of sent | 6026 | // the Decl will be garbage collected by the `codegen_decl` task instead of sent |
| 5997 | // to the linker. | 6027 | // to the linker. |
| 5998 | if (typed_value.ty.isFnOrHasRuntimeBits()) { | 6028 | if (typed_value.ty.isFnOrHasRuntimeBits(mod)) { |
| 5999 | try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl_index }); | 6029 | try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl_index }); |
| 6000 | } | 6030 | } |
| 6001 | } | 6031 | } |
| 6002 | 6032 | ||
| 6003 | pub fn makeIntType(arena: Allocator, signedness: std.builtin.Signedness, bits: u16) !Type { | ||
| 6004 | const int_payload = try arena.create(Type.Payload.Bits); | ||
| 6005 | int_payload.* = .{ | ||
| 6006 | .base = .{ | ||
| 6007 | .tag = switch (signedness) { | ||
| 6008 | .signed => .int_signed, | ||
| 6009 | .unsigned => .int_unsigned, | ||
| 6010 | }, | ||
| 6011 | }, | ||
| 6012 | .data = bits, | ||
| 6013 | }; | ||
| 6014 | return Type.initPayload(&int_payload.base); | ||
| 6015 | } | ||
| 6016 | |||
| 6017 | pub fn errNoteNonLazy( | 6033 | pub fn errNoteNonLazy( |
| 6018 | mod: *Module, | 6034 | mod: *Module, |
| 6019 | src_loc: SrcLoc, | 6035 | src_loc: SrcLoc, |
| ... | @@ -6779,3 +6795,204 @@ pub fn backendSupportsFeature(mod: Module, feature: Feature) bool { | ... | @@ -6779,3 +6795,204 @@ pub fn backendSupportsFeature(mod: Module, feature: Feature) bool { |
| 6779 | .field_reordering => mod.comp.bin_file.options.use_llvm, | 6795 | .field_reordering => mod.comp.bin_file.options.use_llvm, |
| 6780 | }; | 6796 | }; |
| 6781 | } | 6797 | } |
| 6798 | |||
| 6799 | /// Shortcut for calling `intern_pool.get`. | ||
| 6800 | pub fn intern(mod: *Module, key: InternPool.Key) Allocator.Error!InternPool.Index { | ||
| 6801 | return mod.intern_pool.get(mod.gpa, key); | ||
| 6802 | } | ||
| 6803 | |||
| 6804 | pub fn intType(mod: *Module, signedness: std.builtin.Signedness, bits: u16) Allocator.Error!Type { | ||
| 6805 | const i = try intern(mod, .{ .int_type = .{ | ||
| 6806 | .signedness = signedness, | ||
| 6807 | .bits = bits, | ||
| 6808 | } }); | ||
| 6809 | return i.toType(); | ||
| 6810 | } | ||
| 6811 | |||
| 6812 | pub fn smallestUnsignedInt(mod: *Module, max: u64) Allocator.Error!Type { | ||
| 6813 | return intType(mod, .unsigned, Type.smallestUnsignedBits(max)); | ||
| 6814 | } | ||
| 6815 | |||
| 6816 | /// Returns the smallest possible integer type containing both `min` and | ||
| 6817 | /// `max`. Asserts that neither value is undef. | ||
| 6818 | /// TODO: if #3806 is implemented, this becomes trivial | ||
| 6819 | pub fn intFittingRange(mod: *Module, min: Value, max: Value) !Type { | ||
| 6820 | assert(!min.isUndef()); | ||
| 6821 | assert(!max.isUndef()); | ||
| 6822 | |||
| 6823 | if (std.debug.runtime_safety) { | ||
| 6824 | assert(Value.order(min, max, mod).compare(.lte)); | ||
| 6825 | } | ||
| 6826 | |||
| 6827 | const sign = min.orderAgainstZero(mod) == .lt; | ||
| 6828 | |||
| 6829 | const min_val_bits = intBitsForValue(mod, min, sign); | ||
| 6830 | const max_val_bits = intBitsForValue(mod, max, sign); | ||
| 6831 | |||
| 6832 | return mod.intType( | ||
| 6833 | if (sign) .signed else .unsigned, | ||
| 6834 | @max(min_val_bits, max_val_bits), | ||
| 6835 | ); | ||
| 6836 | } | ||
| 6837 | |||
| 6838 | /// Given a value representing an integer, returns the number of bits necessary to represent | ||
| 6839 | /// this value in an integer. If `sign` is true, returns the number of bits necessary in a | ||
| 6840 | /// twos-complement integer; otherwise in an unsigned integer. | ||
| 6841 | /// Asserts that `val` is not undef. If `val` is negative, asserts that `sign` is true. | ||
| 6842 | pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 { | ||
| 6843 | assert(!val.isUndef()); | ||
| 6844 | switch (val.tag()) { | ||
| 6845 | .int_big_positive => { | ||
| 6846 | const limbs = val.castTag(.int_big_positive).?.data; | ||
| 6847 | const big: std.math.big.int.Const = .{ .limbs = limbs, .positive = true }; | ||
| 6848 | return @intCast(u16, big.bitCountAbs() + @boolToInt(sign)); | ||
| 6849 | }, | ||
| 6850 | .int_big_negative => { | ||
| 6851 | const limbs = val.castTag(.int_big_negative).?.data; | ||
| 6852 | // Zero is still a possibility, in which case unsigned is fine | ||
| 6853 | for (limbs) |limb| { | ||
| 6854 | if (limb != 0) break; | ||
| 6855 | } else return 0; // val == 0 | ||
| 6856 | assert(sign); | ||
| 6857 | const big: std.math.big.int.Const = .{ .limbs = limbs, .positive = false }; | ||
| 6858 | return @intCast(u16, big.bitCountTwosComp()); | ||
| 6859 | }, | ||
| 6860 | .int_i64 => { | ||
| 6861 | const x = val.castTag(.int_i64).?.data; | ||
| 6862 | if (x >= 0) return Type.smallestUnsignedBits(@intCast(u64, x)); | ||
| 6863 | assert(sign); | ||
| 6864 | return Type.smallestUnsignedBits(@intCast(u64, -x - 1)) + 1; | ||
| 6865 | }, | ||
| 6866 | else => { | ||
| 6867 | const x = val.toUnsignedInt(mod); | ||
| 6868 | return Type.smallestUnsignedBits(x) + @boolToInt(sign); | ||
| 6869 | }, | ||
| 6870 | } | ||
| 6871 | } | ||
| 6872 | |||
| 6873 | pub const AtomicPtrAlignmentError = error{ | ||
| 6874 | FloatTooBig, | ||
| 6875 | IntTooBig, | ||
| 6876 | BadType, | ||
| 6877 | }; | ||
| 6878 | |||
| 6879 | pub const AtomicPtrAlignmentDiagnostics = struct { | ||
| 6880 | bits: u16 = undefined, | ||
| 6881 | max_bits: u16 = undefined, | ||
| 6882 | }; | ||
| 6883 | |||
| 6884 | /// If ABI alignment of `ty` is OK for atomic operations, returns 0. | ||
| 6885 | /// Otherwise returns the alignment required on a pointer for the target | ||
| 6886 | /// to perform atomic operations. | ||
| 6887 | // TODO this function does not take into account CPU features, which can affect | ||
| 6888 | // this value. Audit this! | ||
| 6889 | pub fn atomicPtrAlignment( | ||
| 6890 | mod: *const Module, | ||
| 6891 | ty: Type, | ||
| 6892 | diags: *AtomicPtrAlignmentDiagnostics, | ||
| 6893 | ) AtomicPtrAlignmentError!u32 { | ||
| 6894 | const target = mod.getTarget(); | ||
| 6895 | const max_atomic_bits: u16 = switch (target.cpu.arch) { | ||
| 6896 | .avr, | ||
| 6897 | .msp430, | ||
| 6898 | .spu_2, | ||
| 6899 | => 16, | ||
| 6900 | |||
| 6901 | .arc, | ||
| 6902 | .arm, | ||
| 6903 | .armeb, | ||
| 6904 | .hexagon, | ||
| 6905 | .m68k, | ||
| 6906 | .le32, | ||
| 6907 | .mips, | ||
| 6908 | .mipsel, | ||
| 6909 | .nvptx, | ||
| 6910 | .powerpc, | ||
| 6911 | .powerpcle, | ||
| 6912 | .r600, | ||
| 6913 | .riscv32, | ||
| 6914 | .sparc, | ||
| 6915 | .sparcel, | ||
| 6916 | .tce, | ||
| 6917 | .tcele, | ||
| 6918 | .thumb, | ||
| 6919 | .thumbeb, | ||
| 6920 | .x86, | ||
| 6921 | .xcore, | ||
| 6922 | .amdil, | ||
| 6923 | .hsail, | ||
| 6924 | .spir, | ||
| 6925 | .kalimba, | ||
| 6926 | .lanai, | ||
| 6927 | .shave, | ||
| 6928 | .wasm32, | ||
| 6929 | .renderscript32, | ||
| 6930 | .csky, | ||
| 6931 | .spirv32, | ||
| 6932 | .dxil, | ||
| 6933 | .loongarch32, | ||
| 6934 | .xtensa, | ||
| 6935 | => 32, | ||
| 6936 | |||
| 6937 | .amdgcn, | ||
| 6938 | .bpfel, | ||
| 6939 | .bpfeb, | ||
| 6940 | .le64, | ||
| 6941 | .mips64, | ||
| 6942 | .mips64el, | ||
| 6943 | .nvptx64, | ||
| 6944 | .powerpc64, | ||
| 6945 | .powerpc64le, | ||
| 6946 | .riscv64, | ||
| 6947 | .sparc64, | ||
| 6948 | .s390x, | ||
| 6949 | .amdil64, | ||
| 6950 | .hsail64, | ||
| 6951 | .spir64, | ||
| 6952 | .wasm64, | ||
| 6953 | .renderscript64, | ||
| 6954 | .ve, | ||
| 6955 | .spirv64, | ||
| 6956 | .loongarch64, | ||
| 6957 | => 64, | ||
| 6958 | |||
| 6959 | .aarch64, | ||
| 6960 | .aarch64_be, | ||
| 6961 | .aarch64_32, | ||
| 6962 | => 128, | ||
| 6963 | |||
| 6964 | .x86_64 => if (std.Target.x86.featureSetHas(target.cpu.features, .cx16)) 128 else 64, | ||
| 6965 | }; | ||
| 6966 | |||
| 6967 | const int_ty = switch (ty.zigTypeTag(mod)) { | ||
| 6968 | .Int => ty, | ||
| 6969 | .Enum => ty.intTagType(), | ||
| 6970 | .Float => { | ||
| 6971 | const bit_count = ty.floatBits(target); | ||
| 6972 | if (bit_count > max_atomic_bits) { | ||
| 6973 | diags.* = .{ | ||
| 6974 | .bits = bit_count, | ||
| 6975 | .max_bits = max_atomic_bits, | ||
| 6976 | }; | ||
| 6977 | return error.FloatTooBig; | ||
| 6978 | } | ||
| 6979 | return 0; | ||
| 6980 | }, | ||
| 6981 | .Bool => return 0, | ||
| 6982 | else => { | ||
| 6983 | if (ty.isPtrAtRuntime(mod)) return 0; | ||
| 6984 | return error.BadType; | ||
| 6985 | }, | ||
| 6986 | }; | ||
| 6987 | |||
| 6988 | const bit_count = int_ty.intInfo(mod).bits; | ||
| 6989 | if (bit_count > max_atomic_bits) { | ||
| 6990 | diags.* = .{ | ||
| 6991 | .bits = bit_count, | ||
| 6992 | .max_bits = max_atomic_bits, | ||
| 6993 | }; | ||
| 6994 | return error.IntTooBig; | ||
| 6995 | } | ||
| 6996 | |||
| 6997 | return 0; | ||
| 6998 | } |
src/RangeSet.zig+6-7| ... | @@ -60,13 +60,14 @@ pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool { | ... | @@ -60,13 +60,14 @@ pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool { |
| 60 | if (self.ranges.items.len == 0) | 60 | if (self.ranges.items.len == 0) |
| 61 | return false; | 61 | return false; |
| 62 | 62 | ||
| 63 | const mod = self.module; | ||
| 63 | std.mem.sort(Range, self.ranges.items, LessThanContext{ | 64 | std.mem.sort(Range, self.ranges.items, LessThanContext{ |
| 64 | .ty = ty, | 65 | .ty = ty, |
| 65 | .module = self.module, | 66 | .module = mod, |
| 66 | }, lessThan); | 67 | }, lessThan); |
| 67 | 68 | ||
| 68 | if (!self.ranges.items[0].first.eql(first, ty, self.module) or | 69 | if (!self.ranges.items[0].first.eql(first, ty, mod) or |
| 69 | !self.ranges.items[self.ranges.items.len - 1].last.eql(last, ty, self.module)) | 70 | !self.ranges.items[self.ranges.items.len - 1].last.eql(last, ty, mod)) |
| 70 | { | 71 | { |
| 71 | return false; | 72 | return false; |
| 72 | } | 73 | } |
| ... | @@ -76,18 +77,16 @@ pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool { | ... | @@ -76,18 +77,16 @@ pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool { |
| 76 | var counter = try std.math.big.int.Managed.init(self.ranges.allocator); | 77 | var counter = try std.math.big.int.Managed.init(self.ranges.allocator); |
| 77 | defer counter.deinit(); | 78 | defer counter.deinit(); |
| 78 | 79 | ||
| 79 | const target = self.module.getTarget(); | ||
| 80 | |||
| 81 | // look for gaps | 80 | // look for gaps |
| 82 | for (self.ranges.items[1..], 0..) |cur, i| { | 81 | for (self.ranges.items[1..], 0..) |cur, i| { |
| 83 | // i starts counting from the second item. | 82 | // i starts counting from the second item. |
| 84 | const prev = self.ranges.items[i]; | 83 | const prev = self.ranges.items[i]; |
| 85 | 84 | ||
| 86 | // prev.last + 1 == cur.first | 85 | // prev.last + 1 == cur.first |
| 87 | try counter.copy(prev.last.toBigInt(&space, target)); | 86 | try counter.copy(prev.last.toBigInt(&space, mod)); |
| 88 | try counter.addScalar(&counter, 1); | 87 | try counter.addScalar(&counter, 1); |
| 89 | 88 | ||
| 90 | const cur_start_int = cur.first.toBigInt(&space, target); | 89 | const cur_start_int = cur.first.toBigInt(&space, mod); |
| 91 | if (!cur_start_int.eq(counter.toConst())) { | 90 | if (!cur_start_int.eq(counter.toConst())) { |
| 92 | return false; | 91 | return false; |
| 93 | } | 92 | } |
src/Sema.zig+1290-1093| ... | @@ -114,6 +114,7 @@ const Package = @import("Package.zig"); | ... | @@ -114,6 +114,7 @@ const Package = @import("Package.zig"); |
| 114 | const crash_report = @import("crash_report.zig"); | 114 | const crash_report = @import("crash_report.zig"); |
| 115 | const build_options = @import("build_options"); | 115 | const build_options = @import("build_options"); |
| 116 | const Compilation = @import("Compilation.zig"); | 116 | const Compilation = @import("Compilation.zig"); |
| 117 | const InternPool = @import("InternPool.zig"); | ||
| 117 | 118 | ||
| 118 | pub const default_branch_quota = 1000; | 119 | pub const default_branch_quota = 1000; |
| 119 | pub const default_reference_trace_len = 2; | 120 | pub const default_reference_trace_len = 2; |
| ... | @@ -1614,6 +1615,7 @@ fn analyzeBodyInner( | ... | @@ -1614,6 +1615,7 @@ fn analyzeBodyInner( |
| 1614 | }, | 1615 | }, |
| 1615 | .@"try" => blk: { | 1616 | .@"try" => blk: { |
| 1616 | if (!block.is_comptime) break :blk try sema.zirTry(block, inst); | 1617 | if (!block.is_comptime) break :blk try sema.zirTry(block, inst); |
| 1618 | const mod = sema.mod; | ||
| 1617 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 1619 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 1618 | const src = inst_data.src(); | 1620 | const src = inst_data.src(); |
| 1619 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | 1621 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| ... | @@ -1621,18 +1623,18 @@ fn analyzeBodyInner( | ... | @@ -1621,18 +1623,18 @@ fn analyzeBodyInner( |
| 1621 | const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len]; | 1623 | const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len]; |
| 1622 | const err_union = try sema.resolveInst(extra.data.operand); | 1624 | const err_union = try sema.resolveInst(extra.data.operand); |
| 1623 | const err_union_ty = sema.typeOf(err_union); | 1625 | const err_union_ty = sema.typeOf(err_union); |
| 1624 | if (err_union_ty.zigTypeTag() != .ErrorUnion) { | 1626 | if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) { |
| 1625 | return sema.fail(block, operand_src, "expected error union type, found '{}'", .{ | 1627 | return sema.fail(block, operand_src, "expected error union type, found '{}'", .{ |
| 1626 | err_union_ty.fmt(sema.mod), | 1628 | err_union_ty.fmt(sema.mod), |
| 1627 | }); | 1629 | }); |
| 1628 | } | 1630 | } |
| 1629 | const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union); | 1631 | const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union); |
| 1630 | assert(is_non_err != .none); | 1632 | assert(is_non_err != .none); |
| 1631 | const is_non_err_tv = sema.resolveInstConst(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known") catch |err| { | 1633 | const is_non_err_val = sema.resolveConstValue(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known") catch |err| { |
| 1632 | if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err); | 1634 | if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err); |
| 1633 | return err; | 1635 | return err; |
| 1634 | }; | 1636 | }; |
| 1635 | if (is_non_err_tv.val.toBool()) { | 1637 | if (is_non_err_val.toBool()) { |
| 1636 | break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false); | 1638 | break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false); |
| 1637 | } | 1639 | } |
| 1638 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse | 1640 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| ... | @@ -1654,11 +1656,11 @@ fn analyzeBodyInner( | ... | @@ -1654,11 +1656,11 @@ fn analyzeBodyInner( |
| 1654 | const err_union = try sema.analyzeLoad(block, src, operand, operand_src); | 1656 | const err_union = try sema.analyzeLoad(block, src, operand, operand_src); |
| 1655 | const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union); | 1657 | const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union); |
| 1656 | assert(is_non_err != .none); | 1658 | assert(is_non_err != .none); |
| 1657 | const is_non_err_tv = sema.resolveInstConst(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known") catch |err| { | 1659 | const is_non_err_val = sema.resolveConstValue(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known") catch |err| { |
| 1658 | if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err); | 1660 | if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err); |
| 1659 | return err; | 1661 | return err; |
| 1660 | }; | 1662 | }; |
| 1661 | if (is_non_err_tv.val.toBool()) { | 1663 | if (is_non_err_val.toBool()) { |
| 1662 | break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false); | 1664 | break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false); |
| 1663 | } | 1665 | } |
| 1664 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse | 1666 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| ... | @@ -1721,17 +1723,12 @@ fn analyzeBodyInner( | ... | @@ -1721,17 +1723,12 @@ fn analyzeBodyInner( |
| 1721 | } | 1723 | } |
| 1722 | 1724 | ||
| 1723 | pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { | 1725 | pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { |
| 1724 | var i: usize = @enumToInt(zir_ref); | 1726 | const i = @enumToInt(zir_ref); |
| 1725 | |||
| 1726 | // First section of indexes correspond to a set number of constant values. | 1727 | // First section of indexes correspond to a set number of constant values. |
| 1727 | if (i < Zir.Inst.Ref.typed_value_map.len) { | 1728 | // We intentionally map the same indexes to the same values between ZIR and AIR. |
| 1728 | // We intentionally map the same indexes to the same values between ZIR and AIR. | 1729 | if (i < InternPool.static_len) return @intToEnum(Air.Inst.Ref, i); |
| 1729 | return zir_ref; | 1730 | // The last section of indexes refers to the map of ZIR => AIR. |
| 1730 | } | 1731 | const inst = sema.inst_map.get(i - InternPool.static_len).?; |
| 1731 | i -= Zir.Inst.Ref.typed_value_map.len; | ||
| 1732 | |||
| 1733 | // Finally, the last section of indexes refers to the map of ZIR=>AIR. | ||
| 1734 | const inst = sema.inst_map.get(@intCast(u32, i)).?; | ||
| 1735 | const ty = sema.typeOf(inst); | 1732 | const ty = sema.typeOf(inst); |
| 1736 | if (ty.tag() == .generic_poison) return error.GenericPoison; | 1733 | if (ty.tag() == .generic_poison) return error.GenericPoison; |
| 1737 | return inst; | 1734 | return inst; |
| ... | @@ -1766,9 +1763,8 @@ pub fn resolveConstString( | ... | @@ -1766,9 +1763,8 @@ pub fn resolveConstString( |
| 1766 | } | 1763 | } |
| 1767 | 1764 | ||
| 1768 | pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type { | 1765 | pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type { |
| 1769 | assert(zir_ref != .var_args_param); | ||
| 1770 | const air_inst = try sema.resolveInst(zir_ref); | 1766 | const air_inst = try sema.resolveInst(zir_ref); |
| 1771 | assert(air_inst != .var_args_param); | 1767 | assert(air_inst != .var_args_param_type); |
| 1772 | const ty = try sema.analyzeAsType(block, src, air_inst); | 1768 | const ty = try sema.analyzeAsType(block, src, air_inst); |
| 1773 | if (ty.tag() == .generic_poison) return error.GenericPoison; | 1769 | if (ty.tag() == .generic_poison) return error.GenericPoison; |
| 1774 | return ty; | 1770 | return ty; |
| ... | @@ -1783,8 +1779,7 @@ fn analyzeAsType( | ... | @@ -1783,8 +1779,7 @@ fn analyzeAsType( |
| 1783 | const wanted_type = Type.initTag(.type); | 1779 | const wanted_type = Type.initTag(.type); |
| 1784 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); | 1780 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); |
| 1785 | const val = try sema.resolveConstValue(block, src, coerced_inst, "types must be comptime-known"); | 1781 | const val = try sema.resolveConstValue(block, src, coerced_inst, "types must be comptime-known"); |
| 1786 | var buffer: Value.ToTypeBuffer = undefined; | 1782 | const ty = val.toType(); |
| 1787 | const ty = val.toType(&buffer); | ||
| 1788 | return ty.copy(sema.arena); | 1783 | return ty.copy(sema.arena); |
| 1789 | } | 1784 | } |
| 1790 | 1785 | ||
| ... | @@ -1950,12 +1945,12 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime( | ... | @@ -1950,12 +1945,12 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime( |
| 1950 | make_runtime: *bool, | 1945 | make_runtime: *bool, |
| 1951 | ) CompileError!?Value { | 1946 | ) CompileError!?Value { |
| 1952 | // First section of indexes correspond to a set number of constant values. | 1947 | // First section of indexes correspond to a set number of constant values. |
| 1953 | var i: usize = @enumToInt(inst); | 1948 | const int = @enumToInt(inst); |
| 1954 | if (i < Air.Inst.Ref.typed_value_map.len) { | 1949 | if (int < InternPool.static_len) { |
| 1955 | return Air.Inst.Ref.typed_value_map[i].val; | 1950 | return @intToEnum(InternPool.Index, int).toValue(); |
| 1956 | } | 1951 | } |
| 1957 | i -= Air.Inst.Ref.typed_value_map.len; | ||
| 1958 | 1952 | ||
| 1953 | const i = int - InternPool.static_len; | ||
| 1959 | const air_tags = sema.air_instructions.items(.tag); | 1954 | const air_tags = sema.air_instructions.items(.tag); |
| 1960 | if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| { | 1955 | if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| { |
| 1961 | if (air_tags[i] == .constant) { | 1956 | if (air_tags[i] == .constant) { |
| ... | @@ -2010,13 +2005,14 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, opt | ... | @@ -2010,13 +2005,14 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, opt |
| 2010 | } | 2005 | } |
| 2011 | 2006 | ||
| 2012 | fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { | 2007 | fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { |
| 2008 | const mod = sema.mod; | ||
| 2013 | const msg = msg: { | 2009 | const msg = msg: { |
| 2014 | const msg = try sema.errMsg(block, src, "type '{}' does not support array initialization syntax", .{ | 2010 | const msg = try sema.errMsg(block, src, "type '{}' does not support array initialization syntax", .{ |
| 2015 | ty.fmt(sema.mod), | 2011 | ty.fmt(mod), |
| 2016 | }); | 2012 | }); |
| 2017 | errdefer msg.destroy(sema.gpa); | 2013 | errdefer msg.destroy(sema.gpa); |
| 2018 | if (ty.isSlice()) { | 2014 | if (ty.isSlice()) { |
| 2019 | try sema.errNote(block, src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2().fmt(sema.mod)}); | 2015 | try sema.errNote(block, src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2(mod).fmt(mod)}); |
| 2020 | } | 2016 | } |
| 2021 | break :msg msg; | 2017 | break :msg msg; |
| 2022 | }; | 2018 | }; |
| ... | @@ -2042,7 +2038,8 @@ fn failWithErrorSetCodeMissing( | ... | @@ -2042,7 +2038,8 @@ fn failWithErrorSetCodeMissing( |
| 2042 | } | 2038 | } |
| 2043 | 2039 | ||
| 2044 | fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: usize) CompileError { | 2040 | fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: usize) CompileError { |
| 2045 | if (int_ty.zigTypeTag() == .Vector) { | 2041 | const mod = sema.mod; |
| 2042 | if (int_ty.zigTypeTag(mod) == .Vector) { | ||
| 2046 | const msg = msg: { | 2043 | const msg = msg: { |
| 2047 | const msg = try sema.errMsg(block, src, "overflow of vector type '{}' with value '{}'", .{ | 2044 | const msg = try sema.errMsg(block, src, "overflow of vector type '{}' with value '{}'", .{ |
| 2048 | int_ty.fmt(sema.mod), val.fmtValue(int_ty, sema.mod), | 2045 | int_ty.fmt(sema.mod), val.fmtValue(int_ty, sema.mod), |
| ... | @@ -2084,12 +2081,13 @@ fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError | ... | @@ -2084,12 +2081,13 @@ fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError |
| 2084 | } | 2081 | } |
| 2085 | 2082 | ||
| 2086 | fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, object_ty: Type, field_name: []const u8) CompileError { | 2083 | fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, object_ty: Type, field_name: []const u8) CompileError { |
| 2084 | const mod = sema.mod; | ||
| 2087 | const inner_ty = if (object_ty.isSinglePointer()) object_ty.childType() else object_ty; | 2085 | const inner_ty = if (object_ty.isSinglePointer()) object_ty.childType() else object_ty; |
| 2088 | 2086 | ||
| 2089 | if (inner_ty.zigTypeTag() == .Optional) opt: { | 2087 | if (inner_ty.zigTypeTag(mod) == .Optional) opt: { |
| 2090 | var buf: Type.Payload.ElemType = undefined; | 2088 | var buf: Type.Payload.ElemType = undefined; |
| 2091 | const child_ty = inner_ty.optionalChild(&buf); | 2089 | const child_ty = inner_ty.optionalChild(&buf); |
| 2092 | if (!typeSupportsFieldAccess(child_ty, field_name)) break :opt; | 2090 | if (!typeSupportsFieldAccess(mod, child_ty, field_name)) break :opt; |
| 2093 | const msg = msg: { | 2091 | const msg = msg: { |
| 2094 | const msg = try sema.errMsg(block, src, "optional type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); | 2092 | const msg = try sema.errMsg(block, src, "optional type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); |
| 2095 | errdefer msg.destroy(sema.gpa); | 2093 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -2097,9 +2095,9 @@ fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, objec | ... | @@ -2097,9 +2095,9 @@ fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, objec |
| 2097 | break :msg msg; | 2095 | break :msg msg; |
| 2098 | }; | 2096 | }; |
| 2099 | return sema.failWithOwnedErrorMsg(msg); | 2097 | return sema.failWithOwnedErrorMsg(msg); |
| 2100 | } else if (inner_ty.zigTypeTag() == .ErrorUnion) err: { | 2098 | } else if (inner_ty.zigTypeTag(mod) == .ErrorUnion) err: { |
| 2101 | const child_ty = inner_ty.errorUnionPayload(); | 2099 | const child_ty = inner_ty.errorUnionPayload(); |
| 2102 | if (!typeSupportsFieldAccess(child_ty, field_name)) break :err; | 2100 | if (!typeSupportsFieldAccess(mod, child_ty, field_name)) break :err; |
| 2103 | const msg = msg: { | 2101 | const msg = msg: { |
| 2104 | const msg = try sema.errMsg(block, src, "error union type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); | 2102 | const msg = try sema.errMsg(block, src, "error union type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); |
| 2105 | errdefer msg.destroy(sema.gpa); | 2103 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -2111,14 +2109,14 @@ fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, objec | ... | @@ -2111,14 +2109,14 @@ fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, objec |
| 2111 | return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); | 2109 | return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); |
| 2112 | } | 2110 | } |
| 2113 | 2111 | ||
| 2114 | fn typeSupportsFieldAccess(ty: Type, field_name: []const u8) bool { | 2112 | fn typeSupportsFieldAccess(mod: *const Module, ty: Type, field_name: []const u8) bool { |
| 2115 | switch (ty.zigTypeTag()) { | 2113 | switch (ty.zigTypeTag(mod)) { |
| 2116 | .Array => return mem.eql(u8, field_name, "len"), | 2114 | .Array => return mem.eql(u8, field_name, "len"), |
| 2117 | .Pointer => { | 2115 | .Pointer => { |
| 2118 | const ptr_info = ty.ptrInfo().data; | 2116 | const ptr_info = ty.ptrInfo().data; |
| 2119 | if (ptr_info.size == .Slice) { | 2117 | if (ptr_info.size == .Slice) { |
| 2120 | return mem.eql(u8, field_name, "ptr") or mem.eql(u8, field_name, "len"); | 2118 | return mem.eql(u8, field_name, "ptr") or mem.eql(u8, field_name, "len"); |
| 2121 | } else if (ptr_info.pointee_type.zigTypeTag() == .Array) { | 2119 | } else if (ptr_info.pointee_type.zigTypeTag(mod) == .Array) { |
| 2122 | return mem.eql(u8, field_name, "len"); | 2120 | return mem.eql(u8, field_name, "len"); |
| 2123 | } else return false; | 2121 | } else return false; |
| 2124 | }, | 2122 | }, |
| ... | @@ -2352,10 +2350,10 @@ fn analyzeAsInt( | ... | @@ -2352,10 +2350,10 @@ fn analyzeAsInt( |
| 2352 | dest_ty: Type, | 2350 | dest_ty: Type, |
| 2353 | reason: []const u8, | 2351 | reason: []const u8, |
| 2354 | ) !u64 { | 2352 | ) !u64 { |
| 2353 | const mod = sema.mod; | ||
| 2355 | const coerced = try sema.coerce(block, dest_ty, air_ref, src); | 2354 | const coerced = try sema.coerce(block, dest_ty, air_ref, src); |
| 2356 | const val = try sema.resolveConstValue(block, src, coerced, reason); | 2355 | const val = try sema.resolveConstValue(block, src, coerced, reason); |
| 2357 | const target = sema.mod.getTarget(); | 2356 | return (try val.getUnsignedIntAdvanced(mod, sema)).?; |
| 2358 | return (try val.getUnsignedIntAdvanced(target, sema)).?; | ||
| 2359 | } | 2357 | } |
| 2360 | 2358 | ||
| 2361 | // Returns a compile error if the value has tag `variable`. See `resolveInstValue` for | 2359 | // Returns a compile error if the value has tag `variable`. See `resolveInstValue` for |
| ... | @@ -2926,23 +2924,23 @@ fn zirEnumDecl( | ... | @@ -2926,23 +2924,23 @@ fn zirEnumDecl( |
| 2926 | 2924 | ||
| 2927 | if (tag_type_ref != .none) { | 2925 | if (tag_type_ref != .none) { |
| 2928 | const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref); | 2926 | const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref); |
| 2929 | if (ty.zigTypeTag() != .Int and ty.zigTypeTag() != .ComptimeInt) { | 2927 | if (ty.zigTypeTag(mod) != .Int and ty.zigTypeTag(mod) != .ComptimeInt) { |
| 2930 | return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)}); | 2928 | return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)}); |
| 2931 | } | 2929 | } |
| 2932 | enum_obj.tag_ty = try ty.copy(decl_arena_allocator); | 2930 | enum_obj.tag_ty = try ty.copy(decl_arena_allocator); |
| 2933 | enum_obj.tag_ty_inferred = false; | 2931 | enum_obj.tag_ty_inferred = false; |
| 2934 | } else if (fields_len == 0) { | 2932 | } else if (fields_len == 0) { |
| 2935 | enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, 0); | 2933 | enum_obj.tag_ty = try mod.intType(.unsigned, 0); |
| 2936 | enum_obj.tag_ty_inferred = true; | 2934 | enum_obj.tag_ty_inferred = true; |
| 2937 | } else { | 2935 | } else { |
| 2938 | const bits = std.math.log2_int_ceil(usize, fields_len); | 2936 | const bits = std.math.log2_int_ceil(usize, fields_len); |
| 2939 | enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, bits); | 2937 | enum_obj.tag_ty = try mod.intType(.unsigned, bits); |
| 2940 | enum_obj.tag_ty_inferred = true; | 2938 | enum_obj.tag_ty_inferred = true; |
| 2941 | } | 2939 | } |
| 2942 | } | 2940 | } |
| 2943 | 2941 | ||
| 2944 | if (small.nonexhaustive and enum_obj.tag_ty.zigTypeTag() != .ComptimeInt) { | 2942 | if (small.nonexhaustive and enum_obj.tag_ty.zigTypeTag(mod) != .ComptimeInt) { |
| 2945 | if (fields_len > 1 and std.math.log2_int(u64, fields_len) == enum_obj.tag_ty.bitSize(sema.mod.getTarget())) { | 2943 | if (fields_len > 1 and std.math.log2_int(u64, fields_len) == enum_obj.tag_ty.bitSize(mod)) { |
| 2946 | return sema.fail(block, src, "non-exhaustive enum specifies every value", .{}); | 2944 | return sema.fail(block, src, "non-exhaustive enum specifies every value", .{}); |
| 2947 | } | 2945 | } |
| 2948 | } | 2946 | } |
| ... | @@ -3319,7 +3317,8 @@ fn ensureResultUsed( | ... | @@ -3319,7 +3317,8 @@ fn ensureResultUsed( |
| 3319 | ty: Type, | 3317 | ty: Type, |
| 3320 | src: LazySrcLoc, | 3318 | src: LazySrcLoc, |
| 3321 | ) CompileError!void { | 3319 | ) CompileError!void { |
| 3322 | switch (ty.zigTypeTag()) { | 3320 | const mod = sema.mod; |
| 3321 | switch (ty.zigTypeTag(mod)) { | ||
| 3323 | .Void, .NoReturn => return, | 3322 | .Void, .NoReturn => return, |
| 3324 | .ErrorSet, .ErrorUnion => { | 3323 | .ErrorSet, .ErrorUnion => { |
| 3325 | const msg = msg: { | 3324 | const msg = msg: { |
| ... | @@ -3347,11 +3346,12 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -3347,11 +3346,12 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 3347 | const tracy = trace(@src()); | 3346 | const tracy = trace(@src()); |
| 3348 | defer tracy.end(); | 3347 | defer tracy.end(); |
| 3349 | 3348 | ||
| 3349 | const mod = sema.mod; | ||
| 3350 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 3350 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 3351 | const operand = try sema.resolveInst(inst_data.operand); | 3351 | const operand = try sema.resolveInst(inst_data.operand); |
| 3352 | const src = inst_data.src(); | 3352 | const src = inst_data.src(); |
| 3353 | const operand_ty = sema.typeOf(operand); | 3353 | const operand_ty = sema.typeOf(operand); |
| 3354 | switch (operand_ty.zigTypeTag()) { | 3354 | switch (operand_ty.zigTypeTag(mod)) { |
| 3355 | .ErrorSet, .ErrorUnion => { | 3355 | .ErrorSet, .ErrorUnion => { |
| 3356 | const msg = msg: { | 3356 | const msg = msg: { |
| 3357 | const msg = try sema.errMsg(block, src, "error is discarded", .{}); | 3357 | const msg = try sema.errMsg(block, src, "error is discarded", .{}); |
| ... | @@ -3369,16 +3369,17 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index | ... | @@ -3369,16 +3369,17 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index |
| 3369 | const tracy = trace(@src()); | 3369 | const tracy = trace(@src()); |
| 3370 | defer tracy.end(); | 3370 | defer tracy.end(); |
| 3371 | 3371 | ||
| 3372 | const mod = sema.mod; | ||
| 3372 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 3373 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 3373 | const src = inst_data.src(); | 3374 | const src = inst_data.src(); |
| 3374 | const operand = try sema.resolveInst(inst_data.operand); | 3375 | const operand = try sema.resolveInst(inst_data.operand); |
| 3375 | const operand_ty = sema.typeOf(operand); | 3376 | const operand_ty = sema.typeOf(operand); |
| 3376 | const err_union_ty = if (operand_ty.zigTypeTag() == .Pointer) | 3377 | const err_union_ty = if (operand_ty.zigTypeTag(mod) == .Pointer) |
| 3377 | operand_ty.childType() | 3378 | operand_ty.childType() |
| 3378 | else | 3379 | else |
| 3379 | operand_ty; | 3380 | operand_ty; |
| 3380 | if (err_union_ty.zigTypeTag() != .ErrorUnion) return; | 3381 | if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) return; |
| 3381 | const payload_ty = err_union_ty.errorUnionPayload().zigTypeTag(); | 3382 | const payload_ty = err_union_ty.errorUnionPayload().zigTypeTag(mod); |
| 3382 | if (payload_ty != .Void and payload_ty != .NoReturn) { | 3383 | if (payload_ty != .Void and payload_ty != .NoReturn) { |
| 3383 | const msg = msg: { | 3384 | const msg = msg: { |
| 3384 | const msg = try sema.errMsg(block, src, "error union payload is ignored", .{}); | 3385 | const msg = try sema.errMsg(block, src, "error union payload is ignored", .{}); |
| ... | @@ -3920,19 +3921,20 @@ fn zirArrayBasePtr( | ... | @@ -3920,19 +3921,20 @@ fn zirArrayBasePtr( |
| 3920 | block: *Block, | 3921 | block: *Block, |
| 3921 | inst: Zir.Inst.Index, | 3922 | inst: Zir.Inst.Index, |
| 3922 | ) CompileError!Air.Inst.Ref { | 3923 | ) CompileError!Air.Inst.Ref { |
| 3924 | const mod = sema.mod; | ||
| 3923 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 3925 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 3924 | const src = inst_data.src(); | 3926 | const src = inst_data.src(); |
| 3925 | 3927 | ||
| 3926 | const start_ptr = try sema.resolveInst(inst_data.operand); | 3928 | const start_ptr = try sema.resolveInst(inst_data.operand); |
| 3927 | var base_ptr = start_ptr; | 3929 | var base_ptr = start_ptr; |
| 3928 | while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) { | 3930 | while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag(mod)) { |
| 3929 | .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true), | 3931 | .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true), |
| 3930 | .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true), | 3932 | .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true), |
| 3931 | else => break, | 3933 | else => break, |
| 3932 | }; | 3934 | }; |
| 3933 | 3935 | ||
| 3934 | const elem_ty = sema.typeOf(base_ptr).childType(); | 3936 | const elem_ty = sema.typeOf(base_ptr).childType(); |
| 3935 | switch (elem_ty.zigTypeTag()) { | 3937 | switch (elem_ty.zigTypeTag(mod)) { |
| 3936 | .Array, .Vector => return base_ptr, | 3938 | .Array, .Vector => return base_ptr, |
| 3937 | .Struct => if (elem_ty.isTuple()) { | 3939 | .Struct => if (elem_ty.isTuple()) { |
| 3938 | // TODO validate element count | 3940 | // TODO validate element count |
| ... | @@ -3948,19 +3950,20 @@ fn zirFieldBasePtr( | ... | @@ -3948,19 +3950,20 @@ fn zirFieldBasePtr( |
| 3948 | block: *Block, | 3950 | block: *Block, |
| 3949 | inst: Zir.Inst.Index, | 3951 | inst: Zir.Inst.Index, |
| 3950 | ) CompileError!Air.Inst.Ref { | 3952 | ) CompileError!Air.Inst.Ref { |
| 3953 | const mod = sema.mod; | ||
| 3951 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 3954 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 3952 | const src = inst_data.src(); | 3955 | const src = inst_data.src(); |
| 3953 | 3956 | ||
| 3954 | const start_ptr = try sema.resolveInst(inst_data.operand); | 3957 | const start_ptr = try sema.resolveInst(inst_data.operand); |
| 3955 | var base_ptr = start_ptr; | 3958 | var base_ptr = start_ptr; |
| 3956 | while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) { | 3959 | while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag(mod)) { |
| 3957 | .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true), | 3960 | .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true), |
| 3958 | .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true), | 3961 | .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true), |
| 3959 | else => break, | 3962 | else => break, |
| 3960 | }; | 3963 | }; |
| 3961 | 3964 | ||
| 3962 | const elem_ty = sema.typeOf(base_ptr).childType(); | 3965 | const elem_ty = sema.typeOf(base_ptr).childType(); |
| 3963 | switch (elem_ty.zigTypeTag()) { | 3966 | switch (elem_ty.zigTypeTag(mod)) { |
| 3964 | .Struct, .Union => return base_ptr, | 3967 | .Struct, .Union => return base_ptr, |
| 3965 | else => {}, | 3968 | else => {}, |
| 3966 | } | 3969 | } |
| ... | @@ -3968,6 +3971,7 @@ fn zirFieldBasePtr( | ... | @@ -3968,6 +3971,7 @@ fn zirFieldBasePtr( |
| 3968 | } | 3971 | } |
| 3969 | 3972 | ||
| 3970 | fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 3973 | fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 3974 | const mod = sema.mod; | ||
| 3971 | const gpa = sema.gpa; | 3975 | const gpa = sema.gpa; |
| 3972 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 3976 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 3973 | const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); | 3977 | const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); |
| ... | @@ -3991,7 +3995,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -3991,7 +3995,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 3991 | const object_ty = sema.typeOf(object); | 3995 | const object_ty = sema.typeOf(object); |
| 3992 | // Each arg could be an indexable, or a range, in which case the length | 3996 | // Each arg could be an indexable, or a range, in which case the length |
| 3993 | // is passed directly as an integer. | 3997 | // is passed directly as an integer. |
| 3994 | const is_int = switch (object_ty.zigTypeTag()) { | 3998 | const is_int = switch (object_ty.zigTypeTag(mod)) { |
| 3995 | .Int, .ComptimeInt => true, | 3999 | .Int, .ComptimeInt => true, |
| 3996 | else => false, | 4000 | else => false, |
| 3997 | }; | 4001 | }; |
| ... | @@ -4000,7 +4004,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -4000,7 +4004,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4000 | .input_index = i, | 4004 | .input_index = i, |
| 4001 | } }; | 4005 | } }; |
| 4002 | const arg_len_uncoerced = if (is_int) object else l: { | 4006 | const arg_len_uncoerced = if (is_int) object else l: { |
| 4003 | if (!object_ty.isIndexable()) { | 4007 | if (!object_ty.isIndexable(mod)) { |
| 4004 | // Instead of using checkIndexable we customize this error. | 4008 | // Instead of using checkIndexable we customize this error. |
| 4005 | const msg = msg: { | 4009 | const msg = msg: { |
| 4006 | const msg = try sema.errMsg(block, arg_src, "type '{}' is not indexable and not a range", .{object_ty.fmt(sema.mod)}); | 4010 | const msg = try sema.errMsg(block, arg_src, "type '{}' is not indexable and not a range", .{object_ty.fmt(sema.mod)}); |
| ... | @@ -4010,7 +4014,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -4010,7 +4014,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4010 | }; | 4014 | }; |
| 4011 | return sema.failWithOwnedErrorMsg(msg); | 4015 | return sema.failWithOwnedErrorMsg(msg); |
| 4012 | } | 4016 | } |
| 4013 | if (!object_ty.indexableHasLen()) continue; | 4017 | if (!object_ty.indexableHasLen(mod)) continue; |
| 4014 | 4018 | ||
| 4015 | break :l try sema.fieldVal(block, arg_src, object, "len", arg_src); | 4019 | break :l try sema.fieldVal(block, arg_src, object, "len", arg_src); |
| 4016 | }; | 4020 | }; |
| ... | @@ -4061,7 +4065,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -4061,7 +4065,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4061 | const object_ty = sema.typeOf(object); | 4065 | const object_ty = sema.typeOf(object); |
| 4062 | // Each arg could be an indexable, or a range, in which case the length | 4066 | // Each arg could be an indexable, or a range, in which case the length |
| 4063 | // is passed directly as an integer. | 4067 | // is passed directly as an integer. |
| 4064 | switch (object_ty.zigTypeTag()) { | 4068 | switch (object_ty.zigTypeTag(mod)) { |
| 4065 | .Int, .ComptimeInt => continue, | 4069 | .Int, .ComptimeInt => continue, |
| 4066 | else => {}, | 4070 | else => {}, |
| 4067 | } | 4071 | } |
| ... | @@ -4096,13 +4100,14 @@ fn validateArrayInitTy( | ... | @@ -4096,13 +4100,14 @@ fn validateArrayInitTy( |
| 4096 | block: *Block, | 4100 | block: *Block, |
| 4097 | inst: Zir.Inst.Index, | 4101 | inst: Zir.Inst.Index, |
| 4098 | ) CompileError!void { | 4102 | ) CompileError!void { |
| 4103 | const mod = sema.mod; | ||
| 4099 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 4104 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 4100 | const src = inst_data.src(); | 4105 | const src = inst_data.src(); |
| 4101 | const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node }; | 4106 | const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node }; |
| 4102 | const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; | 4107 | const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; |
| 4103 | const ty = try sema.resolveType(block, ty_src, extra.ty); | 4108 | const ty = try sema.resolveType(block, ty_src, extra.ty); |
| 4104 | 4109 | ||
| 4105 | switch (ty.zigTypeTag()) { | 4110 | switch (ty.zigTypeTag(mod)) { |
| 4106 | .Array => { | 4111 | .Array => { |
| 4107 | const array_len = ty.arrayLen(); | 4112 | const array_len = ty.arrayLen(); |
| 4108 | if (extra.init_count != array_len) { | 4113 | if (extra.init_count != array_len) { |
| ... | @@ -4141,11 +4146,12 @@ fn validateStructInitTy( | ... | @@ -4141,11 +4146,12 @@ fn validateStructInitTy( |
| 4141 | block: *Block, | 4146 | block: *Block, |
| 4142 | inst: Zir.Inst.Index, | 4147 | inst: Zir.Inst.Index, |
| 4143 | ) CompileError!void { | 4148 | ) CompileError!void { |
| 4149 | const mod = sema.mod; | ||
| 4144 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 4150 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 4145 | const src = inst_data.src(); | 4151 | const src = inst_data.src(); |
| 4146 | const ty = try sema.resolveType(block, src, inst_data.operand); | 4152 | const ty = try sema.resolveType(block, src, inst_data.operand); |
| 4147 | 4153 | ||
| 4148 | switch (ty.zigTypeTag()) { | 4154 | switch (ty.zigTypeTag(mod)) { |
| 4149 | .Struct, .Union => return, | 4155 | .Struct, .Union => return, |
| 4150 | else => {}, | 4156 | else => {}, |
| 4151 | } | 4157 | } |
| ... | @@ -4160,6 +4166,7 @@ fn zirValidateStructInit( | ... | @@ -4160,6 +4166,7 @@ fn zirValidateStructInit( |
| 4160 | const tracy = trace(@src()); | 4166 | const tracy = trace(@src()); |
| 4161 | defer tracy.end(); | 4167 | defer tracy.end(); |
| 4162 | 4168 | ||
| 4169 | const mod = sema.mod; | ||
| 4163 | const validate_inst = sema.code.instructions.items(.data)[inst].pl_node; | 4170 | const validate_inst = sema.code.instructions.items(.data)[inst].pl_node; |
| 4164 | const init_src = validate_inst.src(); | 4171 | const init_src = validate_inst.src(); |
| 4165 | const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index); | 4172 | const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index); |
| ... | @@ -4168,7 +4175,7 @@ fn zirValidateStructInit( | ... | @@ -4168,7 +4175,7 @@ fn zirValidateStructInit( |
| 4168 | const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; | 4175 | const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; |
| 4169 | const object_ptr = try sema.resolveInst(field_ptr_extra.lhs); | 4176 | const object_ptr = try sema.resolveInst(field_ptr_extra.lhs); |
| 4170 | const agg_ty = sema.typeOf(object_ptr).childType(); | 4177 | const agg_ty = sema.typeOf(object_ptr).childType(); |
| 4171 | switch (agg_ty.zigTypeTag()) { | 4178 | switch (agg_ty.zigTypeTag(mod)) { |
| 4172 | .Struct => return sema.validateStructInit( | 4179 | .Struct => return sema.validateStructInit( |
| 4173 | block, | 4180 | block, |
| 4174 | agg_ty, | 4181 | agg_ty, |
| ... | @@ -4589,6 +4596,7 @@ fn zirValidateArrayInit( | ... | @@ -4589,6 +4596,7 @@ fn zirValidateArrayInit( |
| 4589 | block: *Block, | 4596 | block: *Block, |
| 4590 | inst: Zir.Inst.Index, | 4597 | inst: Zir.Inst.Index, |
| 4591 | ) CompileError!void { | 4598 | ) CompileError!void { |
| 4599 | const mod = sema.mod; | ||
| 4592 | const validate_inst = sema.code.instructions.items(.data)[inst].pl_node; | 4600 | const validate_inst = sema.code.instructions.items(.data)[inst].pl_node; |
| 4593 | const init_src = validate_inst.src(); | 4601 | const init_src = validate_inst.src(); |
| 4594 | const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index); | 4602 | const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index); |
| ... | @@ -4599,7 +4607,7 @@ fn zirValidateArrayInit( | ... | @@ -4599,7 +4607,7 @@ fn zirValidateArrayInit( |
| 4599 | const array_ty = sema.typeOf(array_ptr).childType(); | 4607 | const array_ty = sema.typeOf(array_ptr).childType(); |
| 4600 | const array_len = array_ty.arrayLen(); | 4608 | const array_len = array_ty.arrayLen(); |
| 4601 | 4609 | ||
| 4602 | if (instrs.len != array_len) switch (array_ty.zigTypeTag()) { | 4610 | if (instrs.len != array_len) switch (array_ty.zigTypeTag(mod)) { |
| 4603 | .Struct => { | 4611 | .Struct => { |
| 4604 | var root_msg: ?*Module.ErrorMsg = null; | 4612 | var root_msg: ?*Module.ErrorMsg = null; |
| 4605 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); | 4613 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); |
| ... | @@ -4667,7 +4675,7 @@ fn zirValidateArrayInit( | ... | @@ -4667,7 +4675,7 @@ fn zirValidateArrayInit( |
| 4667 | // Determine whether the value stored to this pointer is comptime-known. | 4675 | // Determine whether the value stored to this pointer is comptime-known. |
| 4668 | 4676 | ||
| 4669 | if (array_ty.isTuple()) { | 4677 | if (array_ty.isTuple()) { |
| 4670 | if (array_ty.structFieldValueComptime(i)) |opv| { | 4678 | if (array_ty.structFieldValueComptime(mod, i)) |opv| { |
| 4671 | element_vals[i] = opv; | 4679 | element_vals[i] = opv; |
| 4672 | continue; | 4680 | continue; |
| 4673 | } | 4681 | } |
| ... | @@ -4770,12 +4778,13 @@ fn zirValidateArrayInit( | ... | @@ -4770,12 +4778,13 @@ fn zirValidateArrayInit( |
| 4770 | } | 4778 | } |
| 4771 | 4779 | ||
| 4772 | fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 4780 | fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 4781 | const mod = sema.mod; | ||
| 4773 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 4782 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 4774 | const src = inst_data.src(); | 4783 | const src = inst_data.src(); |
| 4775 | const operand = try sema.resolveInst(inst_data.operand); | 4784 | const operand = try sema.resolveInst(inst_data.operand); |
| 4776 | const operand_ty = sema.typeOf(operand); | 4785 | const operand_ty = sema.typeOf(operand); |
| 4777 | 4786 | ||
| 4778 | if (operand_ty.zigTypeTag() != .Pointer) { | 4787 | if (operand_ty.zigTypeTag(mod) != .Pointer) { |
| 4779 | return sema.fail(block, src, "cannot dereference non-pointer type '{}'", .{operand_ty.fmt(sema.mod)}); | 4788 | return sema.fail(block, src, "cannot dereference non-pointer type '{}'", .{operand_ty.fmt(sema.mod)}); |
| 4780 | } else switch (operand_ty.ptrSize()) { | 4789 | } else switch (operand_ty.ptrSize()) { |
| 4781 | .One, .C => {}, | 4790 | .One, .C => {}, |
| ... | @@ -4788,7 +4797,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -4788,7 +4797,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 4788 | return; | 4797 | return; |
| 4789 | } | 4798 | } |
| 4790 | 4799 | ||
| 4791 | const elem_ty = operand_ty.elemType2(); | 4800 | const elem_ty = operand_ty.elemType2(mod); |
| 4792 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | 4801 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 4793 | if (val.isUndef()) { | 4802 | if (val.isUndef()) { |
| 4794 | return sema.fail(block, src, "cannot dereference undefined value", .{}); | 4803 | return sema.fail(block, src, "cannot dereference undefined value", .{}); |
| ... | @@ -4818,7 +4827,8 @@ fn failWithBadMemberAccess( | ... | @@ -4818,7 +4827,8 @@ fn failWithBadMemberAccess( |
| 4818 | field_src: LazySrcLoc, | 4827 | field_src: LazySrcLoc, |
| 4819 | field_name: []const u8, | 4828 | field_name: []const u8, |
| 4820 | ) CompileError { | 4829 | ) CompileError { |
| 4821 | const kw_name = switch (agg_ty.zigTypeTag()) { | 4830 | const mod = sema.mod; |
| 4831 | const kw_name = switch (agg_ty.zigTypeTag(mod)) { | ||
| 4822 | .Union => "union", | 4832 | .Union => "union", |
| 4823 | .Struct => "struct", | 4833 | .Struct => "struct", |
| 4824 | .Opaque => "opaque", | 4834 | .Opaque => "opaque", |
| ... | @@ -4894,8 +4904,9 @@ fn failWithBadUnionFieldAccess( | ... | @@ -4894,8 +4904,9 @@ fn failWithBadUnionFieldAccess( |
| 4894 | } | 4904 | } |
| 4895 | 4905 | ||
| 4896 | fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !void { | 4906 | fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !void { |
| 4897 | const src_loc = decl_ty.declSrcLocOrNull(sema.mod) orelse return; | 4907 | const mod = sema.mod; |
| 4898 | const category = switch (decl_ty.zigTypeTag()) { | 4908 | const src_loc = decl_ty.declSrcLocOrNull(mod) orelse return; |
| 4909 | const category = switch (decl_ty.zigTypeTag(mod)) { | ||
| 4899 | .Union => "union", | 4910 | .Union => "union", |
| 4900 | .Struct => "struct", | 4911 | .Struct => "struct", |
| 4901 | .Enum => "enum", | 4912 | .Enum => "enum", |
| ... | @@ -4903,7 +4914,7 @@ fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !vo | ... | @@ -4903,7 +4914,7 @@ fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !vo |
| 4903 | .ErrorSet => "error set", | 4914 | .ErrorSet => "error set", |
| 4904 | else => unreachable, | 4915 | else => unreachable, |
| 4905 | }; | 4916 | }; |
| 4906 | try sema.mod.errNoteNonLazy(src_loc, parent, "{s} declared here", .{category}); | 4917 | try mod.errNoteNonLazy(src_loc, parent, "{s} declared here", .{category}); |
| 4907 | } | 4918 | } |
| 4908 | 4919 | ||
| 4909 | fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 4920 | fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | @@ -5028,6 +5039,7 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v | ... | @@ -5028,6 +5039,7 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v |
| 5028 | const tracy = trace(@src()); | 5039 | const tracy = trace(@src()); |
| 5029 | defer tracy.end(); | 5040 | defer tracy.end(); |
| 5030 | 5041 | ||
| 5042 | const mod = sema.mod; | ||
| 5031 | const zir_tags = sema.code.instructions.items(.tag); | 5043 | const zir_tags = sema.code.instructions.items(.tag); |
| 5032 | const zir_datas = sema.code.instructions.items(.data); | 5044 | const zir_datas = sema.code.instructions.items(.data); |
| 5033 | const inst_data = zir_datas[inst].pl_node; | 5045 | const inst_data = zir_datas[inst].pl_node; |
| ... | @@ -5046,9 +5058,9 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v | ... | @@ -5046,9 +5058,9 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v |
| 5046 | // %b = store(%a, %c) | 5058 | // %b = store(%a, %c) |
| 5047 | // Where %c is an error union or error set. In such case we need to add | 5059 | // Where %c is an error union or error set. In such case we need to add |
| 5048 | // to the current function's inferred error set, if any. | 5060 | // to the current function's inferred error set, if any. |
| 5049 | if (is_ret and (sema.typeOf(operand).zigTypeTag() == .ErrorUnion or | 5061 | if (is_ret and (sema.typeOf(operand).zigTypeTag(mod) == .ErrorUnion or |
| 5050 | sema.typeOf(operand).zigTypeTag() == .ErrorSet) and | 5062 | sema.typeOf(operand).zigTypeTag(mod) == .ErrorSet) and |
| 5051 | sema.fn_ret_ty.zigTypeTag() == .ErrorUnion) | 5063 | sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion) |
| 5052 | { | 5064 | { |
| 5053 | try sema.addToInferredErrorSet(operand); | 5065 | try sema.addToInferredErrorSet(operand); |
| 5054 | } | 5066 | } |
| ... | @@ -6270,6 +6282,7 @@ fn zirCall( | ... | @@ -6270,6 +6282,7 @@ fn zirCall( |
| 6270 | const tracy = trace(@src()); | 6282 | const tracy = trace(@src()); |
| 6271 | defer tracy.end(); | 6283 | defer tracy.end(); |
| 6272 | 6284 | ||
| 6285 | const mod = sema.mod; | ||
| 6273 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 6286 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 6274 | const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node }; | 6287 | const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node }; |
| 6275 | const call_src = inst_data.src(); | 6288 | const call_src = inst_data.src(); |
| ... | @@ -6342,7 +6355,7 @@ fn zirCall( | ... | @@ -6342,7 +6355,7 @@ fn zirCall( |
| 6342 | 6355 | ||
| 6343 | sema.inst_map.putAssumeCapacity(inst, inst: { | 6356 | sema.inst_map.putAssumeCapacity(inst, inst: { |
| 6344 | if (arg_index >= fn_params_len) | 6357 | if (arg_index >= fn_params_len) |
| 6345 | break :inst Air.Inst.Ref.var_args_param; | 6358 | break :inst Air.Inst.Ref.var_args_param_type; |
| 6346 | 6359 | ||
| 6347 | if (func_ty_info.param_types[arg_index].tag() == .generic_poison) | 6360 | if (func_ty_info.param_types[arg_index].tag() == .generic_poison) |
| 6348 | break :inst Air.Inst.Ref.generic_poison_type; | 6361 | break :inst Air.Inst.Ref.generic_poison_type; |
| ... | @@ -6352,10 +6365,10 @@ fn zirCall( | ... | @@ -6352,10 +6365,10 @@ fn zirCall( |
| 6352 | 6365 | ||
| 6353 | const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst); | 6366 | const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst); |
| 6354 | const resolved_ty = sema.typeOf(resolved); | 6367 | const resolved_ty = sema.typeOf(resolved); |
| 6355 | if (resolved_ty.zigTypeTag() == .NoReturn) { | 6368 | if (resolved_ty.zigTypeTag(mod) == .NoReturn) { |
| 6356 | return resolved; | 6369 | return resolved; |
| 6357 | } | 6370 | } |
| 6358 | if (resolved_ty.isError()) { | 6371 | if (resolved_ty.isError(mod)) { |
| 6359 | input_is_error = true; | 6372 | input_is_error = true; |
| 6360 | } | 6373 | } |
| 6361 | resolved_args[arg_index] = resolved; | 6374 | resolved_args[arg_index] = resolved; |
| ... | @@ -6380,7 +6393,7 @@ fn zirCall( | ... | @@ -6380,7 +6393,7 @@ fn zirCall( |
| 6380 | 6393 | ||
| 6381 | // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only | 6394 | // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only |
| 6382 | // need to clean-up our own trace if we were passed to a non-error-handling expression. | 6395 | // need to clean-up our own trace if we were passed to a non-error-handling expression. |
| 6383 | if (input_is_error or (pop_error_return_trace and modifier != .always_tail and return_ty.isError())) { | 6396 | if (input_is_error or (pop_error_return_trace and modifier != .always_tail and return_ty.isError(mod))) { |
| 6384 | const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace"); | 6397 | const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace"); |
| 6385 | const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty); | 6398 | const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty); |
| 6386 | const field_index = try sema.structFieldIndex(block, stack_trace_ty, "index", call_src); | 6399 | const field_index = try sema.structFieldIndex(block, stack_trace_ty, "index", call_src); |
| ... | @@ -6417,20 +6430,21 @@ fn checkCallArgumentCount( | ... | @@ -6417,20 +6430,21 @@ fn checkCallArgumentCount( |
| 6417 | total_args: usize, | 6430 | total_args: usize, |
| 6418 | member_fn: bool, | 6431 | member_fn: bool, |
| 6419 | ) !Type { | 6432 | ) !Type { |
| 6433 | const mod = sema.mod; | ||
| 6420 | const func_ty = func_ty: { | 6434 | const func_ty = func_ty: { |
| 6421 | switch (callee_ty.zigTypeTag()) { | 6435 | switch (callee_ty.zigTypeTag(mod)) { |
| 6422 | .Fn => break :func_ty callee_ty, | 6436 | .Fn => break :func_ty callee_ty, |
| 6423 | .Pointer => { | 6437 | .Pointer => { |
| 6424 | const ptr_info = callee_ty.ptrInfo().data; | 6438 | const ptr_info = callee_ty.ptrInfo().data; |
| 6425 | if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Fn) { | 6439 | if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag(mod) == .Fn) { |
| 6426 | break :func_ty ptr_info.pointee_type; | 6440 | break :func_ty ptr_info.pointee_type; |
| 6427 | } | 6441 | } |
| 6428 | }, | 6442 | }, |
| 6429 | .Optional => { | 6443 | .Optional => { |
| 6430 | var buf: Type.Payload.ElemType = undefined; | 6444 | var buf: Type.Payload.ElemType = undefined; |
| 6431 | const opt_child = callee_ty.optionalChild(&buf); | 6445 | const opt_child = callee_ty.optionalChild(&buf); |
| 6432 | if (opt_child.zigTypeTag() == .Fn or (opt_child.isSinglePointer() and | 6446 | if (opt_child.zigTypeTag(mod) == .Fn or (opt_child.isSinglePointer() and |
| 6433 | opt_child.childType().zigTypeTag() == .Fn)) | 6447 | opt_child.childType().zigTypeTag(mod) == .Fn)) |
| 6434 | { | 6448 | { |
| 6435 | const msg = msg: { | 6449 | const msg = msg: { |
| 6436 | const msg = try sema.errMsg(block, func_src, "cannot call optional type '{}'", .{ | 6450 | const msg = try sema.errMsg(block, func_src, "cannot call optional type '{}'", .{ |
| ... | @@ -6488,13 +6502,14 @@ fn callBuiltin( | ... | @@ -6488,13 +6502,14 @@ fn callBuiltin( |
| 6488 | modifier: std.builtin.CallModifier, | 6502 | modifier: std.builtin.CallModifier, |
| 6489 | args: []const Air.Inst.Ref, | 6503 | args: []const Air.Inst.Ref, |
| 6490 | ) !void { | 6504 | ) !void { |
| 6505 | const mod = sema.mod; | ||
| 6491 | const callee_ty = sema.typeOf(builtin_fn); | 6506 | const callee_ty = sema.typeOf(builtin_fn); |
| 6492 | const func_ty = func_ty: { | 6507 | const func_ty = func_ty: { |
| 6493 | switch (callee_ty.zigTypeTag()) { | 6508 | switch (callee_ty.zigTypeTag(mod)) { |
| 6494 | .Fn => break :func_ty callee_ty, | 6509 | .Fn => break :func_ty callee_ty, |
| 6495 | .Pointer => { | 6510 | .Pointer => { |
| 6496 | const ptr_info = callee_ty.ptrInfo().data; | 6511 | const ptr_info = callee_ty.ptrInfo().data; |
| 6497 | if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Fn) { | 6512 | if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag(mod) == .Fn) { |
| 6498 | break :func_ty ptr_info.pointee_type; | 6513 | break :func_ty ptr_info.pointee_type; |
| 6499 | } | 6514 | } |
| 6500 | }, | 6515 | }, |
| ... | @@ -6715,7 +6730,7 @@ fn analyzeCall( | ... | @@ -6715,7 +6730,7 @@ fn analyzeCall( |
| 6715 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), | 6730 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), |
| 6716 | }), | 6731 | }), |
| 6717 | else => { | 6732 | else => { |
| 6718 | assert(callee_ty.isPtrAtRuntime()); | 6733 | assert(callee_ty.isPtrAtRuntime(mod)); |
| 6719 | return sema.fail(block, call_src, "{s} call of function pointer", .{ | 6734 | return sema.fail(block, call_src, "{s} call of function pointer", .{ |
| 6720 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), | 6735 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), |
| 6721 | }); | 6736 | }); |
| ... | @@ -6978,7 +6993,7 @@ fn analyzeCall( | ... | @@ -6978,7 +6993,7 @@ fn analyzeCall( |
| 6978 | break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); | 6993 | break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); |
| 6979 | }; | 6994 | }; |
| 6980 | 6995 | ||
| 6981 | if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag() != .NoReturn) { | 6996 | if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag(mod) != .NoReturn) { |
| 6982 | try sema.emitDbgInline( | 6997 | try sema.emitDbgInline( |
| 6983 | block, | 6998 | block, |
| 6984 | module_fn, | 6999 | module_fn, |
| ... | @@ -7068,7 +7083,7 @@ fn analyzeCall( | ... | @@ -7068,7 +7083,7 @@ fn analyzeCall( |
| 7068 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); | 7083 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); |
| 7069 | 7084 | ||
| 7070 | try sema.queueFullTypeResolution(func_ty_info.return_type); | 7085 | try sema.queueFullTypeResolution(func_ty_info.return_type); |
| 7071 | if (sema.owner_func != null and func_ty_info.return_type.isError()) { | 7086 | if (sema.owner_func != null and func_ty_info.return_type.isError(mod)) { |
| 7072 | sema.owner_func.?.calls_or_awaits_errorable_fn = true; | 7087 | sema.owner_func.?.calls_or_awaits_errorable_fn = true; |
| 7073 | } | 7088 | } |
| 7074 | 7089 | ||
| ... | @@ -7301,8 +7316,9 @@ fn analyzeGenericCallArg( | ... | @@ -7301,8 +7316,9 @@ fn analyzeGenericCallArg( |
| 7301 | new_fn_info: Type.Payload.Function.Data, | 7316 | new_fn_info: Type.Payload.Function.Data, |
| 7302 | runtime_i: *u32, | 7317 | runtime_i: *u32, |
| 7303 | ) !void { | 7318 | ) !void { |
| 7319 | const mod = sema.mod; | ||
| 7304 | const is_runtime = comptime_arg.val.tag() == .generic_poison and | 7320 | const is_runtime = comptime_arg.val.tag() == .generic_poison and |
| 7305 | comptime_arg.ty.hasRuntimeBits() and | 7321 | comptime_arg.ty.hasRuntimeBits(mod) and |
| 7306 | !(try sema.typeRequiresComptime(comptime_arg.ty)); | 7322 | !(try sema.typeRequiresComptime(comptime_arg.ty)); |
| 7307 | if (is_runtime) { | 7323 | if (is_runtime) { |
| 7308 | const param_ty = new_fn_info.param_types[runtime_i.*]; | 7324 | const param_ty = new_fn_info.param_types[runtime_i.*]; |
| ... | @@ -7591,7 +7607,7 @@ fn instantiateGenericCall( | ... | @@ -7591,7 +7607,7 @@ fn instantiateGenericCall( |
| 7591 | 7607 | ||
| 7592 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); | 7608 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); |
| 7593 | 7609 | ||
| 7594 | if (sema.owner_func != null and new_fn_info.return_type.isError()) { | 7610 | if (sema.owner_func != null and new_fn_info.return_type.isError(mod)) { |
| 7595 | sema.owner_func.?.calls_or_awaits_errorable_fn = true; | 7611 | sema.owner_func.?.calls_or_awaits_errorable_fn = true; |
| 7596 | } | 7612 | } |
| 7597 | 7613 | ||
| ... | @@ -7872,8 +7888,9 @@ fn zirIntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -7872,8 +7888,9 @@ fn zirIntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 7872 | const tracy = trace(@src()); | 7888 | const tracy = trace(@src()); |
| 7873 | defer tracy.end(); | 7889 | defer tracy.end(); |
| 7874 | 7890 | ||
| 7891 | const mod = sema.mod; | ||
| 7875 | const int_type = sema.code.instructions.items(.data)[inst].int_type; | 7892 | const int_type = sema.code.instructions.items(.data)[inst].int_type; |
| 7876 | const ty = try Module.makeIntType(sema.arena, int_type.signedness, int_type.bit_count); | 7893 | const ty = try mod.intType(int_type.signedness, int_type.bit_count); |
| 7877 | 7894 | ||
| 7878 | return sema.addType(ty); | 7895 | return sema.addType(ty); |
| 7879 | } | 7896 | } |
| ... | @@ -7882,12 +7899,13 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -7882,12 +7899,13 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 7882 | const tracy = trace(@src()); | 7899 | const tracy = trace(@src()); |
| 7883 | defer tracy.end(); | 7900 | defer tracy.end(); |
| 7884 | 7901 | ||
| 7902 | const mod = sema.mod; | ||
| 7885 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 7903 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 7886 | const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; | 7904 | const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; |
| 7887 | const child_type = try sema.resolveType(block, operand_src, inst_data.operand); | 7905 | const child_type = try sema.resolveType(block, operand_src, inst_data.operand); |
| 7888 | if (child_type.zigTypeTag() == .Opaque) { | 7906 | if (child_type.zigTypeTag(mod) == .Opaque) { |
| 7889 | return sema.fail(block, operand_src, "opaque type '{}' cannot be optional", .{child_type.fmt(sema.mod)}); | 7907 | return sema.fail(block, operand_src, "opaque type '{}' cannot be optional", .{child_type.fmt(sema.mod)}); |
| 7890 | } else if (child_type.zigTypeTag() == .Null) { | 7908 | } else if (child_type.zigTypeTag(mod) == .Null) { |
| 7891 | return sema.fail(block, operand_src, "type '{}' cannot be optional", .{child_type.fmt(sema.mod)}); | 7909 | return sema.fail(block, operand_src, "type '{}' cannot be optional", .{child_type.fmt(sema.mod)}); |
| 7892 | } | 7910 | } |
| 7893 | const opt_type = try Type.optional(sema.arena, child_type); | 7911 | const opt_type = try Type.optional(sema.arena, child_type); |
| ... | @@ -7896,14 +7914,15 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -7896,14 +7914,15 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 7896 | } | 7914 | } |
| 7897 | 7915 | ||
| 7898 | fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 7916 | fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 7917 | const mod = sema.mod; | ||
| 7899 | const bin = sema.code.instructions.items(.data)[inst].bin; | 7918 | const bin = sema.code.instructions.items(.data)[inst].bin; |
| 7900 | const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs); | 7919 | const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs); |
| 7901 | assert(indexable_ty.isIndexable()); // validated by a previous instruction | 7920 | assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction |
| 7902 | if (indexable_ty.zigTypeTag() == .Struct) { | 7921 | if (indexable_ty.zigTypeTag(mod) == .Struct) { |
| 7903 | const elem_type = indexable_ty.structFieldType(@enumToInt(bin.rhs)); | 7922 | const elem_type = indexable_ty.structFieldType(@enumToInt(bin.rhs)); |
| 7904 | return sema.addType(elem_type); | 7923 | return sema.addType(elem_type); |
| 7905 | } else { | 7924 | } else { |
| 7906 | const elem_type = indexable_ty.elemType2(); | 7925 | const elem_type = indexable_ty.elemType2(mod); |
| 7907 | return sema.addType(elem_type); | 7926 | return sema.addType(elem_type); |
| 7908 | } | 7927 | } |
| 7909 | } | 7928 | } |
| ... | @@ -7960,9 +7979,10 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil | ... | @@ -7960,9 +7979,10 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil |
| 7960 | } | 7979 | } |
| 7961 | 7980 | ||
| 7962 | fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src: LazySrcLoc) !void { | 7981 | fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src: LazySrcLoc) !void { |
| 7963 | if (elem_type.zigTypeTag() == .Opaque) { | 7982 | const mod = sema.mod; |
| 7983 | if (elem_type.zigTypeTag(mod) == .Opaque) { | ||
| 7964 | return sema.fail(block, elem_src, "array of opaque type '{}' not allowed", .{elem_type.fmt(sema.mod)}); | 7984 | return sema.fail(block, elem_src, "array of opaque type '{}' not allowed", .{elem_type.fmt(sema.mod)}); |
| 7965 | } else if (elem_type.zigTypeTag() == .NoReturn) { | 7985 | } else if (elem_type.zigTypeTag(mod) == .NoReturn) { |
| 7966 | return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{}); | 7986 | return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{}); |
| 7967 | } | 7987 | } |
| 7968 | } | 7988 | } |
| ... | @@ -7986,6 +8006,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -7986,6 +8006,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 7986 | const tracy = trace(@src()); | 8006 | const tracy = trace(@src()); |
| 7987 | defer tracy.end(); | 8007 | defer tracy.end(); |
| 7988 | 8008 | ||
| 8009 | const mod = sema.mod; | ||
| 7989 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 8010 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 7990 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 8011 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 7991 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | 8012 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| ... | @@ -7993,7 +8014,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -7993,7 +8014,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 7993 | const error_set = try sema.resolveType(block, lhs_src, extra.lhs); | 8014 | const error_set = try sema.resolveType(block, lhs_src, extra.lhs); |
| 7994 | const payload = try sema.resolveType(block, rhs_src, extra.rhs); | 8015 | const payload = try sema.resolveType(block, rhs_src, extra.rhs); |
| 7995 | 8016 | ||
| 7996 | if (error_set.zigTypeTag() != .ErrorSet) { | 8017 | if (error_set.zigTypeTag(mod) != .ErrorSet) { |
| 7997 | return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{ | 8018 | return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{ |
| 7998 | error_set.fmt(sema.mod), | 8019 | error_set.fmt(sema.mod), |
| 7999 | }); | 8020 | }); |
| ... | @@ -8004,11 +8025,12 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -8004,11 +8025,12 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 8004 | } | 8025 | } |
| 8005 | 8026 | ||
| 8006 | fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, payload_src: LazySrcLoc) !void { | 8027 | fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, payload_src: LazySrcLoc) !void { |
| 8007 | if (payload_ty.zigTypeTag() == .Opaque) { | 8028 | const mod = sema.mod; |
| 8029 | if (payload_ty.zigTypeTag(mod) == .Opaque) { | ||
| 8008 | return sema.fail(block, payload_src, "error union with payload of opaque type '{}' not allowed", .{ | 8030 | return sema.fail(block, payload_src, "error union with payload of opaque type '{}' not allowed", .{ |
| 8009 | payload_ty.fmt(sema.mod), | 8031 | payload_ty.fmt(sema.mod), |
| 8010 | }); | 8032 | }); |
| 8011 | } else if (payload_ty.zigTypeTag() == .ErrorSet) { | 8033 | } else if (payload_ty.zigTypeTag(mod) == .ErrorSet) { |
| 8012 | return sema.fail(block, payload_src, "error union with payload of error set type '{}' not allowed", .{ | 8034 | return sema.fail(block, payload_src, "error union with payload of error set type '{}' not allowed", .{ |
| 8013 | payload_ty.fmt(sema.mod), | 8035 | payload_ty.fmt(sema.mod), |
| 8014 | }); | 8036 | }); |
| ... | @@ -8089,10 +8111,10 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -8089,10 +8111,10 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 8089 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 8111 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 8090 | const uncasted_operand = try sema.resolveInst(extra.operand); | 8112 | const uncasted_operand = try sema.resolveInst(extra.operand); |
| 8091 | const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src); | 8113 | const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src); |
| 8092 | const target = sema.mod.getTarget(); | 8114 | const mod = sema.mod; |
| 8093 | 8115 | ||
| 8094 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| { | 8116 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| { |
| 8095 | const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(target)); | 8117 | const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(mod)); |
| 8096 | if (int > sema.mod.global_error_set.count() or int == 0) | 8118 | if (int > sema.mod.global_error_set.count() or int == 0) |
| 8097 | return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int}); | 8119 | return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int}); |
| 8098 | const payload = try sema.arena.create(Value.Payload.Error); | 8120 | const payload = try sema.arena.create(Value.Payload.Error); |
| ... | @@ -8123,6 +8145,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -8123,6 +8145,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 8123 | const tracy = trace(@src()); | 8145 | const tracy = trace(@src()); |
| 8124 | defer tracy.end(); | 8146 | defer tracy.end(); |
| 8125 | 8147 | ||
| 8148 | const mod = sema.mod; | ||
| 8126 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 8149 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 8127 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 8150 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 8128 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 8151 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| ... | @@ -8130,7 +8153,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -8130,7 +8153,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 8130 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; | 8153 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 8131 | const lhs = try sema.resolveInst(extra.lhs); | 8154 | const lhs = try sema.resolveInst(extra.lhs); |
| 8132 | const rhs = try sema.resolveInst(extra.rhs); | 8155 | const rhs = try sema.resolveInst(extra.rhs); |
| 8133 | if (sema.typeOf(lhs).zigTypeTag() == .Bool and sema.typeOf(rhs).zigTypeTag() == .Bool) { | 8156 | if (sema.typeOf(lhs).zigTypeTag(mod) == .Bool and sema.typeOf(rhs).zigTypeTag(mod) == .Bool) { |
| 8134 | const msg = msg: { | 8157 | const msg = msg: { |
| 8135 | const msg = try sema.errMsg(block, lhs_src, "expected error set type, found 'bool'", .{}); | 8158 | const msg = try sema.errMsg(block, lhs_src, "expected error set type, found 'bool'", .{}); |
| 8136 | errdefer msg.destroy(sema.gpa); | 8159 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -8141,9 +8164,9 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -8141,9 +8164,9 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 8141 | } | 8164 | } |
| 8142 | const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs); | 8165 | const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs); |
| 8143 | const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs); | 8166 | const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs); |
| 8144 | if (lhs_ty.zigTypeTag() != .ErrorSet) | 8167 | if (lhs_ty.zigTypeTag(mod) != .ErrorSet) |
| 8145 | return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{lhs_ty.fmt(sema.mod)}); | 8168 | return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{lhs_ty.fmt(sema.mod)}); |
| 8146 | if (rhs_ty.zigTypeTag() != .ErrorSet) | 8169 | if (rhs_ty.zigTypeTag(mod) != .ErrorSet) |
| 8147 | return sema.fail(block, rhs_src, "expected error set type, found '{}'", .{rhs_ty.fmt(sema.mod)}); | 8170 | return sema.fail(block, rhs_src, "expected error set type, found '{}'", .{rhs_ty.fmt(sema.mod)}); |
| 8148 | 8171 | ||
| 8149 | // Anything merged with anyerror is anyerror. | 8172 | // Anything merged with anyerror is anyerror. |
| ... | @@ -8184,6 +8207,7 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -8184,6 +8207,7 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8184 | } | 8207 | } |
| 8185 | 8208 | ||
| 8186 | fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 8209 | fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 8210 | const mod = sema.mod; | ||
| 8187 | const arena = sema.arena; | 8211 | const arena = sema.arena; |
| 8188 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 8212 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 8189 | const src = inst_data.src(); | 8213 | const src = inst_data.src(); |
| ... | @@ -8191,7 +8215,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -8191,7 +8215,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 8191 | const operand = try sema.resolveInst(inst_data.operand); | 8215 | const operand = try sema.resolveInst(inst_data.operand); |
| 8192 | const operand_ty = sema.typeOf(operand); | 8216 | const operand_ty = sema.typeOf(operand); |
| 8193 | 8217 | ||
| 8194 | const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag()) { | 8218 | const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag(mod)) { |
| 8195 | .Enum => operand, | 8219 | .Enum => operand, |
| 8196 | .Union => blk: { | 8220 | .Union => blk: { |
| 8197 | const union_ty = try sema.resolveTypeFields(operand_ty); | 8221 | const union_ty = try sema.resolveTypeFields(operand_ty); |
| ... | @@ -8213,8 +8237,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -8213,8 +8237,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 8213 | }; | 8237 | }; |
| 8214 | const enum_tag_ty = sema.typeOf(enum_tag); | 8238 | const enum_tag_ty = sema.typeOf(enum_tag); |
| 8215 | 8239 | ||
| 8216 | var int_tag_type_buffer: Type.Payload.Bits = undefined; | 8240 | const int_tag_ty = try enum_tag_ty.intTagType().copy(arena); |
| 8217 | const int_tag_ty = try enum_tag_ty.intTagType(&int_tag_type_buffer).copy(arena); | ||
| 8218 | 8241 | ||
| 8219 | if (try sema.typeHasOnePossibleValue(enum_tag_ty)) |opv| { | 8242 | if (try sema.typeHasOnePossibleValue(enum_tag_ty)) |opv| { |
| 8220 | return sema.addConstant(int_tag_ty, opv); | 8243 | return sema.addConstant(int_tag_ty, opv); |
| ... | @@ -8231,6 +8254,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -8231,6 +8254,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 8231 | } | 8254 | } |
| 8232 | 8255 | ||
| 8233 | fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 8256 | fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 8257 | const mod = sema.mod; | ||
| 8234 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 8258 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 8235 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 8259 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 8236 | const src = inst_data.src(); | 8260 | const src = inst_data.src(); |
| ... | @@ -8239,15 +8263,14 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -8239,15 +8263,14 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 8239 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | 8263 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 8240 | const operand = try sema.resolveInst(extra.rhs); | 8264 | const operand = try sema.resolveInst(extra.rhs); |
| 8241 | 8265 | ||
| 8242 | if (dest_ty.zigTypeTag() != .Enum) { | 8266 | if (dest_ty.zigTypeTag(mod) != .Enum) { |
| 8243 | return sema.fail(block, dest_ty_src, "expected enum, found '{}'", .{dest_ty.fmt(sema.mod)}); | 8267 | return sema.fail(block, dest_ty_src, "expected enum, found '{}'", .{dest_ty.fmt(sema.mod)}); |
| 8244 | } | 8268 | } |
| 8245 | _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand)); | 8269 | _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand)); |
| 8246 | 8270 | ||
| 8247 | if (try sema.resolveMaybeUndefVal(operand)) |int_val| { | 8271 | if (try sema.resolveMaybeUndefVal(operand)) |int_val| { |
| 8248 | if (dest_ty.isNonexhaustiveEnum()) { | 8272 | if (dest_ty.isNonexhaustiveEnum()) { |
| 8249 | var buffer: Type.Payload.Bits = undefined; | 8273 | const int_tag_ty = dest_ty.intTagType(); |
| 8250 | const int_tag_ty = dest_ty.intTagType(&buffer); | ||
| 8251 | if (try sema.intFitsInType(int_val, int_tag_ty, null)) { | 8274 | if (try sema.intFitsInType(int_val, int_tag_ty, null)) { |
| 8252 | return sema.addConstant(dest_ty, int_val); | 8275 | return sema.addConstant(dest_ty, int_val); |
| 8253 | } | 8276 | } |
| ... | @@ -8329,11 +8352,12 @@ fn analyzeOptionalPayloadPtr( | ... | @@ -8329,11 +8352,12 @@ fn analyzeOptionalPayloadPtr( |
| 8329 | safety_check: bool, | 8352 | safety_check: bool, |
| 8330 | initializing: bool, | 8353 | initializing: bool, |
| 8331 | ) CompileError!Air.Inst.Ref { | 8354 | ) CompileError!Air.Inst.Ref { |
| 8355 | const mod = sema.mod; | ||
| 8332 | const optional_ptr_ty = sema.typeOf(optional_ptr); | 8356 | const optional_ptr_ty = sema.typeOf(optional_ptr); |
| 8333 | assert(optional_ptr_ty.zigTypeTag() == .Pointer); | 8357 | assert(optional_ptr_ty.zigTypeTag(mod) == .Pointer); |
| 8334 | 8358 | ||
| 8335 | const opt_type = optional_ptr_ty.elemType(); | 8359 | const opt_type = optional_ptr_ty.elemType(); |
| 8336 | if (opt_type.zigTypeTag() != .Optional) { | 8360 | if (opt_type.zigTypeTag(mod) != .Optional) { |
| 8337 | return sema.fail(block, src, "expected optional type, found '{}'", .{opt_type.fmt(sema.mod)}); | 8361 | return sema.fail(block, src, "expected optional type, found '{}'", .{opt_type.fmt(sema.mod)}); |
| 8338 | } | 8362 | } |
| 8339 | 8363 | ||
| ... | @@ -8361,7 +8385,7 @@ fn analyzeOptionalPayloadPtr( | ... | @@ -8361,7 +8385,7 @@ fn analyzeOptionalPayloadPtr( |
| 8361 | ); | 8385 | ); |
| 8362 | } | 8386 | } |
| 8363 | if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| { | 8387 | if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| { |
| 8364 | if (val.isNull()) { | 8388 | if (val.isNull(mod)) { |
| 8365 | return sema.fail(block, src, "unable to unwrap null", .{}); | 8389 | return sema.fail(block, src, "unable to unwrap null", .{}); |
| 8366 | } | 8390 | } |
| 8367 | // The same Value represents the pointer to the optional and the payload. | 8391 | // The same Value represents the pointer to the optional and the payload. |
| ... | @@ -8397,11 +8421,12 @@ fn zirOptionalPayload( | ... | @@ -8397,11 +8421,12 @@ fn zirOptionalPayload( |
| 8397 | const tracy = trace(@src()); | 8421 | const tracy = trace(@src()); |
| 8398 | defer tracy.end(); | 8422 | defer tracy.end(); |
| 8399 | 8423 | ||
| 8424 | const mod = sema.mod; | ||
| 8400 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 8425 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 8401 | const src = inst_data.src(); | 8426 | const src = inst_data.src(); |
| 8402 | const operand = try sema.resolveInst(inst_data.operand); | 8427 | const operand = try sema.resolveInst(inst_data.operand); |
| 8403 | const operand_ty = sema.typeOf(operand); | 8428 | const operand_ty = sema.typeOf(operand); |
| 8404 | const result_ty = switch (operand_ty.zigTypeTag()) { | 8429 | const result_ty = switch (operand_ty.zigTypeTag(mod)) { |
| 8405 | .Optional => try operand_ty.optionalChildAlloc(sema.arena), | 8430 | .Optional => try operand_ty.optionalChildAlloc(sema.arena), |
| 8406 | .Pointer => t: { | 8431 | .Pointer => t: { |
| 8407 | if (operand_ty.ptrSize() != .C) { | 8432 | if (operand_ty.ptrSize() != .C) { |
| ... | @@ -8424,7 +8449,7 @@ fn zirOptionalPayload( | ... | @@ -8424,7 +8449,7 @@ fn zirOptionalPayload( |
| 8424 | }; | 8449 | }; |
| 8425 | 8450 | ||
| 8426 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { | 8451 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { |
| 8427 | if (val.isNull()) { | 8452 | if (val.isNull(mod)) { |
| 8428 | return sema.fail(block, src, "unable to unwrap null", .{}); | 8453 | return sema.fail(block, src, "unable to unwrap null", .{}); |
| 8429 | } | 8454 | } |
| 8430 | if (val.castTag(.opt_payload)) |payload| { | 8455 | if (val.castTag(.opt_payload)) |payload| { |
| ... | @@ -8450,12 +8475,13 @@ fn zirErrUnionPayload( | ... | @@ -8450,12 +8475,13 @@ fn zirErrUnionPayload( |
| 8450 | const tracy = trace(@src()); | 8475 | const tracy = trace(@src()); |
| 8451 | defer tracy.end(); | 8476 | defer tracy.end(); |
| 8452 | 8477 | ||
| 8478 | const mod = sema.mod; | ||
| 8453 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 8479 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 8454 | const src = inst_data.src(); | 8480 | const src = inst_data.src(); |
| 8455 | const operand = try sema.resolveInst(inst_data.operand); | 8481 | const operand = try sema.resolveInst(inst_data.operand); |
| 8456 | const operand_src = src; | 8482 | const operand_src = src; |
| 8457 | const err_union_ty = sema.typeOf(operand); | 8483 | const err_union_ty = sema.typeOf(operand); |
| 8458 | if (err_union_ty.zigTypeTag() != .ErrorUnion) { | 8484 | if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) { |
| 8459 | return sema.fail(block, operand_src, "expected error union type, found '{}'", .{ | 8485 | return sema.fail(block, operand_src, "expected error union type, found '{}'", .{ |
| 8460 | err_union_ty.fmt(sema.mod), | 8486 | err_union_ty.fmt(sema.mod), |
| 8461 | }); | 8487 | }); |
| ... | @@ -8468,7 +8494,7 @@ fn analyzeErrUnionPayload( | ... | @@ -8468,7 +8494,7 @@ fn analyzeErrUnionPayload( |
| 8468 | block: *Block, | 8494 | block: *Block, |
| 8469 | src: LazySrcLoc, | 8495 | src: LazySrcLoc, |
| 8470 | err_union_ty: Type, | 8496 | err_union_ty: Type, |
| 8471 | operand: Zir.Inst.Ref, | 8497 | operand: Air.Inst.Ref, |
| 8472 | operand_src: LazySrcLoc, | 8498 | operand_src: LazySrcLoc, |
| 8473 | safety_check: bool, | 8499 | safety_check: bool, |
| 8474 | ) CompileError!Air.Inst.Ref { | 8500 | ) CompileError!Air.Inst.Ref { |
| ... | @@ -8517,10 +8543,11 @@ fn analyzeErrUnionPayloadPtr( | ... | @@ -8517,10 +8543,11 @@ fn analyzeErrUnionPayloadPtr( |
| 8517 | safety_check: bool, | 8543 | safety_check: bool, |
| 8518 | initializing: bool, | 8544 | initializing: bool, |
| 8519 | ) CompileError!Air.Inst.Ref { | 8545 | ) CompileError!Air.Inst.Ref { |
| 8546 | const mod = sema.mod; | ||
| 8520 | const operand_ty = sema.typeOf(operand); | 8547 | const operand_ty = sema.typeOf(operand); |
| 8521 | assert(operand_ty.zigTypeTag() == .Pointer); | 8548 | assert(operand_ty.zigTypeTag(mod) == .Pointer); |
| 8522 | 8549 | ||
| 8523 | if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) { | 8550 | if (operand_ty.elemType().zigTypeTag(mod) != .ErrorUnion) { |
| 8524 | return sema.fail(block, src, "expected error union type, found '{}'", .{ | 8551 | return sema.fail(block, src, "expected error union type, found '{}'", .{ |
| 8525 | operand_ty.elemType().fmt(sema.mod), | 8552 | operand_ty.elemType().fmt(sema.mod), |
| 8526 | }); | 8553 | }); |
| ... | @@ -8594,8 +8621,9 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -8594,8 +8621,9 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 8594 | } | 8621 | } |
| 8595 | 8622 | ||
| 8596 | fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref { | 8623 | fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref { |
| 8624 | const mod = sema.mod; | ||
| 8597 | const operand_ty = sema.typeOf(operand); | 8625 | const operand_ty = sema.typeOf(operand); |
| 8598 | if (operand_ty.zigTypeTag() != .ErrorUnion) { | 8626 | if (operand_ty.zigTypeTag(mod) != .ErrorUnion) { |
| 8599 | return sema.fail(block, src, "expected error union type, found '{}'", .{ | 8627 | return sema.fail(block, src, "expected error union type, found '{}'", .{ |
| 8600 | operand_ty.fmt(sema.mod), | 8628 | operand_ty.fmt(sema.mod), |
| 8601 | }); | 8629 | }); |
| ... | @@ -8617,13 +8645,14 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -8617,13 +8645,14 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 8617 | const tracy = trace(@src()); | 8645 | const tracy = trace(@src()); |
| 8618 | defer tracy.end(); | 8646 | defer tracy.end(); |
| 8619 | 8647 | ||
| 8648 | const mod = sema.mod; | ||
| 8620 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 8649 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 8621 | const src = inst_data.src(); | 8650 | const src = inst_data.src(); |
| 8622 | const operand = try sema.resolveInst(inst_data.operand); | 8651 | const operand = try sema.resolveInst(inst_data.operand); |
| 8623 | const operand_ty = sema.typeOf(operand); | 8652 | const operand_ty = sema.typeOf(operand); |
| 8624 | assert(operand_ty.zigTypeTag() == .Pointer); | 8653 | assert(operand_ty.zigTypeTag(mod) == .Pointer); |
| 8625 | 8654 | ||
| 8626 | if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) { | 8655 | if (operand_ty.elemType().zigTypeTag(mod) != .ErrorUnion) { |
| 8627 | return sema.fail(block, src, "expected error union type, found '{}'", .{ | 8656 | return sema.fail(block, src, "expected error union type, found '{}'", .{ |
| 8628 | operand_ty.elemType().fmt(sema.mod), | 8657 | operand_ty.elemType().fmt(sema.mod), |
| 8629 | }); | 8658 | }); |
| ... | @@ -8677,8 +8706,7 @@ fn zirFunc( | ... | @@ -8677,8 +8706,7 @@ fn zirFunc( |
| 8677 | extra_index += ret_ty_body.len; | 8706 | extra_index += ret_ty_body.len; |
| 8678 | 8707 | ||
| 8679 | const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, Type.type, "return type must be comptime-known"); | 8708 | const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, Type.type, "return type must be comptime-known"); |
| 8680 | var buffer: Value.ToTypeBuffer = undefined; | 8709 | break :blk try ret_ty_val.toType().copy(sema.arena); |
| 8681 | break :blk try ret_ty_val.toType(&buffer).copy(sema.arena); | ||
| 8682 | }, | 8710 | }, |
| 8683 | }; | 8711 | }; |
| 8684 | 8712 | ||
| ... | @@ -8849,6 +8877,7 @@ fn funcCommon( | ... | @@ -8849,6 +8877,7 @@ fn funcCommon( |
| 8849 | noalias_bits: u32, | 8877 | noalias_bits: u32, |
| 8850 | is_noinline: bool, | 8878 | is_noinline: bool, |
| 8851 | ) CompileError!Air.Inst.Ref { | 8879 | ) CompileError!Air.Inst.Ref { |
| 8880 | const mod = sema.mod; | ||
| 8852 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; | 8881 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; |
| 8853 | const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset }; | 8882 | const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset }; |
| 8854 | const func_src = LazySrcLoc.nodeOffset(src_node_offset); | 8883 | const func_src = LazySrcLoc.nodeOffset(src_node_offset); |
| ... | @@ -8890,31 +8919,6 @@ fn funcCommon( | ... | @@ -8890,31 +8919,6 @@ fn funcCommon( |
| 8890 | 8919 | ||
| 8891 | const target = sema.mod.getTarget(); | 8920 | const target = sema.mod.getTarget(); |
| 8892 | const fn_ty: Type = fn_ty: { | 8921 | const fn_ty: Type = fn_ty: { |
| 8893 | // Hot path for some common function types. | ||
| 8894 | // TODO can we eliminate some of these Type tag values? seems unnecessarily complicated. | ||
| 8895 | if (!is_generic and block.params.items.len == 0 and !var_args and !inferred_error_set and | ||
| 8896 | alignment.? == 0 and | ||
| 8897 | address_space.? == target_util.defaultAddressSpace(target, .function) and | ||
| 8898 | section == .default and | ||
| 8899 | !is_noinline) | ||
| 8900 | { | ||
| 8901 | if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Unspecified) { | ||
| 8902 | break :fn_ty Type.initTag(.fn_noreturn_no_args); | ||
| 8903 | } | ||
| 8904 | |||
| 8905 | if (bare_return_type.zigTypeTag() == .Void and cc.? == .Unspecified) { | ||
| 8906 | break :fn_ty Type.initTag(.fn_void_no_args); | ||
| 8907 | } | ||
| 8908 | |||
| 8909 | if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Naked) { | ||
| 8910 | break :fn_ty Type.initTag(.fn_naked_noreturn_no_args); | ||
| 8911 | } | ||
| 8912 | |||
| 8913 | if (bare_return_type.zigTypeTag() == .Void and cc.? == .C) { | ||
| 8914 | break :fn_ty Type.initTag(.fn_ccc_void_no_args); | ||
| 8915 | } | ||
| 8916 | } | ||
| 8917 | |||
| 8918 | // In the case of generic calling convention, or generic alignment, we use | 8922 | // In the case of generic calling convention, or generic alignment, we use |
| 8919 | // default values which are only meaningful for the generic function, *not* | 8923 | // default values which are only meaningful for the generic function, *not* |
| 8920 | // the instantiation, which can depend on comptime parameters. | 8924 | // the instantiation, which can depend on comptime parameters. |
| ... | @@ -8985,8 +8989,8 @@ fn funcCommon( | ... | @@ -8985,8 +8989,8 @@ fn funcCommon( |
| 8985 | }); | 8989 | }); |
| 8986 | }; | 8990 | }; |
| 8987 | 8991 | ||
| 8988 | if (!return_type.isValidReturnType()) { | 8992 | if (!return_type.isValidReturnType(mod)) { |
| 8989 | const opaque_str = if (return_type.zigTypeTag() == .Opaque) "opaque " else ""; | 8993 | const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else ""; |
| 8990 | const msg = msg: { | 8994 | const msg = msg: { |
| 8991 | const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{ | 8995 | const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{ |
| 8992 | opaque_str, return_type.fmt(sema.mod), | 8996 | opaque_str, return_type.fmt(sema.mod), |
| ... | @@ -9201,22 +9205,23 @@ fn analyzeParameter( | ... | @@ -9201,22 +9205,23 @@ fn analyzeParameter( |
| 9201 | has_body: bool, | 9205 | has_body: bool, |
| 9202 | is_noalias: bool, | 9206 | is_noalias: bool, |
| 9203 | ) !void { | 9207 | ) !void { |
| 9208 | const mod = sema.mod; | ||
| 9204 | const requires_comptime = try sema.typeRequiresComptime(param.ty); | 9209 | const requires_comptime = try sema.typeRequiresComptime(param.ty); |
| 9205 | comptime_params[i] = param.is_comptime or requires_comptime; | 9210 | comptime_params[i] = param.is_comptime or requires_comptime; |
| 9206 | const this_generic = param.ty.tag() == .generic_poison; | 9211 | const this_generic = param.ty.tag() == .generic_poison; |
| 9207 | is_generic.* = is_generic.* or this_generic; | 9212 | is_generic.* = is_generic.* or this_generic; |
| 9208 | const target = sema.mod.getTarget(); | 9213 | const target = mod.getTarget(); |
| 9209 | if (param.is_comptime and !Type.fnCallingConventionAllowsZigTypes(target, cc)) { | 9214 | if (param.is_comptime and !Type.fnCallingConventionAllowsZigTypes(target, cc)) { |
| 9210 | return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); | 9215 | return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); |
| 9211 | } | 9216 | } |
| 9212 | if (this_generic and !sema.no_partial_func_ty and !Type.fnCallingConventionAllowsZigTypes(target, cc)) { | 9217 | if (this_generic and !sema.no_partial_func_ty and !Type.fnCallingConventionAllowsZigTypes(target, cc)) { |
| 9213 | return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); | 9218 | return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); |
| 9214 | } | 9219 | } |
| 9215 | if (!param.ty.isValidParamType()) { | 9220 | if (!param.ty.isValidParamType(mod)) { |
| 9216 | const opaque_str = if (param.ty.zigTypeTag() == .Opaque) "opaque " else ""; | 9221 | const opaque_str = if (param.ty.zigTypeTag(mod) == .Opaque) "opaque " else ""; |
| 9217 | const msg = msg: { | 9222 | const msg = msg: { |
| 9218 | const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{ | 9223 | const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{ |
| 9219 | opaque_str, param.ty.fmt(sema.mod), | 9224 | opaque_str, param.ty.fmt(mod), |
| 9220 | }); | 9225 | }); |
| 9221 | errdefer msg.destroy(sema.gpa); | 9226 | errdefer msg.destroy(sema.gpa); |
| 9222 | 9227 | ||
| ... | @@ -9228,11 +9233,11 @@ fn analyzeParameter( | ... | @@ -9228,11 +9233,11 @@ fn analyzeParameter( |
| 9228 | if (!this_generic and !Type.fnCallingConventionAllowsZigTypes(target, cc) and !try sema.validateExternType(param.ty, .param_ty)) { | 9233 | if (!this_generic and !Type.fnCallingConventionAllowsZigTypes(target, cc) and !try sema.validateExternType(param.ty, .param_ty)) { |
| 9229 | const msg = msg: { | 9234 | const msg = msg: { |
| 9230 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ | 9235 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ |
| 9231 | param.ty.fmt(sema.mod), @tagName(cc), | 9236 | param.ty.fmt(mod), @tagName(cc), |
| 9232 | }); | 9237 | }); |
| 9233 | errdefer msg.destroy(sema.gpa); | 9238 | errdefer msg.destroy(sema.gpa); |
| 9234 | 9239 | ||
| 9235 | const src_decl = sema.mod.declPtr(block.src_decl); | 9240 | const src_decl = mod.declPtr(block.src_decl); |
| 9236 | try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty); | 9241 | try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty); |
| 9237 | 9242 | ||
| 9238 | try sema.addDeclaredHereNote(msg, param.ty); | 9243 | try sema.addDeclaredHereNote(msg, param.ty); |
| ... | @@ -9243,11 +9248,11 @@ fn analyzeParameter( | ... | @@ -9243,11 +9248,11 @@ fn analyzeParameter( |
| 9243 | if (!sema.is_generic_instantiation and requires_comptime and !param.is_comptime and has_body) { | 9248 | if (!sema.is_generic_instantiation and requires_comptime and !param.is_comptime and has_body) { |
| 9244 | const msg = msg: { | 9249 | const msg = msg: { |
| 9245 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{ | 9250 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{ |
| 9246 | param.ty.fmt(sema.mod), | 9251 | param.ty.fmt(mod), |
| 9247 | }); | 9252 | }); |
| 9248 | errdefer msg.destroy(sema.gpa); | 9253 | errdefer msg.destroy(sema.gpa); |
| 9249 | 9254 | ||
| 9250 | const src_decl = sema.mod.declPtr(block.src_decl); | 9255 | const src_decl = mod.declPtr(block.src_decl); |
| 9251 | try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl), param.ty); | 9256 | try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl), param.ty); |
| 9252 | 9257 | ||
| 9253 | try sema.addDeclaredHereNote(msg, param.ty); | 9258 | try sema.addDeclaredHereNote(msg, param.ty); |
| ... | @@ -9256,7 +9261,7 @@ fn analyzeParameter( | ... | @@ -9256,7 +9261,7 @@ fn analyzeParameter( |
| 9256 | return sema.failWithOwnedErrorMsg(msg); | 9261 | return sema.failWithOwnedErrorMsg(msg); |
| 9257 | } | 9262 | } |
| 9258 | if (!sema.is_generic_instantiation and !this_generic and is_noalias and | 9263 | if (!sema.is_generic_instantiation and !this_generic and is_noalias and |
| 9259 | !(param.ty.zigTypeTag() == .Pointer or param.ty.isPtrLikeOptional())) | 9264 | !(param.ty.zigTypeTag(mod) == .Pointer or param.ty.isPtrLikeOptional(mod))) |
| 9260 | { | 9265 | { |
| 9261 | return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{}); | 9266 | return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{}); |
| 9262 | } | 9267 | } |
| ... | @@ -9472,13 +9477,14 @@ fn analyzeAs( | ... | @@ -9472,13 +9477,14 @@ fn analyzeAs( |
| 9472 | zir_operand: Zir.Inst.Ref, | 9477 | zir_operand: Zir.Inst.Ref, |
| 9473 | no_cast_to_comptime_int: bool, | 9478 | no_cast_to_comptime_int: bool, |
| 9474 | ) CompileError!Air.Inst.Ref { | 9479 | ) CompileError!Air.Inst.Ref { |
| 9480 | const mod = sema.mod; | ||
| 9475 | const operand = try sema.resolveInst(zir_operand); | 9481 | const operand = try sema.resolveInst(zir_operand); |
| 9476 | if (zir_dest_type == .var_args_param) return operand; | 9482 | if (zir_dest_type == .var_args_param_type) return operand; |
| 9477 | const dest_ty = sema.resolveType(block, src, zir_dest_type) catch |err| switch (err) { | 9483 | const dest_ty = sema.resolveType(block, src, zir_dest_type) catch |err| switch (err) { |
| 9478 | error.GenericPoison => return operand, | 9484 | error.GenericPoison => return operand, |
| 9479 | else => |e| return e, | 9485 | else => |e| return e, |
| 9480 | }; | 9486 | }; |
| 9481 | if (dest_ty.zigTypeTag() == .NoReturn) { | 9487 | if (dest_ty.zigTypeTag(mod) == .NoReturn) { |
| 9482 | return sema.fail(block, src, "cannot cast to noreturn", .{}); | 9488 | return sema.fail(block, src, "cannot cast to noreturn", .{}); |
| 9483 | } | 9489 | } |
| 9484 | const is_ret = if (Zir.refToIndex(zir_dest_type)) |ptr_index| | 9490 | const is_ret = if (Zir.refToIndex(zir_dest_type)) |ptr_index| |
| ... | @@ -9495,11 +9501,12 @@ fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -9495,11 +9501,12 @@ fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9495 | const tracy = trace(@src()); | 9501 | const tracy = trace(@src()); |
| 9496 | defer tracy.end(); | 9502 | defer tracy.end(); |
| 9497 | 9503 | ||
| 9504 | const mod = sema.mod; | ||
| 9498 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 9505 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 9499 | const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 9506 | const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9500 | const ptr = try sema.resolveInst(inst_data.operand); | 9507 | const ptr = try sema.resolveInst(inst_data.operand); |
| 9501 | const ptr_ty = sema.typeOf(ptr); | 9508 | const ptr_ty = sema.typeOf(ptr); |
| 9502 | if (!ptr_ty.isPtrAtRuntime()) { | 9509 | if (!ptr_ty.isPtrAtRuntime(mod)) { |
| 9503 | return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)}); | 9510 | return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)}); |
| 9504 | } | 9511 | } |
| 9505 | if (try sema.resolveMaybeUndefValIntable(ptr)) |ptr_val| { | 9512 | if (try sema.resolveMaybeUndefValIntable(ptr)) |ptr_val| { |
| ... | @@ -9586,25 +9593,25 @@ fn intCast( | ... | @@ -9586,25 +9593,25 @@ fn intCast( |
| 9586 | operand_src: LazySrcLoc, | 9593 | operand_src: LazySrcLoc, |
| 9587 | runtime_safety: bool, | 9594 | runtime_safety: bool, |
| 9588 | ) CompileError!Air.Inst.Ref { | 9595 | ) CompileError!Air.Inst.Ref { |
| 9596 | const mod = sema.mod; | ||
| 9589 | const operand_ty = sema.typeOf(operand); | 9597 | const operand_ty = sema.typeOf(operand); |
| 9590 | const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, dest_ty_src); | 9598 | const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, dest_ty_src); |
| 9591 | const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src); | 9599 | const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src); |
| 9592 | 9600 | ||
| 9593 | if (try sema.isComptimeKnown(operand)) { | 9601 | if (try sema.isComptimeKnown(operand)) { |
| 9594 | return sema.coerce(block, dest_ty, operand, operand_src); | 9602 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 9595 | } else if (dest_scalar_ty.zigTypeTag() == .ComptimeInt) { | 9603 | } else if (dest_scalar_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 9596 | return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_int'", .{}); | 9604 | return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_int'", .{}); |
| 9597 | } | 9605 | } |
| 9598 | 9606 | ||
| 9599 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, dest_ty_src, operand_src); | 9607 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, dest_ty_src, operand_src); |
| 9600 | const is_vector = dest_ty.zigTypeTag() == .Vector; | 9608 | const is_vector = dest_ty.zigTypeTag(mod) == .Vector; |
| 9601 | 9609 | ||
| 9602 | if ((try sema.typeHasOnePossibleValue(dest_ty))) |opv| { | 9610 | if ((try sema.typeHasOnePossibleValue(dest_ty))) |opv| { |
| 9603 | // requirement: intCast(u0, input) iff input == 0 | 9611 | // requirement: intCast(u0, input) iff input == 0 |
| 9604 | if (runtime_safety and block.wantSafety()) { | 9612 | if (runtime_safety and block.wantSafety()) { |
| 9605 | try sema.requireRuntimeBlock(block, src, operand_src); | 9613 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 9606 | const target = sema.mod.getTarget(); | 9614 | const wanted_info = dest_scalar_ty.intInfo(mod); |
| 9607 | const wanted_info = dest_scalar_ty.intInfo(target); | ||
| 9608 | const wanted_bits = wanted_info.bits; | 9615 | const wanted_bits = wanted_info.bits; |
| 9609 | 9616 | ||
| 9610 | if (wanted_bits == 0) { | 9617 | if (wanted_bits == 0) { |
| ... | @@ -9631,9 +9638,8 @@ fn intCast( | ... | @@ -9631,9 +9638,8 @@ fn intCast( |
| 9631 | 9638 | ||
| 9632 | try sema.requireRuntimeBlock(block, src, operand_src); | 9639 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 9633 | if (runtime_safety and block.wantSafety()) { | 9640 | if (runtime_safety and block.wantSafety()) { |
| 9634 | const target = sema.mod.getTarget(); | 9641 | const actual_info = operand_scalar_ty.intInfo(mod); |
| 9635 | const actual_info = operand_scalar_ty.intInfo(target); | 9642 | const wanted_info = dest_scalar_ty.intInfo(mod); |
| 9636 | const wanted_info = dest_scalar_ty.intInfo(target); | ||
| 9637 | const actual_bits = actual_info.bits; | 9643 | const actual_bits = actual_info.bits; |
| 9638 | const wanted_bits = wanted_info.bits; | 9644 | const wanted_bits = wanted_info.bits; |
| 9639 | const actual_value_bits = actual_bits - @boolToInt(actual_info.signedness == .signed); | 9645 | const actual_value_bits = actual_bits - @boolToInt(actual_info.signedness == .signed); |
| ... | @@ -9642,7 +9648,7 @@ fn intCast( | ... | @@ -9642,7 +9648,7 @@ fn intCast( |
| 9642 | // range shrinkage | 9648 | // range shrinkage |
| 9643 | // requirement: int value fits into target type | 9649 | // requirement: int value fits into target type |
| 9644 | if (wanted_value_bits < actual_value_bits) { | 9650 | if (wanted_value_bits < actual_value_bits) { |
| 9645 | const dest_max_val_scalar = try dest_scalar_ty.maxInt(sema.arena, target); | 9651 | const dest_max_val_scalar = try dest_scalar_ty.maxInt(sema.arena, mod); |
| 9646 | const dest_max_val = if (is_vector) | 9652 | const dest_max_val = if (is_vector) |
| 9647 | try Value.Tag.repeated.create(sema.arena, dest_max_val_scalar) | 9653 | try Value.Tag.repeated.create(sema.arena, dest_max_val_scalar) |
| 9648 | else | 9654 | else |
| ... | @@ -9653,7 +9659,7 @@ fn intCast( | ... | @@ -9653,7 +9659,7 @@ fn intCast( |
| 9653 | if (actual_info.signedness == .signed) { | 9659 | if (actual_info.signedness == .signed) { |
| 9654 | // Reinterpret the sign-bit as part of the value. This will make | 9660 | // Reinterpret the sign-bit as part of the value. This will make |
| 9655 | // negative differences (`operand` > `dest_max`) appear too big. | 9661 | // negative differences (`operand` > `dest_max`) appear too big. |
| 9656 | const unsigned_operand_ty = try Type.Tag.int_unsigned.create(sema.arena, actual_bits); | 9662 | const unsigned_operand_ty = try mod.intType(.unsigned, actual_bits); |
| 9657 | const diff_unsigned = try block.addBitCast(unsigned_operand_ty, diff); | 9663 | const diff_unsigned = try block.addBitCast(unsigned_operand_ty, diff); |
| 9658 | 9664 | ||
| 9659 | // If the destination type is signed, then we need to double its | 9665 | // If the destination type is signed, then we need to double its |
| ... | @@ -9727,6 +9733,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9727,6 +9733,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9727 | const tracy = trace(@src()); | 9733 | const tracy = trace(@src()); |
| 9728 | defer tracy.end(); | 9734 | defer tracy.end(); |
| 9729 | 9735 | ||
| 9736 | const mod = sema.mod; | ||
| 9730 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 9737 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 9731 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 9738 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9732 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 9739 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| ... | @@ -9735,7 +9742,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9735,7 +9742,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9735 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | 9742 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 9736 | const operand = try sema.resolveInst(extra.rhs); | 9743 | const operand = try sema.resolveInst(extra.rhs); |
| 9737 | const operand_ty = sema.typeOf(operand); | 9744 | const operand_ty = sema.typeOf(operand); |
| 9738 | switch (dest_ty.zigTypeTag()) { | 9745 | switch (dest_ty.zigTypeTag(mod)) { |
| 9739 | .AnyFrame, | 9746 | .AnyFrame, |
| 9740 | .ComptimeFloat, | 9747 | .ComptimeFloat, |
| 9741 | .ComptimeInt, | 9748 | .ComptimeInt, |
| ... | @@ -9757,7 +9764,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9757,7 +9764,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9757 | const msg = msg: { | 9764 | const msg = msg: { |
| 9758 | const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)}); | 9765 | const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)}); |
| 9759 | errdefer msg.destroy(sema.gpa); | 9766 | errdefer msg.destroy(sema.gpa); |
| 9760 | switch (operand_ty.zigTypeTag()) { | 9767 | switch (operand_ty.zigTypeTag(mod)) { |
| 9761 | .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum to cast from '{}'", .{operand_ty.fmt(sema.mod)}), | 9768 | .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum to cast from '{}'", .{operand_ty.fmt(sema.mod)}), |
| 9762 | else => {}, | 9769 | else => {}, |
| 9763 | } | 9770 | } |
| ... | @@ -9771,7 +9778,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9771,7 +9778,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9771 | const msg = msg: { | 9778 | const msg = msg: { |
| 9772 | const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)}); | 9779 | const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)}); |
| 9773 | errdefer msg.destroy(sema.gpa); | 9780 | errdefer msg.destroy(sema.gpa); |
| 9774 | switch (operand_ty.zigTypeTag()) { | 9781 | switch (operand_ty.zigTypeTag(mod)) { |
| 9775 | .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToPtr to cast from '{}'", .{operand_ty.fmt(sema.mod)}), | 9782 | .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToPtr to cast from '{}'", .{operand_ty.fmt(sema.mod)}), |
| 9776 | .Pointer => try sema.errNote(block, dest_ty_src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(sema.mod)}), | 9783 | .Pointer => try sema.errNote(block, dest_ty_src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(sema.mod)}), |
| 9777 | else => {}, | 9784 | else => {}, |
| ... | @@ -9782,7 +9789,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9782,7 +9789,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9782 | return sema.failWithOwnedErrorMsg(msg); | 9789 | return sema.failWithOwnedErrorMsg(msg); |
| 9783 | }, | 9790 | }, |
| 9784 | .Struct, .Union => if (dest_ty.containerLayout() == .Auto) { | 9791 | .Struct, .Union => if (dest_ty.containerLayout() == .Auto) { |
| 9785 | const container = switch (dest_ty.zigTypeTag()) { | 9792 | const container = switch (dest_ty.zigTypeTag(mod)) { |
| 9786 | .Struct => "struct", | 9793 | .Struct => "struct", |
| 9787 | .Union => "union", | 9794 | .Union => "union", |
| 9788 | else => unreachable, | 9795 | else => unreachable, |
| ... | @@ -9799,7 +9806,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9799,7 +9806,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9799 | .Vector, | 9806 | .Vector, |
| 9800 | => {}, | 9807 | => {}, |
| 9801 | } | 9808 | } |
| 9802 | switch (operand_ty.zigTypeTag()) { | 9809 | switch (operand_ty.zigTypeTag(mod)) { |
| 9803 | .AnyFrame, | 9810 | .AnyFrame, |
| 9804 | .ComptimeFloat, | 9811 | .ComptimeFloat, |
| 9805 | .ComptimeInt, | 9812 | .ComptimeInt, |
| ... | @@ -9821,7 +9828,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9821,7 +9828,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9821 | const msg = msg: { | 9828 | const msg = msg: { |
| 9822 | const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}); | 9829 | const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}); |
| 9823 | errdefer msg.destroy(sema.gpa); | 9830 | errdefer msg.destroy(sema.gpa); |
| 9824 | switch (dest_ty.zigTypeTag()) { | 9831 | switch (dest_ty.zigTypeTag(mod)) { |
| 9825 | .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @enumToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}), | 9832 | .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @enumToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}), |
| 9826 | else => {}, | 9833 | else => {}, |
| 9827 | } | 9834 | } |
| ... | @@ -9834,7 +9841,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9834,7 +9841,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9834 | const msg = msg: { | 9841 | const msg = msg: { |
| 9835 | const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}); | 9842 | const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}); |
| 9836 | errdefer msg.destroy(sema.gpa); | 9843 | errdefer msg.destroy(sema.gpa); |
| 9837 | switch (dest_ty.zigTypeTag()) { | 9844 | switch (dest_ty.zigTypeTag(mod)) { |
| 9838 | .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @ptrToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}), | 9845 | .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @ptrToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}), |
| 9839 | .Pointer => try sema.errNote(block, operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(sema.mod)}), | 9846 | .Pointer => try sema.errNote(block, operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(sema.mod)}), |
| 9840 | else => {}, | 9847 | else => {}, |
| ... | @@ -9845,7 +9852,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9845,7 +9852,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9845 | return sema.failWithOwnedErrorMsg(msg); | 9852 | return sema.failWithOwnedErrorMsg(msg); |
| 9846 | }, | 9853 | }, |
| 9847 | .Struct, .Union => if (operand_ty.containerLayout() == .Auto) { | 9854 | .Struct, .Union => if (operand_ty.containerLayout() == .Auto) { |
| 9848 | const container = switch (operand_ty.zigTypeTag()) { | 9855 | const container = switch (operand_ty.zigTypeTag(mod)) { |
| 9849 | .Struct => "struct", | 9856 | .Struct => "struct", |
| 9850 | .Union => "union", | 9857 | .Union => "union", |
| 9851 | else => unreachable, | 9858 | else => unreachable, |
| ... | @@ -9869,6 +9876,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -9869,6 +9876,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 9869 | const tracy = trace(@src()); | 9876 | const tracy = trace(@src()); |
| 9870 | defer tracy.end(); | 9877 | defer tracy.end(); |
| 9871 | 9878 | ||
| 9879 | const mod = sema.mod; | ||
| 9872 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 9880 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 9873 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 9881 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9874 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 9882 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| ... | @@ -9878,7 +9886,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -9878,7 +9886,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 9878 | const operand = try sema.resolveInst(extra.rhs); | 9886 | const operand = try sema.resolveInst(extra.rhs); |
| 9879 | 9887 | ||
| 9880 | const target = sema.mod.getTarget(); | 9888 | const target = sema.mod.getTarget(); |
| 9881 | const dest_is_comptime_float = switch (dest_ty.zigTypeTag()) { | 9889 | const dest_is_comptime_float = switch (dest_ty.zigTypeTag(mod)) { |
| 9882 | .ComptimeFloat => true, | 9890 | .ComptimeFloat => true, |
| 9883 | .Float => false, | 9891 | .Float => false, |
| 9884 | else => return sema.fail( | 9892 | else => return sema.fail( |
| ... | @@ -9890,7 +9898,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -9890,7 +9898,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 9890 | }; | 9898 | }; |
| 9891 | 9899 | ||
| 9892 | const operand_ty = sema.typeOf(operand); | 9900 | const operand_ty = sema.typeOf(operand); |
| 9893 | switch (operand_ty.zigTypeTag()) { | 9901 | switch (operand_ty.zigTypeTag(mod)) { |
| 9894 | .ComptimeFloat, .Float, .ComptimeInt => {}, | 9902 | .ComptimeFloat, .Float, .ComptimeInt => {}, |
| 9895 | else => return sema.fail( | 9903 | else => return sema.fail( |
| 9896 | block, | 9904 | block, |
| ... | @@ -9944,20 +9952,21 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9944,20 +9952,21 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9944 | const tracy = trace(@src()); | 9952 | const tracy = trace(@src()); |
| 9945 | defer tracy.end(); | 9953 | defer tracy.end(); |
| 9946 | 9954 | ||
| 9955 | const mod = sema.mod; | ||
| 9947 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 9956 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 9948 | const src = inst_data.src(); | 9957 | const src = inst_data.src(); |
| 9949 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 9958 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 9950 | const array_ptr = try sema.resolveInst(extra.lhs); | 9959 | const array_ptr = try sema.resolveInst(extra.lhs); |
| 9951 | const elem_index = try sema.resolveInst(extra.rhs); | 9960 | const elem_index = try sema.resolveInst(extra.rhs); |
| 9952 | const indexable_ty = sema.typeOf(array_ptr); | 9961 | const indexable_ty = sema.typeOf(array_ptr); |
| 9953 | if (indexable_ty.zigTypeTag() != .Pointer) { | 9962 | if (indexable_ty.zigTypeTag(mod) != .Pointer) { |
| 9954 | const capture_src: LazySrcLoc = .{ .for_capture_from_input = inst_data.src_node }; | 9963 | const capture_src: LazySrcLoc = .{ .for_capture_from_input = inst_data.src_node }; |
| 9955 | const msg = msg: { | 9964 | const msg = msg: { |
| 9956 | const msg = try sema.errMsg(block, capture_src, "pointer capture of non pointer type '{}'", .{ | 9965 | const msg = try sema.errMsg(block, capture_src, "pointer capture of non pointer type '{}'", .{ |
| 9957 | indexable_ty.fmt(sema.mod), | 9966 | indexable_ty.fmt(sema.mod), |
| 9958 | }); | 9967 | }); |
| 9959 | errdefer msg.destroy(sema.gpa); | 9968 | errdefer msg.destroy(sema.gpa); |
| 9960 | if (indexable_ty.zigTypeTag() == .Array) { | 9969 | if (indexable_ty.zigTypeTag(mod) == .Array) { |
| 9961 | try sema.errNote(block, src, msg, "consider using '&' here", .{}); | 9970 | try sema.errNote(block, src, msg, "consider using '&' here", .{}); |
| 9962 | } | 9971 | } |
| 9963 | break :msg msg; | 9972 | break :msg msg; |
| ... | @@ -10076,6 +10085,7 @@ fn zirSwitchCapture( | ... | @@ -10076,6 +10085,7 @@ fn zirSwitchCapture( |
| 10076 | const tracy = trace(@src()); | 10085 | const tracy = trace(@src()); |
| 10077 | defer tracy.end(); | 10086 | defer tracy.end(); |
| 10078 | 10087 | ||
| 10088 | const mod = sema.mod; | ||
| 10079 | const zir_datas = sema.code.instructions.items(.data); | 10089 | const zir_datas = sema.code.instructions.items(.data); |
| 10080 | const capture_info = zir_datas[inst].switch_capture; | 10090 | const capture_info = zir_datas[inst].switch_capture; |
| 10081 | const switch_info = zir_datas[capture_info.switch_inst].pl_node; | 10091 | const switch_info = zir_datas[capture_info.switch_inst].pl_node; |
| ... | @@ -10091,7 +10101,7 @@ fn zirSwitchCapture( | ... | @@ -10091,7 +10101,7 @@ fn zirSwitchCapture( |
| 10091 | 10101 | ||
| 10092 | if (block.inline_case_capture != .none) { | 10102 | if (block.inline_case_capture != .none) { |
| 10093 | const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, undefined) catch unreachable; | 10103 | const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, undefined) catch unreachable; |
| 10094 | if (operand_ty.zigTypeTag() == .Union) { | 10104 | if (operand_ty.zigTypeTag(mod) == .Union) { |
| 10095 | const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(item_val, sema.mod).?); | 10105 | const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(item_val, sema.mod).?); |
| 10096 | const union_obj = operand_ty.cast(Type.Payload.Union).?.data; | 10106 | const union_obj = operand_ty.cast(Type.Payload.Union).?.data; |
| 10097 | const field_ty = union_obj.fields.values()[field_index].ty; | 10107 | const field_ty = union_obj.fields.values()[field_index].ty; |
| ... | @@ -10144,7 +10154,7 @@ fn zirSwitchCapture( | ... | @@ -10144,7 +10154,7 @@ fn zirSwitchCapture( |
| 10144 | return operand_ptr; | 10154 | return operand_ptr; |
| 10145 | } | 10155 | } |
| 10146 | 10156 | ||
| 10147 | switch (operand_ty.zigTypeTag()) { | 10157 | switch (operand_ty.zigTypeTag(mod)) { |
| 10148 | .ErrorSet => if (block.switch_else_err_ty) |some| { | 10158 | .ErrorSet => if (block.switch_else_err_ty) |some| { |
| 10149 | return sema.bitCast(block, some, operand, operand_src, null); | 10159 | return sema.bitCast(block, some, operand, operand_src, null); |
| 10150 | } else { | 10160 | } else { |
| ... | @@ -10162,7 +10172,7 @@ fn zirSwitchCapture( | ... | @@ -10162,7 +10172,7 @@ fn zirSwitchCapture( |
| 10162 | switch_extra.data.getScalarProng(sema.code, switch_extra.end, capture_info.prong_index).item, | 10172 | switch_extra.data.getScalarProng(sema.code, switch_extra.end, capture_info.prong_index).item, |
| 10163 | }; | 10173 | }; |
| 10164 | 10174 | ||
| 10165 | switch (operand_ty.zigTypeTag()) { | 10175 | switch (operand_ty.zigTypeTag(mod)) { |
| 10166 | .Union => { | 10176 | .Union => { |
| 10167 | const union_obj = operand_ty.cast(Type.Payload.Union).?.data; | 10177 | const union_obj = operand_ty.cast(Type.Payload.Union).?.data; |
| 10168 | const first_item = try sema.resolveInst(items[0]); | 10178 | const first_item = try sema.resolveInst(items[0]); |
| ... | @@ -10269,6 +10279,7 @@ fn zirSwitchCapture( | ... | @@ -10269,6 +10279,7 @@ fn zirSwitchCapture( |
| 10269 | } | 10279 | } |
| 10270 | 10280 | ||
| 10271 | fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 10281 | fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 10282 | const mod = sema.mod; | ||
| 10272 | const zir_datas = sema.code.instructions.items(.data); | 10283 | const zir_datas = sema.code.instructions.items(.data); |
| 10273 | const inst_data = zir_datas[inst].un_tok; | 10284 | const inst_data = zir_datas[inst].un_tok; |
| 10274 | const src = inst_data.src(); | 10285 | const src = inst_data.src(); |
| ... | @@ -10280,7 +10291,7 @@ fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile | ... | @@ -10280,7 +10291,7 @@ fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile |
| 10280 | const operand_ptr_ty = sema.typeOf(operand_ptr); | 10291 | const operand_ptr_ty = sema.typeOf(operand_ptr); |
| 10281 | const operand_ty = if (is_ref) operand_ptr_ty.childType() else operand_ptr_ty; | 10292 | const operand_ty = if (is_ref) operand_ptr_ty.childType() else operand_ptr_ty; |
| 10282 | 10293 | ||
| 10283 | if (operand_ty.zigTypeTag() != .Union) { | 10294 | if (operand_ty.zigTypeTag(mod) != .Union) { |
| 10284 | const msg = msg: { | 10295 | const msg = msg: { |
| 10285 | const msg = try sema.errMsg(block, src, "cannot capture tag of non-union type '{}'", .{ | 10296 | const msg = try sema.errMsg(block, src, "cannot capture tag of non-union type '{}'", .{ |
| 10286 | operand_ty.fmt(sema.mod), | 10297 | operand_ty.fmt(sema.mod), |
| ... | @@ -10301,6 +10312,7 @@ fn zirSwitchCond( | ... | @@ -10301,6 +10312,7 @@ fn zirSwitchCond( |
| 10301 | inst: Zir.Inst.Index, | 10312 | inst: Zir.Inst.Index, |
| 10302 | is_ref: bool, | 10313 | is_ref: bool, |
| 10303 | ) CompileError!Air.Inst.Ref { | 10314 | ) CompileError!Air.Inst.Ref { |
| 10315 | const mod = sema.mod; | ||
| 10304 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 10316 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 10305 | const src = inst_data.src(); | 10317 | const src = inst_data.src(); |
| 10306 | const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = inst_data.src_node }; | 10318 | const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = inst_data.src_node }; |
| ... | @@ -10311,7 +10323,7 @@ fn zirSwitchCond( | ... | @@ -10311,7 +10323,7 @@ fn zirSwitchCond( |
| 10311 | operand_ptr; | 10323 | operand_ptr; |
| 10312 | const operand_ty = sema.typeOf(operand); | 10324 | const operand_ty = sema.typeOf(operand); |
| 10313 | 10325 | ||
| 10314 | switch (operand_ty.zigTypeTag()) { | 10326 | switch (operand_ty.zigTypeTag(mod)) { |
| 10315 | .Type, | 10327 | .Type, |
| 10316 | .Void, | 10328 | .Void, |
| 10317 | .Bool, | 10329 | .Bool, |
| ... | @@ -10371,6 +10383,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10371,6 +10383,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10371 | const tracy = trace(@src()); | 10383 | const tracy = trace(@src()); |
| 10372 | defer tracy.end(); | 10384 | defer tracy.end(); |
| 10373 | 10385 | ||
| 10386 | const mod = sema.mod; | ||
| 10374 | const gpa = sema.gpa; | 10387 | const gpa = sema.gpa; |
| 10375 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 10388 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 10376 | const src = inst_data.src(); | 10389 | const src = inst_data.src(); |
| ... | @@ -10415,7 +10428,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10415,7 +10428,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10415 | const target_ty = sema.typeOf(raw_operand); | 10428 | const target_ty = sema.typeOf(raw_operand); |
| 10416 | break :blk if (zir_tags[cond_index] == .switch_cond_ref) target_ty.elemType() else target_ty; | 10429 | break :blk if (zir_tags[cond_index] == .switch_cond_ref) target_ty.elemType() else target_ty; |
| 10417 | }; | 10430 | }; |
| 10418 | const union_originally = maybe_union_ty.zigTypeTag() == .Union; | 10431 | const union_originally = maybe_union_ty.zigTypeTag(mod) == .Union; |
| 10419 | 10432 | ||
| 10420 | // Duplicate checking variables later also used for `inline else`. | 10433 | // Duplicate checking variables later also used for `inline else`. |
| 10421 | var seen_enum_fields: []?Module.SwitchProngSrc = &.{}; | 10434 | var seen_enum_fields: []?Module.SwitchProngSrc = &.{}; |
| ... | @@ -10433,7 +10446,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10433,7 +10446,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10433 | var empty_enum = false; | 10446 | var empty_enum = false; |
| 10434 | 10447 | ||
| 10435 | const operand_ty = sema.typeOf(operand); | 10448 | const operand_ty = sema.typeOf(operand); |
| 10436 | const err_set = operand_ty.zigTypeTag() == .ErrorSet; | 10449 | const err_set = operand_ty.zigTypeTag(mod) == .ErrorSet; |
| 10437 | 10450 | ||
| 10438 | var else_error_ty: ?Type = null; | 10451 | var else_error_ty: ?Type = null; |
| 10439 | 10452 | ||
| ... | @@ -10459,10 +10472,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10459,10 +10472,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10459 | return sema.failWithOwnedErrorMsg(msg); | 10472 | return sema.failWithOwnedErrorMsg(msg); |
| 10460 | } | 10473 | } |
| 10461 | 10474 | ||
| 10462 | const target = sema.mod.getTarget(); | ||
| 10463 | |||
| 10464 | // Validate for duplicate items, missing else prong, and invalid range. | 10475 | // Validate for duplicate items, missing else prong, and invalid range. |
| 10465 | switch (operand_ty.zigTypeTag()) { | 10476 | switch (operand_ty.zigTypeTag(mod)) { |
| 10466 | .Union => unreachable, // handled in zirSwitchCond | 10477 | .Union => unreachable, // handled in zirSwitchCond |
| 10467 | .Enum => { | 10478 | .Enum => { |
| 10468 | seen_enum_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount()); | 10479 | seen_enum_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount()); |
| ... | @@ -10774,12 +10785,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -10774,12 +10785,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10774 | } | 10785 | } |
| 10775 | 10786 | ||
| 10776 | check_range: { | 10787 | check_range: { |
| 10777 | if (operand_ty.zigTypeTag() == .Int) { | 10788 | if (operand_ty.zigTypeTag(mod) == .Int) { |
| 10778 | var arena = std.heap.ArenaAllocator.init(gpa); | 10789 | var arena = std.heap.ArenaAllocator.init(gpa); |
| 10779 | defer arena.deinit(); | 10790 | defer arena.deinit(); |
| 10780 | 10791 | ||
| 10781 | const min_int = try operand_ty.minInt(arena.allocator(), target); | 10792 | const min_int = try operand_ty.minInt(arena.allocator(), mod); |
| 10782 | const max_int = try operand_ty.maxInt(arena.allocator(), target); | 10793 | const max_int = try operand_ty.maxInt(arena.allocator(), mod); |
| 10783 | if (try range_set.spans(min_int, max_int, operand_ty)) { | 10794 | if (try range_set.spans(min_int, max_int, operand_ty)) { |
| 10784 | if (special_prong == .@"else") { | 10795 | if (special_prong == .@"else") { |
| 10785 | return sema.fail( | 10796 | return sema.fail( |
| ... | @@ -11080,7 +11091,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11080,7 +11091,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11080 | if (err_set and try sema.maybeErrorUnwrap(block, special.body, operand)) { | 11091 | if (err_set and try sema.maybeErrorUnwrap(block, special.body, operand)) { |
| 11081 | return Air.Inst.Ref.unreachable_value; | 11092 | return Air.Inst.Ref.unreachable_value; |
| 11082 | } | 11093 | } |
| 11083 | if (sema.mod.backendSupportsFeature(.is_named_enum_value) and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and | 11094 | if (sema.mod.backendSupportsFeature(.is_named_enum_value) and block.wantSafety() and operand_ty.zigTypeTag(mod) == .Enum and |
| 11084 | (!operand_ty.isNonexhaustiveEnum() or union_originally)) | 11095 | (!operand_ty.isNonexhaustiveEnum() or union_originally)) |
| 11085 | { | 11096 | { |
| 11086 | try sema.zirDbgStmt(block, cond_dbg_node_index); | 11097 | try sema.zirDbgStmt(block, cond_dbg_node_index); |
| ... | @@ -11135,7 +11146,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11135,7 +11146,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11135 | const analyze_body = if (union_originally) blk: { | 11146 | const analyze_body = if (union_originally) blk: { |
| 11136 | const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable; | 11147 | const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable; |
| 11137 | const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod); | 11148 | const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod); |
| 11138 | break :blk field_ty.zigTypeTag() != .NoReturn; | 11149 | break :blk field_ty.zigTypeTag(mod) != .NoReturn; |
| 11139 | } else true; | 11150 | } else true; |
| 11140 | 11151 | ||
| 11141 | if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) { | 11152 | if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) { |
| ... | @@ -11242,7 +11253,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11242,7 +11253,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11242 | const analyze_body = if (union_originally) blk: { | 11253 | const analyze_body = if (union_originally) blk: { |
| 11243 | const item_val = sema.resolveConstValue(block, .unneeded, item, undefined) catch unreachable; | 11254 | const item_val = sema.resolveConstValue(block, .unneeded, item, undefined) catch unreachable; |
| 11244 | const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod); | 11255 | const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod); |
| 11245 | break :blk field_ty.zigTypeTag() != .NoReturn; | 11256 | break :blk field_ty.zigTypeTag(mod) != .NoReturn; |
| 11246 | } else true; | 11257 | } else true; |
| 11247 | 11258 | ||
| 11248 | if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) { | 11259 | if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) { |
| ... | @@ -11286,7 +11297,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11286,7 +11297,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11286 | const item = try sema.resolveInst(item_ref); | 11297 | const item = try sema.resolveInst(item_ref); |
| 11287 | const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable; | 11298 | const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable; |
| 11288 | const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod); | 11299 | const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod); |
| 11289 | if (field_ty.zigTypeTag() != .NoReturn) break true; | 11300 | if (field_ty.zigTypeTag(mod) != .NoReturn) break true; |
| 11290 | } else false | 11301 | } else false |
| 11291 | else | 11302 | else |
| 11292 | true; | 11303 | true; |
| ... | @@ -11409,7 +11420,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11409,7 +11420,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11409 | var final_else_body: []const Air.Inst.Index = &.{}; | 11420 | var final_else_body: []const Air.Inst.Index = &.{}; |
| 11410 | if (special.body.len != 0 or !is_first or case_block.wantSafety()) { | 11421 | if (special.body.len != 0 or !is_first or case_block.wantSafety()) { |
| 11411 | var emit_bb = false; | 11422 | var emit_bb = false; |
| 11412 | if (special.is_inline) switch (operand_ty.zigTypeTag()) { | 11423 | if (special.is_inline) switch (operand_ty.zigTypeTag(mod)) { |
| 11413 | .Enum => { | 11424 | .Enum => { |
| 11414 | if (operand_ty.isNonexhaustiveEnum() and !union_originally) { | 11425 | if (operand_ty.isNonexhaustiveEnum() and !union_originally) { |
| 11415 | return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{ | 11426 | return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{ |
| ... | @@ -11429,7 +11440,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11429,7 +11440,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11429 | 11440 | ||
| 11430 | const analyze_body = if (union_originally) blk: { | 11441 | const analyze_body = if (union_originally) blk: { |
| 11431 | const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod); | 11442 | const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod); |
| 11432 | break :blk field_ty.zigTypeTag() != .NoReturn; | 11443 | break :blk field_ty.zigTypeTag(mod) != .NoReturn; |
| 11433 | } else true; | 11444 | } else true; |
| 11434 | 11445 | ||
| 11435 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 11446 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); |
| ... | @@ -11551,7 +11562,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11551,7 +11562,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11551 | case_block.inline_case_capture = .none; | 11562 | case_block.inline_case_capture = .none; |
| 11552 | 11563 | ||
| 11553 | if (sema.mod.backendSupportsFeature(.is_named_enum_value) and special.body.len != 0 and block.wantSafety() and | 11564 | if (sema.mod.backendSupportsFeature(.is_named_enum_value) and special.body.len != 0 and block.wantSafety() and |
| 11554 | operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally)) | 11565 | operand_ty.zigTypeTag(mod) == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally)) |
| 11555 | { | 11566 | { |
| 11556 | try sema.zirDbgStmt(&case_block, cond_dbg_node_index); | 11567 | try sema.zirDbgStmt(&case_block, cond_dbg_node_index); |
| 11557 | const ok = try case_block.addUnOp(.is_named_enum_value, operand); | 11568 | const ok = try case_block.addUnOp(.is_named_enum_value, operand); |
| ... | @@ -11563,7 +11574,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11563,7 +11574,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11563 | if (seen_field != null) continue; | 11574 | if (seen_field != null) continue; |
| 11564 | const union_obj = maybe_union_ty.cast(Type.Payload.Union).?.data; | 11575 | const union_obj = maybe_union_ty.cast(Type.Payload.Union).?.data; |
| 11565 | const field_ty = union_obj.fields.values()[index].ty; | 11576 | const field_ty = union_obj.fields.values()[index].ty; |
| 11566 | if (field_ty.zigTypeTag() != .NoReturn) break true; | 11577 | if (field_ty.zigTypeTag(mod) != .NoReturn) break true; |
| 11567 | } else false | 11578 | } else false |
| 11568 | else | 11579 | else |
| 11569 | true; | 11580 | true; |
| ... | @@ -11629,9 +11640,9 @@ const RangeSetUnhandledIterator = struct { | ... | @@ -11629,9 +11640,9 @@ const RangeSetUnhandledIterator = struct { |
| 11629 | first: bool = true, | 11640 | first: bool = true, |
| 11630 | 11641 | ||
| 11631 | fn init(sema: *Sema, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator { | 11642 | fn init(sema: *Sema, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator { |
| 11632 | const target = sema.mod.getTarget(); | 11643 | const mod = sema.mod; |
| 11633 | const min = try ty.minInt(sema.arena, target); | 11644 | const min = try ty.minInt(sema.arena, mod); |
| 11634 | const max = try ty.maxInt(sema.arena, target); | 11645 | const max = try ty.maxInt(sema.arena, mod); |
| 11635 | 11646 | ||
| 11636 | return RangeSetUnhandledIterator{ | 11647 | return RangeSetUnhandledIterator{ |
| 11637 | .sema = sema, | 11648 | .sema = sema, |
| ... | @@ -11931,18 +11942,19 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op | ... | @@ -11931,18 +11942,19 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op |
| 11931 | } | 11942 | } |
| 11932 | 11943 | ||
| 11933 | fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, cond: Zir.Inst.Ref, cond_src: LazySrcLoc) !void { | 11944 | fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, cond: Zir.Inst.Ref, cond_src: LazySrcLoc) !void { |
| 11945 | const mod = sema.mod; | ||
| 11934 | const index = Zir.refToIndex(cond) orelse return; | 11946 | const index = Zir.refToIndex(cond) orelse return; |
| 11935 | if (sema.code.instructions.items(.tag)[index] != .is_non_err) return; | 11947 | if (sema.code.instructions.items(.tag)[index] != .is_non_err) return; |
| 11936 | 11948 | ||
| 11937 | const err_inst_data = sema.code.instructions.items(.data)[index].un_node; | 11949 | const err_inst_data = sema.code.instructions.items(.data)[index].un_node; |
| 11938 | const err_operand = try sema.resolveInst(err_inst_data.operand); | 11950 | const err_operand = try sema.resolveInst(err_inst_data.operand); |
| 11939 | const operand_ty = sema.typeOf(err_operand); | 11951 | const operand_ty = sema.typeOf(err_operand); |
| 11940 | if (operand_ty.zigTypeTag() == .ErrorSet) { | 11952 | if (operand_ty.zigTypeTag(mod) == .ErrorSet) { |
| 11941 | try sema.maybeErrorUnwrapComptime(block, body, err_operand); | 11953 | try sema.maybeErrorUnwrapComptime(block, body, err_operand); |
| 11942 | return; | 11954 | return; |
| 11943 | } | 11955 | } |
| 11944 | if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| { | 11956 | if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| { |
| 11945 | if (!operand_ty.isError()) return; | 11957 | if (!operand_ty.isError(mod)) return; |
| 11946 | if (val.getError() == null) return; | 11958 | if (val.getError() == null) return; |
| 11947 | try sema.maybeErrorUnwrapComptime(block, body, err_operand); | 11959 | try sema.maybeErrorUnwrapComptime(block, body, err_operand); |
| 11948 | } | 11960 | } |
| ... | @@ -11972,6 +11984,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I | ... | @@ -11972,6 +11984,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I |
| 11972 | } | 11984 | } |
| 11973 | 11985 | ||
| 11974 | fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 11986 | fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 11987 | const mod = sema.mod; | ||
| 11975 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 11988 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 11976 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 11989 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 11977 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 11990 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| ... | @@ -11995,7 +12008,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -11995,7 +12008,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 11995 | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false; | 12008 | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false; |
| 11996 | break :hf field_index < ty.structFieldCount(); | 12009 | break :hf field_index < ty.structFieldCount(); |
| 11997 | } | 12010 | } |
| 11998 | break :hf switch (ty.zigTypeTag()) { | 12011 | break :hf switch (ty.zigTypeTag(mod)) { |
| 11999 | .Struct => ty.structFields().contains(field_name), | 12012 | .Struct => ty.structFields().contains(field_name), |
| 12000 | .Union => ty.unionFields().contains(field_name), | 12013 | .Union => ty.unionFields().contains(field_name), |
| 12001 | .Enum => ty.enumFields().contains(field_name), | 12014 | .Enum => ty.enumFields().contains(field_name), |
| ... | @@ -12126,6 +12139,7 @@ fn zirShl( | ... | @@ -12126,6 +12139,7 @@ fn zirShl( |
| 12126 | const tracy = trace(@src()); | 12139 | const tracy = trace(@src()); |
| 12127 | defer tracy.end(); | 12140 | defer tracy.end(); |
| 12128 | 12141 | ||
| 12142 | const mod = sema.mod; | ||
| 12129 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 12143 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 12130 | const src = inst_data.src(); | 12144 | const src = inst_data.src(); |
| 12131 | sema.src = src; | 12145 | sema.src = src; |
| ... | @@ -12136,11 +12150,10 @@ fn zirShl( | ... | @@ -12136,11 +12150,10 @@ fn zirShl( |
| 12136 | const rhs = try sema.resolveInst(extra.rhs); | 12150 | const rhs = try sema.resolveInst(extra.rhs); |
| 12137 | const lhs_ty = sema.typeOf(lhs); | 12151 | const lhs_ty = sema.typeOf(lhs); |
| 12138 | const rhs_ty = sema.typeOf(rhs); | 12152 | const rhs_ty = sema.typeOf(rhs); |
| 12139 | const target = sema.mod.getTarget(); | ||
| 12140 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 12153 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 12141 | 12154 | ||
| 12142 | const scalar_ty = lhs_ty.scalarType(); | 12155 | const scalar_ty = lhs_ty.scalarType(mod); |
| 12143 | const scalar_rhs_ty = rhs_ty.scalarType(); | 12156 | const scalar_rhs_ty = rhs_ty.scalarType(mod); |
| 12144 | 12157 | ||
| 12145 | // TODO coerce rhs if air_tag is not shl_sat | 12158 | // TODO coerce rhs if air_tag is not shl_sat |
| 12146 | const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, scalar_rhs_ty); | 12159 | const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, scalar_rhs_ty); |
| ... | @@ -12156,18 +12169,18 @@ fn zirShl( | ... | @@ -12156,18 +12169,18 @@ fn zirShl( |
| 12156 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) { | 12169 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) { |
| 12157 | return lhs; | 12170 | return lhs; |
| 12158 | } | 12171 | } |
| 12159 | if (scalar_ty.zigTypeTag() != .ComptimeInt and air_tag != .shl_sat) { | 12172 | if (scalar_ty.zigTypeTag(mod) != .ComptimeInt and air_tag != .shl_sat) { |
| 12160 | var bits_payload = Value.Payload.U64{ | 12173 | var bits_payload = Value.Payload.U64{ |
| 12161 | .base = .{ .tag = .int_u64 }, | 12174 | .base = .{ .tag = .int_u64 }, |
| 12162 | .data = scalar_ty.intInfo(target).bits, | 12175 | .data = scalar_ty.intInfo(mod).bits, |
| 12163 | }; | 12176 | }; |
| 12164 | const bit_value = Value.initPayload(&bits_payload.base); | 12177 | const bit_value = Value.initPayload(&bits_payload.base); |
| 12165 | if (rhs_ty.zigTypeTag() == .Vector) { | 12178 | if (rhs_ty.zigTypeTag(mod) == .Vector) { |
| 12166 | var i: usize = 0; | 12179 | var i: usize = 0; |
| 12167 | while (i < rhs_ty.vectorLen()) : (i += 1) { | 12180 | while (i < rhs_ty.vectorLen()) : (i += 1) { |
| 12168 | var elem_value_buf: Value.ElemValueBuffer = undefined; | 12181 | var elem_value_buf: Value.ElemValueBuffer = undefined; |
| 12169 | const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf); | 12182 | const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf); |
| 12170 | if (rhs_elem.compareHetero(.gte, bit_value, target)) { | 12183 | if (rhs_elem.compareHetero(.gte, bit_value, mod)) { |
| 12171 | return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{ | 12184 | return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{ |
| 12172 | rhs_elem.fmtValue(scalar_ty, sema.mod), | 12185 | rhs_elem.fmtValue(scalar_ty, sema.mod), |
| 12173 | i, | 12186 | i, |
| ... | @@ -12175,26 +12188,26 @@ fn zirShl( | ... | @@ -12175,26 +12188,26 @@ fn zirShl( |
| 12175 | }); | 12188 | }); |
| 12176 | } | 12189 | } |
| 12177 | } | 12190 | } |
| 12178 | } else if (rhs_val.compareHetero(.gte, bit_value, target)) { | 12191 | } else if (rhs_val.compareHetero(.gte, bit_value, mod)) { |
| 12179 | return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{ | 12192 | return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{ |
| 12180 | rhs_val.fmtValue(scalar_ty, sema.mod), | 12193 | rhs_val.fmtValue(scalar_ty, sema.mod), |
| 12181 | scalar_ty.fmt(sema.mod), | 12194 | scalar_ty.fmt(sema.mod), |
| 12182 | }); | 12195 | }); |
| 12183 | } | 12196 | } |
| 12184 | } | 12197 | } |
| 12185 | if (rhs_ty.zigTypeTag() == .Vector) { | 12198 | if (rhs_ty.zigTypeTag(mod) == .Vector) { |
| 12186 | var i: usize = 0; | 12199 | var i: usize = 0; |
| 12187 | while (i < rhs_ty.vectorLen()) : (i += 1) { | 12200 | while (i < rhs_ty.vectorLen()) : (i += 1) { |
| 12188 | var elem_value_buf: Value.ElemValueBuffer = undefined; | 12201 | var elem_value_buf: Value.ElemValueBuffer = undefined; |
| 12189 | const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf); | 12202 | const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf); |
| 12190 | if (rhs_elem.compareHetero(.lt, Value.zero, target)) { | 12203 | if (rhs_elem.compareHetero(.lt, Value.zero, mod)) { |
| 12191 | return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{ | 12204 | return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{ |
| 12192 | rhs_elem.fmtValue(scalar_ty, sema.mod), | 12205 | rhs_elem.fmtValue(scalar_ty, sema.mod), |
| 12193 | i, | 12206 | i, |
| 12194 | }); | 12207 | }); |
| 12195 | } | 12208 | } |
| 12196 | } | 12209 | } |
| 12197 | } else if (rhs_val.compareHetero(.lt, Value.zero, target)) { | 12210 | } else if (rhs_val.compareHetero(.lt, Value.zero, mod)) { |
| 12198 | return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{ | 12211 | return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{ |
| 12199 | rhs_val.fmtValue(scalar_ty, sema.mod), | 12212 | rhs_val.fmtValue(scalar_ty, sema.mod), |
| 12200 | }); | 12213 | }); |
| ... | @@ -12204,7 +12217,7 @@ fn zirShl( | ... | @@ -12204,7 +12217,7 @@ fn zirShl( |
| 12204 | const runtime_src = if (maybe_lhs_val) |lhs_val| rs: { | 12217 | const runtime_src = if (maybe_lhs_val) |lhs_val| rs: { |
| 12205 | if (lhs_val.isUndef()) return sema.addConstUndef(lhs_ty); | 12218 | if (lhs_val.isUndef()) return sema.addConstUndef(lhs_ty); |
| 12206 | const rhs_val = maybe_rhs_val orelse { | 12219 | const rhs_val = maybe_rhs_val orelse { |
| 12207 | if (scalar_ty.zigTypeTag() == .ComptimeInt) { | 12220 | if (scalar_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 12208 | return sema.fail(block, src, "LHS of shift must be a fixed-width integer type, or RHS must be comptime-known", .{}); | 12221 | return sema.fail(block, src, "LHS of shift must be a fixed-width integer type, or RHS must be comptime-known", .{}); |
| 12209 | } | 12222 | } |
| 12210 | break :rs rhs_src; | 12223 | break :rs rhs_src; |
| ... | @@ -12213,7 +12226,7 @@ fn zirShl( | ... | @@ -12213,7 +12226,7 @@ fn zirShl( |
| 12213 | const val = switch (air_tag) { | 12226 | const val = switch (air_tag) { |
| 12214 | .shl_exact => val: { | 12227 | .shl_exact => val: { |
| 12215 | const shifted = try lhs_val.shlWithOverflow(rhs_val, lhs_ty, sema.arena, sema.mod); | 12228 | const shifted = try lhs_val.shlWithOverflow(rhs_val, lhs_ty, sema.arena, sema.mod); |
| 12216 | if (scalar_ty.zigTypeTag() == .ComptimeInt) { | 12229 | if (scalar_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 12217 | break :val shifted.wrapped_result; | 12230 | break :val shifted.wrapped_result; |
| 12218 | } | 12231 | } |
| 12219 | if (shifted.overflow_bit.compareAllWithZero(.eq, sema.mod)) { | 12232 | if (shifted.overflow_bit.compareAllWithZero(.eq, sema.mod)) { |
| ... | @@ -12222,12 +12235,12 @@ fn zirShl( | ... | @@ -12222,12 +12235,12 @@ fn zirShl( |
| 12222 | return sema.fail(block, src, "operation caused overflow", .{}); | 12235 | return sema.fail(block, src, "operation caused overflow", .{}); |
| 12223 | }, | 12236 | }, |
| 12224 | 12237 | ||
| 12225 | .shl_sat => if (scalar_ty.zigTypeTag() == .ComptimeInt) | 12238 | .shl_sat => if (scalar_ty.zigTypeTag(mod) == .ComptimeInt) |
| 12226 | try lhs_val.shl(rhs_val, lhs_ty, sema.arena, sema.mod) | 12239 | try lhs_val.shl(rhs_val, lhs_ty, sema.arena, sema.mod) |
| 12227 | else | 12240 | else |
| 12228 | try lhs_val.shlSat(rhs_val, lhs_ty, sema.arena, sema.mod), | 12241 | try lhs_val.shlSat(rhs_val, lhs_ty, sema.arena, sema.mod), |
| 12229 | 12242 | ||
| 12230 | .shl => if (scalar_ty.zigTypeTag() == .ComptimeInt) | 12243 | .shl => if (scalar_ty.zigTypeTag(mod) == .ComptimeInt) |
| 12231 | try lhs_val.shl(rhs_val, lhs_ty, sema.arena, sema.mod) | 12244 | try lhs_val.shl(rhs_val, lhs_ty, sema.arena, sema.mod) |
| 12232 | else | 12245 | else |
| 12233 | try lhs_val.shlTrunc(rhs_val, lhs_ty, sema.arena, sema.mod), | 12246 | try lhs_val.shlTrunc(rhs_val, lhs_ty, sema.arena, sema.mod), |
| ... | @@ -12241,11 +12254,11 @@ fn zirShl( | ... | @@ -12241,11 +12254,11 @@ fn zirShl( |
| 12241 | const new_rhs = if (air_tag == .shl_sat) rhs: { | 12254 | const new_rhs = if (air_tag == .shl_sat) rhs: { |
| 12242 | // Limit the RHS type for saturating shl to be an integer as small as the LHS. | 12255 | // Limit the RHS type for saturating shl to be an integer as small as the LHS. |
| 12243 | if (rhs_is_comptime_int or | 12256 | if (rhs_is_comptime_int or |
| 12244 | scalar_rhs_ty.intInfo(target).bits > scalar_ty.intInfo(target).bits) | 12257 | scalar_rhs_ty.intInfo(mod).bits > scalar_ty.intInfo(mod).bits) |
| 12245 | { | 12258 | { |
| 12246 | const max_int = try sema.addConstant( | 12259 | const max_int = try sema.addConstant( |
| 12247 | lhs_ty, | 12260 | lhs_ty, |
| 12248 | try lhs_ty.maxInt(sema.arena, target), | 12261 | try lhs_ty.maxInt(sema.arena, mod), |
| 12249 | ); | 12262 | ); |
| 12250 | const rhs_limited = try sema.analyzeMinMax(block, rhs_src, .min, &.{ rhs, max_int }, &.{ rhs_src, rhs_src }); | 12263 | const rhs_limited = try sema.analyzeMinMax(block, rhs_src, .min, &.{ rhs, max_int }, &.{ rhs_src, rhs_src }); |
| 12251 | break :rhs try sema.intCast(block, src, lhs_ty, rhs_src, rhs_limited, rhs_src, false); | 12264 | break :rhs try sema.intCast(block, src, lhs_ty, rhs_src, rhs_limited, rhs_src, false); |
| ... | @@ -12256,11 +12269,11 @@ fn zirShl( | ... | @@ -12256,11 +12269,11 @@ fn zirShl( |
| 12256 | 12269 | ||
| 12257 | try sema.requireRuntimeBlock(block, src, runtime_src); | 12270 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 12258 | if (block.wantSafety()) { | 12271 | if (block.wantSafety()) { |
| 12259 | const bit_count = scalar_ty.intInfo(target).bits; | 12272 | const bit_count = scalar_ty.intInfo(mod).bits; |
| 12260 | if (!std.math.isPowerOfTwo(bit_count)) { | 12273 | if (!std.math.isPowerOfTwo(bit_count)) { |
| 12261 | const bit_count_val = try Value.Tag.int_u64.create(sema.arena, bit_count); | 12274 | const bit_count_val = try Value.Tag.int_u64.create(sema.arena, bit_count); |
| 12262 | 12275 | ||
| 12263 | const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: { | 12276 | const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: { |
| 12264 | const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val)); | 12277 | const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val)); |
| 12265 | const lt = try block.addCmpVector(rhs, bit_count_inst, .lt); | 12278 | const lt = try block.addCmpVector(rhs, bit_count_inst, .lt); |
| 12266 | break :ok try block.addInst(.{ | 12279 | break :ok try block.addInst(.{ |
| ... | @@ -12290,7 +12303,7 @@ fn zirShl( | ... | @@ -12290,7 +12303,7 @@ fn zirShl( |
| 12290 | } }, | 12303 | } }, |
| 12291 | }); | 12304 | }); |
| 12292 | const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty); | 12305 | const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty); |
| 12293 | const any_ov_bit = if (lhs_ty.zigTypeTag() == .Vector) | 12306 | const any_ov_bit = if (lhs_ty.zigTypeTag(mod) == .Vector) |
| 12294 | try block.addInst(.{ | 12307 | try block.addInst(.{ |
| 12295 | .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce, | 12308 | .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce, |
| 12296 | .data = .{ .reduce = .{ | 12309 | .data = .{ .reduce = .{ |
| ... | @@ -12319,6 +12332,7 @@ fn zirShr( | ... | @@ -12319,6 +12332,7 @@ fn zirShr( |
| 12319 | const tracy = trace(@src()); | 12332 | const tracy = trace(@src()); |
| 12320 | defer tracy.end(); | 12333 | defer tracy.end(); |
| 12321 | 12334 | ||
| 12335 | const mod = sema.mod; | ||
| 12322 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 12336 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 12323 | const src = inst_data.src(); | 12337 | const src = inst_data.src(); |
| 12324 | sema.src = src; | 12338 | sema.src = src; |
| ... | @@ -12330,8 +12344,7 @@ fn zirShr( | ... | @@ -12330,8 +12344,7 @@ fn zirShr( |
| 12330 | const lhs_ty = sema.typeOf(lhs); | 12344 | const lhs_ty = sema.typeOf(lhs); |
| 12331 | const rhs_ty = sema.typeOf(rhs); | 12345 | const rhs_ty = sema.typeOf(rhs); |
| 12332 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 12346 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 12333 | const target = sema.mod.getTarget(); | 12347 | const scalar_ty = lhs_ty.scalarType(mod); |
| 12334 | const scalar_ty = lhs_ty.scalarType(); | ||
| 12335 | 12348 | ||
| 12336 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(lhs); | 12349 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(lhs); |
| 12337 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs); | 12350 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs); |
| ... | @@ -12344,18 +12357,18 @@ fn zirShr( | ... | @@ -12344,18 +12357,18 @@ fn zirShr( |
| 12344 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) { | 12357 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) { |
| 12345 | return lhs; | 12358 | return lhs; |
| 12346 | } | 12359 | } |
| 12347 | if (scalar_ty.zigTypeTag() != .ComptimeInt) { | 12360 | if (scalar_ty.zigTypeTag(mod) != .ComptimeInt) { |
| 12348 | var bits_payload = Value.Payload.U64{ | 12361 | var bits_payload = Value.Payload.U64{ |
| 12349 | .base = .{ .tag = .int_u64 }, | 12362 | .base = .{ .tag = .int_u64 }, |
| 12350 | .data = scalar_ty.intInfo(target).bits, | 12363 | .data = scalar_ty.intInfo(mod).bits, |
| 12351 | }; | 12364 | }; |
| 12352 | const bit_value = Value.initPayload(&bits_payload.base); | 12365 | const bit_value = Value.initPayload(&bits_payload.base); |
| 12353 | if (rhs_ty.zigTypeTag() == .Vector) { | 12366 | if (rhs_ty.zigTypeTag(mod) == .Vector) { |
| 12354 | var i: usize = 0; | 12367 | var i: usize = 0; |
| 12355 | while (i < rhs_ty.vectorLen()) : (i += 1) { | 12368 | while (i < rhs_ty.vectorLen()) : (i += 1) { |
| 12356 | var elem_value_buf: Value.ElemValueBuffer = undefined; | 12369 | var elem_value_buf: Value.ElemValueBuffer = undefined; |
| 12357 | const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf); | 12370 | const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf); |
| 12358 | if (rhs_elem.compareHetero(.gte, bit_value, target)) { | 12371 | if (rhs_elem.compareHetero(.gte, bit_value, mod)) { |
| 12359 | return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{ | 12372 | return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{ |
| 12360 | rhs_elem.fmtValue(scalar_ty, sema.mod), | 12373 | rhs_elem.fmtValue(scalar_ty, sema.mod), |
| 12361 | i, | 12374 | i, |
| ... | @@ -12363,26 +12376,26 @@ fn zirShr( | ... | @@ -12363,26 +12376,26 @@ fn zirShr( |
| 12363 | }); | 12376 | }); |
| 12364 | } | 12377 | } |
| 12365 | } | 12378 | } |
| 12366 | } else if (rhs_val.compareHetero(.gte, bit_value, target)) { | 12379 | } else if (rhs_val.compareHetero(.gte, bit_value, mod)) { |
| 12367 | return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{ | 12380 | return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{ |
| 12368 | rhs_val.fmtValue(scalar_ty, sema.mod), | 12381 | rhs_val.fmtValue(scalar_ty, sema.mod), |
| 12369 | scalar_ty.fmt(sema.mod), | 12382 | scalar_ty.fmt(sema.mod), |
| 12370 | }); | 12383 | }); |
| 12371 | } | 12384 | } |
| 12372 | } | 12385 | } |
| 12373 | if (rhs_ty.zigTypeTag() == .Vector) { | 12386 | if (rhs_ty.zigTypeTag(mod) == .Vector) { |
| 12374 | var i: usize = 0; | 12387 | var i: usize = 0; |
| 12375 | while (i < rhs_ty.vectorLen()) : (i += 1) { | 12388 | while (i < rhs_ty.vectorLen()) : (i += 1) { |
| 12376 | var elem_value_buf: Value.ElemValueBuffer = undefined; | 12389 | var elem_value_buf: Value.ElemValueBuffer = undefined; |
| 12377 | const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf); | 12390 | const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf); |
| 12378 | if (rhs_elem.compareHetero(.lt, Value.zero, target)) { | 12391 | if (rhs_elem.compareHetero(.lt, Value.zero, mod)) { |
| 12379 | return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{ | 12392 | return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{ |
| 12380 | rhs_elem.fmtValue(scalar_ty, sema.mod), | 12393 | rhs_elem.fmtValue(scalar_ty, sema.mod), |
| 12381 | i, | 12394 | i, |
| 12382 | }); | 12395 | }); |
| 12383 | } | 12396 | } |
| 12384 | } | 12397 | } |
| 12385 | } else if (rhs_val.compareHetero(.lt, Value.zero, target)) { | 12398 | } else if (rhs_val.compareHetero(.lt, Value.zero, mod)) { |
| 12386 | return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{ | 12399 | return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{ |
| 12387 | rhs_val.fmtValue(scalar_ty, sema.mod), | 12400 | rhs_val.fmtValue(scalar_ty, sema.mod), |
| 12388 | }); | 12401 | }); |
| ... | @@ -12405,18 +12418,18 @@ fn zirShr( | ... | @@ -12405,18 +12418,18 @@ fn zirShr( |
| 12405 | } | 12418 | } |
| 12406 | } else rhs_src; | 12419 | } else rhs_src; |
| 12407 | 12420 | ||
| 12408 | if (maybe_rhs_val == null and scalar_ty.zigTypeTag() == .ComptimeInt) { | 12421 | if (maybe_rhs_val == null and scalar_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 12409 | return sema.fail(block, src, "LHS of shift must be a fixed-width integer type, or RHS must be comptime-known", .{}); | 12422 | return sema.fail(block, src, "LHS of shift must be a fixed-width integer type, or RHS must be comptime-known", .{}); |
| 12410 | } | 12423 | } |
| 12411 | 12424 | ||
| 12412 | try sema.requireRuntimeBlock(block, src, runtime_src); | 12425 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 12413 | const result = try block.addBinOp(air_tag, lhs, rhs); | 12426 | const result = try block.addBinOp(air_tag, lhs, rhs); |
| 12414 | if (block.wantSafety()) { | 12427 | if (block.wantSafety()) { |
| 12415 | const bit_count = scalar_ty.intInfo(target).bits; | 12428 | const bit_count = scalar_ty.intInfo(mod).bits; |
| 12416 | if (!std.math.isPowerOfTwo(bit_count)) { | 12429 | if (!std.math.isPowerOfTwo(bit_count)) { |
| 12417 | const bit_count_val = try Value.Tag.int_u64.create(sema.arena, bit_count); | 12430 | const bit_count_val = try Value.Tag.int_u64.create(sema.arena, bit_count); |
| 12418 | 12431 | ||
| 12419 | const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: { | 12432 | const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: { |
| 12420 | const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val)); | 12433 | const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val)); |
| 12421 | const lt = try block.addCmpVector(rhs, bit_count_inst, .lt); | 12434 | const lt = try block.addCmpVector(rhs, bit_count_inst, .lt); |
| 12422 | break :ok try block.addInst(.{ | 12435 | break :ok try block.addInst(.{ |
| ... | @@ -12436,7 +12449,7 @@ fn zirShr( | ... | @@ -12436,7 +12449,7 @@ fn zirShr( |
| 12436 | if (air_tag == .shr_exact) { | 12449 | if (air_tag == .shr_exact) { |
| 12437 | const back = try block.addBinOp(.shl, result, rhs); | 12450 | const back = try block.addBinOp(.shl, result, rhs); |
| 12438 | 12451 | ||
| 12439 | const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: { | 12452 | const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: { |
| 12440 | const eql = try block.addCmpVector(lhs, back, .eq); | 12453 | const eql = try block.addCmpVector(lhs, back, .eq); |
| 12441 | break :ok try block.addInst(.{ | 12454 | break :ok try block.addInst(.{ |
| 12442 | .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce, | 12455 | .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce, |
| ... | @@ -12461,6 +12474,7 @@ fn zirBitwise( | ... | @@ -12461,6 +12474,7 @@ fn zirBitwise( |
| 12461 | const tracy = trace(@src()); | 12474 | const tracy = trace(@src()); |
| 12462 | defer tracy.end(); | 12475 | defer tracy.end(); |
| 12463 | 12476 | ||
| 12477 | const mod = sema.mod; | ||
| 12464 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 12478 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 12465 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 12479 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| 12466 | sema.src = src; | 12480 | sema.src = src; |
| ... | @@ -12475,8 +12489,8 @@ fn zirBitwise( | ... | @@ -12475,8 +12489,8 @@ fn zirBitwise( |
| 12475 | 12489 | ||
| 12476 | const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; | 12490 | const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; |
| 12477 | const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } }); | 12491 | const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } }); |
| 12478 | const scalar_type = resolved_type.scalarType(); | 12492 | const scalar_type = resolved_type.scalarType(mod); |
| 12479 | const scalar_tag = scalar_type.zigTypeTag(); | 12493 | const scalar_tag = scalar_type.zigTypeTag(mod); |
| 12480 | 12494 | ||
| 12481 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 12495 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 12482 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 12496 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| ... | @@ -12484,7 +12498,7 @@ fn zirBitwise( | ... | @@ -12484,7 +12498,7 @@ fn zirBitwise( |
| 12484 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; | 12498 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; |
| 12485 | 12499 | ||
| 12486 | if (!is_int) { | 12500 | if (!is_int) { |
| 12487 | return sema.fail(block, src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs_ty.zigTypeTag()), @tagName(rhs_ty.zigTypeTag()) }); | 12501 | return sema.fail(block, src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs_ty.zigTypeTag(mod)), @tagName(rhs_ty.zigTypeTag(mod)) }); |
| 12488 | } | 12502 | } |
| 12489 | 12503 | ||
| 12490 | const runtime_src = runtime: { | 12504 | const runtime_src = runtime: { |
| ... | @@ -12515,15 +12529,16 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -12515,15 +12529,16 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 12515 | const tracy = trace(@src()); | 12529 | const tracy = trace(@src()); |
| 12516 | defer tracy.end(); | 12530 | defer tracy.end(); |
| 12517 | 12531 | ||
| 12532 | const mod = sema.mod; | ||
| 12518 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 12533 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 12519 | const src = inst_data.src(); | 12534 | const src = inst_data.src(); |
| 12520 | const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; | 12535 | const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; |
| 12521 | 12536 | ||
| 12522 | const operand = try sema.resolveInst(inst_data.operand); | 12537 | const operand = try sema.resolveInst(inst_data.operand); |
| 12523 | const operand_type = sema.typeOf(operand); | 12538 | const operand_type = sema.typeOf(operand); |
| 12524 | const scalar_type = operand_type.scalarType(); | 12539 | const scalar_type = operand_type.scalarType(mod); |
| 12525 | 12540 | ||
| 12526 | if (scalar_type.zigTypeTag() != .Int) { | 12541 | if (scalar_type.zigTypeTag(mod) != .Int) { |
| 12527 | return sema.fail(block, src, "unable to perform binary not operation on type '{}'", .{ | 12542 | return sema.fail(block, src, "unable to perform binary not operation on type '{}'", .{ |
| 12528 | operand_type.fmt(sema.mod), | 12543 | operand_type.fmt(sema.mod), |
| 12529 | }); | 12544 | }); |
| ... | @@ -12532,7 +12547,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -12532,7 +12547,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 12532 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | 12547 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 12533 | if (val.isUndef()) { | 12548 | if (val.isUndef()) { |
| 12534 | return sema.addConstUndef(operand_type); | 12549 | return sema.addConstUndef(operand_type); |
| 12535 | } else if (operand_type.zigTypeTag() == .Vector) { | 12550 | } else if (operand_type.zigTypeTag(mod) == .Vector) { |
| 12536 | const vec_len = try sema.usizeCast(block, operand_src, operand_type.vectorLen()); | 12551 | const vec_len = try sema.usizeCast(block, operand_src, operand_type.vectorLen()); |
| 12537 | var elem_val_buf: Value.ElemValueBuffer = undefined; | 12552 | var elem_val_buf: Value.ElemValueBuffer = undefined; |
| 12538 | const elems = try sema.arena.alloc(Value, vec_len); | 12553 | const elems = try sema.arena.alloc(Value, vec_len); |
| ... | @@ -12728,18 +12743,19 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12728,18 +12743,19 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12728 | }; | 12743 | }; |
| 12729 | 12744 | ||
| 12730 | const result_ty = try Type.array(sema.arena, result_len, res_sent_val, resolved_elem_ty, sema.mod); | 12745 | const result_ty = try Type.array(sema.arena, result_len, res_sent_val, resolved_elem_ty, sema.mod); |
| 12746 | const mod = sema.mod; | ||
| 12731 | const ptr_addrspace = p: { | 12747 | const ptr_addrspace = p: { |
| 12732 | if (lhs_ty.zigTypeTag() == .Pointer) break :p lhs_ty.ptrAddressSpace(); | 12748 | if (lhs_ty.zigTypeTag(mod) == .Pointer) break :p lhs_ty.ptrAddressSpace(); |
| 12733 | if (rhs_ty.zigTypeTag() == .Pointer) break :p rhs_ty.ptrAddressSpace(); | 12749 | if (rhs_ty.zigTypeTag(mod) == .Pointer) break :p rhs_ty.ptrAddressSpace(); |
| 12734 | break :p null; | 12750 | break :p null; |
| 12735 | }; | 12751 | }; |
| 12736 | 12752 | ||
| 12737 | const runtime_src = if (switch (lhs_ty.zigTypeTag()) { | 12753 | const runtime_src = if (switch (lhs_ty.zigTypeTag(mod)) { |
| 12738 | .Array, .Struct => try sema.resolveMaybeUndefVal(lhs), | 12754 | .Array, .Struct => try sema.resolveMaybeUndefVal(lhs), |
| 12739 | .Pointer => try sema.resolveDefinedValue(block, lhs_src, lhs), | 12755 | .Pointer => try sema.resolveDefinedValue(block, lhs_src, lhs), |
| 12740 | else => unreachable, | 12756 | else => unreachable, |
| 12741 | }) |lhs_val| rs: { | 12757 | }) |lhs_val| rs: { |
| 12742 | if (switch (rhs_ty.zigTypeTag()) { | 12758 | if (switch (rhs_ty.zigTypeTag(mod)) { |
| 12743 | .Array, .Struct => try sema.resolveMaybeUndefVal(rhs), | 12759 | .Array, .Struct => try sema.resolveMaybeUndefVal(rhs), |
| 12744 | .Pointer => try sema.resolveDefinedValue(block, rhs_src, rhs), | 12760 | .Pointer => try sema.resolveDefinedValue(block, rhs_src, rhs), |
| 12745 | else => unreachable, | 12761 | else => unreachable, |
| ... | @@ -12841,8 +12857,9 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12841,8 +12857,9 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12841 | } | 12857 | } |
| 12842 | 12858 | ||
| 12843 | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref, peer_ty: Type) !?Type.ArrayInfo { | 12859 | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref, peer_ty: Type) !?Type.ArrayInfo { |
| 12860 | const mod = sema.mod; | ||
| 12844 | const operand_ty = sema.typeOf(operand); | 12861 | const operand_ty = sema.typeOf(operand); |
| 12845 | switch (operand_ty.zigTypeTag()) { | 12862 | switch (operand_ty.zigTypeTag(mod)) { |
| 12846 | .Array => return operand_ty.arrayInfo(), | 12863 | .Array => return operand_ty.arrayInfo(), |
| 12847 | .Pointer => { | 12864 | .Pointer => { |
| 12848 | const ptr_info = operand_ty.ptrInfo().data; | 12865 | const ptr_info = operand_ty.ptrInfo().data; |
| ... | @@ -12859,7 +12876,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins | ... | @@ -12859,7 +12876,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 12859 | }; | 12876 | }; |
| 12860 | }, | 12877 | }, |
| 12861 | .One => { | 12878 | .One => { |
| 12862 | if (ptr_info.pointee_type.zigTypeTag() == .Array) { | 12879 | if (ptr_info.pointee_type.zigTypeTag(mod) == .Array) { |
| 12863 | return ptr_info.pointee_type.arrayInfo(); | 12880 | return ptr_info.pointee_type.arrayInfo(); |
| 12864 | } | 12881 | } |
| 12865 | }, | 12882 | }, |
| ... | @@ -12867,10 +12884,10 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins | ... | @@ -12867,10 +12884,10 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 12867 | } | 12884 | } |
| 12868 | }, | 12885 | }, |
| 12869 | .Struct => { | 12886 | .Struct => { |
| 12870 | if (operand_ty.isTuple() and peer_ty.isIndexable()) { | 12887 | if (operand_ty.isTuple() and peer_ty.isIndexable(mod)) { |
| 12871 | assert(!peer_ty.isTuple()); | 12888 | assert(!peer_ty.isTuple()); |
| 12872 | return .{ | 12889 | return .{ |
| 12873 | .elem_type = peer_ty.elemType2(), | 12890 | .elem_type = peer_ty.elemType2(mod), |
| 12874 | .sentinel = null, | 12891 | .sentinel = null, |
| 12875 | .len = operand_ty.arrayLen(), | 12892 | .len = operand_ty.arrayLen(), |
| 12876 | }; | 12893 | }; |
| ... | @@ -12970,11 +12987,12 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12970,11 +12987,12 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12970 | } | 12987 | } |
| 12971 | 12988 | ||
| 12972 | // Analyze the lhs first, to catch the case that someone tried to do exponentiation | 12989 | // Analyze the lhs first, to catch the case that someone tried to do exponentiation |
| 12990 | const mod = sema.mod; | ||
| 12973 | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse { | 12991 | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse { |
| 12974 | const msg = msg: { | 12992 | const msg = msg: { |
| 12975 | const msg = try sema.errMsg(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)}); | 12993 | const msg = try sema.errMsg(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)}); |
| 12976 | errdefer msg.destroy(sema.gpa); | 12994 | errdefer msg.destroy(sema.gpa); |
| 12977 | switch (lhs_ty.zigTypeTag()) { | 12995 | switch (lhs_ty.zigTypeTag(mod)) { |
| 12978 | .Int, .Float, .ComptimeFloat, .ComptimeInt, .Vector => { | 12996 | .Int, .Float, .ComptimeFloat, .ComptimeInt, .Vector => { |
| 12979 | try sema.errNote(block, operator_src, msg, "this operator multiplies arrays; use std.math.pow for exponentiation", .{}); | 12997 | try sema.errNote(block, operator_src, msg, "this operator multiplies arrays; use std.math.pow for exponentiation", .{}); |
| 12980 | }, | 12998 | }, |
| ... | @@ -12994,7 +13012,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12994,7 +13012,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12994 | 13012 | ||
| 12995 | const result_ty = try Type.array(sema.arena, result_len, lhs_info.sentinel, lhs_info.elem_type, sema.mod); | 13013 | const result_ty = try Type.array(sema.arena, result_len, lhs_info.sentinel, lhs_info.elem_type, sema.mod); |
| 12996 | 13014 | ||
| 12997 | const ptr_addrspace = if (lhs_ty.zigTypeTag() == .Pointer) lhs_ty.ptrAddressSpace() else null; | 13015 | const ptr_addrspace = if (lhs_ty.zigTypeTag(mod) == .Pointer) lhs_ty.ptrAddressSpace() else null; |
| 12998 | const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len); | 13016 | const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len); |
| 12999 | 13017 | ||
| 13000 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { | 13018 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { |
| ... | @@ -13082,6 +13100,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13082,6 +13100,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13082 | } | 13100 | } |
| 13083 | 13101 | ||
| 13084 | fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 13102 | fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 13103 | const mod = sema.mod; | ||
| 13085 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 13104 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 13086 | const src = inst_data.src(); | 13105 | const src = inst_data.src(); |
| 13087 | const lhs_src = src; | 13106 | const lhs_src = src; |
| ... | @@ -13089,9 +13108,9 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13089,9 +13108,9 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13089 | 13108 | ||
| 13090 | const rhs = try sema.resolveInst(inst_data.operand); | 13109 | const rhs = try sema.resolveInst(inst_data.operand); |
| 13091 | const rhs_ty = sema.typeOf(rhs); | 13110 | const rhs_ty = sema.typeOf(rhs); |
| 13092 | const rhs_scalar_ty = rhs_ty.scalarType(); | 13111 | const rhs_scalar_ty = rhs_ty.scalarType(mod); |
| 13093 | 13112 | ||
| 13094 | if (rhs_scalar_ty.isUnsignedInt() or switch (rhs_scalar_ty.zigTypeTag()) { | 13113 | if (rhs_scalar_ty.isUnsignedInt(mod) or switch (rhs_scalar_ty.zigTypeTag(mod)) { |
| 13095 | .Int, .ComptimeInt, .Float, .ComptimeFloat => false, | 13114 | .Int, .ComptimeInt, .Float, .ComptimeFloat => false, |
| 13096 | else => true, | 13115 | else => true, |
| 13097 | }) { | 13116 | }) { |
| ... | @@ -13108,7 +13127,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13108,7 +13127,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13108 | return block.addUnOp(if (block.float_mode == .Optimized) .neg_optimized else .neg, rhs); | 13127 | return block.addUnOp(if (block.float_mode == .Optimized) .neg_optimized else .neg, rhs); |
| 13109 | } | 13128 | } |
| 13110 | 13129 | ||
| 13111 | const lhs = if (rhs_ty.zigTypeTag() == .Vector) | 13130 | const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector) |
| 13112 | try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero)) | 13131 | try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero)) |
| 13113 | else | 13132 | else |
| 13114 | try sema.resolveInst(.zero); | 13133 | try sema.resolveInst(.zero); |
| ... | @@ -13117,6 +13136,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13117,6 +13136,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13117 | } | 13136 | } |
| 13118 | 13137 | ||
| 13119 | fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 13138 | fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 13139 | const mod = sema.mod; | ||
| 13120 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 13140 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 13121 | const src = inst_data.src(); | 13141 | const src = inst_data.src(); |
| 13122 | const lhs_src = src; | 13142 | const lhs_src = src; |
| ... | @@ -13124,14 +13144,14 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -13124,14 +13144,14 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 13124 | 13144 | ||
| 13125 | const rhs = try sema.resolveInst(inst_data.operand); | 13145 | const rhs = try sema.resolveInst(inst_data.operand); |
| 13126 | const rhs_ty = sema.typeOf(rhs); | 13146 | const rhs_ty = sema.typeOf(rhs); |
| 13127 | const rhs_scalar_ty = rhs_ty.scalarType(); | 13147 | const rhs_scalar_ty = rhs_ty.scalarType(mod); |
| 13128 | 13148 | ||
| 13129 | switch (rhs_scalar_ty.zigTypeTag()) { | 13149 | switch (rhs_scalar_ty.zigTypeTag(mod)) { |
| 13130 | .Int, .ComptimeInt, .Float, .ComptimeFloat => {}, | 13150 | .Int, .ComptimeInt, .Float, .ComptimeFloat => {}, |
| 13131 | else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)}), | 13151 | else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)}), |
| 13132 | } | 13152 | } |
| 13133 | 13153 | ||
| 13134 | const lhs = if (rhs_ty.zigTypeTag() == .Vector) | 13154 | const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector) |
| 13135 | try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero)) | 13155 | try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero)) |
| 13136 | else | 13156 | else |
| 13137 | try sema.resolveInst(.zero); | 13157 | try sema.resolveInst(.zero); |
| ... | @@ -13161,6 +13181,7 @@ fn zirArithmetic( | ... | @@ -13161,6 +13181,7 @@ fn zirArithmetic( |
| 13161 | } | 13181 | } |
| 13162 | 13182 | ||
| 13163 | fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 13183 | fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 13184 | const mod = sema.mod; | ||
| 13164 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 13185 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 13165 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 13186 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| 13166 | sema.src = src; | 13187 | sema.src = src; |
| ... | @@ -13171,8 +13192,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -13171,8 +13192,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13171 | const rhs = try sema.resolveInst(extra.rhs); | 13192 | const rhs = try sema.resolveInst(extra.rhs); |
| 13172 | const lhs_ty = sema.typeOf(lhs); | 13193 | const lhs_ty = sema.typeOf(lhs); |
| 13173 | const rhs_ty = sema.typeOf(rhs); | 13194 | const rhs_ty = sema.typeOf(rhs); |
| 13174 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); | 13195 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod); |
| 13175 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); | 13196 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod); |
| 13176 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 13197 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 13177 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); | 13198 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); |
| 13178 | 13199 | ||
| ... | @@ -13181,25 +13202,24 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -13181,25 +13202,24 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13181 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, | 13202 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, |
| 13182 | }); | 13203 | }); |
| 13183 | 13204 | ||
| 13184 | const is_vector = resolved_type.zigTypeTag() == .Vector; | 13205 | const is_vector = resolved_type.zigTypeTag(mod) == .Vector; |
| 13185 | 13206 | ||
| 13186 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 13207 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 13187 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 13208 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 13188 | 13209 | ||
| 13189 | const lhs_scalar_ty = lhs_ty.scalarType(); | 13210 | const lhs_scalar_ty = lhs_ty.scalarType(mod); |
| 13190 | const rhs_scalar_ty = rhs_ty.scalarType(); | 13211 | const rhs_scalar_ty = rhs_ty.scalarType(mod); |
| 13191 | const scalar_tag = resolved_type.scalarType().zigTypeTag(); | 13212 | const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod); |
| 13192 | 13213 | ||
| 13193 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; | 13214 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; |
| 13194 | 13215 | ||
| 13195 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div); | 13216 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div); |
| 13196 | 13217 | ||
| 13197 | const mod = sema.mod; | ||
| 13198 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); | 13218 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); |
| 13199 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); | 13219 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); |
| 13200 | 13220 | ||
| 13201 | if ((lhs_ty.zigTypeTag() == .ComptimeFloat and rhs_ty.zigTypeTag() == .ComptimeInt) or | 13221 | if ((lhs_ty.zigTypeTag(mod) == .ComptimeFloat and rhs_ty.zigTypeTag(mod) == .ComptimeInt) or |
| 13202 | (lhs_ty.zigTypeTag() == .ComptimeInt and rhs_ty.zigTypeTag() == .ComptimeFloat)) | 13222 | (lhs_ty.zigTypeTag(mod) == .ComptimeInt and rhs_ty.zigTypeTag(mod) == .ComptimeFloat)) |
| 13203 | { | 13223 | { |
| 13204 | // If it makes a difference whether we coerce to ints or floats before doing the division, error. | 13224 | // If it makes a difference whether we coerce to ints or floats before doing the division, error. |
| 13205 | // If lhs % rhs is 0, it doesn't matter. | 13225 | // If lhs % rhs is 0, it doesn't matter. |
| ... | @@ -13268,7 +13288,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -13268,7 +13288,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13268 | const runtime_src = rs: { | 13288 | const runtime_src = rs: { |
| 13269 | if (maybe_lhs_val) |lhs_val| { | 13289 | if (maybe_lhs_val) |lhs_val| { |
| 13270 | if (lhs_val.isUndef()) { | 13290 | if (lhs_val.isUndef()) { |
| 13271 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { | 13291 | if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) { |
| 13272 | if (maybe_rhs_val) |rhs_val| { | 13292 | if (maybe_rhs_val) |rhs_val| { |
| 13273 | if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) { | 13293 | if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) { |
| 13274 | return sema.addConstUndef(resolved_type); | 13294 | return sema.addConstUndef(resolved_type); |
| ... | @@ -13309,7 +13329,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -13309,7 +13329,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13309 | } | 13329 | } |
| 13310 | 13330 | ||
| 13311 | const air_tag = if (is_int) blk: { | 13331 | const air_tag = if (is_int) blk: { |
| 13312 | if (lhs_ty.isSignedInt() or rhs_ty.isSignedInt()) { | 13332 | if (lhs_ty.isSignedInt(mod) or rhs_ty.isSignedInt(mod)) { |
| 13313 | return sema.fail(block, src, "division with '{s}' and '{s}': signed integers must use @divTrunc, @divFloor, or @divExact", .{ @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()) }); | 13333 | return sema.fail(block, src, "division with '{s}' and '{s}': signed integers must use @divTrunc, @divFloor, or @divExact", .{ @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()) }); |
| 13314 | } | 13334 | } |
| 13315 | break :blk Air.Inst.Tag.div_trunc; | 13335 | break :blk Air.Inst.Tag.div_trunc; |
| ... | @@ -13321,6 +13341,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -13321,6 +13341,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13321 | } | 13341 | } |
| 13322 | 13342 | ||
| 13323 | fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 13343 | fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 13344 | const mod = sema.mod; | ||
| 13324 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 13345 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 13325 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 13346 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| 13326 | sema.src = src; | 13347 | sema.src = src; |
| ... | @@ -13331,8 +13352,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13331,8 +13352,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13331 | const rhs = try sema.resolveInst(extra.rhs); | 13352 | const rhs = try sema.resolveInst(extra.rhs); |
| 13332 | const lhs_ty = sema.typeOf(lhs); | 13353 | const lhs_ty = sema.typeOf(lhs); |
| 13333 | const rhs_ty = sema.typeOf(rhs); | 13354 | const rhs_ty = sema.typeOf(rhs); |
| 13334 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); | 13355 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod); |
| 13335 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); | 13356 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod); |
| 13336 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 13357 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 13337 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); | 13358 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); |
| 13338 | 13359 | ||
| ... | @@ -13341,19 +13362,18 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13341,19 +13362,18 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13341 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, | 13362 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, |
| 13342 | }); | 13363 | }); |
| 13343 | 13364 | ||
| 13344 | const is_vector = resolved_type.zigTypeTag() == .Vector; | 13365 | const is_vector = resolved_type.zigTypeTag(mod) == .Vector; |
| 13345 | 13366 | ||
| 13346 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 13367 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 13347 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 13368 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 13348 | 13369 | ||
| 13349 | const lhs_scalar_ty = lhs_ty.scalarType(); | 13370 | const lhs_scalar_ty = lhs_ty.scalarType(mod); |
| 13350 | const scalar_tag = resolved_type.scalarType().zigTypeTag(); | 13371 | const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod); |
| 13351 | 13372 | ||
| 13352 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; | 13373 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; |
| 13353 | 13374 | ||
| 13354 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_exact); | 13375 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_exact); |
| 13355 | 13376 | ||
| 13356 | const mod = sema.mod; | ||
| 13357 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); | 13377 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); |
| 13358 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); | 13378 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); |
| 13359 | 13379 | ||
| ... | @@ -13437,7 +13457,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13437,7 +13457,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13437 | const ok = if (!is_int) ok: { | 13457 | const ok = if (!is_int) ok: { |
| 13438 | const floored = try block.addUnOp(.floor, result); | 13458 | const floored = try block.addUnOp(.floor, result); |
| 13439 | 13459 | ||
| 13440 | if (resolved_type.zigTypeTag() == .Vector) { | 13460 | if (resolved_type.zigTypeTag(mod) == .Vector) { |
| 13441 | const eql = try block.addCmpVector(result, floored, .eq); | 13461 | const eql = try block.addCmpVector(result, floored, .eq); |
| 13442 | break :ok try block.addInst(.{ | 13462 | break :ok try block.addInst(.{ |
| 13443 | .tag = switch (block.float_mode) { | 13463 | .tag = switch (block.float_mode) { |
| ... | @@ -13459,7 +13479,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13459,7 +13479,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13459 | } else ok: { | 13479 | } else ok: { |
| 13460 | const remainder = try block.addBinOp(.rem, casted_lhs, casted_rhs); | 13480 | const remainder = try block.addBinOp(.rem, casted_lhs, casted_rhs); |
| 13461 | 13481 | ||
| 13462 | if (resolved_type.zigTypeTag() == .Vector) { | 13482 | if (resolved_type.zigTypeTag(mod) == .Vector) { |
| 13463 | const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero); | 13483 | const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero); |
| 13464 | const zero = try sema.addConstant(resolved_type, zero_val); | 13484 | const zero = try sema.addConstant(resolved_type, zero_val); |
| 13465 | const eql = try block.addCmpVector(remainder, zero, .eq); | 13485 | const eql = try block.addCmpVector(remainder, zero, .eq); |
| ... | @@ -13484,6 +13504,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13484,6 +13504,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13484 | } | 13504 | } |
| 13485 | 13505 | ||
| 13486 | fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 13506 | fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 13507 | const mod = sema.mod; | ||
| 13487 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 13508 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 13488 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 13509 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| 13489 | sema.src = src; | 13510 | sema.src = src; |
| ... | @@ -13494,8 +13515,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13494,8 +13515,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13494 | const rhs = try sema.resolveInst(extra.rhs); | 13515 | const rhs = try sema.resolveInst(extra.rhs); |
| 13495 | const lhs_ty = sema.typeOf(lhs); | 13516 | const lhs_ty = sema.typeOf(lhs); |
| 13496 | const rhs_ty = sema.typeOf(rhs); | 13517 | const rhs_ty = sema.typeOf(rhs); |
| 13497 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); | 13518 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod); |
| 13498 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); | 13519 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod); |
| 13499 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 13520 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 13500 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); | 13521 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); |
| 13501 | 13522 | ||
| ... | @@ -13504,20 +13525,19 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13504,20 +13525,19 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13504 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, | 13525 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, |
| 13505 | }); | 13526 | }); |
| 13506 | 13527 | ||
| 13507 | const is_vector = resolved_type.zigTypeTag() == .Vector; | 13528 | const is_vector = resolved_type.zigTypeTag(mod) == .Vector; |
| 13508 | 13529 | ||
| 13509 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 13530 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 13510 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 13531 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 13511 | 13532 | ||
| 13512 | const lhs_scalar_ty = lhs_ty.scalarType(); | 13533 | const lhs_scalar_ty = lhs_ty.scalarType(mod); |
| 13513 | const rhs_scalar_ty = rhs_ty.scalarType(); | 13534 | const rhs_scalar_ty = rhs_ty.scalarType(mod); |
| 13514 | const scalar_tag = resolved_type.scalarType().zigTypeTag(); | 13535 | const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod); |
| 13515 | 13536 | ||
| 13516 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; | 13537 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; |
| 13517 | 13538 | ||
| 13518 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_floor); | 13539 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_floor); |
| 13519 | 13540 | ||
| 13520 | const mod = sema.mod; | ||
| 13521 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); | 13541 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); |
| 13522 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); | 13542 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); |
| 13523 | 13543 | ||
| ... | @@ -13562,7 +13582,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13562,7 +13582,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13562 | } | 13582 | } |
| 13563 | if (maybe_lhs_val) |lhs_val| { | 13583 | if (maybe_lhs_val) |lhs_val| { |
| 13564 | if (lhs_val.isUndef()) { | 13584 | if (lhs_val.isUndef()) { |
| 13565 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { | 13585 | if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) { |
| 13566 | if (maybe_rhs_val) |rhs_val| { | 13586 | if (maybe_rhs_val) |rhs_val| { |
| 13567 | if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) { | 13587 | if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) { |
| 13568 | return sema.addConstUndef(resolved_type); | 13588 | return sema.addConstUndef(resolved_type); |
| ... | @@ -13600,6 +13620,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13600,6 +13620,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13600 | } | 13620 | } |
| 13601 | 13621 | ||
| 13602 | fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 13622 | fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 13623 | const mod = sema.mod; | ||
| 13603 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 13624 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 13604 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 13625 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| 13605 | sema.src = src; | 13626 | sema.src = src; |
| ... | @@ -13610,8 +13631,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13610,8 +13631,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13610 | const rhs = try sema.resolveInst(extra.rhs); | 13631 | const rhs = try sema.resolveInst(extra.rhs); |
| 13611 | const lhs_ty = sema.typeOf(lhs); | 13632 | const lhs_ty = sema.typeOf(lhs); |
| 13612 | const rhs_ty = sema.typeOf(rhs); | 13633 | const rhs_ty = sema.typeOf(rhs); |
| 13613 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); | 13634 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod); |
| 13614 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); | 13635 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod); |
| 13615 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 13636 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 13616 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); | 13637 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); |
| 13617 | 13638 | ||
| ... | @@ -13620,20 +13641,19 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13620,20 +13641,19 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13620 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, | 13641 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, |
| 13621 | }); | 13642 | }); |
| 13622 | 13643 | ||
| 13623 | const is_vector = resolved_type.zigTypeTag() == .Vector; | 13644 | const is_vector = resolved_type.zigTypeTag(mod) == .Vector; |
| 13624 | 13645 | ||
| 13625 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 13646 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 13626 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 13647 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 13627 | 13648 | ||
| 13628 | const lhs_scalar_ty = lhs_ty.scalarType(); | 13649 | const lhs_scalar_ty = lhs_ty.scalarType(mod); |
| 13629 | const rhs_scalar_ty = rhs_ty.scalarType(); | 13650 | const rhs_scalar_ty = rhs_ty.scalarType(mod); |
| 13630 | const scalar_tag = resolved_type.scalarType().zigTypeTag(); | 13651 | const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod); |
| 13631 | 13652 | ||
| 13632 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; | 13653 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; |
| 13633 | 13654 | ||
| 13634 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_trunc); | 13655 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_trunc); |
| 13635 | 13656 | ||
| 13636 | const mod = sema.mod; | ||
| 13637 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); | 13657 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); |
| 13638 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); | 13658 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); |
| 13639 | 13659 | ||
| ... | @@ -13677,7 +13697,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13677,7 +13697,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13677 | } | 13697 | } |
| 13678 | if (maybe_lhs_val) |lhs_val| { | 13698 | if (maybe_lhs_val) |lhs_val| { |
| 13679 | if (lhs_val.isUndef()) { | 13699 | if (lhs_val.isUndef()) { |
| 13680 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { | 13700 | if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) { |
| 13681 | if (maybe_rhs_val) |rhs_val| { | 13701 | if (maybe_rhs_val) |rhs_val| { |
| 13682 | if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) { | 13702 | if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) { |
| 13683 | return sema.addConstUndef(resolved_type); | 13703 | return sema.addConstUndef(resolved_type); |
| ... | @@ -13727,22 +13747,20 @@ fn addDivIntOverflowSafety( | ... | @@ -13727,22 +13747,20 @@ fn addDivIntOverflowSafety( |
| 13727 | casted_rhs: Air.Inst.Ref, | 13747 | casted_rhs: Air.Inst.Ref, |
| 13728 | is_int: bool, | 13748 | is_int: bool, |
| 13729 | ) CompileError!void { | 13749 | ) CompileError!void { |
| 13750 | const mod = sema.mod; | ||
| 13730 | if (!is_int) return; | 13751 | if (!is_int) return; |
| 13731 | 13752 | ||
| 13732 | // If the LHS is unsigned, it cannot cause overflow. | 13753 | // If the LHS is unsigned, it cannot cause overflow. |
| 13733 | if (!lhs_scalar_ty.isSignedInt()) return; | 13754 | if (!lhs_scalar_ty.isSignedInt(mod)) return; |
| 13734 | |||
| 13735 | const mod = sema.mod; | ||
| 13736 | const target = mod.getTarget(); | ||
| 13737 | 13755 | ||
| 13738 | // If the LHS is widened to a larger integer type, no overflow is possible. | 13756 | // If the LHS is widened to a larger integer type, no overflow is possible. |
| 13739 | if (lhs_scalar_ty.intInfo(target).bits < resolved_type.intInfo(target).bits) { | 13757 | if (lhs_scalar_ty.intInfo(mod).bits < resolved_type.intInfo(mod).bits) { |
| 13740 | return; | 13758 | return; |
| 13741 | } | 13759 | } |
| 13742 | 13760 | ||
| 13743 | const min_int = try resolved_type.minInt(sema.arena, target); | 13761 | const min_int = try resolved_type.minInt(sema.arena, mod); |
| 13744 | const neg_one_scalar = try Value.Tag.int_i64.create(sema.arena, -1); | 13762 | const neg_one_scalar = try Value.Tag.int_i64.create(sema.arena, -1); |
| 13745 | const neg_one = if (resolved_type.zigTypeTag() == .Vector) | 13763 | const neg_one = if (resolved_type.zigTypeTag(mod) == .Vector) |
| 13746 | try Value.Tag.repeated.create(sema.arena, neg_one_scalar) | 13764 | try Value.Tag.repeated.create(sema.arena, neg_one_scalar) |
| 13747 | else | 13765 | else |
| 13748 | neg_one_scalar; | 13766 | neg_one_scalar; |
| ... | @@ -13759,7 +13777,7 @@ fn addDivIntOverflowSafety( | ... | @@ -13759,7 +13777,7 @@ fn addDivIntOverflowSafety( |
| 13759 | } | 13777 | } |
| 13760 | 13778 | ||
| 13761 | var ok: Air.Inst.Ref = .none; | 13779 | var ok: Air.Inst.Ref = .none; |
| 13762 | if (resolved_type.zigTypeTag() == .Vector) { | 13780 | if (resolved_type.zigTypeTag(mod) == .Vector) { |
| 13763 | if (maybe_lhs_val == null) { | 13781 | if (maybe_lhs_val == null) { |
| 13764 | const min_int_ref = try sema.addConstant(resolved_type, min_int); | 13782 | const min_int_ref = try sema.addConstant(resolved_type, min_int); |
| 13765 | ok = try block.addCmpVector(casted_lhs, min_int_ref, .neq); | 13783 | ok = try block.addCmpVector(casted_lhs, min_int_ref, .neq); |
| ... | @@ -13815,7 +13833,8 @@ fn addDivByZeroSafety( | ... | @@ -13815,7 +13833,8 @@ fn addDivByZeroSafety( |
| 13815 | // emitted above. | 13833 | // emitted above. |
| 13816 | if (maybe_rhs_val != null) return; | 13834 | if (maybe_rhs_val != null) return; |
| 13817 | 13835 | ||
| 13818 | const ok = if (resolved_type.zigTypeTag() == .Vector) ok: { | 13836 | const mod = sema.mod; |
| 13837 | const ok = if (resolved_type.zigTypeTag(mod) == .Vector) ok: { | ||
| 13819 | const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero); | 13838 | const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero); |
| 13820 | const zero = try sema.addConstant(resolved_type, zero_val); | 13839 | const zero = try sema.addConstant(resolved_type, zero_val); |
| 13821 | const ok = try block.addCmpVector(casted_rhs, zero, .neq); | 13840 | const ok = try block.addCmpVector(casted_rhs, zero, .neq); |
| ... | @@ -13842,6 +13861,7 @@ fn airTag(block: *Block, is_int: bool, normal: Air.Inst.Tag, optimized: Air.Inst | ... | @@ -13842,6 +13861,7 @@ fn airTag(block: *Block, is_int: bool, normal: Air.Inst.Tag, optimized: Air.Inst |
| 13842 | } | 13861 | } |
| 13843 | 13862 | ||
| 13844 | fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 13863 | fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 13864 | const mod = sema.mod; | ||
| 13845 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 13865 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 13846 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 13866 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| 13847 | sema.src = src; | 13867 | sema.src = src; |
| ... | @@ -13852,8 +13872,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13852,8 +13872,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13852 | const rhs = try sema.resolveInst(extra.rhs); | 13872 | const rhs = try sema.resolveInst(extra.rhs); |
| 13853 | const lhs_ty = sema.typeOf(lhs); | 13873 | const lhs_ty = sema.typeOf(lhs); |
| 13854 | const rhs_ty = sema.typeOf(rhs); | 13874 | const rhs_ty = sema.typeOf(rhs); |
| 13855 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); | 13875 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod); |
| 13856 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); | 13876 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod); |
| 13857 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 13877 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 13858 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); | 13878 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); |
| 13859 | 13879 | ||
| ... | @@ -13862,20 +13882,19 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13862,20 +13882,19 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13862 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, | 13882 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, |
| 13863 | }); | 13883 | }); |
| 13864 | 13884 | ||
| 13865 | const is_vector = resolved_type.zigTypeTag() == .Vector; | 13885 | const is_vector = resolved_type.zigTypeTag(mod) == .Vector; |
| 13866 | 13886 | ||
| 13867 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 13887 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 13868 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 13888 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 13869 | 13889 | ||
| 13870 | const lhs_scalar_ty = lhs_ty.scalarType(); | 13890 | const lhs_scalar_ty = lhs_ty.scalarType(mod); |
| 13871 | const rhs_scalar_ty = rhs_ty.scalarType(); | 13891 | const rhs_scalar_ty = rhs_ty.scalarType(mod); |
| 13872 | const scalar_tag = resolved_type.scalarType().zigTypeTag(); | 13892 | const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod); |
| 13873 | 13893 | ||
| 13874 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; | 13894 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; |
| 13875 | 13895 | ||
| 13876 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod_rem); | 13896 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod_rem); |
| 13877 | 13897 | ||
| 13878 | const mod = sema.mod; | ||
| 13879 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); | 13898 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); |
| 13880 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); | 13899 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); |
| 13881 | 13900 | ||
| ... | @@ -13904,7 +13923,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13904,7 +13923,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13904 | } else Value.zero; | 13923 | } else Value.zero; |
| 13905 | return sema.addConstant(resolved_type, zero_val); | 13924 | return sema.addConstant(resolved_type, zero_val); |
| 13906 | } | 13925 | } |
| 13907 | } else if (lhs_scalar_ty.isSignedInt()) { | 13926 | } else if (lhs_scalar_ty.isSignedInt(mod)) { |
| 13908 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); | 13927 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); |
| 13909 | } | 13928 | } |
| 13910 | if (maybe_rhs_val) |rhs_val| { | 13929 | if (maybe_rhs_val) |rhs_val| { |
| ... | @@ -13929,7 +13948,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13929,7 +13948,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13929 | return sema.addConstant(resolved_type, rem_result); | 13948 | return sema.addConstant(resolved_type, rem_result); |
| 13930 | } | 13949 | } |
| 13931 | break :rs lhs_src; | 13950 | break :rs lhs_src; |
| 13932 | } else if (rhs_scalar_ty.isSignedInt()) { | 13951 | } else if (rhs_scalar_ty.isSignedInt(mod)) { |
| 13933 | return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty); | 13952 | return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty); |
| 13934 | } else { | 13953 | } else { |
| 13935 | break :rs rhs_src; | 13954 | break :rs rhs_src; |
| ... | @@ -13978,7 +13997,8 @@ fn intRem( | ... | @@ -13978,7 +13997,8 @@ fn intRem( |
| 13978 | lhs: Value, | 13997 | lhs: Value, |
| 13979 | rhs: Value, | 13998 | rhs: Value, |
| 13980 | ) CompileError!Value { | 13999 | ) CompileError!Value { |
| 13981 | if (ty.zigTypeTag() == .Vector) { | 14000 | const mod = sema.mod; |
| 14001 | if (ty.zigTypeTag(mod) == .Vector) { | ||
| 13982 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); | 14002 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 13983 | for (result_data, 0..) |*scalar, i| { | 14003 | for (result_data, 0..) |*scalar, i| { |
| 13984 | var lhs_buf: Value.ElemValueBuffer = undefined; | 14004 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| ... | @@ -13997,13 +14017,13 @@ fn intRemScalar( | ... | @@ -13997,13 +14017,13 @@ fn intRemScalar( |
| 13997 | lhs: Value, | 14017 | lhs: Value, |
| 13998 | rhs: Value, | 14018 | rhs: Value, |
| 13999 | ) CompileError!Value { | 14019 | ) CompileError!Value { |
| 14000 | const target = sema.mod.getTarget(); | 14020 | const mod = sema.mod; |
| 14001 | // TODO is this a performance issue? maybe we should try the operation without | 14021 | // TODO is this a performance issue? maybe we should try the operation without |
| 14002 | // resorting to BigInt first. | 14022 | // resorting to BigInt first. |
| 14003 | var lhs_space: Value.BigIntSpace = undefined; | 14023 | var lhs_space: Value.BigIntSpace = undefined; |
| 14004 | var rhs_space: Value.BigIntSpace = undefined; | 14024 | var rhs_space: Value.BigIntSpace = undefined; |
| 14005 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema); | 14025 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema); |
| 14006 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema); | 14026 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema); |
| 14007 | const limbs_q = try sema.arena.alloc( | 14027 | const limbs_q = try sema.arena.alloc( |
| 14008 | math.big.Limb, | 14028 | math.big.Limb, |
| 14009 | lhs_bigint.limbs.len, | 14029 | lhs_bigint.limbs.len, |
| ... | @@ -14025,6 +14045,7 @@ fn intRemScalar( | ... | @@ -14025,6 +14045,7 @@ fn intRemScalar( |
| 14025 | } | 14045 | } |
| 14026 | 14046 | ||
| 14027 | fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 14047 | fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 14048 | const mod = sema.mod; | ||
| 14028 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 14049 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 14029 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 14050 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| 14030 | sema.src = src; | 14051 | sema.src = src; |
| ... | @@ -14035,8 +14056,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -14035,8 +14056,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 14035 | const rhs = try sema.resolveInst(extra.rhs); | 14056 | const rhs = try sema.resolveInst(extra.rhs); |
| 14036 | const lhs_ty = sema.typeOf(lhs); | 14057 | const lhs_ty = sema.typeOf(lhs); |
| 14037 | const rhs_ty = sema.typeOf(rhs); | 14058 | const rhs_ty = sema.typeOf(rhs); |
| 14038 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); | 14059 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod); |
| 14039 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); | 14060 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod); |
| 14040 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 14061 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 14041 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); | 14062 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); |
| 14042 | 14063 | ||
| ... | @@ -14048,13 +14069,12 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -14048,13 +14069,12 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 14048 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 14069 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 14049 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 14070 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 14050 | 14071 | ||
| 14051 | const scalar_tag = resolved_type.scalarType().zigTypeTag(); | 14072 | const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod); |
| 14052 | 14073 | ||
| 14053 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; | 14074 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; |
| 14054 | 14075 | ||
| 14055 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod); | 14076 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod); |
| 14056 | 14077 | ||
| 14057 | const mod = sema.mod; | ||
| 14058 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); | 14078 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); |
| 14059 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); | 14079 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); |
| 14060 | 14080 | ||
| ... | @@ -14127,6 +14147,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -14127,6 +14147,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 14127 | } | 14147 | } |
| 14128 | 14148 | ||
| 14129 | fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 14149 | fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 14150 | const mod = sema.mod; | ||
| 14130 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 14151 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 14131 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 14152 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| 14132 | sema.src = src; | 14153 | sema.src = src; |
| ... | @@ -14137,8 +14158,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -14137,8 +14158,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 14137 | const rhs = try sema.resolveInst(extra.rhs); | 14158 | const rhs = try sema.resolveInst(extra.rhs); |
| 14138 | const lhs_ty = sema.typeOf(lhs); | 14159 | const lhs_ty = sema.typeOf(lhs); |
| 14139 | const rhs_ty = sema.typeOf(rhs); | 14160 | const rhs_ty = sema.typeOf(rhs); |
| 14140 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); | 14161 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod); |
| 14141 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); | 14162 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod); |
| 14142 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 14163 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 14143 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); | 14164 | try sema.checkInvalidPtrArithmetic(block, src, lhs_ty); |
| 14144 | 14165 | ||
| ... | @@ -14150,13 +14171,12 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -14150,13 +14171,12 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 14150 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 14171 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 14151 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 14172 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 14152 | 14173 | ||
| 14153 | const scalar_tag = resolved_type.scalarType().zigTypeTag(); | 14174 | const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod); |
| 14154 | 14175 | ||
| 14155 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; | 14176 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; |
| 14156 | 14177 | ||
| 14157 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .rem); | 14178 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .rem); |
| 14158 | 14179 | ||
| 14159 | const mod = sema.mod; | ||
| 14160 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); | 14180 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); |
| 14161 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); | 14181 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); |
| 14162 | 14182 | ||
| ... | @@ -14268,7 +14288,7 @@ fn zirOverflowArithmetic( | ... | @@ -14268,7 +14288,7 @@ fn zirOverflowArithmetic( |
| 14268 | const lhs = try sema.coerce(block, dest_ty, uncasted_lhs, lhs_src); | 14288 | const lhs = try sema.coerce(block, dest_ty, uncasted_lhs, lhs_src); |
| 14269 | const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src); | 14289 | const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src); |
| 14270 | 14290 | ||
| 14271 | if (dest_ty.scalarType().zigTypeTag() != .Int) { | 14291 | if (dest_ty.scalarType(mod).zigTypeTag(mod) != .Int) { |
| 14272 | return sema.fail(block, src, "expected vector of integers or integer tag type, found '{}'", .{dest_ty.fmt(mod)}); | 14292 | return sema.fail(block, src, "expected vector of integers or integer tag type, found '{}'", .{dest_ty.fmt(mod)}); |
| 14273 | } | 14293 | } |
| 14274 | 14294 | ||
| ... | @@ -14434,12 +14454,14 @@ fn zirOverflowArithmetic( | ... | @@ -14434,12 +14454,14 @@ fn zirOverflowArithmetic( |
| 14434 | } | 14454 | } |
| 14435 | 14455 | ||
| 14436 | fn maybeRepeated(sema: *Sema, ty: Type, val: Value) !Value { | 14456 | fn maybeRepeated(sema: *Sema, ty: Type, val: Value) !Value { |
| 14437 | if (ty.zigTypeTag() != .Vector) return val; | 14457 | const mod = sema.mod; |
| 14458 | if (ty.zigTypeTag(mod) != .Vector) return val; | ||
| 14438 | return Value.Tag.repeated.create(sema.arena, val); | 14459 | return Value.Tag.repeated.create(sema.arena, val); |
| 14439 | } | 14460 | } |
| 14440 | 14461 | ||
| 14441 | fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type { | 14462 | fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type { |
| 14442 | const ov_ty = if (ty.zigTypeTag() == .Vector) try Type.vector(sema.arena, ty.vectorLen(), Type.u1) else Type.u1; | 14463 | const mod = sema.mod; |
| 14464 | const ov_ty = if (ty.zigTypeTag(mod) == .Vector) try Type.vector(sema.arena, ty.vectorLen(), Type.u1) else Type.u1; | ||
| 14443 | 14465 | ||
| 14444 | const types = try sema.arena.alloc(Type, 2); | 14466 | const types = try sema.arena.alloc(Type, 2); |
| 14445 | const values = try sema.arena.alloc(Value, 2); | 14467 | const values = try sema.arena.alloc(Value, 2); |
| ... | @@ -14468,10 +14490,11 @@ fn analyzeArithmetic( | ... | @@ -14468,10 +14490,11 @@ fn analyzeArithmetic( |
| 14468 | rhs_src: LazySrcLoc, | 14490 | rhs_src: LazySrcLoc, |
| 14469 | want_safety: bool, | 14491 | want_safety: bool, |
| 14470 | ) CompileError!Air.Inst.Ref { | 14492 | ) CompileError!Air.Inst.Ref { |
| 14493 | const mod = sema.mod; | ||
| 14471 | const lhs_ty = sema.typeOf(lhs); | 14494 | const lhs_ty = sema.typeOf(lhs); |
| 14472 | const rhs_ty = sema.typeOf(rhs); | 14495 | const rhs_ty = sema.typeOf(rhs); |
| 14473 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); | 14496 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod); |
| 14474 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); | 14497 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod); |
| 14475 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 14498 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 14476 | 14499 | ||
| 14477 | if (lhs_zig_ty_tag == .Pointer) switch (lhs_ty.ptrSize()) { | 14500 | if (lhs_zig_ty_tag == .Pointer) switch (lhs_ty.ptrSize()) { |
| ... | @@ -14491,18 +14514,17 @@ fn analyzeArithmetic( | ... | @@ -14491,18 +14514,17 @@ fn analyzeArithmetic( |
| 14491 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, | 14514 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, |
| 14492 | }); | 14515 | }); |
| 14493 | 14516 | ||
| 14494 | const is_vector = resolved_type.zigTypeTag() == .Vector; | 14517 | const is_vector = resolved_type.zigTypeTag(mod) == .Vector; |
| 14495 | 14518 | ||
| 14496 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | 14519 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 14497 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | 14520 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 14498 | 14521 | ||
| 14499 | const scalar_tag = resolved_type.scalarType().zigTypeTag(); | 14522 | const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod); |
| 14500 | 14523 | ||
| 14501 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; | 14524 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; |
| 14502 | 14525 | ||
| 14503 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, zir_tag); | 14526 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, zir_tag); |
| 14504 | 14527 | ||
| 14505 | const mod = sema.mod; | ||
| 14506 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); | 14528 | const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs); |
| 14507 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); | 14529 | const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs); |
| 14508 | const rs: struct { src: LazySrcLoc, air_tag: Air.Inst.Tag } = rs: { | 14530 | const rs: struct { src: LazySrcLoc, air_tag: Air.Inst.Tag } = rs: { |
| ... | @@ -14910,7 +14932,7 @@ fn analyzeArithmetic( | ... | @@ -14910,7 +14932,7 @@ fn analyzeArithmetic( |
| 14910 | } }, | 14932 | } }, |
| 14911 | }); | 14933 | }); |
| 14912 | const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty); | 14934 | const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty); |
| 14913 | const any_ov_bit = if (resolved_type.zigTypeTag() == .Vector) | 14935 | const any_ov_bit = if (resolved_type.zigTypeTag(mod) == .Vector) |
| 14914 | try block.addInst(.{ | 14936 | try block.addInst(.{ |
| 14915 | .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce, | 14937 | .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce, |
| 14916 | .data = .{ .reduce = .{ | 14938 | .data = .{ .reduce = .{ |
| ... | @@ -14944,12 +14966,12 @@ fn analyzePtrArithmetic( | ... | @@ -14944,12 +14966,12 @@ fn analyzePtrArithmetic( |
| 14944 | // TODO if the operand is comptime-known to be negative, or is a negative int, | 14966 | // TODO if the operand is comptime-known to be negative, or is a negative int, |
| 14945 | // coerce to isize instead of usize. | 14967 | // coerce to isize instead of usize. |
| 14946 | const offset = try sema.coerce(block, Type.usize, uncasted_offset, offset_src); | 14968 | const offset = try sema.coerce(block, Type.usize, uncasted_offset, offset_src); |
| 14947 | const target = sema.mod.getTarget(); | 14969 | const mod = sema.mod; |
| 14948 | const opt_ptr_val = try sema.resolveMaybeUndefVal(ptr); | 14970 | const opt_ptr_val = try sema.resolveMaybeUndefVal(ptr); |
| 14949 | const opt_off_val = try sema.resolveDefinedValue(block, offset_src, offset); | 14971 | const opt_off_val = try sema.resolveDefinedValue(block, offset_src, offset); |
| 14950 | const ptr_ty = sema.typeOf(ptr); | 14972 | const ptr_ty = sema.typeOf(ptr); |
| 14951 | const ptr_info = ptr_ty.ptrInfo().data; | 14973 | const ptr_info = ptr_ty.ptrInfo().data; |
| 14952 | const elem_ty = if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Array) | 14974 | const elem_ty = if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag(mod) == .Array) |
| 14953 | ptr_info.pointee_type.childType() | 14975 | ptr_info.pointee_type.childType() |
| 14954 | else | 14976 | else |
| 14955 | ptr_info.pointee_type; | 14977 | ptr_info.pointee_type; |
| ... | @@ -14963,9 +14985,9 @@ fn analyzePtrArithmetic( | ... | @@ -14963,9 +14985,9 @@ fn analyzePtrArithmetic( |
| 14963 | } | 14985 | } |
| 14964 | // If the addend is not a comptime-known value we can still count on | 14986 | // If the addend is not a comptime-known value we can still count on |
| 14965 | // it being a multiple of the type size. | 14987 | // it being a multiple of the type size. |
| 14966 | const elem_size = elem_ty.abiSize(target); | 14988 | const elem_size = elem_ty.abiSize(mod); |
| 14967 | const addend = if (opt_off_val) |off_val| a: { | 14989 | const addend = if (opt_off_val) |off_val| a: { |
| 14968 | const off_int = try sema.usizeCast(block, offset_src, off_val.toUnsignedInt(target)); | 14990 | const off_int = try sema.usizeCast(block, offset_src, off_val.toUnsignedInt(mod)); |
| 14969 | break :a elem_size * off_int; | 14991 | break :a elem_size * off_int; |
| 14970 | } else elem_size; | 14992 | } else elem_size; |
| 14971 | 14993 | ||
| ... | @@ -14991,10 +15013,10 @@ fn analyzePtrArithmetic( | ... | @@ -14991,10 +15013,10 @@ fn analyzePtrArithmetic( |
| 14991 | if (opt_off_val) |offset_val| { | 15013 | if (opt_off_val) |offset_val| { |
| 14992 | if (ptr_val.isUndef()) return sema.addConstUndef(new_ptr_ty); | 15014 | if (ptr_val.isUndef()) return sema.addConstUndef(new_ptr_ty); |
| 14993 | 15015 | ||
| 14994 | const offset_int = try sema.usizeCast(block, offset_src, offset_val.toUnsignedInt(target)); | 15016 | const offset_int = try sema.usizeCast(block, offset_src, offset_val.toUnsignedInt(mod)); |
| 14995 | if (offset_int == 0) return ptr; | 15017 | if (offset_int == 0) return ptr; |
| 14996 | if (try ptr_val.getUnsignedIntAdvanced(target, sema)) |addr| { | 15018 | if (try ptr_val.getUnsignedIntAdvanced(mod, sema)) |addr| { |
| 14997 | const elem_size = elem_ty.abiSize(target); | 15019 | const elem_size = elem_ty.abiSize(mod); |
| 14998 | const new_addr = switch (air_tag) { | 15020 | const new_addr = switch (air_tag) { |
| 14999 | .ptr_add => addr + elem_size * offset_int, | 15021 | .ptr_add => addr + elem_size * offset_int, |
| 15000 | .ptr_sub => addr - elem_size * offset_int, | 15022 | .ptr_sub => addr - elem_size * offset_int, |
| ... | @@ -15116,6 +15138,7 @@ fn zirAsm( | ... | @@ -15116,6 +15138,7 @@ fn zirAsm( |
| 15116 | 15138 | ||
| 15117 | const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len); | 15139 | const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len); |
| 15118 | const inputs = try sema.arena.alloc(ConstraintName, inputs_len); | 15140 | const inputs = try sema.arena.alloc(ConstraintName, inputs_len); |
| 15141 | const mod = sema.mod; | ||
| 15119 | 15142 | ||
| 15120 | for (args, 0..) |*arg, arg_i| { | 15143 | for (args, 0..) |*arg, arg_i| { |
| 15121 | const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i); | 15144 | const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i); |
| ... | @@ -15123,7 +15146,7 @@ fn zirAsm( | ... | @@ -15123,7 +15146,7 @@ fn zirAsm( |
| 15123 | 15146 | ||
| 15124 | const uncasted_arg = try sema.resolveInst(input.data.operand); | 15147 | const uncasted_arg = try sema.resolveInst(input.data.operand); |
| 15125 | const uncasted_arg_ty = sema.typeOf(uncasted_arg); | 15148 | const uncasted_arg_ty = sema.typeOf(uncasted_arg); |
| 15126 | switch (uncasted_arg_ty.zigTypeTag()) { | 15149 | switch (uncasted_arg_ty.zigTypeTag(mod)) { |
| 15127 | .ComptimeInt => arg.* = try sema.coerce(block, Type.initTag(.usize), uncasted_arg, src), | 15150 | .ComptimeInt => arg.* = try sema.coerce(block, Type.initTag(.usize), uncasted_arg, src), |
| 15128 | .ComptimeFloat => arg.* = try sema.coerce(block, Type.initTag(.f64), uncasted_arg, src), | 15151 | .ComptimeFloat => arg.* = try sema.coerce(block, Type.initTag(.f64), uncasted_arg, src), |
| 15129 | else => { | 15152 | else => { |
| ... | @@ -15205,6 +15228,7 @@ fn zirCmpEq( | ... | @@ -15205,6 +15228,7 @@ fn zirCmpEq( |
| 15205 | const tracy = trace(@src()); | 15228 | const tracy = trace(@src()); |
| 15206 | defer tracy.end(); | 15229 | defer tracy.end(); |
| 15207 | 15230 | ||
| 15231 | const mod = sema.mod; | ||
| 15208 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 15232 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 15209 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 15233 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 15210 | const src: LazySrcLoc = inst_data.src(); | 15234 | const src: LazySrcLoc = inst_data.src(); |
| ... | @@ -15215,8 +15239,8 @@ fn zirCmpEq( | ... | @@ -15215,8 +15239,8 @@ fn zirCmpEq( |
| 15215 | 15239 | ||
| 15216 | const lhs_ty = sema.typeOf(lhs); | 15240 | const lhs_ty = sema.typeOf(lhs); |
| 15217 | const rhs_ty = sema.typeOf(rhs); | 15241 | const rhs_ty = sema.typeOf(rhs); |
| 15218 | const lhs_ty_tag = lhs_ty.zigTypeTag(); | 15242 | const lhs_ty_tag = lhs_ty.zigTypeTag(mod); |
| 15219 | const rhs_ty_tag = rhs_ty.zigTypeTag(); | 15243 | const rhs_ty_tag = rhs_ty.zigTypeTag(mod); |
| 15220 | if (lhs_ty_tag == .Null and rhs_ty_tag == .Null) { | 15244 | if (lhs_ty_tag == .Null and rhs_ty_tag == .Null) { |
| 15221 | // null == null, null != null | 15245 | // null == null, null != null |
| 15222 | if (op == .eq) { | 15246 | if (op == .eq) { |
| ... | @@ -15295,6 +15319,7 @@ fn analyzeCmpUnionTag( | ... | @@ -15295,6 +15319,7 @@ fn analyzeCmpUnionTag( |
| 15295 | tag_src: LazySrcLoc, | 15319 | tag_src: LazySrcLoc, |
| 15296 | op: std.math.CompareOperator, | 15320 | op: std.math.CompareOperator, |
| 15297 | ) CompileError!Air.Inst.Ref { | 15321 | ) CompileError!Air.Inst.Ref { |
| 15322 | const mod = sema.mod; | ||
| 15298 | const union_ty = try sema.resolveTypeFields(sema.typeOf(un)); | 15323 | const union_ty = try sema.resolveTypeFields(sema.typeOf(un)); |
| 15299 | const union_tag_ty = union_ty.unionTagType() orelse { | 15324 | const union_tag_ty = union_ty.unionTagType() orelse { |
| 15300 | const msg = msg: { | 15325 | const msg = msg: { |
| ... | @@ -15313,7 +15338,7 @@ fn analyzeCmpUnionTag( | ... | @@ -15313,7 +15338,7 @@ fn analyzeCmpUnionTag( |
| 15313 | if (try sema.resolveMaybeUndefVal(coerced_tag)) |enum_val| { | 15338 | if (try sema.resolveMaybeUndefVal(coerced_tag)) |enum_val| { |
| 15314 | if (enum_val.isUndef()) return sema.addConstUndef(Type.bool); | 15339 | if (enum_val.isUndef()) return sema.addConstUndef(Type.bool); |
| 15315 | const field_ty = union_ty.unionFieldType(enum_val, sema.mod); | 15340 | const field_ty = union_ty.unionFieldType(enum_val, sema.mod); |
| 15316 | if (field_ty.zigTypeTag() == .NoReturn) { | 15341 | if (field_ty.zigTypeTag(mod) == .NoReturn) { |
| 15317 | return Air.Inst.Ref.bool_false; | 15342 | return Air.Inst.Ref.bool_false; |
| 15318 | } | 15343 | } |
| 15319 | } | 15344 | } |
| ... | @@ -15352,32 +15377,33 @@ fn analyzeCmp( | ... | @@ -15352,32 +15377,33 @@ fn analyzeCmp( |
| 15352 | rhs_src: LazySrcLoc, | 15377 | rhs_src: LazySrcLoc, |
| 15353 | is_equality_cmp: bool, | 15378 | is_equality_cmp: bool, |
| 15354 | ) CompileError!Air.Inst.Ref { | 15379 | ) CompileError!Air.Inst.Ref { |
| 15380 | const mod = sema.mod; | ||
| 15355 | const lhs_ty = sema.typeOf(lhs); | 15381 | const lhs_ty = sema.typeOf(lhs); |
| 15356 | const rhs_ty = sema.typeOf(rhs); | 15382 | const rhs_ty = sema.typeOf(rhs); |
| 15357 | if (lhs_ty.zigTypeTag() != .Optional and rhs_ty.zigTypeTag() != .Optional) { | 15383 | if (lhs_ty.zigTypeTag(mod) != .Optional and rhs_ty.zigTypeTag(mod) != .Optional) { |
| 15358 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 15384 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 15359 | } | 15385 | } |
| 15360 | 15386 | ||
| 15361 | if (lhs_ty.zigTypeTag() == .Vector and rhs_ty.zigTypeTag() == .Vector) { | 15387 | if (lhs_ty.zigTypeTag(mod) == .Vector and rhs_ty.zigTypeTag(mod) == .Vector) { |
| 15362 | return sema.cmpVector(block, src, lhs, rhs, op, lhs_src, rhs_src); | 15388 | return sema.cmpVector(block, src, lhs, rhs, op, lhs_src, rhs_src); |
| 15363 | } | 15389 | } |
| 15364 | if (lhs_ty.isNumeric() and rhs_ty.isNumeric()) { | 15390 | if (lhs_ty.isNumeric(mod) and rhs_ty.isNumeric(mod)) { |
| 15365 | // This operation allows any combination of integer and float types, regardless of the | 15391 | // This operation allows any combination of integer and float types, regardless of the |
| 15366 | // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for | 15392 | // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for |
| 15367 | // numeric types. | 15393 | // numeric types. |
| 15368 | return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src); | 15394 | return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src); |
| 15369 | } | 15395 | } |
| 15370 | if (is_equality_cmp and lhs_ty.zigTypeTag() == .ErrorUnion and rhs_ty.zigTypeTag() == .ErrorSet) { | 15396 | if (is_equality_cmp and lhs_ty.zigTypeTag(mod) == .ErrorUnion and rhs_ty.zigTypeTag(mod) == .ErrorSet) { |
| 15371 | const casted_lhs = try sema.analyzeErrUnionCode(block, lhs_src, lhs); | 15397 | const casted_lhs = try sema.analyzeErrUnionCode(block, lhs_src, lhs); |
| 15372 | return sema.cmpSelf(block, src, casted_lhs, rhs, op, lhs_src, rhs_src); | 15398 | return sema.cmpSelf(block, src, casted_lhs, rhs, op, lhs_src, rhs_src); |
| 15373 | } | 15399 | } |
| 15374 | if (is_equality_cmp and lhs_ty.zigTypeTag() == .ErrorSet and rhs_ty.zigTypeTag() == .ErrorUnion) { | 15400 | if (is_equality_cmp and lhs_ty.zigTypeTag(mod) == .ErrorSet and rhs_ty.zigTypeTag(mod) == .ErrorUnion) { |
| 15375 | const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs); | 15401 | const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs); |
| 15376 | return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src); | 15402 | return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src); |
| 15377 | } | 15403 | } |
| 15378 | const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; | 15404 | const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; |
| 15379 | const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } }); | 15405 | const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } }); |
| 15380 | if (!resolved_type.isSelfComparable(is_equality_cmp)) { | 15406 | if (!resolved_type.isSelfComparable(mod, is_equality_cmp)) { |
| 15381 | return sema.fail(block, src, "operator {s} not allowed for type '{}'", .{ | 15407 | return sema.fail(block, src, "operator {s} not allowed for type '{}'", .{ |
| 15382 | compareOperatorName(op), resolved_type.fmt(sema.mod), | 15408 | compareOperatorName(op), resolved_type.fmt(sema.mod), |
| 15383 | }); | 15409 | }); |
| ... | @@ -15408,6 +15434,7 @@ fn cmpSelf( | ... | @@ -15408,6 +15434,7 @@ fn cmpSelf( |
| 15408 | lhs_src: LazySrcLoc, | 15434 | lhs_src: LazySrcLoc, |
| 15409 | rhs_src: LazySrcLoc, | 15435 | rhs_src: LazySrcLoc, |
| 15410 | ) CompileError!Air.Inst.Ref { | 15436 | ) CompileError!Air.Inst.Ref { |
| 15437 | const mod = sema.mod; | ||
| 15411 | const resolved_type = sema.typeOf(casted_lhs); | 15438 | const resolved_type = sema.typeOf(casted_lhs); |
| 15412 | const runtime_src: LazySrcLoc = src: { | 15439 | const runtime_src: LazySrcLoc = src: { |
| 15413 | if (try sema.resolveMaybeUndefVal(casted_lhs)) |lhs_val| { | 15440 | if (try sema.resolveMaybeUndefVal(casted_lhs)) |lhs_val| { |
| ... | @@ -15415,7 +15442,7 @@ fn cmpSelf( | ... | @@ -15415,7 +15442,7 @@ fn cmpSelf( |
| 15415 | if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| { | 15442 | if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| { |
| 15416 | if (rhs_val.isUndef()) return sema.addConstUndef(Type.bool); | 15443 | if (rhs_val.isUndef()) return sema.addConstUndef(Type.bool); |
| 15417 | 15444 | ||
| 15418 | if (resolved_type.zigTypeTag() == .Vector) { | 15445 | if (resolved_type.zigTypeTag(mod) == .Vector) { |
| 15419 | const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.bool); | 15446 | const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.bool); |
| 15420 | const cmp_val = try sema.compareVector(lhs_val, op, rhs_val, resolved_type); | 15447 | const cmp_val = try sema.compareVector(lhs_val, op, rhs_val, resolved_type); |
| 15421 | return sema.addConstant(result_ty, cmp_val); | 15448 | return sema.addConstant(result_ty, cmp_val); |
| ... | @@ -15427,7 +15454,7 @@ fn cmpSelf( | ... | @@ -15427,7 +15454,7 @@ fn cmpSelf( |
| 15427 | return Air.Inst.Ref.bool_false; | 15454 | return Air.Inst.Ref.bool_false; |
| 15428 | } | 15455 | } |
| 15429 | } else { | 15456 | } else { |
| 15430 | if (resolved_type.zigTypeTag() == .Bool) { | 15457 | if (resolved_type.zigTypeTag(mod) == .Bool) { |
| 15431 | // We can lower bool eq/neq more efficiently. | 15458 | // We can lower bool eq/neq more efficiently. |
| 15432 | return sema.runtimeBoolCmp(block, src, op, casted_rhs, lhs_val.toBool(), rhs_src); | 15459 | return sema.runtimeBoolCmp(block, src, op, casted_rhs, lhs_val.toBool(), rhs_src); |
| 15433 | } | 15460 | } |
| ... | @@ -15436,7 +15463,7 @@ fn cmpSelf( | ... | @@ -15436,7 +15463,7 @@ fn cmpSelf( |
| 15436 | } else { | 15463 | } else { |
| 15437 | // For bools, we still check the other operand, because we can lower | 15464 | // For bools, we still check the other operand, because we can lower |
| 15438 | // bool eq/neq more efficiently. | 15465 | // bool eq/neq more efficiently. |
| 15439 | if (resolved_type.zigTypeTag() == .Bool) { | 15466 | if (resolved_type.zigTypeTag(mod) == .Bool) { |
| 15440 | if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| { | 15467 | if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| { |
| 15441 | if (rhs_val.isUndef()) return sema.addConstUndef(Type.bool); | 15468 | if (rhs_val.isUndef()) return sema.addConstUndef(Type.bool); |
| 15442 | return sema.runtimeBoolCmp(block, src, op, casted_lhs, rhs_val.toBool(), lhs_src); | 15469 | return sema.runtimeBoolCmp(block, src, op, casted_lhs, rhs_val.toBool(), lhs_src); |
| ... | @@ -15446,7 +15473,7 @@ fn cmpSelf( | ... | @@ -15446,7 +15473,7 @@ fn cmpSelf( |
| 15446 | } | 15473 | } |
| 15447 | }; | 15474 | }; |
| 15448 | try sema.requireRuntimeBlock(block, src, runtime_src); | 15475 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 15449 | if (resolved_type.zigTypeTag() == .Vector) { | 15476 | if (resolved_type.zigTypeTag(mod) == .Vector) { |
| 15450 | return block.addCmpVector(casted_lhs, casted_rhs, op); | 15477 | return block.addCmpVector(casted_lhs, casted_rhs, op); |
| 15451 | } | 15478 | } |
| 15452 | const tag = Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized); | 15479 | const tag = Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized); |
| ... | @@ -15475,10 +15502,11 @@ fn runtimeBoolCmp( | ... | @@ -15475,10 +15502,11 @@ fn runtimeBoolCmp( |
| 15475 | } | 15502 | } |
| 15476 | 15503 | ||
| 15477 | fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 15504 | fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 15505 | const mod = sema.mod; | ||
| 15478 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 15506 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 15479 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 15507 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 15480 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); | 15508 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 15481 | switch (ty.zigTypeTag()) { | 15509 | switch (ty.zigTypeTag(mod)) { |
| 15482 | .Fn, | 15510 | .Fn, |
| 15483 | .NoReturn, | 15511 | .NoReturn, |
| 15484 | .Undefined, | 15512 | .Undefined, |
| ... | @@ -15509,8 +15537,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -15509,8 +15537,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15509 | .AnyFrame, | 15537 | .AnyFrame, |
| 15510 | => {}, | 15538 | => {}, |
| 15511 | } | 15539 | } |
| 15512 | const target = sema.mod.getTarget(); | 15540 | const val = try ty.lazyAbiSize(mod, sema.arena); |
| 15513 | const val = try ty.lazyAbiSize(target, sema.arena); | ||
| 15514 | if (val.tag() == .lazy_size) { | 15541 | if (val.tag() == .lazy_size) { |
| 15515 | try sema.queueFullTypeResolution(ty); | 15542 | try sema.queueFullTypeResolution(ty); |
| 15516 | } | 15543 | } |
| ... | @@ -15518,10 +15545,11 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -15518,10 +15545,11 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15518 | } | 15545 | } |
| 15519 | 15546 | ||
| 15520 | fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 15547 | fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 15548 | const mod = sema.mod; | ||
| 15521 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 15549 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 15522 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 15550 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 15523 | const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand); | 15551 | const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 15524 | switch (operand_ty.zigTypeTag()) { | 15552 | switch (operand_ty.zigTypeTag(mod)) { |
| 15525 | .Fn, | 15553 | .Fn, |
| 15526 | .NoReturn, | 15554 | .NoReturn, |
| 15527 | .Undefined, | 15555 | .Undefined, |
| ... | @@ -15552,8 +15580,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -15552,8 +15580,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 15552 | .AnyFrame, | 15580 | .AnyFrame, |
| 15553 | => {}, | 15581 | => {}, |
| 15554 | } | 15582 | } |
| 15555 | const target = sema.mod.getTarget(); | 15583 | const bit_size = try operand_ty.bitSizeAdvanced(mod, sema); |
| 15556 | const bit_size = try operand_ty.bitSizeAdvanced(target, sema); | ||
| 15557 | return sema.addIntUnsigned(Type.comptime_int, bit_size); | 15584 | return sema.addIntUnsigned(Type.comptime_int, bit_size); |
| 15558 | } | 15585 | } |
| 15559 | 15586 | ||
| ... | @@ -15765,13 +15792,13 @@ fn zirBuiltinSrc( | ... | @@ -15765,13 +15792,13 @@ fn zirBuiltinSrc( |
| 15765 | } | 15792 | } |
| 15766 | 15793 | ||
| 15767 | fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 15794 | fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 15795 | const mod = sema.mod; | ||
| 15768 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 15796 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 15769 | const src = inst_data.src(); | 15797 | const src = inst_data.src(); |
| 15770 | const ty = try sema.resolveType(block, src, inst_data.operand); | 15798 | const ty = try sema.resolveType(block, src, inst_data.operand); |
| 15771 | const type_info_ty = try sema.getBuiltinType("Type"); | 15799 | const type_info_ty = try sema.getBuiltinType("Type"); |
| 15772 | const target = sema.mod.getTarget(); | ||
| 15773 | 15800 | ||
| 15774 | switch (ty.zigTypeTag()) { | 15801 | switch (ty.zigTypeTag(mod)) { |
| 15775 | .Type => return sema.addConstant( | 15802 | .Type => return sema.addConstant( |
| 15776 | type_info_ty, | 15803 | type_info_ty, |
| 15777 | try Value.Tag.@"union".create(sema.arena, .{ | 15804 | try Value.Tag.@"union".create(sema.arena, .{ |
| ... | @@ -15881,8 +15908,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -15881,8 +15908,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15881 | try sema.mod.declareDeclDependency(sema.owner_decl_index, fn_info_decl_index); | 15908 | try sema.mod.declareDeclDependency(sema.owner_decl_index, fn_info_decl_index); |
| 15882 | try sema.ensureDeclAnalyzed(fn_info_decl_index); | 15909 | try sema.ensureDeclAnalyzed(fn_info_decl_index); |
| 15883 | const fn_info_decl = sema.mod.declPtr(fn_info_decl_index); | 15910 | const fn_info_decl = sema.mod.declPtr(fn_info_decl_index); |
| 15884 | var fn_ty_buffer: Value.ToTypeBuffer = undefined; | 15911 | const fn_ty = fn_info_decl.val.toType(); |
| 15885 | const fn_ty = fn_info_decl.val.toType(&fn_ty_buffer); | ||
| 15886 | const param_info_decl_index = (try sema.namespaceLookup( | 15912 | const param_info_decl_index = (try sema.namespaceLookup( |
| 15887 | block, | 15913 | block, |
| 15888 | src, | 15914 | src, |
| ... | @@ -15892,8 +15918,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -15892,8 +15918,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15892 | try sema.mod.declareDeclDependency(sema.owner_decl_index, param_info_decl_index); | 15918 | try sema.mod.declareDeclDependency(sema.owner_decl_index, param_info_decl_index); |
| 15893 | try sema.ensureDeclAnalyzed(param_info_decl_index); | 15919 | try sema.ensureDeclAnalyzed(param_info_decl_index); |
| 15894 | const param_info_decl = sema.mod.declPtr(param_info_decl_index); | 15920 | const param_info_decl = sema.mod.declPtr(param_info_decl_index); |
| 15895 | var param_buffer: Value.ToTypeBuffer = undefined; | 15921 | const param_ty = param_info_decl.val.toType(); |
| 15896 | const param_ty = param_info_decl.val.toType(&param_buffer); | ||
| 15897 | const new_decl = try params_anon_decl.finish( | 15922 | const new_decl = try params_anon_decl.finish( |
| 15898 | try Type.Tag.array.create(params_anon_decl.arena(), .{ | 15923 | try Type.Tag.array.create(params_anon_decl.arena(), .{ |
| 15899 | .len = param_vals.len, | 15924 | .len = param_vals.len, |
| ... | @@ -15924,7 +15949,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -15924,7 +15949,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15924 | // calling_convention: CallingConvention, | 15949 | // calling_convention: CallingConvention, |
| 15925 | try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.cc)), | 15950 | try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.cc)), |
| 15926 | // alignment: comptime_int, | 15951 | // alignment: comptime_int, |
| 15927 | try Value.Tag.int_u64.create(sema.arena, ty.abiAlignment(target)), | 15952 | try Value.Tag.int_u64.create(sema.arena, ty.abiAlignment(mod)), |
| 15928 | // is_generic: bool, | 15953 | // is_generic: bool, |
| 15929 | Value.makeBool(info.is_generic), | 15954 | Value.makeBool(info.is_generic), |
| 15930 | // is_var_args: bool, | 15955 | // is_var_args: bool, |
| ... | @@ -15944,7 +15969,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -15944,7 +15969,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15944 | ); | 15969 | ); |
| 15945 | }, | 15970 | }, |
| 15946 | .Int => { | 15971 | .Int => { |
| 15947 | const info = ty.intInfo(target); | 15972 | const info = ty.intInfo(mod); |
| 15948 | const field_values = try sema.arena.alloc(Value, 2); | 15973 | const field_values = try sema.arena.alloc(Value, 2); |
| 15949 | // signedness: Signedness, | 15974 | // signedness: Signedness, |
| 15950 | field_values[0] = try Value.Tag.enum_field_index.create( | 15975 | field_values[0] = try Value.Tag.enum_field_index.create( |
| ... | @@ -15965,7 +15990,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -15965,7 +15990,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15965 | .Float => { | 15990 | .Float => { |
| 15966 | const field_values = try sema.arena.alloc(Value, 1); | 15991 | const field_values = try sema.arena.alloc(Value, 1); |
| 15967 | // bits: comptime_int, | 15992 | // bits: comptime_int, |
| 15968 | field_values[0] = try Value.Tag.int_u64.create(sema.arena, ty.bitSize(target)); | 15993 | field_values[0] = try Value.Tag.int_u64.create(sema.arena, ty.bitSize(mod)); |
| 15969 | 15994 | ||
| 15970 | return sema.addConstant( | 15995 | return sema.addConstant( |
| 15971 | type_info_ty, | 15996 | type_info_ty, |
| ... | @@ -15980,7 +16005,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -15980,7 +16005,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15980 | const alignment = if (info.@"align" != 0) | 16005 | const alignment = if (info.@"align" != 0) |
| 15981 | try Value.Tag.int_u64.create(sema.arena, info.@"align") | 16006 | try Value.Tag.int_u64.create(sema.arena, info.@"align") |
| 15982 | else | 16007 | else |
| 15983 | try info.pointee_type.lazyAbiAlignment(target, sema.arena); | 16008 | try info.pointee_type.lazyAbiAlignment(mod, sema.arena); |
| 15984 | 16009 | ||
| 15985 | const field_values = try sema.arena.create([8]Value); | 16010 | const field_values = try sema.arena.create([8]Value); |
| 15986 | field_values.* = .{ | 16011 | field_values.* = .{ |
| ... | @@ -16072,8 +16097,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16072,8 +16097,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16072 | try sema.mod.declareDeclDependency(sema.owner_decl_index, set_field_ty_decl_index); | 16097 | try sema.mod.declareDeclDependency(sema.owner_decl_index, set_field_ty_decl_index); |
| 16073 | try sema.ensureDeclAnalyzed(set_field_ty_decl_index); | 16098 | try sema.ensureDeclAnalyzed(set_field_ty_decl_index); |
| 16074 | const set_field_ty_decl = sema.mod.declPtr(set_field_ty_decl_index); | 16099 | const set_field_ty_decl = sema.mod.declPtr(set_field_ty_decl_index); |
| 16075 | var buffer: Value.ToTypeBuffer = undefined; | 16100 | break :t try set_field_ty_decl.val.toType().copy(fields_anon_decl.arena()); |
| 16076 | break :t try set_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena()); | ||
| 16077 | }; | 16101 | }; |
| 16078 | 16102 | ||
| 16079 | try sema.queueFullTypeResolution(try error_field_ty.copy(sema.arena)); | 16103 | try sema.queueFullTypeResolution(try error_field_ty.copy(sema.arena)); |
| ... | @@ -16164,8 +16188,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16164,8 +16188,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16164 | }, | 16188 | }, |
| 16165 | .Enum => { | 16189 | .Enum => { |
| 16166 | // TODO: look into memoizing this result. | 16190 | // TODO: look into memoizing this result. |
| 16167 | var int_tag_type_buffer: Type.Payload.Bits = undefined; | 16191 | const int_tag_ty = try ty.intTagType().copy(sema.arena); |
| 16168 | const int_tag_ty = try ty.intTagType(&int_tag_type_buffer).copy(sema.arena); | ||
| 16169 | 16192 | ||
| 16170 | const is_exhaustive = Value.makeBool(!ty.isNonexhaustiveEnum()); | 16193 | const is_exhaustive = Value.makeBool(!ty.isNonexhaustiveEnum()); |
| 16171 | 16194 | ||
| ... | @@ -16182,8 +16205,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16182,8 +16205,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16182 | try sema.mod.declareDeclDependency(sema.owner_decl_index, enum_field_ty_decl_index); | 16205 | try sema.mod.declareDeclDependency(sema.owner_decl_index, enum_field_ty_decl_index); |
| 16183 | try sema.ensureDeclAnalyzed(enum_field_ty_decl_index); | 16206 | try sema.ensureDeclAnalyzed(enum_field_ty_decl_index); |
| 16184 | const enum_field_ty_decl = sema.mod.declPtr(enum_field_ty_decl_index); | 16207 | const enum_field_ty_decl = sema.mod.declPtr(enum_field_ty_decl_index); |
| 16185 | var buffer: Value.ToTypeBuffer = undefined; | 16208 | break :t try enum_field_ty_decl.val.toType().copy(fields_anon_decl.arena()); |
| 16186 | break :t try enum_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena()); | ||
| 16187 | }; | 16209 | }; |
| 16188 | 16210 | ||
| 16189 | const enum_fields = ty.enumFields(); | 16211 | const enum_fields = ty.enumFields(); |
| ... | @@ -16275,8 +16297,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16275,8 +16297,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16275 | try sema.mod.declareDeclDependency(sema.owner_decl_index, union_field_ty_decl_index); | 16297 | try sema.mod.declareDeclDependency(sema.owner_decl_index, union_field_ty_decl_index); |
| 16276 | try sema.ensureDeclAnalyzed(union_field_ty_decl_index); | 16298 | try sema.ensureDeclAnalyzed(union_field_ty_decl_index); |
| 16277 | const union_field_ty_decl = sema.mod.declPtr(union_field_ty_decl_index); | 16299 | const union_field_ty_decl = sema.mod.declPtr(union_field_ty_decl_index); |
| 16278 | var buffer: Value.ToTypeBuffer = undefined; | 16300 | break :t try union_field_ty_decl.val.toType().copy(fields_anon_decl.arena()); |
| 16279 | break :t try union_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena()); | ||
| 16280 | }; | 16301 | }; |
| 16281 | 16302 | ||
| 16282 | const union_ty = try sema.resolveTypeFields(ty); | 16303 | const union_ty = try sema.resolveTypeFields(ty); |
| ... | @@ -16383,8 +16404,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16383,8 +16404,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16383 | try sema.mod.declareDeclDependency(sema.owner_decl_index, struct_field_ty_decl_index); | 16404 | try sema.mod.declareDeclDependency(sema.owner_decl_index, struct_field_ty_decl_index); |
| 16384 | try sema.ensureDeclAnalyzed(struct_field_ty_decl_index); | 16405 | try sema.ensureDeclAnalyzed(struct_field_ty_decl_index); |
| 16385 | const struct_field_ty_decl = sema.mod.declPtr(struct_field_ty_decl_index); | 16406 | const struct_field_ty_decl = sema.mod.declPtr(struct_field_ty_decl_index); |
| 16386 | var buffer: Value.ToTypeBuffer = undefined; | 16407 | break :t try struct_field_ty_decl.val.toType().copy(fields_anon_decl.arena()); |
| 16387 | break :t try struct_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena()); | ||
| 16388 | }; | 16408 | }; |
| 16389 | const struct_ty = try sema.resolveTypeFields(ty); | 16409 | const struct_ty = try sema.resolveTypeFields(ty); |
| 16390 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout | 16410 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout |
| ... | @@ -16430,7 +16450,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16430,7 +16450,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16430 | // is_comptime: bool, | 16450 | // is_comptime: bool, |
| 16431 | Value.makeBool(is_comptime), | 16451 | Value.makeBool(is_comptime), |
| 16432 | // alignment: comptime_int, | 16452 | // alignment: comptime_int, |
| 16433 | try field_ty.lazyAbiAlignment(target, fields_anon_decl.arena()), | 16453 | try field_ty.lazyAbiAlignment(mod, fields_anon_decl.arena()), |
| 16434 | }; | 16454 | }; |
| 16435 | struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields); | 16455 | struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields); |
| 16436 | } | 16456 | } |
| ... | @@ -16463,7 +16483,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16463,7 +16483,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16463 | else | 16483 | else |
| 16464 | field.default_val; | 16484 | field.default_val; |
| 16465 | const default_val_ptr = try sema.optRefValue(block, field.ty, opt_default_val); | 16485 | const default_val_ptr = try sema.optRefValue(block, field.ty, opt_default_val); |
| 16466 | const alignment = field.alignment(target, layout); | 16486 | const alignment = field.alignment(mod, layout); |
| 16467 | 16487 | ||
| 16468 | struct_field_fields.* = .{ | 16488 | struct_field_fields.* = .{ |
| 16469 | // name: []const u8, | 16489 | // name: []const u8, |
| ... | @@ -16506,7 +16526,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16506,7 +16526,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16506 | if (layout == .Packed) { | 16526 | if (layout == .Packed) { |
| 16507 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 16527 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 16508 | assert(struct_obj.haveLayout()); | 16528 | assert(struct_obj.haveLayout()); |
| 16509 | assert(struct_obj.backing_int_ty.isInt()); | 16529 | assert(struct_obj.backing_int_ty.isInt(mod)); |
| 16510 | const backing_int_ty_val = try Value.Tag.ty.create(sema.arena, struct_obj.backing_int_ty); | 16530 | const backing_int_ty_val = try Value.Tag.ty.create(sema.arena, struct_obj.backing_int_ty); |
| 16511 | break :blk try Value.Tag.opt_payload.create(sema.arena, backing_int_ty_val); | 16531 | break :blk try Value.Tag.opt_payload.create(sema.arena, backing_int_ty_val); |
| 16512 | } else { | 16532 | } else { |
| ... | @@ -16584,8 +16604,7 @@ fn typeInfoDecls( | ... | @@ -16584,8 +16604,7 @@ fn typeInfoDecls( |
| 16584 | try sema.mod.declareDeclDependency(sema.owner_decl_index, declaration_ty_decl_index); | 16604 | try sema.mod.declareDeclDependency(sema.owner_decl_index, declaration_ty_decl_index); |
| 16585 | try sema.ensureDeclAnalyzed(declaration_ty_decl_index); | 16605 | try sema.ensureDeclAnalyzed(declaration_ty_decl_index); |
| 16586 | const declaration_ty_decl = sema.mod.declPtr(declaration_ty_decl_index); | 16606 | const declaration_ty_decl = sema.mod.declPtr(declaration_ty_decl_index); |
| 16587 | var buffer: Value.ToTypeBuffer = undefined; | 16607 | break :t try declaration_ty_decl.val.toType().copy(decls_anon_decl.arena()); |
| 16588 | break :t try declaration_ty_decl.val.toType(&buffer).copy(decls_anon_decl.arena()); | ||
| 16589 | }; | 16608 | }; |
| 16590 | try sema.queueFullTypeResolution(try declaration_ty.copy(sema.arena)); | 16609 | try sema.queueFullTypeResolution(try declaration_ty.copy(sema.arena)); |
| 16591 | 16610 | ||
| ... | @@ -16632,8 +16651,7 @@ fn typeInfoNamespaceDecls( | ... | @@ -16632,8 +16651,7 @@ fn typeInfoNamespaceDecls( |
| 16632 | if (decl.kind == .@"usingnamespace") { | 16651 | if (decl.kind == .@"usingnamespace") { |
| 16633 | if (decl.analysis == .in_progress) continue; | 16652 | if (decl.analysis == .in_progress) continue; |
| 16634 | try sema.mod.ensureDeclAnalyzed(decl_index); | 16653 | try sema.mod.ensureDeclAnalyzed(decl_index); |
| 16635 | var buf: Value.ToTypeBuffer = undefined; | 16654 | const new_ns = decl.val.toType().getNamespace().?; |
| 16636 | const new_ns = decl.val.toType(&buf).getNamespace().?; | ||
| 16637 | try sema.typeInfoNamespaceDecls(block, decls_anon_decl, new_ns, decl_vals, seen_namespaces); | 16655 | try sema.typeInfoNamespaceDecls(block, decls_anon_decl, new_ns, decl_vals, seen_namespaces); |
| 16638 | continue; | 16656 | continue; |
| 16639 | } | 16657 | } |
| ... | @@ -16709,10 +16727,11 @@ fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil | ... | @@ -16709,10 +16727,11 @@ fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil |
| 16709 | } | 16727 | } |
| 16710 | 16728 | ||
| 16711 | fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) CompileError!Type { | 16729 | fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) CompileError!Type { |
| 16712 | switch (operand.zigTypeTag()) { | 16730 | const mod = sema.mod; |
| 16731 | switch (operand.zigTypeTag(mod)) { | ||
| 16713 | .ComptimeInt => return Type.comptime_int, | 16732 | .ComptimeInt => return Type.comptime_int, |
| 16714 | .Int => { | 16733 | .Int => { |
| 16715 | const bits = operand.bitSize(sema.mod.getTarget()); | 16734 | const bits = operand.bitSize(mod); |
| 16716 | const count = if (bits == 0) | 16735 | const count = if (bits == 0) |
| 16717 | 0 | 16736 | 0 |
| 16718 | else blk: { | 16737 | else blk: { |
| ... | @@ -16723,10 +16742,10 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi | ... | @@ -16723,10 +16742,10 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi |
| 16723 | } | 16742 | } |
| 16724 | break :blk count; | 16743 | break :blk count; |
| 16725 | }; | 16744 | }; |
| 16726 | return Module.makeIntType(sema.arena, .unsigned, count); | 16745 | return mod.intType(.unsigned, count); |
| 16727 | }, | 16746 | }, |
| 16728 | .Vector => { | 16747 | .Vector => { |
| 16729 | const elem_ty = operand.elemType2(); | 16748 | const elem_ty = operand.elemType2(mod); |
| 16730 | const log2_elem_ty = try sema.log2IntType(block, elem_ty, src); | 16749 | const log2_elem_ty = try sema.log2IntType(block, elem_ty, src); |
| 16731 | return Type.Tag.vector.create(sema.arena, .{ | 16750 | return Type.Tag.vector.create(sema.arena, .{ |
| 16732 | .len = operand.vectorLen(), | 16751 | .len = operand.vectorLen(), |
| ... | @@ -16920,9 +16939,10 @@ fn finishCondBr( | ... | @@ -16920,9 +16939,10 @@ fn finishCondBr( |
| 16920 | } | 16939 | } |
| 16921 | 16940 | ||
| 16922 | fn checkNullableType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | 16941 | fn checkNullableType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { |
| 16923 | switch (ty.zigTypeTag()) { | 16942 | const mod = sema.mod; |
| 16943 | switch (ty.zigTypeTag(mod)) { | ||
| 16924 | .Optional, .Null, .Undefined => return, | 16944 | .Optional, .Null, .Undefined => return, |
| 16925 | .Pointer => if (ty.isPtrLikeOptional()) return, | 16945 | .Pointer => if (ty.isPtrLikeOptional(mod)) return, |
| 16926 | else => {}, | 16946 | else => {}, |
| 16927 | } | 16947 | } |
| 16928 | return sema.failWithExpectedOptionalType(block, src, ty); | 16948 | return sema.failWithExpectedOptionalType(block, src, ty); |
| ... | @@ -16951,10 +16971,11 @@ fn zirIsNonNullPtr( | ... | @@ -16951,10 +16971,11 @@ fn zirIsNonNullPtr( |
| 16951 | const tracy = trace(@src()); | 16971 | const tracy = trace(@src()); |
| 16952 | defer tracy.end(); | 16972 | defer tracy.end(); |
| 16953 | 16973 | ||
| 16974 | const mod = sema.mod; | ||
| 16954 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 16975 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 16955 | const src = inst_data.src(); | 16976 | const src = inst_data.src(); |
| 16956 | const ptr = try sema.resolveInst(inst_data.operand); | 16977 | const ptr = try sema.resolveInst(inst_data.operand); |
| 16957 | try sema.checkNullableType(block, src, sema.typeOf(ptr).elemType2()); | 16978 | try sema.checkNullableType(block, src, sema.typeOf(ptr).elemType2(mod)); |
| 16958 | if ((try sema.resolveMaybeUndefVal(ptr)) == null) { | 16979 | if ((try sema.resolveMaybeUndefVal(ptr)) == null) { |
| 16959 | return block.addUnOp(.is_non_null_ptr, ptr); | 16980 | return block.addUnOp(.is_non_null_ptr, ptr); |
| 16960 | } | 16981 | } |
| ... | @@ -16963,7 +16984,8 @@ fn zirIsNonNullPtr( | ... | @@ -16963,7 +16984,8 @@ fn zirIsNonNullPtr( |
| 16963 | } | 16984 | } |
| 16964 | 16985 | ||
| 16965 | fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | 16986 | fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { |
| 16966 | switch (ty.zigTypeTag()) { | 16987 | const mod = sema.mod; |
| 16988 | switch (ty.zigTypeTag(mod)) { | ||
| 16967 | .ErrorSet, .ErrorUnion, .Undefined => return, | 16989 | .ErrorSet, .ErrorUnion, .Undefined => return, |
| 16968 | else => return sema.fail(block, src, "expected error union type, found '{}'", .{ | 16990 | else => return sema.fail(block, src, "expected error union type, found '{}'", .{ |
| 16969 | ty.fmt(sema.mod), | 16991 | ty.fmt(sema.mod), |
| ... | @@ -16986,10 +17008,11 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -16986,10 +17008,11 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 16986 | const tracy = trace(@src()); | 17008 | const tracy = trace(@src()); |
| 16987 | defer tracy.end(); | 17009 | defer tracy.end(); |
| 16988 | 17010 | ||
| 17011 | const mod = sema.mod; | ||
| 16989 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 17012 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 16990 | const src = inst_data.src(); | 17013 | const src = inst_data.src(); |
| 16991 | const ptr = try sema.resolveInst(inst_data.operand); | 17014 | const ptr = try sema.resolveInst(inst_data.operand); |
| 16992 | try sema.checkErrorType(block, src, sema.typeOf(ptr).elemType2()); | 17015 | try sema.checkErrorType(block, src, sema.typeOf(ptr).elemType2(mod)); |
| 16993 | const loaded = try sema.analyzeLoad(block, src, ptr, src); | 17016 | const loaded = try sema.analyzeLoad(block, src, ptr, src); |
| 16994 | return sema.analyzeIsNonErr(block, src, loaded); | 17017 | return sema.analyzeIsNonErr(block, src, loaded); |
| 16995 | } | 17018 | } |
| ... | @@ -17012,6 +17035,7 @@ fn zirCondbr( | ... | @@ -17012,6 +17035,7 @@ fn zirCondbr( |
| 17012 | const tracy = trace(@src()); | 17035 | const tracy = trace(@src()); |
| 17013 | defer tracy.end(); | 17036 | defer tracy.end(); |
| 17014 | 17037 | ||
| 17038 | const mod = sema.mod; | ||
| 17015 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 17039 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 17016 | const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node }; | 17040 | const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node }; |
| 17017 | const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index); | 17041 | const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index); |
| ... | @@ -17052,7 +17076,7 @@ fn zirCondbr( | ... | @@ -17052,7 +17076,7 @@ fn zirCondbr( |
| 17052 | const err_inst_data = sema.code.instructions.items(.data)[index].un_node; | 17076 | const err_inst_data = sema.code.instructions.items(.data)[index].un_node; |
| 17053 | const err_operand = try sema.resolveInst(err_inst_data.operand); | 17077 | const err_operand = try sema.resolveInst(err_inst_data.operand); |
| 17054 | const operand_ty = sema.typeOf(err_operand); | 17078 | const operand_ty = sema.typeOf(err_operand); |
| 17055 | assert(operand_ty.zigTypeTag() == .ErrorUnion); | 17079 | assert(operand_ty.zigTypeTag(mod) == .ErrorUnion); |
| 17056 | const result_ty = operand_ty.errorUnionSet(); | 17080 | const result_ty = operand_ty.errorUnionSet(); |
| 17057 | break :blk try sub_block.addTyOp(.unwrap_errunion_err, result_ty, err_operand); | 17081 | break :blk try sub_block.addTyOp(.unwrap_errunion_err, result_ty, err_operand); |
| 17058 | }; | 17082 | }; |
| ... | @@ -17079,7 +17103,7 @@ fn zirCondbr( | ... | @@ -17079,7 +17103,7 @@ fn zirCondbr( |
| 17079 | return always_noreturn; | 17103 | return always_noreturn; |
| 17080 | } | 17104 | } |
| 17081 | 17105 | ||
| 17082 | fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref { | 17106 | fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 17083 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 17107 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 17084 | const src = inst_data.src(); | 17108 | const src = inst_data.src(); |
| 17085 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | 17109 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| ... | @@ -17087,7 +17111,8 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -17087,7 +17111,8 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! |
| 17087 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; | 17111 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; |
| 17088 | const err_union = try sema.resolveInst(extra.data.operand); | 17112 | const err_union = try sema.resolveInst(extra.data.operand); |
| 17089 | const err_union_ty = sema.typeOf(err_union); | 17113 | const err_union_ty = sema.typeOf(err_union); |
| 17090 | if (err_union_ty.zigTypeTag() != .ErrorUnion) { | 17114 | const mod = sema.mod; |
| 17115 | if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) { | ||
| 17091 | return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{ | 17116 | return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{ |
| 17092 | err_union_ty.fmt(sema.mod), | 17117 | err_union_ty.fmt(sema.mod), |
| 17093 | }); | 17118 | }); |
| ... | @@ -17124,7 +17149,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -17124,7 +17149,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! |
| 17124 | return try_inst; | 17149 | return try_inst; |
| 17125 | } | 17150 | } |
| 17126 | 17151 | ||
| 17127 | fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref { | 17152 | fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 17128 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 17153 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 17129 | const src = inst_data.src(); | 17154 | const src = inst_data.src(); |
| 17130 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | 17155 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| ... | @@ -17133,7 +17158,8 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -17133,7 +17158,8 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr |
| 17133 | const operand = try sema.resolveInst(extra.data.operand); | 17158 | const operand = try sema.resolveInst(extra.data.operand); |
| 17134 | const err_union = try sema.analyzeLoad(parent_block, src, operand, operand_src); | 17159 | const err_union = try sema.analyzeLoad(parent_block, src, operand, operand_src); |
| 17135 | const err_union_ty = sema.typeOf(err_union); | 17160 | const err_union_ty = sema.typeOf(err_union); |
| 17136 | if (err_union_ty.zigTypeTag() != .ErrorUnion) { | 17161 | const mod = sema.mod; |
| 17162 | if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) { | ||
| 17137 | return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{ | 17163 | return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{ |
| 17138 | err_union_ty.fmt(sema.mod), | 17164 | err_union_ty.fmt(sema.mod), |
| 17139 | }); | 17165 | }); |
| ... | @@ -17275,16 +17301,17 @@ fn zirRetImplicit( | ... | @@ -17275,16 +17301,17 @@ fn zirRetImplicit( |
| 17275 | const tracy = trace(@src()); | 17301 | const tracy = trace(@src()); |
| 17276 | defer tracy.end(); | 17302 | defer tracy.end(); |
| 17277 | 17303 | ||
| 17304 | const mod = sema.mod; | ||
| 17278 | const inst_data = sema.code.instructions.items(.data)[inst].un_tok; | 17305 | const inst_data = sema.code.instructions.items(.data)[inst].un_tok; |
| 17279 | const operand = try sema.resolveInst(inst_data.operand); | 17306 | const operand = try sema.resolveInst(inst_data.operand); |
| 17280 | 17307 | ||
| 17281 | const r_brace_src = inst_data.src(); | 17308 | const r_brace_src = inst_data.src(); |
| 17282 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; | 17309 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; |
| 17283 | const base_tag = sema.fn_ret_ty.baseZigTypeTag(); | 17310 | const base_tag = sema.fn_ret_ty.baseZigTypeTag(mod); |
| 17284 | if (base_tag == .NoReturn) { | 17311 | if (base_tag == .NoReturn) { |
| 17285 | const msg = msg: { | 17312 | const msg = msg: { |
| 17286 | const msg = try sema.errMsg(block, ret_ty_src, "function declared '{}' implicitly returns", .{ | 17313 | const msg = try sema.errMsg(block, ret_ty_src, "function declared '{}' implicitly returns", .{ |
| 17287 | sema.fn_ret_ty.fmt(sema.mod), | 17314 | sema.fn_ret_ty.fmt(mod), |
| 17288 | }); | 17315 | }); |
| 17289 | errdefer msg.destroy(sema.gpa); | 17316 | errdefer msg.destroy(sema.gpa); |
| 17290 | try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{}); | 17317 | try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{}); |
| ... | @@ -17294,7 +17321,7 @@ fn zirRetImplicit( | ... | @@ -17294,7 +17321,7 @@ fn zirRetImplicit( |
| 17294 | } else if (base_tag != .Void) { | 17321 | } else if (base_tag != .Void) { |
| 17295 | const msg = msg: { | 17322 | const msg = msg: { |
| 17296 | const msg = try sema.errMsg(block, ret_ty_src, "function with non-void return type '{}' implicitly returns", .{ | 17323 | const msg = try sema.errMsg(block, ret_ty_src, "function with non-void return type '{}' implicitly returns", .{ |
| 17297 | sema.fn_ret_ty.fmt(sema.mod), | 17324 | sema.fn_ret_ty.fmt(mod), |
| 17298 | }); | 17325 | }); |
| 17299 | errdefer msg.destroy(sema.gpa); | 17326 | errdefer msg.destroy(sema.gpa); |
| 17300 | try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{}); | 17327 | try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{}); |
| ... | @@ -17397,17 +17424,19 @@ fn retWithErrTracing( | ... | @@ -17397,17 +17424,19 @@ fn retWithErrTracing( |
| 17397 | } | 17424 | } |
| 17398 | 17425 | ||
| 17399 | fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool { | 17426 | fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool { |
| 17400 | if (!sema.mod.backendSupportsFeature(.error_return_trace)) return false; | 17427 | const mod = sema.mod; |
| 17428 | if (!mod.backendSupportsFeature(.error_return_trace)) return false; | ||
| 17401 | 17429 | ||
| 17402 | return fn_ret_ty.isError() and | 17430 | return fn_ret_ty.isError(mod) and |
| 17403 | sema.mod.comp.bin_file.options.error_return_tracing; | 17431 | mod.comp.bin_file.options.error_return_tracing; |
| 17404 | } | 17432 | } |
| 17405 | 17433 | ||
| 17406 | fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 17434 | fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 17435 | const mod = sema.mod; | ||
| 17407 | const inst_data = sema.code.instructions.items(.data)[inst].save_err_ret_index; | 17436 | const inst_data = sema.code.instructions.items(.data)[inst].save_err_ret_index; |
| 17408 | 17437 | ||
| 17409 | if (!sema.mod.backendSupportsFeature(.error_return_trace)) return; | 17438 | if (!mod.backendSupportsFeature(.error_return_trace)) return; |
| 17410 | if (!sema.mod.comp.bin_file.options.error_return_tracing) return; | 17439 | if (!mod.comp.bin_file.options.error_return_tracing) return; |
| 17411 | 17440 | ||
| 17412 | // This is only relevant at runtime. | 17441 | // This is only relevant at runtime. |
| 17413 | if (block.is_comptime or block.is_typeof) return; | 17442 | if (block.is_comptime or block.is_typeof) return; |
| ... | @@ -17415,7 +17444,7 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -17415,7 +17444,7 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 17415 | const save_index = inst_data.operand == .none or b: { | 17444 | const save_index = inst_data.operand == .none or b: { |
| 17416 | const operand = try sema.resolveInst(inst_data.operand); | 17445 | const operand = try sema.resolveInst(inst_data.operand); |
| 17417 | const operand_ty = sema.typeOf(operand); | 17446 | const operand_ty = sema.typeOf(operand); |
| 17418 | break :b operand_ty.isError(); | 17447 | break :b operand_ty.isError(mod); |
| 17419 | }; | 17448 | }; |
| 17420 | 17449 | ||
| 17421 | if (save_index) | 17450 | if (save_index) |
| ... | @@ -17467,11 +17496,12 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) | ... | @@ -17467,11 +17496,12 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) |
| 17467 | } | 17496 | } |
| 17468 | 17497 | ||
| 17469 | fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void { | 17498 | fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void { |
| 17470 | assert(sema.fn_ret_ty.zigTypeTag() == .ErrorUnion); | 17499 | const mod = sema.mod; |
| 17500 | assert(sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion); | ||
| 17471 | 17501 | ||
| 17472 | if (sema.fn_ret_ty.errorUnionSet().castTag(.error_set_inferred)) |payload| { | 17502 | if (sema.fn_ret_ty.errorUnionSet().castTag(.error_set_inferred)) |payload| { |
| 17473 | const op_ty = sema.typeOf(uncasted_operand); | 17503 | const op_ty = sema.typeOf(uncasted_operand); |
| 17474 | switch (op_ty.zigTypeTag()) { | 17504 | switch (op_ty.zigTypeTag(mod)) { |
| 17475 | .ErrorSet => { | 17505 | .ErrorSet => { |
| 17476 | try payload.data.addErrorSet(sema.gpa, op_ty); | 17506 | try payload.data.addErrorSet(sema.gpa, op_ty); |
| 17477 | }, | 17507 | }, |
| ... | @@ -17492,7 +17522,8 @@ fn analyzeRet( | ... | @@ -17492,7 +17522,8 @@ fn analyzeRet( |
| 17492 | // Special case for returning an error to an inferred error set; we need to | 17522 | // Special case for returning an error to an inferred error set; we need to |
| 17493 | // add the error tag to the inferred error set of the in-scope function, so | 17523 | // add the error tag to the inferred error set of the in-scope function, so |
| 17494 | // that the coercion below works correctly. | 17524 | // that the coercion below works correctly. |
| 17495 | if (sema.fn_ret_ty.zigTypeTag() == .ErrorUnion) { | 17525 | const mod = sema.mod; |
| 17526 | if (sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion) { | ||
| 17496 | try sema.addToInferredErrorSet(uncasted_operand); | 17527 | try sema.addToInferredErrorSet(uncasted_operand); |
| 17497 | } | 17528 | } |
| 17498 | const operand = sema.coerceExtra(block, sema.fn_ret_ty, uncasted_operand, src, .{ .is_ret = true }) catch |err| switch (err) { | 17529 | const operand = sema.coerceExtra(block, sema.fn_ret_ty, uncasted_operand, src, .{ .is_ret = true }) catch |err| switch (err) { |
| ... | @@ -17540,6 +17571,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17540,6 +17571,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17540 | const tracy = trace(@src()); | 17571 | const tracy = trace(@src()); |
| 17541 | defer tracy.end(); | 17572 | defer tracy.end(); |
| 17542 | 17573 | ||
| 17574 | const mod = sema.mod; | ||
| 17543 | const inst_data = sema.code.instructions.items(.data)[inst].ptr_type; | 17575 | const inst_data = sema.code.instructions.items(.data)[inst].ptr_type; |
| 17544 | const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index); | 17576 | const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index); |
| 17545 | const elem_ty_src: LazySrcLoc = .{ .node_offset_ptr_elem = extra.data.src_node }; | 17577 | const elem_ty_src: LazySrcLoc = .{ .node_offset_ptr_elem = extra.data.src_node }; |
| ... | @@ -17582,7 +17614,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17582,7 +17614,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17582 | break :blk 0; | 17614 | break :blk 0; |
| 17583 | } | 17615 | } |
| 17584 | } | 17616 | } |
| 17585 | const abi_align = @intCast(u32, (try val.getUnsignedIntAdvanced(target, sema)).?); | 17617 | const abi_align = @intCast(u32, (try val.getUnsignedIntAdvanced(mod, sema)).?); |
| 17586 | try sema.validateAlign(block, align_src, abi_align); | 17618 | try sema.validateAlign(block, align_src, abi_align); |
| 17587 | break :blk abi_align; | 17619 | break :blk abi_align; |
| 17588 | } else 0; | 17620 | } else 0; |
| ... | @@ -17591,7 +17623,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17591,7 +17623,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17591 | const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]); | 17623 | const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]); |
| 17592 | extra_i += 1; | 17624 | extra_i += 1; |
| 17593 | break :blk try sema.analyzeAddressSpace(block, addrspace_src, ref, .pointer); | 17625 | break :blk try sema.analyzeAddressSpace(block, addrspace_src, ref, .pointer); |
| 17594 | } else if (elem_ty.zigTypeTag() == .Fn and target.cpu.arch == .avr) .flash else .generic; | 17626 | } else if (elem_ty.zigTypeTag(mod) == .Fn and target.cpu.arch == .avr) .flash else .generic; |
| 17595 | 17627 | ||
| 17596 | const bit_offset = if (inst_data.flags.has_bit_range) blk: { | 17628 | const bit_offset = if (inst_data.flags.has_bit_range) blk: { |
| 17597 | const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]); | 17629 | const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]); |
| ... | @@ -17611,9 +17643,9 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17611,9 +17643,9 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17611 | return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{}); | 17643 | return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{}); |
| 17612 | } | 17644 | } |
| 17613 | 17645 | ||
| 17614 | if (elem_ty.zigTypeTag() == .NoReturn) { | 17646 | if (elem_ty.zigTypeTag(mod) == .NoReturn) { |
| 17615 | return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{}); | 17647 | return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{}); |
| 17616 | } else if (elem_ty.zigTypeTag() == .Fn) { | 17648 | } else if (elem_ty.zigTypeTag(mod) == .Fn) { |
| 17617 | if (inst_data.size != .One) { | 17649 | if (inst_data.size != .One) { |
| 17618 | return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{}); | 17650 | return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{}); |
| 17619 | } | 17651 | } |
| ... | @@ -17623,7 +17655,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17623,7 +17655,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17623 | { | 17655 | { |
| 17624 | return sema.fail(block, align_src, "function pointer alignment disagrees with function alignment", .{}); | 17656 | return sema.fail(block, align_src, "function pointer alignment disagrees with function alignment", .{}); |
| 17625 | } | 17657 | } |
| 17626 | } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) { | 17658 | } else if (inst_data.size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) { |
| 17627 | return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{}); | 17659 | return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{}); |
| 17628 | } else if (inst_data.size == .C) { | 17660 | } else if (inst_data.size == .C) { |
| 17629 | if (!try sema.validateExternType(elem_ty, .other)) { | 17661 | if (!try sema.validateExternType(elem_ty, .other)) { |
| ... | @@ -17639,7 +17671,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17639,7 +17671,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17639 | }; | 17671 | }; |
| 17640 | return sema.failWithOwnedErrorMsg(msg); | 17672 | return sema.failWithOwnedErrorMsg(msg); |
| 17641 | } | 17673 | } |
| 17642 | if (elem_ty.zigTypeTag() == .Opaque) { | 17674 | if (elem_ty.zigTypeTag(mod) == .Opaque) { |
| 17643 | return sema.fail(block, elem_ty_src, "C pointers cannot point to opaque types", .{}); | 17675 | return sema.fail(block, elem_ty_src, "C pointers cannot point to opaque types", .{}); |
| 17644 | } | 17676 | } |
| 17645 | } | 17677 | } |
| ... | @@ -17666,8 +17698,9 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -17666,8 +17698,9 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 17666 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 17698 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 17667 | const src = inst_data.src(); | 17699 | const src = inst_data.src(); |
| 17668 | const obj_ty = try sema.resolveType(block, src, inst_data.operand); | 17700 | const obj_ty = try sema.resolveType(block, src, inst_data.operand); |
| 17701 | const mod = sema.mod; | ||
| 17669 | 17702 | ||
| 17670 | switch (obj_ty.zigTypeTag()) { | 17703 | switch (obj_ty.zigTypeTag(mod)) { |
| 17671 | .Struct => return sema.structInitEmpty(block, obj_ty, src, src), | 17704 | .Struct => return sema.structInitEmpty(block, obj_ty, src, src), |
| 17672 | .Array, .Vector => return sema.arrayInitEmpty(block, src, obj_ty), | 17705 | .Array, .Vector => return sema.arrayInitEmpty(block, src, obj_ty), |
| 17673 | .Void => return sema.addConstant(obj_ty, Value.void), | 17706 | .Void => return sema.addConstant(obj_ty, Value.void), |
| ... | @@ -17696,9 +17729,10 @@ fn structInitEmpty( | ... | @@ -17696,9 +17729,10 @@ fn structInitEmpty( |
| 17696 | } | 17729 | } |
| 17697 | 17730 | ||
| 17698 | fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) CompileError!Air.Inst.Ref { | 17731 | fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) CompileError!Air.Inst.Ref { |
| 17732 | const mod = sema.mod; | ||
| 17699 | const arr_len = obj_ty.arrayLen(); | 17733 | const arr_len = obj_ty.arrayLen(); |
| 17700 | if (arr_len != 0) { | 17734 | if (arr_len != 0) { |
| 17701 | if (obj_ty.zigTypeTag() == .Array) { | 17735 | if (obj_ty.zigTypeTag(mod) == .Array) { |
| 17702 | return sema.fail(block, src, "expected {d} array elements; found 0", .{arr_len}); | 17736 | return sema.fail(block, src, "expected {d} array elements; found 0", .{arr_len}); |
| 17703 | } else { | 17737 | } else { |
| 17704 | return sema.fail(block, src, "expected {d} vector elements; found 0", .{arr_len}); | 17738 | return sema.fail(block, src, "expected {d} vector elements; found 0", .{arr_len}); |
| ... | @@ -17766,13 +17800,14 @@ fn zirStructInit( | ... | @@ -17766,13 +17800,14 @@ fn zirStructInit( |
| 17766 | const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index); | 17800 | const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index); |
| 17767 | const src = inst_data.src(); | 17801 | const src = inst_data.src(); |
| 17768 | 17802 | ||
| 17803 | const mod = sema.mod; | ||
| 17769 | const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data; | 17804 | const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data; |
| 17770 | const first_field_type_data = zir_datas[first_item.field_type].pl_node; | 17805 | const first_field_type_data = zir_datas[first_item.field_type].pl_node; |
| 17771 | const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data; | 17806 | const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data; |
| 17772 | const resolved_ty = try sema.resolveType(block, src, first_field_type_extra.container_type); | 17807 | const resolved_ty = try sema.resolveType(block, src, first_field_type_extra.container_type); |
| 17773 | try sema.resolveTypeLayout(resolved_ty); | 17808 | try sema.resolveTypeLayout(resolved_ty); |
| 17774 | 17809 | ||
| 17775 | if (resolved_ty.zigTypeTag() == .Struct) { | 17810 | if (resolved_ty.zigTypeTag(mod) == .Struct) { |
| 17776 | // This logic must be synchronized with that in `zirStructInitEmpty`. | 17811 | // This logic must be synchronized with that in `zirStructInitEmpty`. |
| 17777 | 17812 | ||
| 17778 | // Maps field index to field_type index of where it was already initialized. | 17813 | // Maps field index to field_type index of where it was already initialized. |
| ... | @@ -17815,7 +17850,7 @@ fn zirStructInit( | ... | @@ -17815,7 +17850,7 @@ fn zirStructInit( |
| 17815 | } | 17850 | } |
| 17816 | found_fields[field_index] = item.data.field_type; | 17851 | found_fields[field_index] = item.data.field_type; |
| 17817 | field_inits[field_index] = try sema.resolveInst(item.data.init); | 17852 | field_inits[field_index] = try sema.resolveInst(item.data.init); |
| 17818 | if (!is_packed) if (resolved_ty.structFieldValueComptime(field_index)) |default_value| { | 17853 | if (!is_packed) if (resolved_ty.structFieldValueComptime(mod, field_index)) |default_value| { |
| 17819 | const init_val = (try sema.resolveMaybeUndefVal(field_inits[field_index])) orelse { | 17854 | const init_val = (try sema.resolveMaybeUndefVal(field_inits[field_index])) orelse { |
| 17820 | return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known"); | 17855 | return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known"); |
| 17821 | }; | 17856 | }; |
| ... | @@ -17827,7 +17862,7 @@ fn zirStructInit( | ... | @@ -17827,7 +17862,7 @@ fn zirStructInit( |
| 17827 | } | 17862 | } |
| 17828 | 17863 | ||
| 17829 | return sema.finishStructInit(block, src, src, field_inits, resolved_ty, is_ref); | 17864 | return sema.finishStructInit(block, src, src, field_inits, resolved_ty, is_ref); |
| 17830 | } else if (resolved_ty.zigTypeTag() == .Union) { | 17865 | } else if (resolved_ty.zigTypeTag(mod) == .Union) { |
| 17831 | if (extra.data.fields_len != 1) { | 17866 | if (extra.data.fields_len != 1) { |
| 17832 | return sema.fail(block, src, "union initialization expects exactly one field", .{}); | 17867 | return sema.fail(block, src, "union initialization expects exactly one field", .{}); |
| 17833 | } | 17868 | } |
| ... | @@ -18014,6 +18049,7 @@ fn zirStructInitAnon( | ... | @@ -18014,6 +18049,7 @@ fn zirStructInitAnon( |
| 18014 | inst: Zir.Inst.Index, | 18049 | inst: Zir.Inst.Index, |
| 18015 | is_ref: bool, | 18050 | is_ref: bool, |
| 18016 | ) CompileError!Air.Inst.Ref { | 18051 | ) CompileError!Air.Inst.Ref { |
| 18052 | const mod = sema.mod; | ||
| 18017 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 18053 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 18018 | const src = inst_data.src(); | 18054 | const src = inst_data.src(); |
| 18019 | const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index); | 18055 | const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index); |
| ... | @@ -18050,7 +18086,7 @@ fn zirStructInitAnon( | ... | @@ -18050,7 +18086,7 @@ fn zirStructInitAnon( |
| 18050 | 18086 | ||
| 18051 | const init = try sema.resolveInst(item.data.init); | 18087 | const init = try sema.resolveInst(item.data.init); |
| 18052 | field_ty.* = sema.typeOf(init); | 18088 | field_ty.* = sema.typeOf(init); |
| 18053 | if (types[i].zigTypeTag() == .Opaque) { | 18089 | if (types[i].zigTypeTag(mod) == .Opaque) { |
| 18054 | const msg = msg: { | 18090 | const msg = msg: { |
| 18055 | const decl = sema.mod.declPtr(block.src_decl); | 18091 | const decl = sema.mod.declPtr(block.src_decl); |
| 18056 | const field_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, i); | 18092 | const field_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, i); |
| ... | @@ -18148,15 +18184,16 @@ fn zirArrayInit( | ... | @@ -18148,15 +18184,16 @@ fn zirArrayInit( |
| 18148 | 18184 | ||
| 18149 | const array_ty = try sema.resolveType(block, src, args[0]); | 18185 | const array_ty = try sema.resolveType(block, src, args[0]); |
| 18150 | const sentinel_val = array_ty.sentinel(); | 18186 | const sentinel_val = array_ty.sentinel(); |
| 18187 | const mod = sema.mod; | ||
| 18151 | 18188 | ||
| 18152 | const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @boolToInt(sentinel_val != null)); | 18189 | const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @boolToInt(sentinel_val != null)); |
| 18153 | defer gpa.free(resolved_args); | 18190 | defer gpa.free(resolved_args); |
| 18154 | for (args[1..], 0..) |arg, i| { | 18191 | for (args[1..], 0..) |arg, i| { |
| 18155 | const resolved_arg = try sema.resolveInst(arg); | 18192 | const resolved_arg = try sema.resolveInst(arg); |
| 18156 | const elem_ty = if (array_ty.zigTypeTag() == .Struct) | 18193 | const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct) |
| 18157 | array_ty.structFieldType(i) | 18194 | array_ty.structFieldType(i) |
| 18158 | else | 18195 | else |
| 18159 | array_ty.elemType2(); | 18196 | array_ty.elemType2(mod); |
| 18160 | resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) { | 18197 | resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) { |
| 18161 | error.NeededSourceLocation => { | 18198 | error.NeededSourceLocation => { |
| 18162 | const decl = sema.mod.declPtr(block.src_decl); | 18199 | const decl = sema.mod.declPtr(block.src_decl); |
| ... | @@ -18169,7 +18206,7 @@ fn zirArrayInit( | ... | @@ -18169,7 +18206,7 @@ fn zirArrayInit( |
| 18169 | } | 18206 | } |
| 18170 | 18207 | ||
| 18171 | if (sentinel_val) |some| { | 18208 | if (sentinel_val) |some| { |
| 18172 | resolved_args[resolved_args.len - 1] = try sema.addConstant(array_ty.elemType2(), some); | 18209 | resolved_args[resolved_args.len - 1] = try sema.addConstant(array_ty.elemType2(mod), some); |
| 18173 | } | 18210 | } |
| 18174 | 18211 | ||
| 18175 | const opt_runtime_index: ?u32 = for (resolved_args, 0..) |arg, i| { | 18212 | const opt_runtime_index: ?u32 = for (resolved_args, 0..) |arg, i| { |
| ... | @@ -18227,7 +18264,7 @@ fn zirArrayInit( | ... | @@ -18227,7 +18264,7 @@ fn zirArrayInit( |
| 18227 | const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | 18264 | const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| 18228 | .mutable = true, | 18265 | .mutable = true, |
| 18229 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), | 18266 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 18230 | .pointee_type = array_ty.elemType2(), | 18267 | .pointee_type = array_ty.elemType2(mod), |
| 18231 | }); | 18268 | }); |
| 18232 | const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty); | 18269 | const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty); |
| 18233 | 18270 | ||
| ... | @@ -18252,6 +18289,7 @@ fn zirArrayInitAnon( | ... | @@ -18252,6 +18289,7 @@ fn zirArrayInitAnon( |
| 18252 | const src = inst_data.src(); | 18289 | const src = inst_data.src(); |
| 18253 | const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); | 18290 | const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); |
| 18254 | const operands = sema.code.refSlice(extra.end, extra.data.operands_len); | 18291 | const operands = sema.code.refSlice(extra.end, extra.data.operands_len); |
| 18292 | const mod = sema.mod; | ||
| 18255 | 18293 | ||
| 18256 | const types = try sema.arena.alloc(Type, operands.len); | 18294 | const types = try sema.arena.alloc(Type, operands.len); |
| 18257 | const values = try sema.arena.alloc(Value, operands.len); | 18295 | const values = try sema.arena.alloc(Value, operands.len); |
| ... | @@ -18262,7 +18300,7 @@ fn zirArrayInitAnon( | ... | @@ -18262,7 +18300,7 @@ fn zirArrayInitAnon( |
| 18262 | const operand_src = src; // TODO better source location | 18300 | const operand_src = src; // TODO better source location |
| 18263 | const elem = try sema.resolveInst(operand); | 18301 | const elem = try sema.resolveInst(operand); |
| 18264 | types[i] = sema.typeOf(elem); | 18302 | types[i] = sema.typeOf(elem); |
| 18265 | if (types[i].zigTypeTag() == .Opaque) { | 18303 | if (types[i].zigTypeTag(mod) == .Opaque) { |
| 18266 | const msg = msg: { | 18304 | const msg = msg: { |
| 18267 | const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); | 18305 | const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); |
| 18268 | errdefer msg.destroy(sema.gpa); | 18306 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -18379,11 +18417,12 @@ fn fieldType( | ... | @@ -18379,11 +18417,12 @@ fn fieldType( |
| 18379 | field_src: LazySrcLoc, | 18417 | field_src: LazySrcLoc, |
| 18380 | ty_src: LazySrcLoc, | 18418 | ty_src: LazySrcLoc, |
| 18381 | ) CompileError!Air.Inst.Ref { | 18419 | ) CompileError!Air.Inst.Ref { |
| 18420 | const mod = sema.mod; | ||
| 18382 | var cur_ty = aggregate_ty; | 18421 | var cur_ty = aggregate_ty; |
| 18383 | while (true) { | 18422 | while (true) { |
| 18384 | const resolved_ty = try sema.resolveTypeFields(cur_ty); | 18423 | const resolved_ty = try sema.resolveTypeFields(cur_ty); |
| 18385 | cur_ty = resolved_ty; | 18424 | cur_ty = resolved_ty; |
| 18386 | switch (cur_ty.zigTypeTag()) { | 18425 | switch (cur_ty.zigTypeTag(mod)) { |
| 18387 | .Struct => { | 18426 | .Struct => { |
| 18388 | if (cur_ty.isAnonStruct()) { | 18427 | if (cur_ty.isAnonStruct()) { |
| 18389 | const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src); | 18428 | const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src); |
| ... | @@ -18449,14 +18488,14 @@ fn zirFrame( | ... | @@ -18449,14 +18488,14 @@ fn zirFrame( |
| 18449 | } | 18488 | } |
| 18450 | 18489 | ||
| 18451 | fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 18490 | fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 18491 | const mod = sema.mod; | ||
| 18452 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 18492 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 18453 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 18493 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 18454 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); | 18494 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 18455 | if (ty.isNoReturn()) { | 18495 | if (ty.isNoReturn()) { |
| 18456 | return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)}); | 18496 | return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)}); |
| 18457 | } | 18497 | } |
| 18458 | const target = sema.mod.getTarget(); | 18498 | const val = try ty.lazyAbiAlignment(mod, sema.arena); |
| 18459 | const val = try ty.lazyAbiAlignment(target, sema.arena); | ||
| 18460 | if (val.tag() == .lazy_align) { | 18499 | if (val.tag() == .lazy_align) { |
| 18461 | try sema.queueFullTypeResolution(ty); | 18500 | try sema.queueFullTypeResolution(ty); |
| 18462 | } | 18501 | } |
| ... | @@ -18499,16 +18538,17 @@ fn zirUnaryMath( | ... | @@ -18499,16 +18538,17 @@ fn zirUnaryMath( |
| 18499 | const tracy = trace(@src()); | 18538 | const tracy = trace(@src()); |
| 18500 | defer tracy.end(); | 18539 | defer tracy.end(); |
| 18501 | 18540 | ||
| 18541 | const mod = sema.mod; | ||
| 18502 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 18542 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 18503 | const operand = try sema.resolveInst(inst_data.operand); | 18543 | const operand = try sema.resolveInst(inst_data.operand); |
| 18504 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 18544 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 18505 | const operand_ty = sema.typeOf(operand); | 18545 | const operand_ty = sema.typeOf(operand); |
| 18506 | 18546 | ||
| 18507 | switch (operand_ty.zigTypeTag()) { | 18547 | switch (operand_ty.zigTypeTag(mod)) { |
| 18508 | .ComptimeFloat, .Float => {}, | 18548 | .ComptimeFloat, .Float => {}, |
| 18509 | .Vector => { | 18549 | .Vector => { |
| 18510 | const scalar_ty = operand_ty.scalarType(); | 18550 | const scalar_ty = operand_ty.scalarType(mod); |
| 18511 | switch (scalar_ty.zigTypeTag()) { | 18551 | switch (scalar_ty.zigTypeTag(mod)) { |
| 18512 | .ComptimeFloat, .Float => {}, | 18552 | .ComptimeFloat, .Float => {}, |
| 18513 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{scalar_ty.fmt(sema.mod)}), | 18553 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{scalar_ty.fmt(sema.mod)}), |
| 18514 | } | 18554 | } |
| ... | @@ -18516,9 +18556,9 @@ fn zirUnaryMath( | ... | @@ -18516,9 +18556,9 @@ fn zirUnaryMath( |
| 18516 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{operand_ty.fmt(sema.mod)}), | 18556 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{operand_ty.fmt(sema.mod)}), |
| 18517 | } | 18557 | } |
| 18518 | 18558 | ||
| 18519 | switch (operand_ty.zigTypeTag()) { | 18559 | switch (operand_ty.zigTypeTag(mod)) { |
| 18520 | .Vector => { | 18560 | .Vector => { |
| 18521 | const scalar_ty = operand_ty.scalarType(); | 18561 | const scalar_ty = operand_ty.scalarType(mod); |
| 18522 | const vec_len = operand_ty.vectorLen(); | 18562 | const vec_len = operand_ty.vectorLen(); |
| 18523 | const result_ty = try Type.vector(sema.arena, vec_len, scalar_ty); | 18563 | const result_ty = try Type.vector(sema.arena, vec_len, scalar_ty); |
| 18524 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | 18564 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| ... | @@ -18564,7 +18604,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -18564,7 +18604,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18564 | const mod = sema.mod; | 18604 | const mod = sema.mod; |
| 18565 | 18605 | ||
| 18566 | try sema.resolveTypeLayout(operand_ty); | 18606 | try sema.resolveTypeLayout(operand_ty); |
| 18567 | const enum_ty = switch (operand_ty.zigTypeTag()) { | 18607 | const enum_ty = switch (operand_ty.zigTypeTag(mod)) { |
| 18568 | .EnumLiteral => { | 18608 | .EnumLiteral => { |
| 18569 | const val = try sema.resolveConstValue(block, .unneeded, operand, ""); | 18609 | const val = try sema.resolveConstValue(block, .unneeded, operand, ""); |
| 18570 | const bytes = val.castTag(.enum_literal).?.data; | 18610 | const bytes = val.castTag(.enum_literal).?.data; |
| ... | @@ -18654,11 +18694,8 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18654,11 +18694,8 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18654 | const bits_val = struct_val[1]; | 18694 | const bits_val = struct_val[1]; |
| 18655 | 18695 | ||
| 18656 | const signedness = signedness_val.toEnum(std.builtin.Signedness); | 18696 | const signedness = signedness_val.toEnum(std.builtin.Signedness); |
| 18657 | const bits = @intCast(u16, bits_val.toUnsignedInt(target)); | 18697 | const bits = @intCast(u16, bits_val.toUnsignedInt(mod)); |
| 18658 | const ty = switch (signedness) { | 18698 | const ty = try mod.intType(signedness, bits); |
| 18659 | .signed => try Type.Tag.int_signed.create(sema.arena, bits), | ||
| 18660 | .unsigned => try Type.Tag.int_unsigned.create(sema.arena, bits), | ||
| 18661 | }; | ||
| 18662 | return sema.addType(ty); | 18699 | return sema.addType(ty); |
| 18663 | }, | 18700 | }, |
| 18664 | .Vector => { | 18701 | .Vector => { |
| ... | @@ -18667,9 +18704,8 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18667,9 +18704,8 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18667 | const len_val = struct_val[0]; | 18704 | const len_val = struct_val[0]; |
| 18668 | const child_val = struct_val[1]; | 18705 | const child_val = struct_val[1]; |
| 18669 | 18706 | ||
| 18670 | const len = len_val.toUnsignedInt(target); | 18707 | const len = len_val.toUnsignedInt(mod); |
| 18671 | var buffer: Value.ToTypeBuffer = undefined; | 18708 | const child_ty = child_val.toType(); |
| 18672 | const child_ty = child_val.toType(&buffer); | ||
| 18673 | 18709 | ||
| 18674 | try sema.checkVectorElemType(block, src, child_ty); | 18710 | try sema.checkVectorElemType(block, src, child_ty); |
| 18675 | 18711 | ||
| ... | @@ -18682,7 +18718,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18682,7 +18718,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18682 | // bits: comptime_int, | 18718 | // bits: comptime_int, |
| 18683 | const bits_val = struct_val[0]; | 18719 | const bits_val = struct_val[0]; |
| 18684 | 18720 | ||
| 18685 | const bits = @intCast(u16, bits_val.toUnsignedInt(target)); | 18721 | const bits = @intCast(u16, bits_val.toUnsignedInt(mod)); |
| 18686 | const ty = switch (bits) { | 18722 | const ty = switch (bits) { |
| 18687 | 16 => Type.f16, | 18723 | 16 => Type.f16, |
| 18688 | 32 => Type.f32, | 18724 | 32 => Type.f32, |
| ... | @@ -18708,10 +18744,9 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18708,10 +18744,9 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18708 | if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { | 18744 | if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { |
| 18709 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); | 18745 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); |
| 18710 | } | 18746 | } |
| 18711 | const abi_align = @intCast(u29, (try alignment_val.getUnsignedIntAdvanced(target, sema)).?); | 18747 | const abi_align = @intCast(u29, (try alignment_val.getUnsignedIntAdvanced(mod, sema)).?); |
| 18712 | 18748 | ||
| 18713 | var buffer: Value.ToTypeBuffer = undefined; | 18749 | const unresolved_elem_ty = child_val.toType(); |
| 18714 | const unresolved_elem_ty = child_val.toType(&buffer); | ||
| 18715 | const elem_ty = if (abi_align == 0) | 18750 | const elem_ty = if (abi_align == 0) |
| 18716 | unresolved_elem_ty | 18751 | unresolved_elem_ty |
| 18717 | else t: { | 18752 | else t: { |
| ... | @@ -18723,7 +18758,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18723,7 +18758,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18723 | const ptr_size = size_val.toEnum(std.builtin.Type.Pointer.Size); | 18758 | const ptr_size = size_val.toEnum(std.builtin.Type.Pointer.Size); |
| 18724 | 18759 | ||
| 18725 | var actual_sentinel: ?Value = null; | 18760 | var actual_sentinel: ?Value = null; |
| 18726 | if (!sentinel_val.isNull()) { | 18761 | if (!sentinel_val.isNull(mod)) { |
| 18727 | if (ptr_size == .One or ptr_size == .C) { | 18762 | if (ptr_size == .One or ptr_size == .C) { |
| 18728 | return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{}); | 18763 | return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{}); |
| 18729 | } | 18764 | } |
| ... | @@ -18735,9 +18770,9 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18735,9 +18770,9 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18735 | actual_sentinel = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?; | 18770 | actual_sentinel = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?; |
| 18736 | } | 18771 | } |
| 18737 | 18772 | ||
| 18738 | if (elem_ty.zigTypeTag() == .NoReturn) { | 18773 | if (elem_ty.zigTypeTag(mod) == .NoReturn) { |
| 18739 | return sema.fail(block, src, "pointer to noreturn not allowed", .{}); | 18774 | return sema.fail(block, src, "pointer to noreturn not allowed", .{}); |
| 18740 | } else if (elem_ty.zigTypeTag() == .Fn) { | 18775 | } else if (elem_ty.zigTypeTag(mod) == .Fn) { |
| 18741 | if (ptr_size != .One) { | 18776 | if (ptr_size != .One) { |
| 18742 | return sema.fail(block, src, "function pointers must be single pointers", .{}); | 18777 | return sema.fail(block, src, "function pointers must be single pointers", .{}); |
| 18743 | } | 18778 | } |
| ... | @@ -18747,7 +18782,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18747,7 +18782,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18747 | { | 18782 | { |
| 18748 | return sema.fail(block, src, "function pointer alignment disagrees with function alignment", .{}); | 18783 | return sema.fail(block, src, "function pointer alignment disagrees with function alignment", .{}); |
| 18749 | } | 18784 | } |
| 18750 | } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) { | 18785 | } else if (ptr_size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) { |
| 18751 | return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); | 18786 | return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); |
| 18752 | } else if (ptr_size == .C) { | 18787 | } else if (ptr_size == .C) { |
| 18753 | if (!try sema.validateExternType(elem_ty, .other)) { | 18788 | if (!try sema.validateExternType(elem_ty, .other)) { |
| ... | @@ -18763,7 +18798,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18763,7 +18798,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18763 | }; | 18798 | }; |
| 18764 | return sema.failWithOwnedErrorMsg(msg); | 18799 | return sema.failWithOwnedErrorMsg(msg); |
| 18765 | } | 18800 | } |
| 18766 | if (elem_ty.zigTypeTag() == .Opaque) { | 18801 | if (elem_ty.zigTypeTag(mod) == .Opaque) { |
| 18767 | return sema.fail(block, src, "C pointers cannot point to opaque types", .{}); | 18802 | return sema.fail(block, src, "C pointers cannot point to opaque types", .{}); |
| 18768 | } | 18803 | } |
| 18769 | } | 18804 | } |
| ... | @@ -18790,9 +18825,8 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18790,9 +18825,8 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18790 | // sentinel: ?*const anyopaque, | 18825 | // sentinel: ?*const anyopaque, |
| 18791 | const sentinel_val = struct_val[2]; | 18826 | const sentinel_val = struct_val[2]; |
| 18792 | 18827 | ||
| 18793 | const len = len_val.toUnsignedInt(target); | 18828 | const len = len_val.toUnsignedInt(mod); |
| 18794 | var buffer: Value.ToTypeBuffer = undefined; | 18829 | const child_ty = try child_val.toType().copy(sema.arena); |
| 18795 | const child_ty = try child_val.toType(&buffer).copy(sema.arena); | ||
| 18796 | const sentinel = if (sentinel_val.castTag(.opt_payload)) |p| blk: { | 18830 | const sentinel = if (sentinel_val.castTag(.opt_payload)) |p| blk: { |
| 18797 | const ptr_ty = try Type.ptr(sema.arena, mod, .{ | 18831 | const ptr_ty = try Type.ptr(sema.arena, mod, .{ |
| 18798 | .@"addrspace" = .generic, | 18832 | .@"addrspace" = .generic, |
| ... | @@ -18810,8 +18844,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18810,8 +18844,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18810 | // child: type, | 18844 | // child: type, |
| 18811 | const child_val = struct_val[0]; | 18845 | const child_val = struct_val[0]; |
| 18812 | 18846 | ||
| 18813 | var buffer: Value.ToTypeBuffer = undefined; | 18847 | const child_ty = try child_val.toType().copy(sema.arena); |
| 18814 | const child_ty = try child_val.toType(&buffer).copy(sema.arena); | ||
| 18815 | 18848 | ||
| 18816 | const ty = try Type.optional(sema.arena, child_ty); | 18849 | const ty = try Type.optional(sema.arena, child_ty); |
| 18817 | return sema.addType(ty); | 18850 | return sema.addType(ty); |
| ... | @@ -18824,11 +18857,10 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18824,11 +18857,10 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18824 | // payload: type, | 18857 | // payload: type, |
| 18825 | const payload_val = struct_val[1]; | 18858 | const payload_val = struct_val[1]; |
| 18826 | 18859 | ||
| 18827 | var buffer: Value.ToTypeBuffer = undefined; | 18860 | const error_set_ty = try error_set_val.toType().copy(sema.arena); |
| 18828 | const error_set_ty = try error_set_val.toType(&buffer).copy(sema.arena); | 18861 | const payload_ty = try payload_val.toType().copy(sema.arena); |
| 18829 | const payload_ty = try payload_val.toType(&buffer).copy(sema.arena); | ||
| 18830 | 18862 | ||
| 18831 | if (error_set_ty.zigTypeTag() != .ErrorSet) { | 18863 | if (error_set_ty.zigTypeTag(mod) != .ErrorSet) { |
| 18832 | return sema.fail(block, src, "Type.ErrorUnion.error_set must be an error set type", .{}); | 18864 | return sema.fail(block, src, "Type.ErrorUnion.error_set must be an error set type", .{}); |
| 18833 | } | 18865 | } |
| 18834 | 18866 | ||
| ... | @@ -18839,11 +18871,11 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18839,11 +18871,11 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18839 | return sema.addType(ty); | 18871 | return sema.addType(ty); |
| 18840 | }, | 18872 | }, |
| 18841 | .ErrorSet => { | 18873 | .ErrorSet => { |
| 18842 | const payload_val = union_val.val.optionalValue() orelse | 18874 | const payload_val = union_val.val.optionalValue(mod) orelse |
| 18843 | return sema.addType(Type.initTag(.anyerror)); | 18875 | return sema.addType(Type.initTag(.anyerror)); |
| 18844 | const slice_val = payload_val.castTag(.slice).?.data; | 18876 | const slice_val = payload_val.castTag(.slice).?.data; |
| 18845 | 18877 | ||
| 18846 | const len = try sema.usizeCast(block, src, slice_val.len.toUnsignedInt(mod.getTarget())); | 18878 | const len = try sema.usizeCast(block, src, slice_val.len.toUnsignedInt(mod)); |
| 18847 | var names: Module.ErrorSet.NameMap = .{}; | 18879 | var names: Module.ErrorSet.NameMap = .{}; |
| 18848 | try names.ensureUnusedCapacity(sema.arena, len); | 18880 | try names.ensureUnusedCapacity(sema.arena, len); |
| 18849 | var i: usize = 0; | 18881 | var i: usize = 0; |
| ... | @@ -18890,7 +18922,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18890,7 +18922,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18890 | return sema.fail(block, src, "reified structs must have no decls", .{}); | 18922 | return sema.fail(block, src, "reified structs must have no decls", .{}); |
| 18891 | } | 18923 | } |
| 18892 | 18924 | ||
| 18893 | if (layout != .Packed and !backing_int_val.isNull()) { | 18925 | if (layout != .Packed and !backing_int_val.isNull(mod)) { |
| 18894 | return sema.fail(block, src, "non-packed struct does not support backing integer type", .{}); | 18926 | return sema.fail(block, src, "non-packed struct does not support backing integer type", .{}); |
| 18895 | } | 18927 | } |
| 18896 | 18928 | ||
| ... | @@ -18954,10 +18986,9 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -18954,10 +18986,9 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18954 | }; | 18986 | }; |
| 18955 | 18987 | ||
| 18956 | // Enum tag type | 18988 | // Enum tag type |
| 18957 | var buffer: Value.ToTypeBuffer = undefined; | 18989 | const int_tag_ty = try tag_type_val.toType().copy(new_decl_arena_allocator); |
| 18958 | const int_tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator); | ||
| 18959 | 18990 | ||
| 18960 | if (int_tag_ty.zigTypeTag() != .Int) { | 18991 | if (int_tag_ty.zigTypeTag(mod) != .Int) { |
| 18961 | return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{}); | 18992 | return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{}); |
| 18962 | } | 18993 | } |
| 18963 | enum_obj.tag_ty = int_tag_ty; | 18994 | enum_obj.tag_ty = int_tag_ty; |
| ... | @@ -19090,7 +19121,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -19090,7 +19121,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 19090 | const new_decl_arena_allocator = new_decl_arena.allocator(); | 19121 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| 19091 | 19122 | ||
| 19092 | const union_obj = try new_decl_arena_allocator.create(Module.Union); | 19123 | const union_obj = try new_decl_arena_allocator.create(Module.Union); |
| 19093 | const type_tag = if (!tag_type_val.isNull()) | 19124 | const type_tag = if (!tag_type_val.isNull(mod)) |
| 19094 | Type.Tag.union_tagged | 19125 | Type.Tag.union_tagged |
| 19095 | else if (layout != .Auto) | 19126 | else if (layout != .Auto) |
| 19096 | Type.Tag.@"union" | 19127 | Type.Tag.@"union" |
| ... | @@ -19130,11 +19161,10 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -19130,11 +19161,10 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 19130 | var tag_ty_field_names: ?Module.EnumFull.NameMap = null; | 19161 | var tag_ty_field_names: ?Module.EnumFull.NameMap = null; |
| 19131 | var enum_field_names: ?*Module.EnumNumbered.NameMap = null; | 19162 | var enum_field_names: ?*Module.EnumNumbered.NameMap = null; |
| 19132 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); | 19163 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); |
| 19133 | if (tag_type_val.optionalValue()) |payload_val| { | 19164 | if (tag_type_val.optionalValue(mod)) |payload_val| { |
| 19134 | var buffer: Value.ToTypeBuffer = undefined; | 19165 | union_obj.tag_ty = try payload_val.toType().copy(new_decl_arena_allocator); |
| 19135 | union_obj.tag_ty = try payload_val.toType(&buffer).copy(new_decl_arena_allocator); | ||
| 19136 | 19166 | ||
| 19137 | if (union_obj.tag_ty.zigTypeTag() != .Enum) { | 19167 | if (union_obj.tag_ty.zigTypeTag(mod) != .Enum) { |
| 19138 | return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}); | 19168 | return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}); |
| 19139 | } | 19169 | } |
| 19140 | tag_ty_field_names = try union_obj.tag_ty.enumFields().clone(sema.arena); | 19170 | tag_ty_field_names = try union_obj.tag_ty.enumFields().clone(sema.arena); |
| ... | @@ -19187,14 +19217,13 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -19187,14 +19217,13 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 19187 | return sema.fail(block, src, "duplicate union field {s}", .{field_name}); | 19217 | return sema.fail(block, src, "duplicate union field {s}", .{field_name}); |
| 19188 | } | 19218 | } |
| 19189 | 19219 | ||
| 19190 | var buffer: Value.ToTypeBuffer = undefined; | 19220 | const field_ty = try type_val.toType().copy(new_decl_arena_allocator); |
| 19191 | const field_ty = try type_val.toType(&buffer).copy(new_decl_arena_allocator); | ||
| 19192 | gop.value_ptr.* = .{ | 19221 | gop.value_ptr.* = .{ |
| 19193 | .ty = field_ty, | 19222 | .ty = field_ty, |
| 19194 | .abi_align = @intCast(u32, (try alignment_val.getUnsignedIntAdvanced(target, sema)).?), | 19223 | .abi_align = @intCast(u32, (try alignment_val.getUnsignedIntAdvanced(mod, sema)).?), |
| 19195 | }; | 19224 | }; |
| 19196 | 19225 | ||
| 19197 | if (field_ty.zigTypeTag() == .Opaque) { | 19226 | if (field_ty.zigTypeTag(mod) == .Opaque) { |
| 19198 | const msg = msg: { | 19227 | const msg = msg: { |
| 19199 | const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); | 19228 | const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); |
| 19200 | errdefer msg.destroy(sema.gpa); | 19229 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -19216,7 +19245,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -19216,7 +19245,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 19216 | break :msg msg; | 19245 | break :msg msg; |
| 19217 | }; | 19246 | }; |
| 19218 | return sema.failWithOwnedErrorMsg(msg); | 19247 | return sema.failWithOwnedErrorMsg(msg); |
| 19219 | } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) { | 19248 | } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) { |
| 19220 | const msg = msg: { | 19249 | const msg = msg: { |
| 19221 | const msg = try sema.errMsg(block, src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); | 19250 | const msg = try sema.errMsg(block, src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); |
| 19222 | errdefer msg.destroy(sema.gpa); | 19251 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -19280,20 +19309,18 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -19280,20 +19309,18 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 19280 | if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { | 19309 | if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { |
| 19281 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); | 19310 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); |
| 19282 | } | 19311 | } |
| 19283 | const alignment = @intCast(u29, alignment_val.toUnsignedInt(target)); | 19312 | const alignment = @intCast(u29, alignment_val.toUnsignedInt(mod)); |
| 19284 | if (alignment == target_util.defaultFunctionAlignment(target)) { | 19313 | if (alignment == target_util.defaultFunctionAlignment(target)) { |
| 19285 | break :alignment 0; | 19314 | break :alignment 0; |
| 19286 | } else { | 19315 | } else { |
| 19287 | break :alignment alignment; | 19316 | break :alignment alignment; |
| 19288 | } | 19317 | } |
| 19289 | }; | 19318 | }; |
| 19290 | const return_type = return_type_val.optionalValue() orelse | 19319 | const return_type = return_type_val.optionalValue(mod) orelse |
| 19291 | return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{}); | 19320 | return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{}); |
| 19292 | 19321 | ||
| 19293 | var buf: Value.ToTypeBuffer = undefined; | ||
| 19294 | |||
| 19295 | const args_slice_val = args_val.castTag(.slice).?.data; | 19322 | const args_slice_val = args_val.castTag(.slice).?.data; |
| 19296 | const args_len = try sema.usizeCast(block, src, args_slice_val.len.toUnsignedInt(mod.getTarget())); | 19323 | const args_len = try sema.usizeCast(block, src, args_slice_val.len.toUnsignedInt(mod)); |
| 19297 | 19324 | ||
| 19298 | const param_types = try sema.arena.alloc(Type, args_len); | 19325 | const param_types = try sema.arena.alloc(Type, args_len); |
| 19299 | const comptime_params = try sema.arena.alloc(bool, args_len); | 19326 | const comptime_params = try sema.arena.alloc(bool, args_len); |
| ... | @@ -19316,12 +19343,12 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -19316,12 +19343,12 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 19316 | return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{}); | 19343 | return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{}); |
| 19317 | } | 19344 | } |
| 19318 | 19345 | ||
| 19319 | const param_type_val = param_type_opt_val.optionalValue() orelse | 19346 | const param_type_val = param_type_opt_val.optionalValue(mod) orelse |
| 19320 | return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{}); | 19347 | return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{}); |
| 19321 | const param_type = try param_type_val.toType(&buf).copy(sema.arena); | 19348 | const param_type = try param_type_val.toType().copy(sema.arena); |
| 19322 | 19349 | ||
| 19323 | if (arg_is_noalias) { | 19350 | if (arg_is_noalias) { |
| 19324 | if (!param_type.isPtrAtRuntime()) { | 19351 | if (!param_type.isPtrAtRuntime(mod)) { |
| 19325 | return sema.fail(block, src, "non-pointer parameter declared noalias", .{}); | 19352 | return sema.fail(block, src, "non-pointer parameter declared noalias", .{}); |
| 19326 | } | 19353 | } |
| 19327 | noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse | 19354 | noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse |
| ... | @@ -19336,7 +19363,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -19336,7 +19363,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 19336 | .param_types = param_types, | 19363 | .param_types = param_types, |
| 19337 | .comptime_params = comptime_params.ptr, | 19364 | .comptime_params = comptime_params.ptr, |
| 19338 | .noalias_bits = noalias_bits, | 19365 | .noalias_bits = noalias_bits, |
| 19339 | .return_type = try return_type.toType(&buf).copy(sema.arena), | 19366 | .return_type = try return_type.toType().copy(sema.arena), |
| 19340 | .alignment = alignment, | 19367 | .alignment = alignment, |
| 19341 | .cc = cc, | 19368 | .cc = cc, |
| 19342 | .is_var_args = is_var_args, | 19369 | .is_var_args = is_var_args, |
| ... | @@ -19396,8 +19423,6 @@ fn reifyStruct( | ... | @@ -19396,8 +19423,6 @@ fn reifyStruct( |
| 19396 | }, | 19423 | }, |
| 19397 | }; | 19424 | }; |
| 19398 | 19425 | ||
| 19399 | const target = mod.getTarget(); | ||
| 19400 | |||
| 19401 | // Fields | 19426 | // Fields |
| 19402 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); | 19427 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); |
| 19403 | try struct_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); | 19428 | try struct_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| ... | @@ -19420,7 +19445,7 @@ fn reifyStruct( | ... | @@ -19420,7 +19445,7 @@ fn reifyStruct( |
| 19420 | if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { | 19445 | if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { |
| 19421 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); | 19446 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); |
| 19422 | } | 19447 | } |
| 19423 | const abi_align = @intCast(u29, (try alignment_val.getUnsignedIntAdvanced(target, sema)).?); | 19448 | const abi_align = @intCast(u29, (try alignment_val.getUnsignedIntAdvanced(mod, sema)).?); |
| 19424 | 19449 | ||
| 19425 | if (layout == .Packed) { | 19450 | if (layout == .Packed) { |
| 19426 | if (abi_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{}); | 19451 | if (abi_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{}); |
| ... | @@ -19461,7 +19486,7 @@ fn reifyStruct( | ... | @@ -19461,7 +19486,7 @@ fn reifyStruct( |
| 19461 | return sema.fail(block, src, "duplicate struct field {s}", .{field_name}); | 19486 | return sema.fail(block, src, "duplicate struct field {s}", .{field_name}); |
| 19462 | } | 19487 | } |
| 19463 | 19488 | ||
| 19464 | const default_val = if (default_value_val.optionalValue()) |opt_val| blk: { | 19489 | const default_val = if (default_value_val.optionalValue(mod)) |opt_val| blk: { |
| 19465 | const payload_val = if (opt_val.pointerDecl()) |opt_decl| | 19490 | const payload_val = if (opt_val.pointerDecl()) |opt_decl| |
| 19466 | mod.declPtr(opt_decl).val | 19491 | mod.declPtr(opt_decl).val |
| 19467 | else | 19492 | else |
| ... | @@ -19472,8 +19497,7 @@ fn reifyStruct( | ... | @@ -19472,8 +19497,7 @@ fn reifyStruct( |
| 19472 | return sema.fail(block, src, "comptime field without default initialization value", .{}); | 19497 | return sema.fail(block, src, "comptime field without default initialization value", .{}); |
| 19473 | } | 19498 | } |
| 19474 | 19499 | ||
| 19475 | var buffer: Value.ToTypeBuffer = undefined; | 19500 | const field_ty = try type_val.toType().copy(new_decl_arena_allocator); |
| 19476 | const field_ty = try type_val.toType(&buffer).copy(new_decl_arena_allocator); | ||
| 19477 | gop.value_ptr.* = .{ | 19501 | gop.value_ptr.* = .{ |
| 19478 | .ty = field_ty, | 19502 | .ty = field_ty, |
| 19479 | .abi_align = abi_align, | 19503 | .abi_align = abi_align, |
| ... | @@ -19482,7 +19506,7 @@ fn reifyStruct( | ... | @@ -19482,7 +19506,7 @@ fn reifyStruct( |
| 19482 | .offset = undefined, | 19506 | .offset = undefined, |
| 19483 | }; | 19507 | }; |
| 19484 | 19508 | ||
| 19485 | if (field_ty.zigTypeTag() == .Opaque) { | 19509 | if (field_ty.zigTypeTag(mod) == .Opaque) { |
| 19486 | const msg = msg: { | 19510 | const msg = msg: { |
| 19487 | const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); | 19511 | const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); |
| 19488 | errdefer msg.destroy(sema.gpa); | 19512 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -19492,7 +19516,7 @@ fn reifyStruct( | ... | @@ -19492,7 +19516,7 @@ fn reifyStruct( |
| 19492 | }; | 19516 | }; |
| 19493 | return sema.failWithOwnedErrorMsg(msg); | 19517 | return sema.failWithOwnedErrorMsg(msg); |
| 19494 | } | 19518 | } |
| 19495 | if (field_ty.zigTypeTag() == .NoReturn) { | 19519 | if (field_ty.zigTypeTag(mod) == .NoReturn) { |
| 19496 | const msg = msg: { | 19520 | const msg = msg: { |
| 19497 | const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{}); | 19521 | const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{}); |
| 19498 | errdefer msg.destroy(sema.gpa); | 19522 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -19514,7 +19538,7 @@ fn reifyStruct( | ... | @@ -19514,7 +19538,7 @@ fn reifyStruct( |
| 19514 | break :msg msg; | 19538 | break :msg msg; |
| 19515 | }; | 19539 | }; |
| 19516 | return sema.failWithOwnedErrorMsg(msg); | 19540 | return sema.failWithOwnedErrorMsg(msg); |
| 19517 | } else if (struct_obj.layout == .Packed and !(validatePackedType(field_ty))) { | 19541 | } else if (struct_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) { |
| 19518 | const msg = msg: { | 19542 | const msg = msg: { |
| 19519 | const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); | 19543 | const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); |
| 19520 | errdefer msg.destroy(sema.gpa); | 19544 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -19545,20 +19569,15 @@ fn reifyStruct( | ... | @@ -19545,20 +19569,15 @@ fn reifyStruct( |
| 19545 | 19569 | ||
| 19546 | var fields_bit_sum: u64 = 0; | 19570 | var fields_bit_sum: u64 = 0; |
| 19547 | for (struct_obj.fields.values()) |field| { | 19571 | for (struct_obj.fields.values()) |field| { |
| 19548 | fields_bit_sum += field.ty.bitSize(target); | 19572 | fields_bit_sum += field.ty.bitSize(mod); |
| 19549 | } | 19573 | } |
| 19550 | 19574 | ||
| 19551 | if (backing_int_val.optionalValue()) |payload| { | 19575 | if (backing_int_val.optionalValue(mod)) |payload| { |
| 19552 | var buf: Value.ToTypeBuffer = undefined; | 19576 | const backing_int_ty = payload.toType(); |
| 19553 | const backing_int_ty = payload.toType(&buf); | ||
| 19554 | try sema.checkBackingIntType(block, src, backing_int_ty, fields_bit_sum); | 19577 | try sema.checkBackingIntType(block, src, backing_int_ty, fields_bit_sum); |
| 19555 | struct_obj.backing_int_ty = try backing_int_ty.copy(new_decl_arena_allocator); | 19578 | struct_obj.backing_int_ty = try backing_int_ty.copy(new_decl_arena_allocator); |
| 19556 | } else { | 19579 | } else { |
| 19557 | var buf: Type.Payload.Bits = .{ | 19580 | struct_obj.backing_int_ty = try mod.intType(.unsigned, @intCast(u16, fields_bit_sum)); |
| 19558 | .base = .{ .tag = .int_unsigned }, | ||
| 19559 | .data = @intCast(u16, fields_bit_sum), | ||
| 19560 | }; | ||
| 19561 | struct_obj.backing_int_ty = try Type.initPayload(&buf.base).copy(new_decl_arena_allocator); | ||
| 19562 | } | 19581 | } |
| 19563 | 19582 | ||
| 19564 | struct_obj.status = .have_layout; | 19583 | struct_obj.status = .have_layout; |
| ... | @@ -19569,6 +19588,7 @@ fn reifyStruct( | ... | @@ -19569,6 +19588,7 @@ fn reifyStruct( |
| 19569 | } | 19588 | } |
| 19570 | 19589 | ||
| 19571 | fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 19590 | fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 19591 | const mod = sema.mod; | ||
| 19572 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; | 19592 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 19573 | const src = LazySrcLoc.nodeOffset(extra.node); | 19593 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 19574 | const addrspace_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 19594 | const addrspace_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| ... | @@ -19594,7 +19614,7 @@ fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst | ... | @@ -19594,7 +19614,7 @@ fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 19594 | 19614 | ||
| 19595 | ptr_info.@"addrspace" = dest_addrspace; | 19615 | ptr_info.@"addrspace" = dest_addrspace; |
| 19596 | const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info); | 19616 | const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info); |
| 19597 | const dest_ty = if (ptr_ty.zigTypeTag() == .Optional) | 19617 | const dest_ty = if (ptr_ty.zigTypeTag(mod) == .Optional) |
| 19598 | try Type.optional(sema.arena, dest_ptr_ty) | 19618 | try Type.optional(sema.arena, dest_ptr_ty) |
| 19599 | else | 19619 | else |
| 19600 | dest_ptr_ty; | 19620 | dest_ptr_ty; |
| ... | @@ -19716,6 +19736,7 @@ fn zirFrameSize(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -19716,6 +19736,7 @@ fn zirFrameSize(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 19716 | } | 19736 | } |
| 19717 | 19737 | ||
| 19718 | fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 19738 | fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 19739 | const mod = sema.mod; | ||
| 19719 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 19740 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 19720 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 19741 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 19721 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 19742 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| ... | @@ -19730,12 +19751,12 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -19730,12 +19751,12 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 19730 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | 19751 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 19731 | const result_val = try sema.floatToInt(block, operand_src, val, operand_ty, dest_ty); | 19752 | const result_val = try sema.floatToInt(block, operand_src, val, operand_ty, dest_ty); |
| 19732 | return sema.addConstant(dest_ty, result_val); | 19753 | return sema.addConstant(dest_ty, result_val); |
| 19733 | } else if (dest_ty.zigTypeTag() == .ComptimeInt) { | 19754 | } else if (dest_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 19734 | return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_int' must be comptime-known"); | 19755 | return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_int' must be comptime-known"); |
| 19735 | } | 19756 | } |
| 19736 | 19757 | ||
| 19737 | try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); | 19758 | try sema.requireRuntimeBlock(block, inst_data.src(), operand_src); |
| 19738 | if (dest_ty.intInfo(sema.mod.getTarget()).bits == 0) { | 19759 | if (dest_ty.intInfo(mod).bits == 0) { |
| 19739 | if (block.wantSafety()) { | 19760 | if (block.wantSafety()) { |
| 19740 | const ok = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, try sema.addConstant(operand_ty, Value.zero)); | 19761 | const ok = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, try sema.addConstant(operand_ty, Value.zero)); |
| 19741 | try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds); | 19762 | try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds); |
| ... | @@ -19755,6 +19776,7 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -19755,6 +19776,7 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 19755 | } | 19776 | } |
| 19756 | 19777 | ||
| 19757 | fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 19778 | fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 19779 | const mod = sema.mod; | ||
| 19758 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 19780 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 19759 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 19781 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 19760 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 19782 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| ... | @@ -19769,7 +19791,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -19769,7 +19791,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 19769 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | 19791 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 19770 | const result_val = try val.intToFloatAdvanced(sema.arena, operand_ty, dest_ty, sema.mod, sema); | 19792 | const result_val = try val.intToFloatAdvanced(sema.arena, operand_ty, dest_ty, sema.mod, sema); |
| 19771 | return sema.addConstant(dest_ty, result_val); | 19793 | return sema.addConstant(dest_ty, result_val); |
| 19772 | } else if (dest_ty.zigTypeTag() == .ComptimeFloat) { | 19794 | } else if (dest_ty.zigTypeTag(mod) == .ComptimeFloat) { |
| 19773 | return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_float' must be comptime-known"); | 19795 | return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_float' must be comptime-known"); |
| 19774 | } | 19796 | } |
| 19775 | 19797 | ||
| ... | @@ -19778,6 +19800,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -19778,6 +19800,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 19778 | } | 19800 | } |
| 19779 | 19801 | ||
| 19780 | fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 19802 | fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 19803 | const mod = sema.mod; | ||
| 19781 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 19804 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 19782 | const src = inst_data.src(); | 19805 | const src = inst_data.src(); |
| 19783 | 19806 | ||
| ... | @@ -19790,9 +19813,8 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -19790,9 +19813,8 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 19790 | const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 19813 | const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 19791 | const ptr_ty = try sema.resolveType(block, src, extra.lhs); | 19814 | const ptr_ty = try sema.resolveType(block, src, extra.lhs); |
| 19792 | try sema.checkPtrType(block, type_src, ptr_ty); | 19815 | try sema.checkPtrType(block, type_src, ptr_ty); |
| 19793 | const elem_ty = ptr_ty.elemType2(); | 19816 | const elem_ty = ptr_ty.elemType2(mod); |
| 19794 | const target = sema.mod.getTarget(); | 19817 | const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema); |
| 19795 | const ptr_align = try ptr_ty.ptrAlignmentAdvanced(target, sema); | ||
| 19796 | 19818 | ||
| 19797 | if (ptr_ty.isSlice()) { | 19819 | if (ptr_ty.isSlice()) { |
| 19798 | const msg = msg: { | 19820 | const msg = msg: { |
| ... | @@ -19805,8 +19827,8 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -19805,8 +19827,8 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 19805 | } | 19827 | } |
| 19806 | 19828 | ||
| 19807 | if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { | 19829 | if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { |
| 19808 | const addr = val.toUnsignedInt(target); | 19830 | const addr = val.toUnsignedInt(mod); |
| 19809 | if (!ptr_ty.isAllowzeroPtr() and addr == 0) | 19831 | if (!ptr_ty.isAllowzeroPtr(mod) and addr == 0) |
| 19810 | return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(sema.mod)}); | 19832 | return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(sema.mod)}); |
| 19811 | if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0) | 19833 | if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0) |
| 19812 | return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)}); | 19834 | return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)}); |
| ... | @@ -19820,8 +19842,8 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -19820,8 +19842,8 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 19820 | } | 19842 | } |
| 19821 | 19843 | ||
| 19822 | try sema.requireRuntimeBlock(block, src, operand_src); | 19844 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 19823 | if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag() == .Fn)) { | 19845 | if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) { |
| 19824 | if (!ptr_ty.isAllowzeroPtr()) { | 19846 | if (!ptr_ty.isAllowzeroPtr(mod)) { |
| 19825 | const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize); | 19847 | const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize); |
| 19826 | try sema.addSafetyCheck(block, is_non_zero, .cast_to_null); | 19848 | try sema.addSafetyCheck(block, is_non_zero, .cast_to_null); |
| 19827 | } | 19849 | } |
| ... | @@ -19926,6 +19948,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -19926,6 +19948,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 19926 | } | 19948 | } |
| 19927 | 19949 | ||
| 19928 | fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 19950 | fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 19951 | const mod = sema.mod; | ||
| 19929 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 19952 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 19930 | const src = inst_data.src(); | 19953 | const src = inst_data.src(); |
| 19931 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 19954 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| ... | @@ -19934,7 +19957,6 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -19934,7 +19957,6 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 19934 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | 19957 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 19935 | const operand = try sema.resolveInst(extra.rhs); | 19958 | const operand = try sema.resolveInst(extra.rhs); |
| 19936 | const operand_ty = sema.typeOf(operand); | 19959 | const operand_ty = sema.typeOf(operand); |
| 19937 | const target = sema.mod.getTarget(); | ||
| 19938 | 19960 | ||
| 19939 | try sema.checkPtrType(block, dest_ty_src, dest_ty); | 19961 | try sema.checkPtrType(block, dest_ty_src, dest_ty); |
| 19940 | try sema.checkPtrOperand(block, operand_src, operand_ty); | 19962 | try sema.checkPtrOperand(block, operand_src, operand_ty); |
| ... | @@ -19982,18 +20004,18 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -19982,18 +20004,18 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 19982 | else | 20004 | else |
| 19983 | operand; | 20005 | operand; |
| 19984 | 20006 | ||
| 19985 | const dest_elem_ty = dest_ty.elemType2(); | 20007 | const dest_elem_ty = dest_ty.elemType2(mod); |
| 19986 | try sema.resolveTypeLayout(dest_elem_ty); | 20008 | try sema.resolveTypeLayout(dest_elem_ty); |
| 19987 | const dest_align = dest_ty.ptrAlignment(target); | 20009 | const dest_align = dest_ty.ptrAlignment(mod); |
| 19988 | 20010 | ||
| 19989 | const operand_elem_ty = operand_ty.elemType2(); | 20011 | const operand_elem_ty = operand_ty.elemType2(mod); |
| 19990 | try sema.resolveTypeLayout(operand_elem_ty); | 20012 | try sema.resolveTypeLayout(operand_elem_ty); |
| 19991 | const operand_align = operand_ty.ptrAlignment(target); | 20013 | const operand_align = operand_ty.ptrAlignment(mod); |
| 19992 | 20014 | ||
| 19993 | // If the destination is less aligned than the source, preserve the source alignment | 20015 | // If the destination is less aligned than the source, preserve the source alignment |
| 19994 | const aligned_dest_ty = if (operand_align <= dest_align) dest_ty else blk: { | 20016 | const aligned_dest_ty = if (operand_align <= dest_align) dest_ty else blk: { |
| 19995 | // Unwrap the pointer (or pointer-like optional) type, set alignment, and re-wrap into result | 20017 | // Unwrap the pointer (or pointer-like optional) type, set alignment, and re-wrap into result |
| 19996 | if (dest_ty.zigTypeTag() == .Optional) { | 20018 | if (dest_ty.zigTypeTag(mod) == .Optional) { |
| 19997 | var buf: Type.Payload.ElemType = undefined; | 20019 | var buf: Type.Payload.ElemType = undefined; |
| 19998 | var dest_ptr_info = dest_ty.optionalChild(&buf).ptrInfo().data; | 20020 | var dest_ptr_info = dest_ty.optionalChild(&buf).ptrInfo().data; |
| 19999 | dest_ptr_info.@"align" = operand_align; | 20021 | dest_ptr_info.@"align" = operand_align; |
| ... | @@ -20006,8 +20028,8 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -20006,8 +20028,8 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 20006 | }; | 20028 | }; |
| 20007 | 20029 | ||
| 20008 | if (dest_is_slice) { | 20030 | if (dest_is_slice) { |
| 20009 | const operand_elem_size = operand_elem_ty.abiSize(target); | 20031 | const operand_elem_size = operand_elem_ty.abiSize(mod); |
| 20010 | const dest_elem_size = dest_elem_ty.abiSize(target); | 20032 | const dest_elem_size = dest_elem_ty.abiSize(mod); |
| 20011 | if (operand_elem_size != dest_elem_size) { | 20033 | if (operand_elem_size != dest_elem_size) { |
| 20012 | return sema.fail(block, dest_ty_src, "TODO: implement @ptrCast between slices changing the length", .{}); | 20034 | return sema.fail(block, dest_ty_src, "TODO: implement @ptrCast between slices changing the length", .{}); |
| 20013 | } | 20035 | } |
| ... | @@ -20032,21 +20054,21 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -20032,21 +20054,21 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 20032 | } | 20054 | } |
| 20033 | 20055 | ||
| 20034 | if (try sema.resolveMaybeUndefVal(ptr)) |operand_val| { | 20056 | if (try sema.resolveMaybeUndefVal(ptr)) |operand_val| { |
| 20035 | if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) { | 20057 | if (!dest_ty.ptrAllowsZero(mod) and operand_val.isUndef()) { |
| 20036 | return sema.failWithUseOfUndef(block, operand_src); | 20058 | return sema.failWithUseOfUndef(block, operand_src); |
| 20037 | } | 20059 | } |
| 20038 | if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) { | 20060 | if (!dest_ty.ptrAllowsZero(mod) and operand_val.isNull(mod)) { |
| 20039 | return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)}); | 20061 | return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)}); |
| 20040 | } | 20062 | } |
| 20041 | if (dest_ty.zigTypeTag() == .Optional and sema.typeOf(ptr).zigTypeTag() != .Optional) { | 20063 | if (dest_ty.zigTypeTag(mod) == .Optional and sema.typeOf(ptr).zigTypeTag(mod) != .Optional) { |
| 20042 | return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, operand_val)); | 20064 | return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, operand_val)); |
| 20043 | } | 20065 | } |
| 20044 | return sema.addConstant(aligned_dest_ty, operand_val); | 20066 | return sema.addConstant(aligned_dest_ty, operand_val); |
| 20045 | } | 20067 | } |
| 20046 | 20068 | ||
| 20047 | try sema.requireRuntimeBlock(block, src, null); | 20069 | try sema.requireRuntimeBlock(block, src, null); |
| 20048 | if (block.wantSafety() and operand_ty.ptrAllowsZero() and !dest_ty.ptrAllowsZero() and | 20070 | if (block.wantSafety() and operand_ty.ptrAllowsZero(mod) and !dest_ty.ptrAllowsZero(mod) and |
| 20049 | (try sema.typeHasRuntimeBits(dest_ty.elemType2()) or dest_ty.elemType2().zigTypeTag() == .Fn)) | 20071 | (try sema.typeHasRuntimeBits(dest_ty.elemType2(mod)) or dest_ty.elemType2(mod).zigTypeTag(mod) == .Fn)) |
| 20050 | { | 20072 | { |
| 20051 | const ptr_int = try block.addUnOp(.ptrtoint, ptr); | 20073 | const ptr_int = try block.addUnOp(.ptrtoint, ptr); |
| 20052 | const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize); | 20074 | const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize); |
| ... | @@ -20102,6 +20124,7 @@ fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD | ... | @@ -20102,6 +20124,7 @@ fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 20102 | } | 20124 | } |
| 20103 | 20125 | ||
| 20104 | fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 20126 | fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 20127 | const mod = sema.mod; | ||
| 20105 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 20128 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 20106 | const src = inst_data.src(); | 20129 | const src = inst_data.src(); |
| 20107 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 20130 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| ... | @@ -20112,7 +20135,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -20112,7 +20135,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 20112 | const dest_is_comptime_int = try sema.checkIntType(block, dest_ty_src, dest_scalar_ty); | 20135 | const dest_is_comptime_int = try sema.checkIntType(block, dest_ty_src, dest_scalar_ty); |
| 20113 | const operand_ty = sema.typeOf(operand); | 20136 | const operand_ty = sema.typeOf(operand); |
| 20114 | const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src); | 20137 | const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src); |
| 20115 | const is_vector = operand_ty.zigTypeTag() == .Vector; | 20138 | const is_vector = operand_ty.zigTypeTag(mod) == .Vector; |
| 20116 | const dest_ty = if (is_vector) | 20139 | const dest_ty = if (is_vector) |
| 20117 | try Type.vector(sema.arena, operand_ty.vectorLen(), dest_scalar_ty) | 20140 | try Type.vector(sema.arena, operand_ty.vectorLen(), dest_scalar_ty) |
| 20118 | else | 20141 | else |
| ... | @@ -20122,15 +20145,14 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -20122,15 +20145,14 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 20122 | return sema.coerce(block, dest_ty, operand, operand_src); | 20145 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 20123 | } | 20146 | } |
| 20124 | 20147 | ||
| 20125 | const target = sema.mod.getTarget(); | 20148 | const dest_info = dest_scalar_ty.intInfo(mod); |
| 20126 | const dest_info = dest_scalar_ty.intInfo(target); | ||
| 20127 | 20149 | ||
| 20128 | if (try sema.typeHasOnePossibleValue(dest_ty)) |val| { | 20150 | if (try sema.typeHasOnePossibleValue(dest_ty)) |val| { |
| 20129 | return sema.addConstant(dest_ty, val); | 20151 | return sema.addConstant(dest_ty, val); |
| 20130 | } | 20152 | } |
| 20131 | 20153 | ||
| 20132 | if (operand_scalar_ty.zigTypeTag() != .ComptimeInt) { | 20154 | if (operand_scalar_ty.zigTypeTag(mod) != .ComptimeInt) { |
| 20133 | const operand_info = operand_ty.intInfo(target); | 20155 | const operand_info = operand_ty.intInfo(mod); |
| 20134 | if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { | 20156 | if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { |
| 20135 | return sema.addConstant(operand_ty, val); | 20157 | return sema.addConstant(operand_ty, val); |
| 20136 | } | 20158 | } |
| ... | @@ -20186,6 +20208,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -20186,6 +20208,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 20186 | } | 20208 | } |
| 20187 | 20209 | ||
| 20188 | fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 20210 | fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 20211 | const mod = sema.mod; | ||
| 20189 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 20212 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 20190 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 20213 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 20191 | const align_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 20214 | const align_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| ... | @@ -20199,12 +20222,12 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -20199,12 +20222,12 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 20199 | var ptr_info = ptr_ty.ptrInfo().data; | 20222 | var ptr_info = ptr_ty.ptrInfo().data; |
| 20200 | ptr_info.@"align" = dest_align; | 20223 | ptr_info.@"align" = dest_align; |
| 20201 | var dest_ty = try Type.ptr(sema.arena, sema.mod, ptr_info); | 20224 | var dest_ty = try Type.ptr(sema.arena, sema.mod, ptr_info); |
| 20202 | if (ptr_ty.zigTypeTag() == .Optional) { | 20225 | if (ptr_ty.zigTypeTag(mod) == .Optional) { |
| 20203 | dest_ty = try Type.Tag.optional.create(sema.arena, dest_ty); | 20226 | dest_ty = try Type.Tag.optional.create(sema.arena, dest_ty); |
| 20204 | } | 20227 | } |
| 20205 | 20228 | ||
| 20206 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |val| { | 20229 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |val| { |
| 20207 | if (try val.getUnsignedIntAdvanced(sema.mod.getTarget(), null)) |addr| { | 20230 | if (try val.getUnsignedIntAdvanced(mod, null)) |addr| { |
| 20208 | if (addr % dest_align != 0) { | 20231 | if (addr % dest_align != 0) { |
| 20209 | return sema.fail(block, ptr_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ addr, dest_align }); | 20232 | return sema.fail(block, ptr_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ addr, dest_align }); |
| 20210 | } | 20233 | } |
| ... | @@ -20247,23 +20270,23 @@ fn zirBitCount( | ... | @@ -20247,23 +20270,23 @@ fn zirBitCount( |
| 20247 | block: *Block, | 20270 | block: *Block, |
| 20248 | inst: Zir.Inst.Index, | 20271 | inst: Zir.Inst.Index, |
| 20249 | air_tag: Air.Inst.Tag, | 20272 | air_tag: Air.Inst.Tag, |
| 20250 | comptime comptimeOp: fn (val: Value, ty: Type, target: std.Target) u64, | 20273 | comptime comptimeOp: fn (val: Value, ty: Type, mod: *const Module) u64, |
| 20251 | ) CompileError!Air.Inst.Ref { | 20274 | ) CompileError!Air.Inst.Ref { |
| 20275 | const mod = sema.mod; | ||
| 20252 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 20276 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 20253 | const src = inst_data.src(); | 20277 | const src = inst_data.src(); |
| 20254 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 20278 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 20255 | const operand = try sema.resolveInst(inst_data.operand); | 20279 | const operand = try sema.resolveInst(inst_data.operand); |
| 20256 | const operand_ty = sema.typeOf(operand); | 20280 | const operand_ty = sema.typeOf(operand); |
| 20257 | _ = try sema.checkIntOrVector(block, operand, operand_src); | 20281 | _ = try sema.checkIntOrVector(block, operand, operand_src); |
| 20258 | const target = sema.mod.getTarget(); | 20282 | const bits = operand_ty.intInfo(mod).bits; |
| 20259 | const bits = operand_ty.intInfo(target).bits; | ||
| 20260 | 20283 | ||
| 20261 | if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { | 20284 | if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { |
| 20262 | return sema.addConstant(operand_ty, val); | 20285 | return sema.addConstant(operand_ty, val); |
| 20263 | } | 20286 | } |
| 20264 | 20287 | ||
| 20265 | const result_scalar_ty = try Type.smallestUnsignedInt(sema.arena, bits); | 20288 | const result_scalar_ty = try mod.smallestUnsignedInt(bits); |
| 20266 | switch (operand_ty.zigTypeTag()) { | 20289 | switch (operand_ty.zigTypeTag(mod)) { |
| 20267 | .Vector => { | 20290 | .Vector => { |
| 20268 | const vec_len = operand_ty.vectorLen(); | 20291 | const vec_len = operand_ty.vectorLen(); |
| 20269 | const result_ty = try Type.vector(sema.arena, vec_len, result_scalar_ty); | 20292 | const result_ty = try Type.vector(sema.arena, vec_len, result_scalar_ty); |
| ... | @@ -20272,10 +20295,10 @@ fn zirBitCount( | ... | @@ -20272,10 +20295,10 @@ fn zirBitCount( |
| 20272 | 20295 | ||
| 20273 | var elem_buf: Value.ElemValueBuffer = undefined; | 20296 | var elem_buf: Value.ElemValueBuffer = undefined; |
| 20274 | const elems = try sema.arena.alloc(Value, vec_len); | 20297 | const elems = try sema.arena.alloc(Value, vec_len); |
| 20275 | const scalar_ty = operand_ty.scalarType(); | 20298 | const scalar_ty = operand_ty.scalarType(mod); |
| 20276 | for (elems, 0..) |*elem, i| { | 20299 | for (elems, 0..) |*elem, i| { |
| 20277 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); | 20300 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); |
| 20278 | const count = comptimeOp(elem_val, scalar_ty, target); | 20301 | const count = comptimeOp(elem_val, scalar_ty, mod); |
| 20279 | elem.* = try Value.Tag.int_u64.create(sema.arena, count); | 20302 | elem.* = try Value.Tag.int_u64.create(sema.arena, count); |
| 20280 | } | 20303 | } |
| 20281 | return sema.addConstant( | 20304 | return sema.addConstant( |
| ... | @@ -20291,7 +20314,7 @@ fn zirBitCount( | ... | @@ -20291,7 +20314,7 @@ fn zirBitCount( |
| 20291 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | 20314 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 20292 | if (val.isUndef()) return sema.addConstUndef(result_scalar_ty); | 20315 | if (val.isUndef()) return sema.addConstUndef(result_scalar_ty); |
| 20293 | try sema.resolveLazyValue(val); | 20316 | try sema.resolveLazyValue(val); |
| 20294 | return sema.addIntUnsigned(result_scalar_ty, comptimeOp(val, operand_ty, target)); | 20317 | return sema.addIntUnsigned(result_scalar_ty, comptimeOp(val, operand_ty, mod)); |
| 20295 | } else { | 20318 | } else { |
| 20296 | try sema.requireRuntimeBlock(block, src, operand_src); | 20319 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 20297 | return block.addTyOp(air_tag, result_scalar_ty, operand); | 20320 | return block.addTyOp(air_tag, result_scalar_ty, operand); |
| ... | @@ -20302,14 +20325,14 @@ fn zirBitCount( | ... | @@ -20302,14 +20325,14 @@ fn zirBitCount( |
| 20302 | } | 20325 | } |
| 20303 | 20326 | ||
| 20304 | fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 20327 | fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 20328 | const mod = sema.mod; | ||
| 20305 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 20329 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 20306 | const src = inst_data.src(); | 20330 | const src = inst_data.src(); |
| 20307 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 20331 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 20308 | const operand = try sema.resolveInst(inst_data.operand); | 20332 | const operand = try sema.resolveInst(inst_data.operand); |
| 20309 | const operand_ty = sema.typeOf(operand); | 20333 | const operand_ty = sema.typeOf(operand); |
| 20310 | const scalar_ty = try sema.checkIntOrVector(block, operand, operand_src); | 20334 | const scalar_ty = try sema.checkIntOrVector(block, operand, operand_src); |
| 20311 | const target = sema.mod.getTarget(); | 20335 | const bits = scalar_ty.intInfo(mod).bits; |
| 20312 | const bits = scalar_ty.intInfo(target).bits; | ||
| 20313 | if (bits % 8 != 0) { | 20336 | if (bits % 8 != 0) { |
| 20314 | return sema.fail( | 20337 | return sema.fail( |
| 20315 | block, | 20338 | block, |
| ... | @@ -20323,11 +20346,11 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -20323,11 +20346,11 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 20323 | return sema.addConstant(operand_ty, val); | 20346 | return sema.addConstant(operand_ty, val); |
| 20324 | } | 20347 | } |
| 20325 | 20348 | ||
| 20326 | switch (operand_ty.zigTypeTag()) { | 20349 | switch (operand_ty.zigTypeTag(mod)) { |
| 20327 | .Int => { | 20350 | .Int => { |
| 20328 | const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| { | 20351 | const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 20329 | if (val.isUndef()) return sema.addConstUndef(operand_ty); | 20352 | if (val.isUndef()) return sema.addConstUndef(operand_ty); |
| 20330 | const result_val = try val.byteSwap(operand_ty, target, sema.arena); | 20353 | const result_val = try val.byteSwap(operand_ty, mod, sema.arena); |
| 20331 | return sema.addConstant(operand_ty, result_val); | 20354 | return sema.addConstant(operand_ty, result_val); |
| 20332 | } else operand_src; | 20355 | } else operand_src; |
| 20333 | 20356 | ||
| ... | @@ -20344,7 +20367,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -20344,7 +20367,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 20344 | const elems = try sema.arena.alloc(Value, vec_len); | 20367 | const elems = try sema.arena.alloc(Value, vec_len); |
| 20345 | for (elems, 0..) |*elem, i| { | 20368 | for (elems, 0..) |*elem, i| { |
| 20346 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); | 20369 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); |
| 20347 | elem.* = try elem_val.byteSwap(operand_ty, target, sema.arena); | 20370 | elem.* = try elem_val.byteSwap(operand_ty, mod, sema.arena); |
| 20348 | } | 20371 | } |
| 20349 | return sema.addConstant( | 20372 | return sema.addConstant( |
| 20350 | operand_ty, | 20373 | operand_ty, |
| ... | @@ -20371,12 +20394,12 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -20371,12 +20394,12 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 20371 | return sema.addConstant(operand_ty, val); | 20394 | return sema.addConstant(operand_ty, val); |
| 20372 | } | 20395 | } |
| 20373 | 20396 | ||
| 20374 | const target = sema.mod.getTarget(); | 20397 | const mod = sema.mod; |
| 20375 | switch (operand_ty.zigTypeTag()) { | 20398 | switch (operand_ty.zigTypeTag(mod)) { |
| 20376 | .Int => { | 20399 | .Int => { |
| 20377 | const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| { | 20400 | const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 20378 | if (val.isUndef()) return sema.addConstUndef(operand_ty); | 20401 | if (val.isUndef()) return sema.addConstUndef(operand_ty); |
| 20379 | const result_val = try val.bitReverse(operand_ty, target, sema.arena); | 20402 | const result_val = try val.bitReverse(operand_ty, mod, sema.arena); |
| 20380 | return sema.addConstant(operand_ty, result_val); | 20403 | return sema.addConstant(operand_ty, result_val); |
| 20381 | } else operand_src; | 20404 | } else operand_src; |
| 20382 | 20405 | ||
| ... | @@ -20393,7 +20416,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -20393,7 +20416,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 20393 | const elems = try sema.arena.alloc(Value, vec_len); | 20416 | const elems = try sema.arena.alloc(Value, vec_len); |
| 20394 | for (elems, 0..) |*elem, i| { | 20417 | for (elems, 0..) |*elem, i| { |
| 20395 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); | 20418 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); |
| 20396 | elem.* = try elem_val.bitReverse(scalar_ty, target, sema.arena); | 20419 | elem.* = try elem_val.bitReverse(scalar_ty, mod, sema.arena); |
| 20397 | } | 20420 | } |
| 20398 | return sema.addConstant( | 20421 | return sema.addConstant( |
| 20399 | operand_ty, | 20422 | operand_ty, |
| ... | @@ -20429,10 +20452,10 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 | ... | @@ -20429,10 +20452,10 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 20429 | 20452 | ||
| 20430 | const ty = try sema.resolveType(block, lhs_src, extra.lhs); | 20453 | const ty = try sema.resolveType(block, lhs_src, extra.lhs); |
| 20431 | const field_name = try sema.resolveConstString(block, rhs_src, extra.rhs, "name of field must be comptime-known"); | 20454 | const field_name = try sema.resolveConstString(block, rhs_src, extra.rhs, "name of field must be comptime-known"); |
| 20432 | const target = sema.mod.getTarget(); | ||
| 20433 | 20455 | ||
| 20456 | const mod = sema.mod; | ||
| 20434 | try sema.resolveTypeLayout(ty); | 20457 | try sema.resolveTypeLayout(ty); |
| 20435 | switch (ty.zigTypeTag()) { | 20458 | switch (ty.zigTypeTag(mod)) { |
| 20436 | .Struct => {}, | 20459 | .Struct => {}, |
| 20437 | else => { | 20460 | else => { |
| 20438 | const msg = msg: { | 20461 | const msg = msg: { |
| ... | @@ -20464,15 +20487,16 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 | ... | @@ -20464,15 +20487,16 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 20464 | if (i == field_index) { | 20487 | if (i == field_index) { |
| 20465 | return bit_sum; | 20488 | return bit_sum; |
| 20466 | } | 20489 | } |
| 20467 | bit_sum += field.ty.bitSize(target); | 20490 | bit_sum += field.ty.bitSize(mod); |
| 20468 | } else unreachable; | 20491 | } else unreachable; |
| 20469 | }, | 20492 | }, |
| 20470 | else => return ty.structFieldOffset(field_index, target) * 8, | 20493 | else => return ty.structFieldOffset(field_index, mod) * 8, |
| 20471 | } | 20494 | } |
| 20472 | } | 20495 | } |
| 20473 | 20496 | ||
| 20474 | fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { | 20497 | fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { |
| 20475 | switch (ty.zigTypeTag()) { | 20498 | const mod = sema.mod; |
| 20499 | switch (ty.zigTypeTag(mod)) { | ||
| 20476 | .Struct, .Enum, .Union, .Opaque => return, | 20500 | .Struct, .Enum, .Union, .Opaque => return, |
| 20477 | else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{}'", .{ty.fmt(sema.mod)}), | 20501 | else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{}'", .{ty.fmt(sema.mod)}), |
| 20478 | } | 20502 | } |
| ... | @@ -20480,7 +20504,8 @@ fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Com | ... | @@ -20480,7 +20504,8 @@ fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Com |
| 20480 | 20504 | ||
| 20481 | /// Returns `true` if the type was a comptime_int. | 20505 | /// Returns `true` if the type was a comptime_int. |
| 20482 | fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool { | 20506 | fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool { |
| 20483 | switch (try ty.zigTypeTagOrPoison()) { | 20507 | const mod = sema.mod; |
| 20508 | switch (try ty.zigTypeTagOrPoison(mod)) { | ||
| 20484 | .ComptimeInt => return true, | 20509 | .ComptimeInt => return true, |
| 20485 | .Int => return false, | 20510 | .Int => return false, |
| 20486 | else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(sema.mod)}), | 20511 | else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(sema.mod)}), |
| ... | @@ -20493,7 +20518,8 @@ fn checkInvalidPtrArithmetic( | ... | @@ -20493,7 +20518,8 @@ fn checkInvalidPtrArithmetic( |
| 20493 | src: LazySrcLoc, | 20518 | src: LazySrcLoc, |
| 20494 | ty: Type, | 20519 | ty: Type, |
| 20495 | ) CompileError!void { | 20520 | ) CompileError!void { |
| 20496 | switch (try ty.zigTypeTagOrPoison()) { | 20521 | const mod = sema.mod; |
| 20522 | switch (try ty.zigTypeTagOrPoison(mod)) { | ||
| 20497 | .Pointer => switch (ty.ptrSize()) { | 20523 | .Pointer => switch (ty.ptrSize()) { |
| 20498 | .One, .Slice => return, | 20524 | .One, .Slice => return, |
| 20499 | .Many, .C => return sema.fail( | 20525 | .Many, .C => return sema.fail( |
| ... | @@ -20532,7 +20558,8 @@ fn checkPtrOperand( | ... | @@ -20532,7 +20558,8 @@ fn checkPtrOperand( |
| 20532 | ty_src: LazySrcLoc, | 20558 | ty_src: LazySrcLoc, |
| 20533 | ty: Type, | 20559 | ty: Type, |
| 20534 | ) CompileError!void { | 20560 | ) CompileError!void { |
| 20535 | switch (ty.zigTypeTag()) { | 20561 | const mod = sema.mod; |
| 20562 | switch (ty.zigTypeTag(mod)) { | ||
| 20536 | .Pointer => return, | 20563 | .Pointer => return, |
| 20537 | .Fn => { | 20564 | .Fn => { |
| 20538 | const msg = msg: { | 20565 | const msg = msg: { |
| ... | @@ -20550,7 +20577,7 @@ fn checkPtrOperand( | ... | @@ -20550,7 +20577,7 @@ fn checkPtrOperand( |
| 20550 | }; | 20577 | }; |
| 20551 | return sema.failWithOwnedErrorMsg(msg); | 20578 | return sema.failWithOwnedErrorMsg(msg); |
| 20552 | }, | 20579 | }, |
| 20553 | .Optional => if (ty.isPtrLikeOptional()) return, | 20580 | .Optional => if (ty.isPtrLikeOptional(mod)) return, |
| 20554 | else => {}, | 20581 | else => {}, |
| 20555 | } | 20582 | } |
| 20556 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)}); | 20583 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)}); |
| ... | @@ -20562,7 +20589,8 @@ fn checkPtrType( | ... | @@ -20562,7 +20589,8 @@ fn checkPtrType( |
| 20562 | ty_src: LazySrcLoc, | 20589 | ty_src: LazySrcLoc, |
| 20563 | ty: Type, | 20590 | ty: Type, |
| 20564 | ) CompileError!void { | 20591 | ) CompileError!void { |
| 20565 | switch (ty.zigTypeTag()) { | 20592 | const mod = sema.mod; |
| 20593 | switch (ty.zigTypeTag(mod)) { | ||
| 20566 | .Pointer => return, | 20594 | .Pointer => return, |
| 20567 | .Fn => { | 20595 | .Fn => { |
| 20568 | const msg = msg: { | 20596 | const msg = msg: { |
| ... | @@ -20580,7 +20608,7 @@ fn checkPtrType( | ... | @@ -20580,7 +20608,7 @@ fn checkPtrType( |
| 20580 | }; | 20608 | }; |
| 20581 | return sema.failWithOwnedErrorMsg(msg); | 20609 | return sema.failWithOwnedErrorMsg(msg); |
| 20582 | }, | 20610 | }, |
| 20583 | .Optional => if (ty.isPtrLikeOptional()) return, | 20611 | .Optional => if (ty.isPtrLikeOptional(mod)) return, |
| 20584 | else => {}, | 20612 | else => {}, |
| 20585 | } | 20613 | } |
| 20586 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)}); | 20614 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)}); |
| ... | @@ -20592,9 +20620,10 @@ fn checkVectorElemType( | ... | @@ -20592,9 +20620,10 @@ fn checkVectorElemType( |
| 20592 | ty_src: LazySrcLoc, | 20620 | ty_src: LazySrcLoc, |
| 20593 | ty: Type, | 20621 | ty: Type, |
| 20594 | ) CompileError!void { | 20622 | ) CompileError!void { |
| 20595 | switch (ty.zigTypeTag()) { | 20623 | const mod = sema.mod; |
| 20624 | switch (ty.zigTypeTag(mod)) { | ||
| 20596 | .Int, .Float, .Bool => return, | 20625 | .Int, .Float, .Bool => return, |
| 20597 | else => if (ty.isPtrAtRuntime()) return, | 20626 | else => if (ty.isPtrAtRuntime(mod)) return, |
| 20598 | } | 20627 | } |
| 20599 | return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{}'", .{ty.fmt(sema.mod)}); | 20628 | return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{}'", .{ty.fmt(sema.mod)}); |
| 20600 | } | 20629 | } |
| ... | @@ -20605,7 +20634,8 @@ fn checkFloatType( | ... | @@ -20605,7 +20634,8 @@ fn checkFloatType( |
| 20605 | ty_src: LazySrcLoc, | 20634 | ty_src: LazySrcLoc, |
| 20606 | ty: Type, | 20635 | ty: Type, |
| 20607 | ) CompileError!void { | 20636 | ) CompileError!void { |
| 20608 | switch (ty.zigTypeTag()) { | 20637 | const mod = sema.mod; |
| 20638 | switch (ty.zigTypeTag(mod)) { | ||
| 20609 | .ComptimeInt, .ComptimeFloat, .Float => {}, | 20639 | .ComptimeInt, .ComptimeFloat, .Float => {}, |
| 20610 | else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty.fmt(sema.mod)}), | 20640 | else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty.fmt(sema.mod)}), |
| 20611 | } | 20641 | } |
| ... | @@ -20617,9 +20647,10 @@ fn checkNumericType( | ... | @@ -20617,9 +20647,10 @@ fn checkNumericType( |
| 20617 | ty_src: LazySrcLoc, | 20647 | ty_src: LazySrcLoc, |
| 20618 | ty: Type, | 20648 | ty: Type, |
| 20619 | ) CompileError!void { | 20649 | ) CompileError!void { |
| 20620 | switch (ty.zigTypeTag()) { | 20650 | const mod = sema.mod; |
| 20651 | switch (ty.zigTypeTag(mod)) { | ||
| 20621 | .ComptimeFloat, .Float, .ComptimeInt, .Int => {}, | 20652 | .ComptimeFloat, .Float, .ComptimeInt, .Int => {}, |
| 20622 | .Vector => switch (ty.childType().zigTypeTag()) { | 20653 | .Vector => switch (ty.childType().zigTypeTag(mod)) { |
| 20623 | .ComptimeFloat, .Float, .ComptimeInt, .Int => {}, | 20654 | .ComptimeFloat, .Float, .ComptimeInt, .Int => {}, |
| 20624 | else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}), | 20655 | else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}), |
| 20625 | }, | 20656 | }, |
| ... | @@ -20637,9 +20668,9 @@ fn checkAtomicPtrOperand( | ... | @@ -20637,9 +20668,9 @@ fn checkAtomicPtrOperand( |
| 20637 | ptr_src: LazySrcLoc, | 20668 | ptr_src: LazySrcLoc, |
| 20638 | ptr_const: bool, | 20669 | ptr_const: bool, |
| 20639 | ) CompileError!Air.Inst.Ref { | 20670 | ) CompileError!Air.Inst.Ref { |
| 20640 | const target = sema.mod.getTarget(); | 20671 | const mod = sema.mod; |
| 20641 | var diag: target_util.AtomicPtrAlignmentDiagnostics = .{}; | 20672 | var diag: Module.AtomicPtrAlignmentDiagnostics = .{}; |
| 20642 | const alignment = target_util.atomicPtrAlignment(target, elem_ty, &diag) catch |err| switch (err) { | 20673 | const alignment = mod.atomicPtrAlignment(elem_ty, &diag) catch |err| switch (err) { |
| 20643 | error.FloatTooBig => return sema.fail( | 20674 | error.FloatTooBig => return sema.fail( |
| 20644 | block, | 20675 | block, |
| 20645 | elem_ty_src, | 20676 | elem_ty_src, |
| ... | @@ -20668,7 +20699,7 @@ fn checkAtomicPtrOperand( | ... | @@ -20668,7 +20699,7 @@ fn checkAtomicPtrOperand( |
| 20668 | }; | 20699 | }; |
| 20669 | 20700 | ||
| 20670 | const ptr_ty = sema.typeOf(ptr); | 20701 | const ptr_ty = sema.typeOf(ptr); |
| 20671 | const ptr_data = switch (try ptr_ty.zigTypeTagOrPoison()) { | 20702 | const ptr_data = switch (try ptr_ty.zigTypeTagOrPoison(mod)) { |
| 20672 | .Pointer => ptr_ty.ptrInfo().data, | 20703 | .Pointer => ptr_ty.ptrInfo().data, |
| 20673 | else => { | 20704 | else => { |
| 20674 | const wanted_ptr_ty = try Type.ptr(sema.arena, sema.mod, wanted_ptr_data); | 20705 | const wanted_ptr_ty = try Type.ptr(sema.arena, sema.mod, wanted_ptr_data); |
| ... | @@ -20735,12 +20766,13 @@ fn checkIntOrVector( | ... | @@ -20735,12 +20766,13 @@ fn checkIntOrVector( |
| 20735 | operand: Air.Inst.Ref, | 20766 | operand: Air.Inst.Ref, |
| 20736 | operand_src: LazySrcLoc, | 20767 | operand_src: LazySrcLoc, |
| 20737 | ) CompileError!Type { | 20768 | ) CompileError!Type { |
| 20769 | const mod = sema.mod; | ||
| 20738 | const operand_ty = sema.typeOf(operand); | 20770 | const operand_ty = sema.typeOf(operand); |
| 20739 | switch (try operand_ty.zigTypeTagOrPoison()) { | 20771 | switch (try operand_ty.zigTypeTagOrPoison(mod)) { |
| 20740 | .Int => return operand_ty, | 20772 | .Int => return operand_ty, |
| 20741 | .Vector => { | 20773 | .Vector => { |
| 20742 | const elem_ty = operand_ty.childType(); | 20774 | const elem_ty = operand_ty.childType(); |
| 20743 | switch (try elem_ty.zigTypeTagOrPoison()) { | 20775 | switch (try elem_ty.zigTypeTagOrPoison(mod)) { |
| 20744 | .Int => return elem_ty, | 20776 | .Int => return elem_ty, |
| 20745 | else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{ | 20777 | else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{ |
| 20746 | elem_ty.fmt(sema.mod), | 20778 | elem_ty.fmt(sema.mod), |
| ... | @@ -20759,11 +20791,12 @@ fn checkIntOrVectorAllowComptime( | ... | @@ -20759,11 +20791,12 @@ fn checkIntOrVectorAllowComptime( |
| 20759 | operand_ty: Type, | 20791 | operand_ty: Type, |
| 20760 | operand_src: LazySrcLoc, | 20792 | operand_src: LazySrcLoc, |
| 20761 | ) CompileError!Type { | 20793 | ) CompileError!Type { |
| 20762 | switch (try operand_ty.zigTypeTagOrPoison()) { | 20794 | const mod = sema.mod; |
| 20795 | switch (try operand_ty.zigTypeTagOrPoison(mod)) { | ||
| 20763 | .Int, .ComptimeInt => return operand_ty, | 20796 | .Int, .ComptimeInt => return operand_ty, |
| 20764 | .Vector => { | 20797 | .Vector => { |
| 20765 | const elem_ty = operand_ty.childType(); | 20798 | const elem_ty = operand_ty.childType(); |
| 20766 | switch (try elem_ty.zigTypeTagOrPoison()) { | 20799 | switch (try elem_ty.zigTypeTagOrPoison(mod)) { |
| 20767 | .Int, .ComptimeInt => return elem_ty, | 20800 | .Int, .ComptimeInt => return elem_ty, |
| 20768 | else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{ | 20801 | else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{ |
| 20769 | elem_ty.fmt(sema.mod), | 20802 | elem_ty.fmt(sema.mod), |
| ... | @@ -20777,7 +20810,8 @@ fn checkIntOrVectorAllowComptime( | ... | @@ -20777,7 +20810,8 @@ fn checkIntOrVectorAllowComptime( |
| 20777 | } | 20810 | } |
| 20778 | 20811 | ||
| 20779 | fn checkErrorSetType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { | 20812 | fn checkErrorSetType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { |
| 20780 | switch (ty.zigTypeTag()) { | 20813 | const mod = sema.mod; |
| 20814 | switch (ty.zigTypeTag(mod)) { | ||
| 20781 | .ErrorSet => return, | 20815 | .ErrorSet => return, |
| 20782 | else => return sema.fail(block, src, "expected error set type, found '{}'", .{ty.fmt(sema.mod)}), | 20816 | else => return sema.fail(block, src, "expected error set type, found '{}'", .{ty.fmt(sema.mod)}), |
| 20783 | } | 20817 | } |
| ... | @@ -20805,11 +20839,12 @@ fn checkSimdBinOp( | ... | @@ -20805,11 +20839,12 @@ fn checkSimdBinOp( |
| 20805 | lhs_src: LazySrcLoc, | 20839 | lhs_src: LazySrcLoc, |
| 20806 | rhs_src: LazySrcLoc, | 20840 | rhs_src: LazySrcLoc, |
| 20807 | ) CompileError!SimdBinOp { | 20841 | ) CompileError!SimdBinOp { |
| 20842 | const mod = sema.mod; | ||
| 20808 | const lhs_ty = sema.typeOf(uncasted_lhs); | 20843 | const lhs_ty = sema.typeOf(uncasted_lhs); |
| 20809 | const rhs_ty = sema.typeOf(uncasted_rhs); | 20844 | const rhs_ty = sema.typeOf(uncasted_rhs); |
| 20810 | 20845 | ||
| 20811 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 20846 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 20812 | var vec_len: ?usize = if (lhs_ty.zigTypeTag() == .Vector) lhs_ty.vectorLen() else null; | 20847 | var vec_len: ?usize = if (lhs_ty.zigTypeTag(mod) == .Vector) lhs_ty.vectorLen() else null; |
| 20813 | const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{ | 20848 | const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{ |
| 20814 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, | 20849 | .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, |
| 20815 | }); | 20850 | }); |
| ... | @@ -20823,7 +20858,7 @@ fn checkSimdBinOp( | ... | @@ -20823,7 +20858,7 @@ fn checkSimdBinOp( |
| 20823 | .lhs_val = try sema.resolveMaybeUndefVal(lhs), | 20858 | .lhs_val = try sema.resolveMaybeUndefVal(lhs), |
| 20824 | .rhs_val = try sema.resolveMaybeUndefVal(rhs), | 20859 | .rhs_val = try sema.resolveMaybeUndefVal(rhs), |
| 20825 | .result_ty = result_ty, | 20860 | .result_ty = result_ty, |
| 20826 | .scalar_ty = result_ty.scalarType(), | 20861 | .scalar_ty = result_ty.scalarType(mod), |
| 20827 | }; | 20862 | }; |
| 20828 | } | 20863 | } |
| 20829 | 20864 | ||
| ... | @@ -20836,8 +20871,9 @@ fn checkVectorizableBinaryOperands( | ... | @@ -20836,8 +20871,9 @@ fn checkVectorizableBinaryOperands( |
| 20836 | lhs_src: LazySrcLoc, | 20871 | lhs_src: LazySrcLoc, |
| 20837 | rhs_src: LazySrcLoc, | 20872 | rhs_src: LazySrcLoc, |
| 20838 | ) CompileError!void { | 20873 | ) CompileError!void { |
| 20839 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); | 20874 | const mod = sema.mod; |
| 20840 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); | 20875 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod); |
| 20876 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod); | ||
| 20841 | if (lhs_zig_ty_tag != .Vector and rhs_zig_ty_tag != .Vector) return; | 20877 | if (lhs_zig_ty_tag != .Vector and rhs_zig_ty_tag != .Vector) return; |
| 20842 | 20878 | ||
| 20843 | const lhs_is_vector = switch (lhs_zig_ty_tag) { | 20879 | const lhs_is_vector = switch (lhs_zig_ty_tag) { |
| ... | @@ -20892,6 +20928,7 @@ fn resolveExportOptions( | ... | @@ -20892,6 +20928,7 @@ fn resolveExportOptions( |
| 20892 | src: LazySrcLoc, | 20928 | src: LazySrcLoc, |
| 20893 | zir_ref: Zir.Inst.Ref, | 20929 | zir_ref: Zir.Inst.Ref, |
| 20894 | ) CompileError!std.builtin.ExportOptions { | 20930 | ) CompileError!std.builtin.ExportOptions { |
| 20931 | const mod = sema.mod; | ||
| 20895 | const export_options_ty = try sema.getBuiltinType("ExportOptions"); | 20932 | const export_options_ty = try sema.getBuiltinType("ExportOptions"); |
| 20896 | const air_ref = try sema.resolveInst(zir_ref); | 20933 | const air_ref = try sema.resolveInst(zir_ref); |
| 20897 | const options = try sema.coerce(block, export_options_ty, air_ref, src); | 20934 | const options = try sema.coerce(block, export_options_ty, air_ref, src); |
| ... | @@ -20904,7 +20941,7 @@ fn resolveExportOptions( | ... | @@ -20904,7 +20941,7 @@ fn resolveExportOptions( |
| 20904 | const name_operand = try sema.fieldVal(block, src, options, "name", name_src); | 20941 | const name_operand = try sema.fieldVal(block, src, options, "name", name_src); |
| 20905 | const name_val = try sema.resolveConstValue(block, name_src, name_operand, "name of exported value must be comptime-known"); | 20942 | const name_val = try sema.resolveConstValue(block, name_src, name_operand, "name of exported value must be comptime-known"); |
| 20906 | const name_ty = Type.initTag(.const_slice_u8); | 20943 | const name_ty = Type.initTag(.const_slice_u8); |
| 20907 | const name = try name_val.toAllocatedBytes(name_ty, sema.arena, sema.mod); | 20944 | const name = try name_val.toAllocatedBytes(name_ty, sema.arena, mod); |
| 20908 | 20945 | ||
| 20909 | const linkage_operand = try sema.fieldVal(block, src, options, "linkage", linkage_src); | 20946 | const linkage_operand = try sema.fieldVal(block, src, options, "linkage", linkage_src); |
| 20910 | const linkage_val = try sema.resolveConstValue(block, linkage_src, linkage_operand, "linkage of exported value must be comptime-known"); | 20947 | const linkage_val = try sema.resolveConstValue(block, linkage_src, linkage_operand, "linkage of exported value must be comptime-known"); |
| ... | @@ -20913,8 +20950,8 @@ fn resolveExportOptions( | ... | @@ -20913,8 +20950,8 @@ fn resolveExportOptions( |
| 20913 | const section_operand = try sema.fieldVal(block, src, options, "section", section_src); | 20950 | const section_operand = try sema.fieldVal(block, src, options, "section", section_src); |
| 20914 | const section_opt_val = try sema.resolveConstValue(block, section_src, section_operand, "linksection of exported value must be comptime-known"); | 20951 | const section_opt_val = try sema.resolveConstValue(block, section_src, section_operand, "linksection of exported value must be comptime-known"); |
| 20915 | const section_ty = Type.initTag(.const_slice_u8); | 20952 | const section_ty = Type.initTag(.const_slice_u8); |
| 20916 | const section = if (section_opt_val.optionalValue()) |section_val| | 20953 | const section = if (section_opt_val.optionalValue(mod)) |section_val| |
| 20917 | try section_val.toAllocatedBytes(section_ty, sema.arena, sema.mod) | 20954 | try section_val.toAllocatedBytes(section_ty, sema.arena, mod) |
| 20918 | else | 20955 | else |
| 20919 | null; | 20956 | null; |
| 20920 | 20957 | ||
| ... | @@ -20979,6 +21016,7 @@ fn zirCmpxchg( | ... | @@ -20979,6 +21016,7 @@ fn zirCmpxchg( |
| 20979 | block: *Block, | 21016 | block: *Block, |
| 20980 | extended: Zir.Inst.Extended.InstData, | 21017 | extended: Zir.Inst.Extended.InstData, |
| 20981 | ) CompileError!Air.Inst.Ref { | 21018 | ) CompileError!Air.Inst.Ref { |
| 21019 | const mod = sema.mod; | ||
| 20982 | const extra = sema.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data; | 21020 | const extra = sema.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data; |
| 20983 | const air_tag: Air.Inst.Tag = switch (extended.small) { | 21021 | const air_tag: Air.Inst.Tag = switch (extended.small) { |
| 20984 | 0 => .cmpxchg_weak, | 21022 | 0 => .cmpxchg_weak, |
| ... | @@ -20996,7 +21034,7 @@ fn zirCmpxchg( | ... | @@ -20996,7 +21034,7 @@ fn zirCmpxchg( |
| 20996 | // zig fmt: on | 21034 | // zig fmt: on |
| 20997 | const expected_value = try sema.resolveInst(extra.expected_value); | 21035 | const expected_value = try sema.resolveInst(extra.expected_value); |
| 20998 | const elem_ty = sema.typeOf(expected_value); | 21036 | const elem_ty = sema.typeOf(expected_value); |
| 20999 | if (elem_ty.zigTypeTag() == .Float) { | 21037 | if (elem_ty.zigTypeTag(mod) == .Float) { |
| 21000 | return sema.fail( | 21038 | return sema.fail( |
| 21001 | block, | 21039 | block, |
| 21002 | elem_ty_src, | 21040 | elem_ty_src, |
| ... | @@ -21102,26 +21140,26 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -21102,26 +21140,26 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 21102 | const operation = try sema.resolveBuiltinEnum(block, op_src, extra.lhs, "ReduceOp", "@reduce operation must be comptime-known"); | 21140 | const operation = try sema.resolveBuiltinEnum(block, op_src, extra.lhs, "ReduceOp", "@reduce operation must be comptime-known"); |
| 21103 | const operand = try sema.resolveInst(extra.rhs); | 21141 | const operand = try sema.resolveInst(extra.rhs); |
| 21104 | const operand_ty = sema.typeOf(operand); | 21142 | const operand_ty = sema.typeOf(operand); |
| 21105 | const target = sema.mod.getTarget(); | 21143 | const mod = sema.mod; |
| 21106 | 21144 | ||
| 21107 | if (operand_ty.zigTypeTag() != .Vector) { | 21145 | if (operand_ty.zigTypeTag(mod) != .Vector) { |
| 21108 | return sema.fail(block, operand_src, "expected vector, found '{}'", .{operand_ty.fmt(sema.mod)}); | 21146 | return sema.fail(block, operand_src, "expected vector, found '{}'", .{operand_ty.fmt(mod)}); |
| 21109 | } | 21147 | } |
| 21110 | 21148 | ||
| 21111 | const scalar_ty = operand_ty.childType(); | 21149 | const scalar_ty = operand_ty.childType(); |
| 21112 | 21150 | ||
| 21113 | // Type-check depending on operation. | 21151 | // Type-check depending on operation. |
| 21114 | switch (operation) { | 21152 | switch (operation) { |
| 21115 | .And, .Or, .Xor => switch (scalar_ty.zigTypeTag()) { | 21153 | .And, .Or, .Xor => switch (scalar_ty.zigTypeTag(mod)) { |
| 21116 | .Int, .Bool => {}, | 21154 | .Int, .Bool => {}, |
| 21117 | else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or boolean operand; found '{}'", .{ | 21155 | else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or boolean operand; found '{}'", .{ |
| 21118 | @tagName(operation), operand_ty.fmt(sema.mod), | 21156 | @tagName(operation), operand_ty.fmt(mod), |
| 21119 | }), | 21157 | }), |
| 21120 | }, | 21158 | }, |
| 21121 | .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag()) { | 21159 | .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag(mod)) { |
| 21122 | .Int, .Float => {}, | 21160 | .Int, .Float => {}, |
| 21123 | else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or float operand; found '{}'", .{ | 21161 | else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or float operand; found '{}'", .{ |
| 21124 | @tagName(operation), operand_ty.fmt(sema.mod), | 21162 | @tagName(operation), operand_ty.fmt(mod), |
| 21125 | }), | 21163 | }), |
| 21126 | }, | 21164 | }, |
| 21127 | } | 21165 | } |
| ... | @@ -21136,19 +21174,19 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -21136,19 +21174,19 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 21136 | if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { | 21174 | if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { |
| 21137 | if (operand_val.isUndef()) return sema.addConstUndef(scalar_ty); | 21175 | if (operand_val.isUndef()) return sema.addConstUndef(scalar_ty); |
| 21138 | 21176 | ||
| 21139 | var accum: Value = try operand_val.elemValue(sema.mod, sema.arena, 0); | 21177 | var accum: Value = try operand_val.elemValue(mod, sema.arena, 0); |
| 21140 | var elem_buf: Value.ElemValueBuffer = undefined; | 21178 | var elem_buf: Value.ElemValueBuffer = undefined; |
| 21141 | var i: u32 = 1; | 21179 | var i: u32 = 1; |
| 21142 | while (i < vec_len) : (i += 1) { | 21180 | while (i < vec_len) : (i += 1) { |
| 21143 | const elem_val = operand_val.elemValueBuffer(sema.mod, i, &elem_buf); | 21181 | const elem_val = operand_val.elemValueBuffer(mod, i, &elem_buf); |
| 21144 | switch (operation) { | 21182 | switch (operation) { |
| 21145 | .And => accum = try accum.bitwiseAnd(elem_val, scalar_ty, sema.arena, sema.mod), | 21183 | .And => accum = try accum.bitwiseAnd(elem_val, scalar_ty, sema.arena, mod), |
| 21146 | .Or => accum = try accum.bitwiseOr(elem_val, scalar_ty, sema.arena, sema.mod), | 21184 | .Or => accum = try accum.bitwiseOr(elem_val, scalar_ty, sema.arena, mod), |
| 21147 | .Xor => accum = try accum.bitwiseXor(elem_val, scalar_ty, sema.arena, sema.mod), | 21185 | .Xor => accum = try accum.bitwiseXor(elem_val, scalar_ty, sema.arena, mod), |
| 21148 | .Min => accum = accum.numberMin(elem_val, target), | 21186 | .Min => accum = accum.numberMin(elem_val, mod), |
| 21149 | .Max => accum = accum.numberMax(elem_val, target), | 21187 | .Max => accum = accum.numberMax(elem_val, mod), |
| 21150 | .Add => accum = try sema.numberAddWrapScalar(accum, elem_val, scalar_ty), | 21188 | .Add => accum = try sema.numberAddWrapScalar(accum, elem_val, scalar_ty), |
| 21151 | .Mul => accum = try accum.numberMulWrap(elem_val, scalar_ty, sema.arena, sema.mod), | 21189 | .Mul => accum = try accum.numberMulWrap(elem_val, scalar_ty, sema.arena, mod), |
| 21152 | } | 21190 | } |
| 21153 | } | 21191 | } |
| 21154 | return sema.addConstant(scalar_ty, accum); | 21192 | return sema.addConstant(scalar_ty, accum); |
| ... | @@ -21165,6 +21203,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -21165,6 +21203,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 21165 | } | 21203 | } |
| 21166 | 21204 | ||
| 21167 | fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 21205 | fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 21206 | const mod = sema.mod; | ||
| 21168 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 21207 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 21169 | const extra = sema.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data; | 21208 | const extra = sema.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data; |
| 21170 | const elem_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 21209 | const elem_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| ... | @@ -21177,7 +21216,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -21177,7 +21216,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 21177 | var mask = try sema.resolveInst(extra.mask); | 21216 | var mask = try sema.resolveInst(extra.mask); |
| 21178 | var mask_ty = sema.typeOf(mask); | 21217 | var mask_ty = sema.typeOf(mask); |
| 21179 | 21218 | ||
| 21180 | const mask_len = switch (sema.typeOf(mask).zigTypeTag()) { | 21219 | const mask_len = switch (sema.typeOf(mask).zigTypeTag(mod)) { |
| 21181 | .Array, .Vector => sema.typeOf(mask).arrayLen(), | 21220 | .Array, .Vector => sema.typeOf(mask).arrayLen(), |
| 21182 | else => return sema.fail(block, mask_src, "expected vector or array, found '{}'", .{sema.typeOf(mask).fmt(sema.mod)}), | 21221 | else => return sema.fail(block, mask_src, "expected vector or array, found '{}'", .{sema.typeOf(mask).fmt(sema.mod)}), |
| 21183 | }; | 21222 | }; |
| ... | @@ -21200,6 +21239,7 @@ fn analyzeShuffle( | ... | @@ -21200,6 +21239,7 @@ fn analyzeShuffle( |
| 21200 | mask: Value, | 21239 | mask: Value, |
| 21201 | mask_len: u32, | 21240 | mask_len: u32, |
| 21202 | ) CompileError!Air.Inst.Ref { | 21241 | ) CompileError!Air.Inst.Ref { |
| 21242 | const mod = sema.mod; | ||
| 21203 | const a_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = src_node }; | 21243 | const a_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = src_node }; |
| 21204 | const b_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = src_node }; | 21244 | const b_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = src_node }; |
| 21205 | const mask_src: LazySrcLoc = .{ .node_offset_builtin_call_arg3 = src_node }; | 21245 | const mask_src: LazySrcLoc = .{ .node_offset_builtin_call_arg3 = src_node }; |
| ... | @@ -21211,7 +21251,7 @@ fn analyzeShuffle( | ... | @@ -21211,7 +21251,7 @@ fn analyzeShuffle( |
| 21211 | .elem_type = elem_ty, | 21251 | .elem_type = elem_ty, |
| 21212 | }); | 21252 | }); |
| 21213 | 21253 | ||
| 21214 | var maybe_a_len = switch (sema.typeOf(a).zigTypeTag()) { | 21254 | var maybe_a_len = switch (sema.typeOf(a).zigTypeTag(mod)) { |
| 21215 | .Array, .Vector => sema.typeOf(a).arrayLen(), | 21255 | .Array, .Vector => sema.typeOf(a).arrayLen(), |
| 21216 | .Undefined => null, | 21256 | .Undefined => null, |
| 21217 | else => return sema.fail(block, a_src, "expected vector or array with element type '{}', found '{}'", .{ | 21257 | else => return sema.fail(block, a_src, "expected vector or array with element type '{}', found '{}'", .{ |
| ... | @@ -21219,7 +21259,7 @@ fn analyzeShuffle( | ... | @@ -21219,7 +21259,7 @@ fn analyzeShuffle( |
| 21219 | sema.typeOf(a).fmt(sema.mod), | 21259 | sema.typeOf(a).fmt(sema.mod), |
| 21220 | }), | 21260 | }), |
| 21221 | }; | 21261 | }; |
| 21222 | var maybe_b_len = switch (sema.typeOf(b).zigTypeTag()) { | 21262 | var maybe_b_len = switch (sema.typeOf(b).zigTypeTag(mod)) { |
| 21223 | .Array, .Vector => sema.typeOf(b).arrayLen(), | 21263 | .Array, .Vector => sema.typeOf(b).arrayLen(), |
| 21224 | .Undefined => null, | 21264 | .Undefined => null, |
| 21225 | else => return sema.fail(block, b_src, "expected vector or array with element type '{}', found '{}'", .{ | 21265 | else => return sema.fail(block, b_src, "expected vector or array with element type '{}', found '{}'", .{ |
| ... | @@ -21255,7 +21295,7 @@ fn analyzeShuffle( | ... | @@ -21255,7 +21295,7 @@ fn analyzeShuffle( |
| 21255 | var buf: Value.ElemValueBuffer = undefined; | 21295 | var buf: Value.ElemValueBuffer = undefined; |
| 21256 | const elem = mask.elemValueBuffer(sema.mod, i, &buf); | 21296 | const elem = mask.elemValueBuffer(sema.mod, i, &buf); |
| 21257 | if (elem.isUndef()) continue; | 21297 | if (elem.isUndef()) continue; |
| 21258 | const int = elem.toSignedInt(sema.mod.getTarget()); | 21298 | const int = elem.toSignedInt(mod); |
| 21259 | var unsigned: u32 = undefined; | 21299 | var unsigned: u32 = undefined; |
| 21260 | var chosen: u32 = undefined; | 21300 | var chosen: u32 = undefined; |
| 21261 | if (int >= 0) { | 21301 | if (int >= 0) { |
| ... | @@ -21297,7 +21337,7 @@ fn analyzeShuffle( | ... | @@ -21297,7 +21337,7 @@ fn analyzeShuffle( |
| 21297 | values[i] = Value.undef; | 21337 | values[i] = Value.undef; |
| 21298 | continue; | 21338 | continue; |
| 21299 | } | 21339 | } |
| 21300 | const int = mask_elem_val.toSignedInt(sema.mod.getTarget()); | 21340 | const int = mask_elem_val.toSignedInt(mod); |
| 21301 | const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int); | 21341 | const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int); |
| 21302 | if (int >= 0) { | 21342 | if (int >= 0) { |
| 21303 | values[i] = try a_val.elemValue(sema.mod, sema.arena, unsigned); | 21343 | values[i] = try a_val.elemValue(sema.mod, sema.arena, unsigned); |
| ... | @@ -21356,6 +21396,7 @@ fn analyzeShuffle( | ... | @@ -21356,6 +21396,7 @@ fn analyzeShuffle( |
| 21356 | } | 21396 | } |
| 21357 | 21397 | ||
| 21358 | fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 21398 | fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 21399 | const mod = sema.mod; | ||
| 21359 | const extra = sema.code.extraData(Zir.Inst.Select, extended.operand).data; | 21400 | const extra = sema.code.extraData(Zir.Inst.Select, extended.operand).data; |
| 21360 | 21401 | ||
| 21361 | const src = LazySrcLoc.nodeOffset(extra.node); | 21402 | const src = LazySrcLoc.nodeOffset(extra.node); |
| ... | @@ -21369,7 +21410,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C | ... | @@ -21369,7 +21410,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C |
| 21369 | const pred_uncoerced = try sema.resolveInst(extra.pred); | 21410 | const pred_uncoerced = try sema.resolveInst(extra.pred); |
| 21370 | const pred_ty = sema.typeOf(pred_uncoerced); | 21411 | const pred_ty = sema.typeOf(pred_uncoerced); |
| 21371 | 21412 | ||
| 21372 | const vec_len_u64 = switch (try pred_ty.zigTypeTagOrPoison()) { | 21413 | const vec_len_u64 = switch (try pred_ty.zigTypeTagOrPoison(mod)) { |
| 21373 | .Vector, .Array => pred_ty.arrayLen(), | 21414 | .Vector, .Array => pred_ty.arrayLen(), |
| 21374 | else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(sema.mod)}), | 21415 | else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(sema.mod)}), |
| 21375 | }; | 21416 | }; |
| ... | @@ -21489,6 +21530,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -21489,6 +21530,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 21489 | } | 21530 | } |
| 21490 | 21531 | ||
| 21491 | fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 21532 | fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 21533 | const mod = sema.mod; | ||
| 21492 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 21534 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 21493 | const extra = sema.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data; | 21535 | const extra = sema.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data; |
| 21494 | const src = inst_data.src(); | 21536 | const src = inst_data.src(); |
| ... | @@ -21505,7 +21547,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -21505,7 +21547,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 21505 | const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false); | 21547 | const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false); |
| 21506 | const op = try sema.resolveAtomicRmwOp(block, op_src, extra.operation); | 21548 | const op = try sema.resolveAtomicRmwOp(block, op_src, extra.operation); |
| 21507 | 21549 | ||
| 21508 | switch (elem_ty.zigTypeTag()) { | 21550 | switch (elem_ty.zigTypeTag(mod)) { |
| 21509 | .Enum => if (op != .Xchg) { | 21551 | .Enum => if (op != .Xchg) { |
| 21510 | return sema.fail(block, op_src, "@atomicRmw with enum only allowed with .Xchg", .{}); | 21552 | return sema.fail(block, op_src, "@atomicRmw with enum only allowed with .Xchg", .{}); |
| 21511 | }, | 21553 | }, |
| ... | @@ -21536,7 +21578,6 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -21536,7 +21578,6 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 21536 | break :rs operand_src; | 21578 | break :rs operand_src; |
| 21537 | }; | 21579 | }; |
| 21538 | if (ptr_val.isComptimeMutablePtr()) { | 21580 | if (ptr_val.isComptimeMutablePtr()) { |
| 21539 | const target = sema.mod.getTarget(); | ||
| 21540 | const ptr_ty = sema.typeOf(ptr); | 21581 | const ptr_ty = sema.typeOf(ptr); |
| 21541 | const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src; | 21582 | const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src; |
| 21542 | const new_val = switch (op) { | 21583 | const new_val = switch (op) { |
| ... | @@ -21544,12 +21585,12 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -21544,12 +21585,12 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 21544 | .Xchg => operand_val, | 21585 | .Xchg => operand_val, |
| 21545 | .Add => try sema.numberAddWrapScalar(stored_val, operand_val, elem_ty), | 21586 | .Add => try sema.numberAddWrapScalar(stored_val, operand_val, elem_ty), |
| 21546 | .Sub => try sema.numberSubWrapScalar(stored_val, operand_val, elem_ty), | 21587 | .Sub => try sema.numberSubWrapScalar(stored_val, operand_val, elem_ty), |
| 21547 | .And => try stored_val.bitwiseAnd (operand_val, elem_ty, sema.arena, sema.mod), | 21588 | .And => try stored_val.bitwiseAnd (operand_val, elem_ty, sema.arena, mod), |
| 21548 | .Nand => try stored_val.bitwiseNand (operand_val, elem_ty, sema.arena, sema.mod), | 21589 | .Nand => try stored_val.bitwiseNand (operand_val, elem_ty, sema.arena, mod), |
| 21549 | .Or => try stored_val.bitwiseOr (operand_val, elem_ty, sema.arena, sema.mod), | 21590 | .Or => try stored_val.bitwiseOr (operand_val, elem_ty, sema.arena, mod), |
| 21550 | .Xor => try stored_val.bitwiseXor (operand_val, elem_ty, sema.arena, sema.mod), | 21591 | .Xor => try stored_val.bitwiseXor (operand_val, elem_ty, sema.arena, mod), |
| 21551 | .Max => stored_val.numberMax (operand_val, target), | 21592 | .Max => stored_val.numberMax (operand_val, mod), |
| 21552 | .Min => stored_val.numberMin (operand_val, target), | 21593 | .Min => stored_val.numberMin (operand_val, mod), |
| 21553 | // zig fmt: on | 21594 | // zig fmt: on |
| 21554 | }; | 21595 | }; |
| 21555 | try sema.storePtrVal(block, src, ptr_val, new_val, elem_ty); | 21596 | try sema.storePtrVal(block, src, ptr_val, new_val, elem_ty); |
| ... | @@ -21623,8 +21664,9 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -21623,8 +21664,9 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 21623 | const maybe_mulend1 = try sema.resolveMaybeUndefVal(mulend1); | 21664 | const maybe_mulend1 = try sema.resolveMaybeUndefVal(mulend1); |
| 21624 | const maybe_mulend2 = try sema.resolveMaybeUndefVal(mulend2); | 21665 | const maybe_mulend2 = try sema.resolveMaybeUndefVal(mulend2); |
| 21625 | const maybe_addend = try sema.resolveMaybeUndefVal(addend); | 21666 | const maybe_addend = try sema.resolveMaybeUndefVal(addend); |
| 21667 | const mod = sema.mod; | ||
| 21626 | 21668 | ||
| 21627 | switch (ty.zigTypeTag()) { | 21669 | switch (ty.zigTypeTag(mod)) { |
| 21628 | .ComptimeFloat, .Float, .Vector => {}, | 21670 | .ComptimeFloat, .Float, .Vector => {}, |
| 21629 | else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty.fmt(sema.mod)}), | 21671 | else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty.fmt(sema.mod)}), |
| 21630 | } | 21672 | } |
| ... | @@ -21743,7 +21785,6 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -21743,7 +21785,6 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 21743 | 21785 | ||
| 21744 | const callee_ty = sema.typeOf(func); | 21786 | const callee_ty = sema.typeOf(func); |
| 21745 | const func_ty = try sema.checkCallArgumentCount(block, func, func_src, callee_ty, resolved_args.len, false); | 21787 | const func_ty = try sema.checkCallArgumentCount(block, func, func_src, callee_ty, resolved_args.len, false); |
| 21746 | |||
| 21747 | const ensure_result_used = extra.flags.ensure_result_used; | 21788 | const ensure_result_used = extra.flags.ensure_result_used; |
| 21748 | return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, null, null); | 21789 | return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, null, null); |
| 21749 | } | 21790 | } |
| ... | @@ -21760,13 +21801,14 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -21760,13 +21801,14 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 21760 | const field_name = try sema.resolveConstString(block, name_src, extra.field_name, "field name must be comptime-known"); | 21801 | const field_name = try sema.resolveConstString(block, name_src, extra.field_name, "field name must be comptime-known"); |
| 21761 | const field_ptr = try sema.resolveInst(extra.field_ptr); | 21802 | const field_ptr = try sema.resolveInst(extra.field_ptr); |
| 21762 | const field_ptr_ty = sema.typeOf(field_ptr); | 21803 | const field_ptr_ty = sema.typeOf(field_ptr); |
| 21804 | const mod = sema.mod; | ||
| 21763 | 21805 | ||
| 21764 | if (parent_ty.zigTypeTag() != .Struct and parent_ty.zigTypeTag() != .Union) { | 21806 | if (parent_ty.zigTypeTag(mod) != .Struct and parent_ty.zigTypeTag(mod) != .Union) { |
| 21765 | return sema.fail(block, ty_src, "expected struct or union type, found '{}'", .{parent_ty.fmt(sema.mod)}); | 21807 | return sema.fail(block, ty_src, "expected struct or union type, found '{}'", .{parent_ty.fmt(sema.mod)}); |
| 21766 | } | 21808 | } |
| 21767 | try sema.resolveTypeLayout(parent_ty); | 21809 | try sema.resolveTypeLayout(parent_ty); |
| 21768 | 21810 | ||
| 21769 | const field_index = switch (parent_ty.zigTypeTag()) { | 21811 | const field_index = switch (parent_ty.zigTypeTag(mod)) { |
| 21770 | .Struct => blk: { | 21812 | .Struct => blk: { |
| 21771 | if (parent_ty.isTuple()) { | 21813 | if (parent_ty.isTuple()) { |
| 21772 | if (mem.eql(u8, field_name, "len")) { | 21814 | if (mem.eql(u8, field_name, "len")) { |
| ... | @@ -21781,7 +21823,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -21781,7 +21823,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 21781 | else => unreachable, | 21823 | else => unreachable, |
| 21782 | }; | 21824 | }; |
| 21783 | 21825 | ||
| 21784 | if (parent_ty.zigTypeTag() == .Struct and parent_ty.structFieldIsComptime(field_index)) { | 21826 | if (parent_ty.zigTypeTag(mod) == .Struct and parent_ty.structFieldIsComptime(field_index)) { |
| 21785 | return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{}); | 21827 | return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{}); |
| 21786 | } | 21828 | } |
| 21787 | 21829 | ||
| ... | @@ -21913,15 +21955,14 @@ fn analyzeMinMax( | ... | @@ -21913,15 +21955,14 @@ fn analyzeMinMax( |
| 21913 | ) CompileError!Air.Inst.Ref { | 21955 | ) CompileError!Air.Inst.Ref { |
| 21914 | assert(operands.len == operand_srcs.len); | 21956 | assert(operands.len == operand_srcs.len); |
| 21915 | assert(operands.len > 0); | 21957 | assert(operands.len > 0); |
| 21958 | const mod = sema.mod; | ||
| 21916 | 21959 | ||
| 21917 | if (operands.len == 1) return operands[0]; | 21960 | if (operands.len == 1) return operands[0]; |
| 21918 | 21961 | ||
| 21919 | const mod = sema.mod; | ||
| 21920 | const target = mod.getTarget(); | ||
| 21921 | const opFunc = switch (air_tag) { | 21962 | const opFunc = switch (air_tag) { |
| 21922 | .min => Value.numberMin, | 21963 | .min => Value.numberMin, |
| 21923 | .max => Value.numberMax, | 21964 | .max => Value.numberMax, |
| 21924 | else => unreachable, | 21965 | else => @compileError("unreachable"), |
| 21925 | }; | 21966 | }; |
| 21926 | 21967 | ||
| 21927 | // First, find all comptime-known arguments, and get their min/max | 21968 | // First, find all comptime-known arguments, and get their min/max |
| ... | @@ -21949,7 +21990,7 @@ fn analyzeMinMax( | ... | @@ -21949,7 +21990,7 @@ fn analyzeMinMax( |
| 21949 | try sema.resolveLazyValue(operand_val); | 21990 | try sema.resolveLazyValue(operand_val); |
| 21950 | 21991 | ||
| 21951 | const vec_len = simd_op.len orelse { | 21992 | const vec_len = simd_op.len orelse { |
| 21952 | const result_val = opFunc(cur_val, operand_val, target); | 21993 | const result_val = opFunc(cur_val, operand_val, mod); |
| 21953 | cur_minmax = try sema.addConstant(simd_op.result_ty, result_val); | 21994 | cur_minmax = try sema.addConstant(simd_op.result_ty, result_val); |
| 21954 | continue; | 21995 | continue; |
| 21955 | }; | 21996 | }; |
| ... | @@ -21959,7 +22000,7 @@ fn analyzeMinMax( | ... | @@ -21959,7 +22000,7 @@ fn analyzeMinMax( |
| 21959 | for (elems, 0..) |*elem, i| { | 22000 | for (elems, 0..) |*elem, i| { |
| 21960 | const lhs_elem_val = cur_val.elemValueBuffer(mod, i, &lhs_buf); | 22001 | const lhs_elem_val = cur_val.elemValueBuffer(mod, i, &lhs_buf); |
| 21961 | const rhs_elem_val = operand_val.elemValueBuffer(mod, i, &rhs_buf); | 22002 | const rhs_elem_val = operand_val.elemValueBuffer(mod, i, &rhs_buf); |
| 21962 | elem.* = opFunc(lhs_elem_val, rhs_elem_val, target); | 22003 | elem.* = opFunc(lhs_elem_val, rhs_elem_val, mod); |
| 21963 | } | 22004 | } |
| 21964 | cur_minmax = try sema.addConstant( | 22005 | cur_minmax = try sema.addConstant( |
| 21965 | simd_op.result_ty, | 22006 | simd_op.result_ty, |
| ... | @@ -21984,7 +22025,7 @@ fn analyzeMinMax( | ... | @@ -21984,7 +22025,7 @@ fn analyzeMinMax( |
| 21984 | break :refined orig_ty; | 22025 | break :refined orig_ty; |
| 21985 | } | 22026 | } |
| 21986 | 22027 | ||
| 21987 | const refined_ty = if (orig_ty.zigTypeTag() == .Vector) blk: { | 22028 | const refined_ty = if (orig_ty.zigTypeTag(mod) == .Vector) blk: { |
| 21988 | const elem_ty = orig_ty.childType(); | 22029 | const elem_ty = orig_ty.childType(); |
| 21989 | const len = orig_ty.vectorLen(); | 22030 | const len = orig_ty.vectorLen(); |
| 21990 | 22031 | ||
| ... | @@ -21996,16 +22037,16 @@ fn analyzeMinMax( | ... | @@ -21996,16 +22037,16 @@ fn analyzeMinMax( |
| 21996 | for (1..len) |idx| { | 22037 | for (1..len) |idx| { |
| 21997 | const elem_val = try val.elemValue(mod, sema.arena, idx); | 22038 | const elem_val = try val.elemValue(mod, sema.arena, idx); |
| 21998 | if (elem_val.isUndef()) break :blk orig_ty; // can't refine undef | 22039 | if (elem_val.isUndef()) break :blk orig_ty; // can't refine undef |
| 21999 | if (Value.order(elem_val, cur_min, target).compare(.lt)) cur_min = elem_val; | 22040 | if (Value.order(elem_val, cur_min, mod).compare(.lt)) cur_min = elem_val; |
| 22000 | if (Value.order(elem_val, cur_max, target).compare(.gt)) cur_max = elem_val; | 22041 | if (Value.order(elem_val, cur_max, mod).compare(.gt)) cur_max = elem_val; |
| 22001 | } | 22042 | } |
| 22002 | 22043 | ||
| 22003 | const refined_elem_ty = try Type.intFittingRange(target, sema.arena, cur_min, cur_max); | 22044 | const refined_elem_ty = try mod.intFittingRange(cur_min, cur_max); |
| 22004 | break :blk try Type.vector(sema.arena, len, refined_elem_ty); | 22045 | break :blk try Type.vector(sema.arena, len, refined_elem_ty); |
| 22005 | } else blk: { | 22046 | } else blk: { |
| 22006 | if (orig_ty.isAnyFloat()) break :blk orig_ty; // can't refine floats | 22047 | if (orig_ty.isAnyFloat()) break :blk orig_ty; // can't refine floats |
| 22007 | if (val.isUndef()) break :blk orig_ty; // can't refine undef | 22048 | if (val.isUndef()) break :blk orig_ty; // can't refine undef |
| 22008 | break :blk try Type.intFittingRange(target, sema.arena, val, val); | 22049 | break :blk try mod.intFittingRange(val, val); |
| 22009 | }; | 22050 | }; |
| 22010 | 22051 | ||
| 22011 | // Apply the refined type to the current value - this isn't strictly necessary in the | 22052 | // Apply the refined type to the current value - this isn't strictly necessary in the |
| ... | @@ -22061,7 +22102,7 @@ fn analyzeMinMax( | ... | @@ -22061,7 +22102,7 @@ fn analyzeMinMax( |
| 22061 | // Finally, refine the type based on the comptime-known bound. | 22102 | // Finally, refine the type based on the comptime-known bound. |
| 22062 | if (known_undef) break :refine; // can't refine undef | 22103 | if (known_undef) break :refine; // can't refine undef |
| 22063 | const unrefined_ty = sema.typeOf(cur_minmax.?); | 22104 | const unrefined_ty = sema.typeOf(cur_minmax.?); |
| 22064 | const is_vector = unrefined_ty.zigTypeTag() == .Vector; | 22105 | const is_vector = unrefined_ty.zigTypeTag(mod) == .Vector; |
| 22065 | const comptime_elem_ty = if (is_vector) comptime_ty.childType() else comptime_ty; | 22106 | const comptime_elem_ty = if (is_vector) comptime_ty.childType() else comptime_ty; |
| 22066 | const unrefined_elem_ty = if (is_vector) unrefined_ty.childType() else unrefined_ty; | 22107 | const unrefined_elem_ty = if (is_vector) unrefined_ty.childType() else unrefined_ty; |
| 22067 | 22108 | ||
| ... | @@ -22069,18 +22110,18 @@ fn analyzeMinMax( | ... | @@ -22069,18 +22110,18 @@ fn analyzeMinMax( |
| 22069 | 22110 | ||
| 22070 | // Compute the final bounds based on the runtime type and the comptime-known bound type | 22111 | // Compute the final bounds based on the runtime type and the comptime-known bound type |
| 22071 | const min_val = switch (air_tag) { | 22112 | const min_val = switch (air_tag) { |
| 22072 | .min => try unrefined_elem_ty.minInt(sema.arena, target), | 22113 | .min => try unrefined_elem_ty.minInt(sema.arena, mod), |
| 22073 | .max => try comptime_elem_ty.minInt(sema.arena, target), // @max(ct, rt) >= ct | 22114 | .max => try comptime_elem_ty.minInt(sema.arena, mod), // @max(ct, rt) >= ct |
| 22074 | else => unreachable, | 22115 | else => unreachable, |
| 22075 | }; | 22116 | }; |
| 22076 | const max_val = switch (air_tag) { | 22117 | const max_val = switch (air_tag) { |
| 22077 | .min => try comptime_elem_ty.maxInt(sema.arena, target), // @min(ct, rt) <= ct | 22118 | .min => try comptime_elem_ty.maxInt(sema.arena, mod), // @min(ct, rt) <= ct |
| 22078 | .max => try unrefined_elem_ty.maxInt(sema.arena, target), | 22119 | .max => try unrefined_elem_ty.maxInt(sema.arena, mod), |
| 22079 | else => unreachable, | 22120 | else => unreachable, |
| 22080 | }; | 22121 | }; |
| 22081 | 22122 | ||
| 22082 | // Find the smallest type which can contain these bounds | 22123 | // Find the smallest type which can contain these bounds |
| 22083 | const final_elem_ty = try Type.intFittingRange(target, sema.arena, min_val, max_val); | 22124 | const final_elem_ty = try mod.intFittingRange(min_val, max_val); |
| 22084 | 22125 | ||
| 22085 | const final_ty = if (is_vector) | 22126 | const final_ty = if (is_vector) |
| 22086 | try Type.vector(sema.arena, unrefined_ty.vectorLen(), final_elem_ty) | 22127 | try Type.vector(sema.arena, unrefined_ty.vectorLen(), final_elem_ty) |
| ... | @@ -22132,6 +22173,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22132,6 +22173,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22132 | const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr); | 22173 | const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr); |
| 22133 | const src_len = try indexablePtrLenOrNone(sema, block, src_src, src_ptr); | 22174 | const src_len = try indexablePtrLenOrNone(sema, block, src_src, src_ptr); |
| 22134 | const target = sema.mod.getTarget(); | 22175 | const target = sema.mod.getTarget(); |
| 22176 | const mod = sema.mod; | ||
| 22135 | 22177 | ||
| 22136 | if (dest_ty.isConstPtr()) { | 22178 | if (dest_ty.isConstPtr()) { |
| 22137 | return sema.fail(block, dest_src, "cannot memcpy to constant pointer", .{}); | 22179 | return sema.fail(block, dest_src, "cannot memcpy to constant pointer", .{}); |
| ... | @@ -22196,7 +22238,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22196,7 +22238,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22196 | const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: { | 22238 | const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: { |
| 22197 | if (!dest_ptr_val.isComptimeMutablePtr()) break :rs dest_src; | 22239 | if (!dest_ptr_val.isComptimeMutablePtr()) break :rs dest_src; |
| 22198 | if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| { | 22240 | if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| { |
| 22199 | const len_u64 = (try len_val.?.getUnsignedIntAdvanced(target, sema)).?; | 22241 | const len_u64 = (try len_val.?.getUnsignedIntAdvanced(mod, sema)).?; |
| 22200 | const len = try sema.usizeCast(block, dest_src, len_u64); | 22242 | const len = try sema.usizeCast(block, dest_src, len_u64); |
| 22201 | for (0..len) |i| { | 22243 | for (0..len) |i| { |
| 22202 | const elem_index = try sema.addIntUnsigned(Type.usize, i); | 22244 | const elem_index = try sema.addIntUnsigned(Type.usize, i); |
| ... | @@ -22239,12 +22281,12 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22239,12 +22281,12 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22239 | // lowering. The AIR instruction requires pointers with element types of | 22281 | // lowering. The AIR instruction requires pointers with element types of |
| 22240 | // equal ABI size. | 22282 | // equal ABI size. |
| 22241 | 22283 | ||
| 22242 | if (dest_ty.zigTypeTag() != .Pointer or src_ty.zigTypeTag() != .Pointer) { | 22284 | if (dest_ty.zigTypeTag(mod) != .Pointer or src_ty.zigTypeTag(mod) != .Pointer) { |
| 22243 | return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the source or destination iterable is a tuple", .{}); | 22285 | return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the source or destination iterable is a tuple", .{}); |
| 22244 | } | 22286 | } |
| 22245 | 22287 | ||
| 22246 | const dest_elem_ty = dest_ty.elemType2(); | 22288 | const dest_elem_ty = dest_ty.elemType2(mod); |
| 22247 | const src_elem_ty = src_ty.elemType2(); | 22289 | const src_elem_ty = src_ty.elemType2(mod); |
| 22248 | if (.ok != try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, true, target, dest_src, src_src)) { | 22290 | if (.ok != try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, true, target, dest_src, src_src)) { |
| 22249 | return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the element types have different ABI sizes", .{}); | 22291 | return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the element types have different ABI sizes", .{}); |
| 22250 | } | 22292 | } |
| ... | @@ -22255,7 +22297,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22255,7 +22297,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22255 | var new_dest_ptr = dest_ptr; | 22297 | var new_dest_ptr = dest_ptr; |
| 22256 | var new_src_ptr = src_ptr; | 22298 | var new_src_ptr = src_ptr; |
| 22257 | if (len_val) |val| { | 22299 | if (len_val) |val| { |
| 22258 | const len = val.toUnsignedInt(target); | 22300 | const len = val.toUnsignedInt(mod); |
| 22259 | if (len == 0) { | 22301 | if (len == 0) { |
| 22260 | // This AIR instruction guarantees length > 0 if it is comptime-known. | 22302 | // This AIR instruction guarantees length > 0 if it is comptime-known. |
| 22261 | return; | 22303 | return; |
| ... | @@ -22320,6 +22362,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22320,6 +22362,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22320 | } | 22362 | } |
| 22321 | 22363 | ||
| 22322 | fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 22364 | fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 22365 | const mod = sema.mod; | ||
| 22323 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 22366 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 22324 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 22367 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 22325 | const src = inst_data.src(); | 22368 | const src = inst_data.src(); |
| ... | @@ -22334,14 +22377,13 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22334,14 +22377,13 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22334 | return sema.fail(block, dest_src, "cannot memset constant pointer", .{}); | 22377 | return sema.fail(block, dest_src, "cannot memset constant pointer", .{}); |
| 22335 | } | 22378 | } |
| 22336 | 22379 | ||
| 22337 | const dest_elem_ty = dest_ptr_ty.elemType2(); | 22380 | const dest_elem_ty = dest_ptr_ty.elemType2(mod); |
| 22338 | const target = sema.mod.getTarget(); | ||
| 22339 | 22381 | ||
| 22340 | const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: { | 22382 | const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: { |
| 22341 | const len_air_ref = try sema.fieldVal(block, src, dest_ptr, "len", dest_src); | 22383 | const len_air_ref = try sema.fieldVal(block, src, dest_ptr, "len", dest_src); |
| 22342 | const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse | 22384 | const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse |
| 22343 | break :rs dest_src; | 22385 | break :rs dest_src; |
| 22344 | const len_u64 = (try len_val.getUnsignedIntAdvanced(target, sema)).?; | 22386 | const len_u64 = (try len_val.getUnsignedIntAdvanced(mod, sema)).?; |
| 22345 | const len = try sema.usizeCast(block, dest_src, len_u64); | 22387 | const len = try sema.usizeCast(block, dest_src, len_u64); |
| 22346 | if (len == 0) { | 22388 | if (len == 0) { |
| 22347 | // This AIR instruction guarantees length > 0 if it is comptime-known. | 22389 | // This AIR instruction guarantees length > 0 if it is comptime-known. |
| ... | @@ -22499,9 +22541,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -22499,9 +22541,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 22499 | const tracy = trace(@src()); | 22541 | const tracy = trace(@src()); |
| 22500 | defer tracy.end(); | 22542 | defer tracy.end(); |
| 22501 | 22543 | ||
| 22544 | const mod = sema.mod; | ||
| 22502 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 22545 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 22503 | const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); | 22546 | const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); |
| 22504 | const target = sema.mod.getTarget(); | 22547 | const target = mod.getTarget(); |
| 22505 | 22548 | ||
| 22506 | const align_src: LazySrcLoc = .{ .node_offset_fn_type_align = inst_data.src_node }; | 22549 | const align_src: LazySrcLoc = .{ .node_offset_fn_type_align = inst_data.src_node }; |
| 22507 | const addrspace_src: LazySrcLoc = .{ .node_offset_fn_type_addrspace = inst_data.src_node }; | 22550 | const addrspace_src: LazySrcLoc = .{ .node_offset_fn_type_addrspace = inst_data.src_node }; |
| ... | @@ -22535,7 +22578,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -22535,7 +22578,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 22535 | if (val.tag() == .generic_poison) { | 22578 | if (val.tag() == .generic_poison) { |
| 22536 | break :blk null; | 22579 | break :blk null; |
| 22537 | } | 22580 | } |
| 22538 | const alignment = @intCast(u32, val.toUnsignedInt(target)); | 22581 | const alignment = @intCast(u32, val.toUnsignedInt(mod)); |
| 22539 | try sema.validateAlign(block, align_src, alignment); | 22582 | try sema.validateAlign(block, align_src, alignment); |
| 22540 | if (alignment == target_util.defaultFunctionAlignment(target)) { | 22583 | if (alignment == target_util.defaultFunctionAlignment(target)) { |
| 22541 | break :blk 0; | 22584 | break :blk 0; |
| ... | @@ -22551,7 +22594,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -22551,7 +22594,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 22551 | }, | 22594 | }, |
| 22552 | else => |e| return e, | 22595 | else => |e| return e, |
| 22553 | }; | 22596 | }; |
| 22554 | const alignment = @intCast(u32, align_tv.val.toUnsignedInt(target)); | 22597 | const alignment = @intCast(u32, align_tv.val.toUnsignedInt(mod)); |
| 22555 | try sema.validateAlign(block, align_src, alignment); | 22598 | try sema.validateAlign(block, align_src, alignment); |
| 22556 | if (alignment == target_util.defaultFunctionAlignment(target)) { | 22599 | if (alignment == target_util.defaultFunctionAlignment(target)) { |
| 22557 | break :blk 0; | 22600 | break :blk 0; |
| ... | @@ -22642,8 +22685,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -22642,8 +22685,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 22642 | extra_index += body.len; | 22685 | extra_index += body.len; |
| 22643 | 22686 | ||
| 22644 | const val = try sema.resolveGenericBody(block, ret_src, body, inst, Type.type, "return type must be comptime-known"); | 22687 | const val = try sema.resolveGenericBody(block, ret_src, body, inst, Type.type, "return type must be comptime-known"); |
| 22645 | var buffer: Value.ToTypeBuffer = undefined; | 22688 | const ty = try val.toType().copy(sema.arena); |
| 22646 | const ty = try val.toType(&buffer).copy(sema.arena); | ||
| 22647 | break :blk ty; | 22689 | break :blk ty; |
| 22648 | } else if (extra.data.bits.has_ret_ty_ref) blk: { | 22690 | } else if (extra.data.bits.has_ret_ty_ref) blk: { |
| 22649 | const ret_ty_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 22691 | const ret_ty_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| ... | @@ -22654,8 +22696,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -22654,8 +22696,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 22654 | }, | 22696 | }, |
| 22655 | else => |e| return e, | 22697 | else => |e| return e, |
| 22656 | }; | 22698 | }; |
| 22657 | var buffer: Value.ToTypeBuffer = undefined; | 22699 | const ty = try ret_ty_tv.val.toType().copy(sema.arena); |
| 22658 | const ty = try ret_ty_tv.val.toType(&buffer).copy(sema.arena); | ||
| 22659 | break :blk ty; | 22700 | break :blk ty; |
| 22660 | } else Type.void; | 22701 | } else Type.void; |
| 22661 | 22702 | ||
| ... | @@ -22727,13 +22768,14 @@ fn zirCDefine( | ... | @@ -22727,13 +22768,14 @@ fn zirCDefine( |
| 22727 | block: *Block, | 22768 | block: *Block, |
| 22728 | extended: Zir.Inst.Extended.InstData, | 22769 | extended: Zir.Inst.Extended.InstData, |
| 22729 | ) CompileError!Air.Inst.Ref { | 22770 | ) CompileError!Air.Inst.Ref { |
| 22771 | const mod = sema.mod; | ||
| 22730 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; | 22772 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 22731 | const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 22773 | const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 22732 | const val_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; | 22774 | const val_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; |
| 22733 | 22775 | ||
| 22734 | const name = try sema.resolveConstString(block, name_src, extra.lhs, "name of macro being undefined must be comptime-known"); | 22776 | const name = try sema.resolveConstString(block, name_src, extra.lhs, "name of macro being undefined must be comptime-known"); |
| 22735 | const rhs = try sema.resolveInst(extra.rhs); | 22777 | const rhs = try sema.resolveInst(extra.rhs); |
| 22736 | if (sema.typeOf(rhs).zigTypeTag() != .Void) { | 22778 | if (sema.typeOf(rhs).zigTypeTag(mod) != .Void) { |
| 22737 | const value = try sema.resolveConstString(block, val_src, extra.rhs, "value of macro being undefined must be comptime-known"); | 22779 | const value = try sema.resolveConstString(block, val_src, extra.rhs, "value of macro being undefined must be comptime-known"); |
| 22738 | try block.c_import_buf.?.writer().print("#define {s} {s}\n", .{ name, value }); | 22780 | try block.c_import_buf.?.writer().print("#define {s} {s}\n", .{ name, value }); |
| 22739 | } else { | 22781 | } else { |
| ... | @@ -22799,9 +22841,9 @@ fn resolvePrefetchOptions( | ... | @@ -22799,9 +22841,9 @@ fn resolvePrefetchOptions( |
| 22799 | src: LazySrcLoc, | 22841 | src: LazySrcLoc, |
| 22800 | zir_ref: Zir.Inst.Ref, | 22842 | zir_ref: Zir.Inst.Ref, |
| 22801 | ) CompileError!std.builtin.PrefetchOptions { | 22843 | ) CompileError!std.builtin.PrefetchOptions { |
| 22844 | const mod = sema.mod; | ||
| 22802 | const options_ty = try sema.getBuiltinType("PrefetchOptions"); | 22845 | const options_ty = try sema.getBuiltinType("PrefetchOptions"); |
| 22803 | const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src); | 22846 | const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src); |
| 22804 | const target = sema.mod.getTarget(); | ||
| 22805 | 22847 | ||
| 22806 | const rw_src = sema.maybeOptionsSrc(block, src, "rw"); | 22848 | const rw_src = sema.maybeOptionsSrc(block, src, "rw"); |
| 22807 | const locality_src = sema.maybeOptionsSrc(block, src, "locality"); | 22849 | const locality_src = sema.maybeOptionsSrc(block, src, "locality"); |
| ... | @@ -22818,7 +22860,7 @@ fn resolvePrefetchOptions( | ... | @@ -22818,7 +22860,7 @@ fn resolvePrefetchOptions( |
| 22818 | 22860 | ||
| 22819 | return std.builtin.PrefetchOptions{ | 22861 | return std.builtin.PrefetchOptions{ |
| 22820 | .rw = rw_val.toEnum(std.builtin.PrefetchOptions.Rw), | 22862 | .rw = rw_val.toEnum(std.builtin.PrefetchOptions.Rw), |
| 22821 | .locality = @intCast(u2, locality_val.toUnsignedInt(target)), | 22863 | .locality = @intCast(u2, locality_val.toUnsignedInt(mod)), |
| 22822 | .cache = cache_val.toEnum(std.builtin.PrefetchOptions.Cache), | 22864 | .cache = cache_val.toEnum(std.builtin.PrefetchOptions.Cache), |
| 22823 | }; | 22865 | }; |
| 22824 | } | 22866 | } |
| ... | @@ -22887,7 +22929,7 @@ fn resolveExternOptions( | ... | @@ -22887,7 +22929,7 @@ fn resolveExternOptions( |
| 22887 | const is_thread_local = try sema.fieldVal(block, src, options, "is_thread_local", thread_local_src); | 22929 | const is_thread_local = try sema.fieldVal(block, src, options, "is_thread_local", thread_local_src); |
| 22888 | const is_thread_local_val = try sema.resolveConstValue(block, thread_local_src, is_thread_local, "threadlocality of the extern symbol must be comptime-known"); | 22930 | const is_thread_local_val = try sema.resolveConstValue(block, thread_local_src, is_thread_local, "threadlocality of the extern symbol must be comptime-known"); |
| 22889 | 22931 | ||
| 22890 | const library_name = if (!library_name_val.isNull()) blk: { | 22932 | const library_name = if (!library_name_val.isNull(mod)) blk: { |
| 22891 | const payload = library_name_val.castTag(.opt_payload).?.data; | 22933 | const payload = library_name_val.castTag(.opt_payload).?.data; |
| 22892 | const library_name = try payload.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod); | 22934 | const library_name = try payload.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod); |
| 22893 | if (library_name.len == 0) { | 22935 | if (library_name.len == 0) { |
| ... | @@ -22917,17 +22959,17 @@ fn zirBuiltinExtern( | ... | @@ -22917,17 +22959,17 @@ fn zirBuiltinExtern( |
| 22917 | block: *Block, | 22959 | block: *Block, |
| 22918 | extended: Zir.Inst.Extended.InstData, | 22960 | extended: Zir.Inst.Extended.InstData, |
| 22919 | ) CompileError!Air.Inst.Ref { | 22961 | ) CompileError!Air.Inst.Ref { |
| 22962 | const mod = sema.mod; | ||
| 22920 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; | 22963 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 22921 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 22964 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 22922 | const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; | 22965 | const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; |
| 22923 | 22966 | ||
| 22924 | var ty = try sema.resolveType(block, ty_src, extra.lhs); | 22967 | var ty = try sema.resolveType(block, ty_src, extra.lhs); |
| 22925 | if (!ty.isPtrAtRuntime()) { | 22968 | if (!ty.isPtrAtRuntime(mod)) { |
| 22926 | return sema.fail(block, ty_src, "expected (optional) pointer", .{}); | 22969 | return sema.fail(block, ty_src, "expected (optional) pointer", .{}); |
| 22927 | } | 22970 | } |
| 22928 | if (!try sema.validateExternType(ty.childType(), .other)) { | 22971 | if (!try sema.validateExternType(ty.childType(), .other)) { |
| 22929 | const msg = msg: { | 22972 | const msg = msg: { |
| 22930 | const mod = sema.mod; | ||
| 22931 | const msg = try sema.errMsg(block, ty_src, "extern symbol cannot have type '{}'", .{ty.fmt(mod)}); | 22973 | const msg = try sema.errMsg(block, ty_src, "extern symbol cannot have type '{}'", .{ty.fmt(mod)}); |
| 22932 | errdefer msg.destroy(sema.gpa); | 22974 | errdefer msg.destroy(sema.gpa); |
| 22933 | const src_decl = sema.mod.declPtr(block.src_decl); | 22975 | const src_decl = sema.mod.declPtr(block.src_decl); |
| ... | @@ -22945,7 +22987,7 @@ fn zirBuiltinExtern( | ... | @@ -22945,7 +22987,7 @@ fn zirBuiltinExtern( |
| 22945 | else => |e| return e, | 22987 | else => |e| return e, |
| 22946 | }; | 22988 | }; |
| 22947 | 22989 | ||
| 22948 | if (options.linkage == .Weak and !ty.ptrAllowsZero()) { | 22990 | if (options.linkage == .Weak and !ty.ptrAllowsZero(mod)) { |
| 22949 | ty = try Type.optional(sema.arena, ty); | 22991 | ty = try Type.optional(sema.arena, ty); |
| 22950 | } | 22992 | } |
| 22951 | 22993 | ||
| ... | @@ -23087,7 +23129,7 @@ fn validateVarType( | ... | @@ -23087,7 +23129,7 @@ fn validateVarType( |
| 23087 | 23129 | ||
| 23088 | const src_decl = mod.declPtr(block.src_decl); | 23130 | const src_decl = mod.declPtr(block.src_decl); |
| 23089 | try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl), var_ty); | 23131 | try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl), var_ty); |
| 23090 | if (var_ty.zigTypeTag() == .ComptimeInt or var_ty.zigTypeTag() == .ComptimeFloat) { | 23132 | if (var_ty.zigTypeTag(mod) == .ComptimeInt or var_ty.zigTypeTag(mod) == .ComptimeFloat) { |
| 23091 | try sema.errNote(block, src, msg, "to modify this variable at runtime, it must be given an explicit fixed-size number type", .{}); | 23133 | try sema.errNote(block, src, msg, "to modify this variable at runtime, it must be given an explicit fixed-size number type", .{}); |
| 23092 | } | 23134 | } |
| 23093 | 23135 | ||
| ... | @@ -23101,8 +23143,9 @@ fn validateRunTimeType( | ... | @@ -23101,8 +23143,9 @@ fn validateRunTimeType( |
| 23101 | var_ty: Type, | 23143 | var_ty: Type, |
| 23102 | is_extern: bool, | 23144 | is_extern: bool, |
| 23103 | ) CompileError!bool { | 23145 | ) CompileError!bool { |
| 23146 | const mod = sema.mod; | ||
| 23104 | var ty = var_ty; | 23147 | var ty = var_ty; |
| 23105 | while (true) switch (ty.zigTypeTag()) { | 23148 | while (true) switch (ty.zigTypeTag(mod)) { |
| 23106 | .Bool, | 23149 | .Bool, |
| 23107 | .Int, | 23150 | .Int, |
| 23108 | .Float, | 23151 | .Float, |
| ... | @@ -23126,9 +23169,9 @@ fn validateRunTimeType( | ... | @@ -23126,9 +23169,9 @@ fn validateRunTimeType( |
| 23126 | 23169 | ||
| 23127 | .Pointer => { | 23170 | .Pointer => { |
| 23128 | const elem_ty = ty.childType(); | 23171 | const elem_ty = ty.childType(); |
| 23129 | switch (elem_ty.zigTypeTag()) { | 23172 | switch (elem_ty.zigTypeTag(mod)) { |
| 23130 | .Opaque => return true, | 23173 | .Opaque => return true, |
| 23131 | .Fn => return elem_ty.isFnOrHasRuntimeBits(), | 23174 | .Fn => return elem_ty.isFnOrHasRuntimeBits(mod), |
| 23132 | else => ty = elem_ty, | 23175 | else => ty = elem_ty, |
| 23133 | } | 23176 | } |
| 23134 | }, | 23177 | }, |
| ... | @@ -23174,7 +23217,7 @@ fn explainWhyTypeIsComptimeInner( | ... | @@ -23174,7 +23217,7 @@ fn explainWhyTypeIsComptimeInner( |
| 23174 | type_set: *TypeSet, | 23217 | type_set: *TypeSet, |
| 23175 | ) CompileError!void { | 23218 | ) CompileError!void { |
| 23176 | const mod = sema.mod; | 23219 | const mod = sema.mod; |
| 23177 | switch (ty.zigTypeTag()) { | 23220 | switch (ty.zigTypeTag(mod)) { |
| 23178 | .Bool, | 23221 | .Bool, |
| 23179 | .Int, | 23222 | .Int, |
| 23180 | .Float, | 23223 | .Float, |
| ... | @@ -23211,8 +23254,8 @@ fn explainWhyTypeIsComptimeInner( | ... | @@ -23211,8 +23254,8 @@ fn explainWhyTypeIsComptimeInner( |
| 23211 | try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.elemType(), type_set); | 23254 | try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.elemType(), type_set); |
| 23212 | }, | 23255 | }, |
| 23213 | .Pointer => { | 23256 | .Pointer => { |
| 23214 | const elem_ty = ty.elemType2(); | 23257 | const elem_ty = ty.elemType2(mod); |
| 23215 | if (elem_ty.zigTypeTag() == .Fn) { | 23258 | if (elem_ty.zigTypeTag(mod) == .Fn) { |
| 23216 | const fn_info = elem_ty.fnInfo(); | 23259 | const fn_info = elem_ty.fnInfo(); |
| 23217 | if (fn_info.is_generic) { | 23260 | if (fn_info.is_generic) { |
| 23218 | try mod.errNoteNonLazy(src_loc, msg, "function is generic", .{}); | 23261 | try mod.errNoteNonLazy(src_loc, msg, "function is generic", .{}); |
| ... | @@ -23221,7 +23264,7 @@ fn explainWhyTypeIsComptimeInner( | ... | @@ -23221,7 +23264,7 @@ fn explainWhyTypeIsComptimeInner( |
| 23221 | .Inline => try mod.errNoteNonLazy(src_loc, msg, "function has inline calling convention", .{}), | 23264 | .Inline => try mod.errNoteNonLazy(src_loc, msg, "function has inline calling convention", .{}), |
| 23222 | else => {}, | 23265 | else => {}, |
| 23223 | } | 23266 | } |
| 23224 | if (fn_info.return_type.comptimeOnly()) { | 23267 | if (fn_info.return_type.comptimeOnly(mod)) { |
| 23225 | try mod.errNoteNonLazy(src_loc, msg, "function has a comptime-only return type", .{}); | 23268 | try mod.errNoteNonLazy(src_loc, msg, "function has a comptime-only return type", .{}); |
| 23226 | } | 23269 | } |
| 23227 | return; | 23270 | return; |
| ... | @@ -23295,7 +23338,8 @@ fn validateExternType( | ... | @@ -23295,7 +23338,8 @@ fn validateExternType( |
| 23295 | ty: Type, | 23338 | ty: Type, |
| 23296 | position: ExternPosition, | 23339 | position: ExternPosition, |
| 23297 | ) !bool { | 23340 | ) !bool { |
| 23298 | switch (ty.zigTypeTag()) { | 23341 | const mod = sema.mod; |
| 23342 | switch (ty.zigTypeTag(mod)) { | ||
| 23299 | .Type, | 23343 | .Type, |
| 23300 | .ComptimeFloat, | 23344 | .ComptimeFloat, |
| 23301 | .ComptimeInt, | 23345 | .ComptimeInt, |
| ... | @@ -23314,7 +23358,7 @@ fn validateExternType( | ... | @@ -23314,7 +23358,7 @@ fn validateExternType( |
| 23314 | .AnyFrame, | 23358 | .AnyFrame, |
| 23315 | => return true, | 23359 | => return true, |
| 23316 | .Pointer => return !(ty.isSlice() or try sema.typeRequiresComptime(ty)), | 23360 | .Pointer => return !(ty.isSlice() or try sema.typeRequiresComptime(ty)), |
| 23317 | .Int => switch (ty.intInfo(sema.mod.getTarget()).bits) { | 23361 | .Int => switch (ty.intInfo(mod).bits) { |
| 23318 | 8, 16, 32, 64, 128 => return true, | 23362 | 8, 16, 32, 64, 128 => return true, |
| 23319 | else => return false, | 23363 | else => return false, |
| 23320 | }, | 23364 | }, |
| ... | @@ -23329,14 +23373,12 @@ fn validateExternType( | ... | @@ -23329,14 +23373,12 @@ fn validateExternType( |
| 23329 | return !Type.fnCallingConventionAllowsZigTypes(target, ty.fnCallingConvention()); | 23373 | return !Type.fnCallingConventionAllowsZigTypes(target, ty.fnCallingConvention()); |
| 23330 | }, | 23374 | }, |
| 23331 | .Enum => { | 23375 | .Enum => { |
| 23332 | var buf: Type.Payload.Bits = undefined; | 23376 | return sema.validateExternType(ty.intTagType(), position); |
| 23333 | return sema.validateExternType(ty.intTagType(&buf), position); | ||
| 23334 | }, | 23377 | }, |
| 23335 | .Struct, .Union => switch (ty.containerLayout()) { | 23378 | .Struct, .Union => switch (ty.containerLayout()) { |
| 23336 | .Extern => return true, | 23379 | .Extern => return true, |
| 23337 | .Packed => { | 23380 | .Packed => { |
| 23338 | const target = sema.mod.getTarget(); | 23381 | const bit_size = try ty.bitSizeAdvanced(mod, sema); |
| 23339 | const bit_size = try ty.bitSizeAdvanced(target, sema); | ||
| 23340 | switch (bit_size) { | 23382 | switch (bit_size) { |
| 23341 | 8, 16, 32, 64, 128 => return true, | 23383 | 8, 16, 32, 64, 128 => return true, |
| 23342 | else => return false, | 23384 | else => return false, |
| ... | @@ -23346,10 +23388,10 @@ fn validateExternType( | ... | @@ -23346,10 +23388,10 @@ fn validateExternType( |
| 23346 | }, | 23388 | }, |
| 23347 | .Array => { | 23389 | .Array => { |
| 23348 | if (position == .ret_ty or position == .param_ty) return false; | 23390 | if (position == .ret_ty or position == .param_ty) return false; |
| 23349 | return sema.validateExternType(ty.elemType2(), .element); | 23391 | return sema.validateExternType(ty.elemType2(mod), .element); |
| 23350 | }, | 23392 | }, |
| 23351 | .Vector => return sema.validateExternType(ty.elemType2(), .element), | 23393 | .Vector => return sema.validateExternType(ty.elemType2(mod), .element), |
| 23352 | .Optional => return ty.isPtrLikeOptional(), | 23394 | .Optional => return ty.isPtrLikeOptional(mod), |
| 23353 | } | 23395 | } |
| 23354 | } | 23396 | } |
| 23355 | 23397 | ||
| ... | @@ -23361,7 +23403,7 @@ fn explainWhyTypeIsNotExtern( | ... | @@ -23361,7 +23403,7 @@ fn explainWhyTypeIsNotExtern( |
| 23361 | position: ExternPosition, | 23403 | position: ExternPosition, |
| 23362 | ) CompileError!void { | 23404 | ) CompileError!void { |
| 23363 | const mod = sema.mod; | 23405 | const mod = sema.mod; |
| 23364 | switch (ty.zigTypeTag()) { | 23406 | switch (ty.zigTypeTag(mod)) { |
| 23365 | .Opaque, | 23407 | .Opaque, |
| 23366 | .Bool, | 23408 | .Bool, |
| 23367 | .Float, | 23409 | .Float, |
| ... | @@ -23390,7 +23432,7 @@ fn explainWhyTypeIsNotExtern( | ... | @@ -23390,7 +23432,7 @@ fn explainWhyTypeIsNotExtern( |
| 23390 | }, | 23432 | }, |
| 23391 | .Void => try mod.errNoteNonLazy(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}), | 23433 | .Void => try mod.errNoteNonLazy(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}), |
| 23392 | .NoReturn => try mod.errNoteNonLazy(src_loc, msg, "'noreturn' is only allowed as a return type", .{}), | 23434 | .NoReturn => try mod.errNoteNonLazy(src_loc, msg, "'noreturn' is only allowed as a return type", .{}), |
| 23393 | .Int => if (!std.math.isPowerOfTwo(ty.intInfo(sema.mod.getTarget()).bits)) { | 23435 | .Int => if (!std.math.isPowerOfTwo(ty.intInfo(mod).bits)) { |
| 23394 | try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{}); | 23436 | try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{}); |
| 23395 | } else { | 23437 | } else { |
| 23396 | try mod.errNoteNonLazy(src_loc, msg, "only integers with 8, 16, 32, 64 and 128 bits are extern compatible", .{}); | 23438 | try mod.errNoteNonLazy(src_loc, msg, "only integers with 8, 16, 32, 64 and 128 bits are extern compatible", .{}); |
| ... | @@ -23409,8 +23451,7 @@ fn explainWhyTypeIsNotExtern( | ... | @@ -23409,8 +23451,7 @@ fn explainWhyTypeIsNotExtern( |
| 23409 | } | 23451 | } |
| 23410 | }, | 23452 | }, |
| 23411 | .Enum => { | 23453 | .Enum => { |
| 23412 | var buf: Type.Payload.Bits = undefined; | 23454 | const tag_ty = ty.intTagType(); |
| 23413 | const tag_ty = ty.intTagType(&buf); | ||
| 23414 | try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)}); | 23455 | try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)}); |
| 23415 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); | 23456 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); |
| 23416 | }, | 23457 | }, |
| ... | @@ -23422,17 +23463,17 @@ fn explainWhyTypeIsNotExtern( | ... | @@ -23422,17 +23463,17 @@ fn explainWhyTypeIsNotExtern( |
| 23422 | } else if (position == .param_ty) { | 23463 | } else if (position == .param_ty) { |
| 23423 | return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{}); | 23464 | return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{}); |
| 23424 | } | 23465 | } |
| 23425 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element); | 23466 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(mod), .element); |
| 23426 | }, | 23467 | }, |
| 23427 | .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element), | 23468 | .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(mod), .element), |
| 23428 | .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}), | 23469 | .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}), |
| 23429 | } | 23470 | } |
| 23430 | } | 23471 | } |
| 23431 | 23472 | ||
| 23432 | /// Returns true if `ty` is allowed in packed types. | 23473 | /// Returns true if `ty` is allowed in packed types. |
| 23433 | /// Does *NOT* require `ty` to be resolved in any way. | 23474 | /// Does *NOT* require `ty` to be resolved in any way. |
| 23434 | fn validatePackedType(ty: Type) bool { | 23475 | fn validatePackedType(ty: Type, mod: *const Module) bool { |
| 23435 | switch (ty.zigTypeTag()) { | 23476 | switch (ty.zigTypeTag(mod)) { |
| 23436 | .Type, | 23477 | .Type, |
| 23437 | .ComptimeFloat, | 23478 | .ComptimeFloat, |
| 23438 | .ComptimeInt, | 23479 | .ComptimeInt, |
| ... | @@ -23448,7 +23489,7 @@ fn validatePackedType(ty: Type) bool { | ... | @@ -23448,7 +23489,7 @@ fn validatePackedType(ty: Type) bool { |
| 23448 | .Fn, | 23489 | .Fn, |
| 23449 | .Array, | 23490 | .Array, |
| 23450 | => return false, | 23491 | => return false, |
| 23451 | .Optional => return ty.isPtrLikeOptional(), | 23492 | .Optional => return ty.isPtrLikeOptional(mod), |
| 23452 | .Void, | 23493 | .Void, |
| 23453 | .Bool, | 23494 | .Bool, |
| 23454 | .Float, | 23495 | .Float, |
| ... | @@ -23468,7 +23509,7 @@ fn explainWhyTypeIsNotPacked( | ... | @@ -23468,7 +23509,7 @@ fn explainWhyTypeIsNotPacked( |
| 23468 | ty: Type, | 23509 | ty: Type, |
| 23469 | ) CompileError!void { | 23510 | ) CompileError!void { |
| 23470 | const mod = sema.mod; | 23511 | const mod = sema.mod; |
| 23471 | switch (ty.zigTypeTag()) { | 23512 | switch (ty.zigTypeTag(mod)) { |
| 23472 | .Void, | 23513 | .Void, |
| 23473 | .Bool, | 23514 | .Bool, |
| 23474 | .Float, | 23515 | .Float, |
| ... | @@ -23731,6 +23772,7 @@ fn panicSentinelMismatch( | ... | @@ -23731,6 +23772,7 @@ fn panicSentinelMismatch( |
| 23731 | sentinel_index: Air.Inst.Ref, | 23772 | sentinel_index: Air.Inst.Ref, |
| 23732 | ) !void { | 23773 | ) !void { |
| 23733 | assert(!parent_block.is_comptime); | 23774 | assert(!parent_block.is_comptime); |
| 23775 | const mod = sema.mod; | ||
| 23734 | const expected_sentinel_val = maybe_sentinel orelse return; | 23776 | const expected_sentinel_val = maybe_sentinel orelse return; |
| 23735 | const expected_sentinel = try sema.addConstant(sentinel_ty, expected_sentinel_val); | 23777 | const expected_sentinel = try sema.addConstant(sentinel_ty, expected_sentinel_val); |
| 23736 | 23778 | ||
| ... | @@ -23743,7 +23785,7 @@ fn panicSentinelMismatch( | ... | @@ -23743,7 +23785,7 @@ fn panicSentinelMismatch( |
| 23743 | break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr); | 23785 | break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr); |
| 23744 | }; | 23786 | }; |
| 23745 | 23787 | ||
| 23746 | const ok = if (sentinel_ty.zigTypeTag() == .Vector) ok: { | 23788 | const ok = if (sentinel_ty.zigTypeTag(mod) == .Vector) ok: { |
| 23747 | const eql = | 23789 | const eql = |
| 23748 | try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq); | 23790 | try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq); |
| 23749 | break :ok try parent_block.addInst(.{ | 23791 | break :ok try parent_block.addInst(.{ |
| ... | @@ -23753,7 +23795,7 @@ fn panicSentinelMismatch( | ... | @@ -23753,7 +23795,7 @@ fn panicSentinelMismatch( |
| 23753 | .operation = .And, | 23795 | .operation = .And, |
| 23754 | } }, | 23796 | } }, |
| 23755 | }); | 23797 | }); |
| 23756 | } else if (sentinel_ty.isSelfComparable(true)) | 23798 | } else if (sentinel_ty.isSelfComparable(mod, true)) |
| 23757 | try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel) | 23799 | try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel) |
| 23758 | else { | 23800 | else { |
| 23759 | const panic_fn = try sema.getBuiltin("checkNonScalarSentinel"); | 23801 | const panic_fn = try sema.getBuiltin("checkNonScalarSentinel"); |
| ... | @@ -23848,6 +23890,7 @@ fn fieldVal( | ... | @@ -23848,6 +23890,7 @@ fn fieldVal( |
| 23848 | // When editing this function, note that there is corresponding logic to be edited | 23890 | // When editing this function, note that there is corresponding logic to be edited |
| 23849 | // in `fieldPtr`. This function takes a value and returns a value. | 23891 | // in `fieldPtr`. This function takes a value and returns a value. |
| 23850 | 23892 | ||
| 23893 | const mod = sema.mod; | ||
| 23851 | const arena = sema.arena; | 23894 | const arena = sema.arena; |
| 23852 | const object_src = src; // TODO better source location | 23895 | const object_src = src; // TODO better source location |
| 23853 | const object_ty = sema.typeOf(object); | 23896 | const object_ty = sema.typeOf(object); |
| ... | @@ -23862,7 +23905,7 @@ fn fieldVal( | ... | @@ -23862,7 +23905,7 @@ fn fieldVal( |
| 23862 | else | 23905 | else |
| 23863 | object_ty; | 23906 | object_ty; |
| 23864 | 23907 | ||
| 23865 | switch (inner_ty.zigTypeTag()) { | 23908 | switch (inner_ty.zigTypeTag(mod)) { |
| 23866 | .Array => { | 23909 | .Array => { |
| 23867 | if (mem.eql(u8, field_name, "len")) { | 23910 | if (mem.eql(u8, field_name, "len")) { |
| 23868 | return sema.addConstant( | 23911 | return sema.addConstant( |
| ... | @@ -23926,10 +23969,9 @@ fn fieldVal( | ... | @@ -23926,10 +23969,9 @@ fn fieldVal( |
| 23926 | object; | 23969 | object; |
| 23927 | 23970 | ||
| 23928 | const val = (try sema.resolveDefinedValue(block, object_src, dereffed_type)).?; | 23971 | const val = (try sema.resolveDefinedValue(block, object_src, dereffed_type)).?; |
| 23929 | var to_type_buffer: Value.ToTypeBuffer = undefined; | 23972 | const child_type = val.toType(); |
| 23930 | const child_type = val.toType(&to_type_buffer); | ||
| 23931 | 23973 | ||
| 23932 | switch (try child_type.zigTypeTagOrPoison()) { | 23974 | switch (try child_type.zigTypeTagOrPoison(mod)) { |
| 23933 | .ErrorSet => { | 23975 | .ErrorSet => { |
| 23934 | const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: { | 23976 | const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: { |
| 23935 | if (payload.data.names.getEntry(field_name)) |entry| { | 23977 | if (payload.data.names.getEntry(field_name)) |entry| { |
| ... | @@ -23997,7 +24039,7 @@ fn fieldVal( | ... | @@ -23997,7 +24039,7 @@ fn fieldVal( |
| 23997 | const msg = try sema.errMsg(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}); | 24039 | const msg = try sema.errMsg(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}); |
| 23998 | errdefer msg.destroy(sema.gpa); | 24040 | errdefer msg.destroy(sema.gpa); |
| 23999 | if (child_type.isSlice()) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{}); | 24041 | if (child_type.isSlice()) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{}); |
| 24000 | if (child_type.zigTypeTag() == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{}); | 24042 | if (child_type.zigTypeTag(mod) == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{}); |
| 24001 | break :msg msg; | 24043 | break :msg msg; |
| 24002 | }; | 24044 | }; |
| 24003 | return sema.failWithOwnedErrorMsg(msg); | 24045 | return sema.failWithOwnedErrorMsg(msg); |
| ... | @@ -24035,9 +24077,10 @@ fn fieldPtr( | ... | @@ -24035,9 +24077,10 @@ fn fieldPtr( |
| 24035 | // When editing this function, note that there is corresponding logic to be edited | 24077 | // When editing this function, note that there is corresponding logic to be edited |
| 24036 | // in `fieldVal`. This function takes a pointer and returns a pointer. | 24078 | // in `fieldVal`. This function takes a pointer and returns a pointer. |
| 24037 | 24079 | ||
| 24080 | const mod = sema.mod; | ||
| 24038 | const object_ptr_src = src; // TODO better source location | 24081 | const object_ptr_src = src; // TODO better source location |
| 24039 | const object_ptr_ty = sema.typeOf(object_ptr); | 24082 | const object_ptr_ty = sema.typeOf(object_ptr); |
| 24040 | const object_ty = switch (object_ptr_ty.zigTypeTag()) { | 24083 | const object_ty = switch (object_ptr_ty.zigTypeTag(mod)) { |
| 24041 | .Pointer => object_ptr_ty.elemType(), | 24084 | .Pointer => object_ptr_ty.elemType(), |
| 24042 | else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty.fmt(sema.mod)}), | 24085 | else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty.fmt(sema.mod)}), |
| 24043 | }; | 24086 | }; |
| ... | @@ -24052,7 +24095,7 @@ fn fieldPtr( | ... | @@ -24052,7 +24095,7 @@ fn fieldPtr( |
| 24052 | else | 24095 | else |
| 24053 | object_ty; | 24096 | object_ty; |
| 24054 | 24097 | ||
| 24055 | switch (inner_ty.zigTypeTag()) { | 24098 | switch (inner_ty.zigTypeTag(mod)) { |
| 24056 | .Array => { | 24099 | .Array => { |
| 24057 | if (mem.eql(u8, field_name, "len")) { | 24100 | if (mem.eql(u8, field_name, "len")) { |
| 24058 | var anon_decl = try block.startAnonDecl(); | 24101 | var anon_decl = try block.startAnonDecl(); |
| ... | @@ -24142,10 +24185,9 @@ fn fieldPtr( | ... | @@ -24142,10 +24185,9 @@ fn fieldPtr( |
| 24142 | result; | 24185 | result; |
| 24143 | 24186 | ||
| 24144 | const val = (sema.resolveDefinedValue(block, src, inner) catch unreachable).?; | 24187 | const val = (sema.resolveDefinedValue(block, src, inner) catch unreachable).?; |
| 24145 | var to_type_buffer: Value.ToTypeBuffer = undefined; | 24188 | const child_type = val.toType(); |
| 24146 | const child_type = val.toType(&to_type_buffer); | ||
| 24147 | 24189 | ||
| 24148 | switch (child_type.zigTypeTag()) { | 24190 | switch (child_type.zigTypeTag(mod)) { |
| 24149 | .ErrorSet => { | 24191 | .ErrorSet => { |
| 24150 | // TODO resolve inferred error sets | 24192 | // TODO resolve inferred error sets |
| 24151 | const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: { | 24193 | const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: { |
| ... | @@ -24258,15 +24300,16 @@ fn fieldCallBind( | ... | @@ -24258,15 +24300,16 @@ fn fieldCallBind( |
| 24258 | // When editing this function, note that there is corresponding logic to be edited | 24300 | // When editing this function, note that there is corresponding logic to be edited |
| 24259 | // in `fieldVal`. This function takes a pointer and returns a pointer. | 24301 | // in `fieldVal`. This function takes a pointer and returns a pointer. |
| 24260 | 24302 | ||
| 24303 | const mod = sema.mod; | ||
| 24261 | const raw_ptr_src = src; // TODO better source location | 24304 | const raw_ptr_src = src; // TODO better source location |
| 24262 | const raw_ptr_ty = sema.typeOf(raw_ptr); | 24305 | const raw_ptr_ty = sema.typeOf(raw_ptr); |
| 24263 | const inner_ty = if (raw_ptr_ty.zigTypeTag() == .Pointer and (raw_ptr_ty.ptrSize() == .One or raw_ptr_ty.ptrSize() == .C)) | 24306 | const inner_ty = if (raw_ptr_ty.zigTypeTag(mod) == .Pointer and (raw_ptr_ty.ptrSize() == .One or raw_ptr_ty.ptrSize() == .C)) |
| 24264 | raw_ptr_ty.childType() | 24307 | raw_ptr_ty.childType() |
| 24265 | else | 24308 | else |
| 24266 | return sema.fail(block, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty.fmt(sema.mod)}); | 24309 | return sema.fail(block, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty.fmt(sema.mod)}); |
| 24267 | 24310 | ||
| 24268 | // Optionally dereference a second pointer to get the concrete type. | 24311 | // Optionally dereference a second pointer to get the concrete type. |
| 24269 | const is_double_ptr = inner_ty.zigTypeTag() == .Pointer and inner_ty.ptrSize() == .One; | 24312 | const is_double_ptr = inner_ty.zigTypeTag(mod) == .Pointer and inner_ty.ptrSize() == .One; |
| 24270 | const concrete_ty = if (is_double_ptr) inner_ty.childType() else inner_ty; | 24313 | const concrete_ty = if (is_double_ptr) inner_ty.childType() else inner_ty; |
| 24271 | const ptr_ty = if (is_double_ptr) inner_ty else raw_ptr_ty; | 24314 | const ptr_ty = if (is_double_ptr) inner_ty else raw_ptr_ty; |
| 24272 | const object_ptr = if (is_double_ptr) | 24315 | const object_ptr = if (is_double_ptr) |
| ... | @@ -24275,7 +24318,7 @@ fn fieldCallBind( | ... | @@ -24275,7 +24318,7 @@ fn fieldCallBind( |
| 24275 | raw_ptr; | 24318 | raw_ptr; |
| 24276 | 24319 | ||
| 24277 | find_field: { | 24320 | find_field: { |
| 24278 | switch (concrete_ty.zigTypeTag()) { | 24321 | switch (concrete_ty.zigTypeTag(mod)) { |
| 24279 | .Struct => { | 24322 | .Struct => { |
| 24280 | const struct_ty = try sema.resolveTypeFields(concrete_ty); | 24323 | const struct_ty = try sema.resolveTypeFields(concrete_ty); |
| 24281 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | 24324 | if (struct_ty.castTag(.@"struct")) |struct_obj| { |
| ... | @@ -24321,21 +24364,21 @@ fn fieldCallBind( | ... | @@ -24321,21 +24364,21 @@ fn fieldCallBind( |
| 24321 | } | 24364 | } |
| 24322 | 24365 | ||
| 24323 | // If we get here, we need to look for a decl in the struct type instead. | 24366 | // If we get here, we need to look for a decl in the struct type instead. |
| 24324 | const found_decl = switch (concrete_ty.zigTypeTag()) { | 24367 | const found_decl = switch (concrete_ty.zigTypeTag(mod)) { |
| 24325 | .Struct, .Opaque, .Union, .Enum => found_decl: { | 24368 | .Struct, .Opaque, .Union, .Enum => found_decl: { |
| 24326 | if (concrete_ty.getNamespace()) |namespace| { | 24369 | if (concrete_ty.getNamespace()) |namespace| { |
| 24327 | if (try sema.namespaceLookup(block, src, namespace, field_name)) |decl_idx| { | 24370 | if (try sema.namespaceLookup(block, src, namespace, field_name)) |decl_idx| { |
| 24328 | try sema.addReferencedBy(block, src, decl_idx); | 24371 | try sema.addReferencedBy(block, src, decl_idx); |
| 24329 | const decl_val = try sema.analyzeDeclVal(block, src, decl_idx); | 24372 | const decl_val = try sema.analyzeDeclVal(block, src, decl_idx); |
| 24330 | const decl_type = sema.typeOf(decl_val); | 24373 | const decl_type = sema.typeOf(decl_val); |
| 24331 | if (decl_type.zigTypeTag() == .Fn and | 24374 | if (decl_type.zigTypeTag(mod) == .Fn and |
| 24332 | decl_type.fnParamLen() >= 1) | 24375 | decl_type.fnParamLen() >= 1) |
| 24333 | { | 24376 | { |
| 24334 | const first_param_type = decl_type.fnParamType(0); | 24377 | const first_param_type = decl_type.fnParamType(0); |
| 24335 | const first_param_tag = first_param_type.tag(); | 24378 | const first_param_tag = first_param_type.tag(); |
| 24336 | // zig fmt: off | 24379 | // zig fmt: off |
| 24337 | if (first_param_tag == .generic_poison or ( | 24380 | if (first_param_tag == .generic_poison or ( |
| 24338 | first_param_type.zigTypeTag() == .Pointer and | 24381 | first_param_type.zigTypeTag(mod) == .Pointer and |
| 24339 | (first_param_type.ptrSize() == .One or | 24382 | (first_param_type.ptrSize() == .One or |
| 24340 | first_param_type.ptrSize() == .C) and | 24383 | first_param_type.ptrSize() == .C) and |
| 24341 | first_param_type.childType().eql(concrete_ty, sema.mod))) | 24384 | first_param_type.childType().eql(concrete_ty, sema.mod))) |
| ... | @@ -24356,7 +24399,7 @@ fn fieldCallBind( | ... | @@ -24356,7 +24399,7 @@ fn fieldCallBind( |
| 24356 | .func_inst = decl_val, | 24399 | .func_inst = decl_val, |
| 24357 | .arg0_inst = deref, | 24400 | .arg0_inst = deref, |
| 24358 | } }; | 24401 | } }; |
| 24359 | } else if (first_param_type.zigTypeTag() == .Optional) { | 24402 | } else if (first_param_type.zigTypeTag(mod) == .Optional) { |
| 24360 | var opt_buf: Type.Payload.ElemType = undefined; | 24403 | var opt_buf: Type.Payload.ElemType = undefined; |
| 24361 | const child = first_param_type.optionalChild(&opt_buf); | 24404 | const child = first_param_type.optionalChild(&opt_buf); |
| 24362 | if (child.eql(concrete_ty, sema.mod)) { | 24405 | if (child.eql(concrete_ty, sema.mod)) { |
| ... | @@ -24365,7 +24408,7 @@ fn fieldCallBind( | ... | @@ -24365,7 +24408,7 @@ fn fieldCallBind( |
| 24365 | .func_inst = decl_val, | 24408 | .func_inst = decl_val, |
| 24366 | .arg0_inst = deref, | 24409 | .arg0_inst = deref, |
| 24367 | } }; | 24410 | } }; |
| 24368 | } else if (child.zigTypeTag() == .Pointer and | 24411 | } else if (child.zigTypeTag(mod) == .Pointer and |
| 24369 | child.ptrSize() == .One and | 24412 | child.ptrSize() == .One and |
| 24370 | child.childType().eql(concrete_ty, sema.mod)) | 24413 | child.childType().eql(concrete_ty, sema.mod)) |
| 24371 | { | 24414 | { |
| ... | @@ -24374,7 +24417,7 @@ fn fieldCallBind( | ... | @@ -24374,7 +24417,7 @@ fn fieldCallBind( |
| 24374 | .arg0_inst = object_ptr, | 24417 | .arg0_inst = object_ptr, |
| 24375 | } }; | 24418 | } }; |
| 24376 | } | 24419 | } |
| 24377 | } else if (first_param_type.zigTypeTag() == .ErrorUnion and | 24420 | } else if (first_param_type.zigTypeTag(mod) == .ErrorUnion and |
| 24378 | first_param_type.errorUnionPayload().eql(concrete_ty, sema.mod)) | 24421 | first_param_type.errorUnionPayload().eql(concrete_ty, sema.mod)) |
| 24379 | { | 24422 | { |
| 24380 | const deref = try sema.analyzeLoad(block, src, object_ptr, src); | 24423 | const deref = try sema.analyzeLoad(block, src, object_ptr, src); |
| ... | @@ -24421,9 +24464,10 @@ fn finishFieldCallBind( | ... | @@ -24421,9 +24464,10 @@ fn finishFieldCallBind( |
| 24421 | .@"addrspace" = ptr_ty.ptrAddressSpace(), | 24464 | .@"addrspace" = ptr_ty.ptrAddressSpace(), |
| 24422 | }); | 24465 | }); |
| 24423 | 24466 | ||
| 24467 | const mod = sema.mod; | ||
| 24424 | const container_ty = ptr_ty.childType(); | 24468 | const container_ty = ptr_ty.childType(); |
| 24425 | if (container_ty.zigTypeTag() == .Struct) { | 24469 | if (container_ty.zigTypeTag(mod) == .Struct) { |
| 24426 | if (container_ty.structFieldValueComptime(field_index)) |default_val| { | 24470 | if (container_ty.structFieldValueComptime(mod, field_index)) |default_val| { |
| 24427 | return .{ .direct = try sema.addConstant(field_ty, default_val) }; | 24471 | return .{ .direct = try sema.addConstant(field_ty, default_val) }; |
| 24428 | } | 24472 | } |
| 24429 | } | 24473 | } |
| ... | @@ -24504,7 +24548,8 @@ fn structFieldPtr( | ... | @@ -24504,7 +24548,8 @@ fn structFieldPtr( |
| 24504 | unresolved_struct_ty: Type, | 24548 | unresolved_struct_ty: Type, |
| 24505 | initializing: bool, | 24549 | initializing: bool, |
| 24506 | ) CompileError!Air.Inst.Ref { | 24550 | ) CompileError!Air.Inst.Ref { |
| 24507 | assert(unresolved_struct_ty.zigTypeTag() == .Struct); | 24551 | const mod = sema.mod; |
| 24552 | assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct); | ||
| 24508 | 24553 | ||
| 24509 | const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty); | 24554 | const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty); |
| 24510 | try sema.resolveStructLayout(struct_ty); | 24555 | try sema.resolveStructLayout(struct_ty); |
| ... | @@ -24544,6 +24589,7 @@ fn structFieldPtrByIndex( | ... | @@ -24544,6 +24589,7 @@ fn structFieldPtrByIndex( |
| 24544 | return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index, initializing); | 24589 | return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index, initializing); |
| 24545 | } | 24590 | } |
| 24546 | 24591 | ||
| 24592 | const mod = sema.mod; | ||
| 24547 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 24593 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 24548 | const field = struct_obj.fields.values()[field_index]; | 24594 | const field = struct_obj.fields.values()[field_index]; |
| 24549 | const struct_ptr_ty = sema.typeOf(struct_ptr); | 24595 | const struct_ptr_ty = sema.typeOf(struct_ptr); |
| ... | @@ -24568,7 +24614,7 @@ fn structFieldPtrByIndex( | ... | @@ -24568,7 +24614,7 @@ fn structFieldPtrByIndex( |
| 24568 | if (i == field_index) { | 24614 | if (i == field_index) { |
| 24569 | ptr_ty_data.bit_offset = running_bits; | 24615 | ptr_ty_data.bit_offset = running_bits; |
| 24570 | } | 24616 | } |
| 24571 | running_bits += @intCast(u16, f.ty.bitSize(target)); | 24617 | running_bits += @intCast(u16, f.ty.bitSize(mod)); |
| 24572 | } | 24618 | } |
| 24573 | ptr_ty_data.host_size = (running_bits + 7) / 8; | 24619 | ptr_ty_data.host_size = (running_bits + 7) / 8; |
| 24574 | 24620 | ||
| ... | @@ -24582,7 +24628,7 @@ fn structFieldPtrByIndex( | ... | @@ -24582,7 +24628,7 @@ fn structFieldPtrByIndex( |
| 24582 | const parent_align = if (struct_ptr_ty_info.@"align" != 0) | 24628 | const parent_align = if (struct_ptr_ty_info.@"align" != 0) |
| 24583 | struct_ptr_ty_info.@"align" | 24629 | struct_ptr_ty_info.@"align" |
| 24584 | else | 24630 | else |
| 24585 | struct_ptr_ty_info.pointee_type.abiAlignment(target); | 24631 | struct_ptr_ty_info.pointee_type.abiAlignment(mod); |
| 24586 | ptr_ty_data.@"align" = parent_align; | 24632 | ptr_ty_data.@"align" = parent_align; |
| 24587 | 24633 | ||
| 24588 | // If the field happens to be byte-aligned, simplify the pointer type. | 24634 | // If the field happens to be byte-aligned, simplify the pointer type. |
| ... | @@ -24596,8 +24642,8 @@ fn structFieldPtrByIndex( | ... | @@ -24596,8 +24642,8 @@ fn structFieldPtrByIndex( |
| 24596 | if (parent_align != 0 and ptr_ty_data.bit_offset % 8 == 0 and | 24642 | if (parent_align != 0 and ptr_ty_data.bit_offset % 8 == 0 and |
| 24597 | target.cpu.arch.endian() == .Little) | 24643 | target.cpu.arch.endian() == .Little) |
| 24598 | { | 24644 | { |
| 24599 | const elem_size_bytes = ptr_ty_data.pointee_type.abiSize(target); | 24645 | const elem_size_bytes = ptr_ty_data.pointee_type.abiSize(mod); |
| 24600 | const elem_size_bits = ptr_ty_data.pointee_type.bitSize(target); | 24646 | const elem_size_bits = ptr_ty_data.pointee_type.bitSize(mod); |
| 24601 | if (elem_size_bytes * 8 == elem_size_bits) { | 24647 | if (elem_size_bytes * 8 == elem_size_bits) { |
| 24602 | const byte_offset = ptr_ty_data.bit_offset / 8; | 24648 | const byte_offset = ptr_ty_data.bit_offset / 8; |
| 24603 | const new_align = @as(u32, 1) << @intCast(u5, @ctz(byte_offset | parent_align)); | 24649 | const new_align = @as(u32, 1) << @intCast(u5, @ctz(byte_offset | parent_align)); |
| ... | @@ -24644,7 +24690,8 @@ fn structFieldVal( | ... | @@ -24644,7 +24690,8 @@ fn structFieldVal( |
| 24644 | field_name_src: LazySrcLoc, | 24690 | field_name_src: LazySrcLoc, |
| 24645 | unresolved_struct_ty: Type, | 24691 | unresolved_struct_ty: Type, |
| 24646 | ) CompileError!Air.Inst.Ref { | 24692 | ) CompileError!Air.Inst.Ref { |
| 24647 | assert(unresolved_struct_ty.zigTypeTag() == .Struct); | 24693 | const mod = sema.mod; |
| 24694 | assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct); | ||
| 24648 | 24695 | ||
| 24649 | const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty); | 24696 | const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty); |
| 24650 | switch (struct_ty.tag()) { | 24697 | switch (struct_ty.tag()) { |
| ... | @@ -24728,9 +24775,10 @@ fn tupleFieldValByIndex( | ... | @@ -24728,9 +24775,10 @@ fn tupleFieldValByIndex( |
| 24728 | field_index: u32, | 24775 | field_index: u32, |
| 24729 | tuple_ty: Type, | 24776 | tuple_ty: Type, |
| 24730 | ) CompileError!Air.Inst.Ref { | 24777 | ) CompileError!Air.Inst.Ref { |
| 24778 | const mod = sema.mod; | ||
| 24731 | const field_ty = tuple_ty.structFieldType(field_index); | 24779 | const field_ty = tuple_ty.structFieldType(field_index); |
| 24732 | 24780 | ||
| 24733 | if (tuple_ty.structFieldValueComptime(field_index)) |default_value| { | 24781 | if (tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| { |
| 24734 | return sema.addConstant(field_ty, default_value); | 24782 | return sema.addConstant(field_ty, default_value); |
| 24735 | } | 24783 | } |
| 24736 | 24784 | ||
| ... | @@ -24743,7 +24791,7 @@ fn tupleFieldValByIndex( | ... | @@ -24743,7 +24791,7 @@ fn tupleFieldValByIndex( |
| 24743 | return sema.addConstant(field_ty, field_values[field_index]); | 24791 | return sema.addConstant(field_ty, field_values[field_index]); |
| 24744 | } | 24792 | } |
| 24745 | 24793 | ||
| 24746 | if (tuple_ty.structFieldValueComptime(field_index)) |default_val| { | 24794 | if (tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| { |
| 24747 | return sema.addConstant(field_ty, default_val); | 24795 | return sema.addConstant(field_ty, default_val); |
| 24748 | } | 24796 | } |
| 24749 | 24797 | ||
| ... | @@ -24762,7 +24810,9 @@ fn unionFieldPtr( | ... | @@ -24762,7 +24810,9 @@ fn unionFieldPtr( |
| 24762 | initializing: bool, | 24810 | initializing: bool, |
| 24763 | ) CompileError!Air.Inst.Ref { | 24811 | ) CompileError!Air.Inst.Ref { |
| 24764 | const arena = sema.arena; | 24812 | const arena = sema.arena; |
| 24765 | assert(unresolved_union_ty.zigTypeTag() == .Union); | 24813 | const mod = sema.mod; |
| 24814 | |||
| 24815 | assert(unresolved_union_ty.zigTypeTag(mod) == .Union); | ||
| 24766 | 24816 | ||
| 24767 | const union_ptr_ty = sema.typeOf(union_ptr); | 24817 | const union_ptr_ty = sema.typeOf(union_ptr); |
| 24768 | const union_ty = try sema.resolveTypeFields(unresolved_union_ty); | 24818 | const union_ty = try sema.resolveTypeFields(unresolved_union_ty); |
| ... | @@ -24777,7 +24827,7 @@ fn unionFieldPtr( | ... | @@ -24777,7 +24827,7 @@ fn unionFieldPtr( |
| 24777 | }); | 24827 | }); |
| 24778 | const enum_field_index = @intCast(u32, union_obj.tag_ty.enumFieldIndex(field_name).?); | 24828 | const enum_field_index = @intCast(u32, union_obj.tag_ty.enumFieldIndex(field_name).?); |
| 24779 | 24829 | ||
| 24780 | if (initializing and field.ty.zigTypeTag() == .NoReturn) { | 24830 | if (initializing and field.ty.zigTypeTag(mod) == .NoReturn) { |
| 24781 | const msg = msg: { | 24831 | const msg = msg: { |
| 24782 | const msg = try sema.errMsg(block, src, "cannot initialize 'noreturn' field of union", .{}); | 24832 | const msg = try sema.errMsg(block, src, "cannot initialize 'noreturn' field of union", .{}); |
| 24783 | errdefer msg.destroy(sema.gpa); | 24833 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -24839,7 +24889,7 @@ fn unionFieldPtr( | ... | @@ -24839,7 +24889,7 @@ fn unionFieldPtr( |
| 24839 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_val); | 24889 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_val); |
| 24840 | try sema.panicInactiveUnionField(block, active_tag, wanted_tag); | 24890 | try sema.panicInactiveUnionField(block, active_tag, wanted_tag); |
| 24841 | } | 24891 | } |
| 24842 | if (field.ty.zigTypeTag() == .NoReturn) { | 24892 | if (field.ty.zigTypeTag(mod) == .NoReturn) { |
| 24843 | _ = try block.addNoOp(.unreach); | 24893 | _ = try block.addNoOp(.unreach); |
| 24844 | return Air.Inst.Ref.unreachable_value; | 24894 | return Air.Inst.Ref.unreachable_value; |
| 24845 | } | 24895 | } |
| ... | @@ -24855,7 +24905,8 @@ fn unionFieldVal( | ... | @@ -24855,7 +24905,8 @@ fn unionFieldVal( |
| 24855 | field_name_src: LazySrcLoc, | 24905 | field_name_src: LazySrcLoc, |
| 24856 | unresolved_union_ty: Type, | 24906 | unresolved_union_ty: Type, |
| 24857 | ) CompileError!Air.Inst.Ref { | 24907 | ) CompileError!Air.Inst.Ref { |
| 24858 | assert(unresolved_union_ty.zigTypeTag() == .Union); | 24908 | const mod = sema.mod; |
| 24909 | assert(unresolved_union_ty.zigTypeTag(mod) == .Union); | ||
| 24859 | 24910 | ||
| 24860 | const union_ty = try sema.resolveTypeFields(unresolved_union_ty); | 24911 | const union_ty = try sema.resolveTypeFields(unresolved_union_ty); |
| 24861 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | 24912 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| ... | @@ -24911,7 +24962,7 @@ fn unionFieldVal( | ... | @@ -24911,7 +24962,7 @@ fn unionFieldVal( |
| 24911 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_byval); | 24962 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_byval); |
| 24912 | try sema.panicInactiveUnionField(block, active_tag, wanted_tag); | 24963 | try sema.panicInactiveUnionField(block, active_tag, wanted_tag); |
| 24913 | } | 24964 | } |
| 24914 | if (field.ty.zigTypeTag() == .NoReturn) { | 24965 | if (field.ty.zigTypeTag(mod) == .NoReturn) { |
| 24915 | _ = try block.addNoOp(.unreach); | 24966 | _ = try block.addNoOp(.unreach); |
| 24916 | return Air.Inst.Ref.unreachable_value; | 24967 | return Air.Inst.Ref.unreachable_value; |
| 24917 | } | 24968 | } |
| ... | @@ -24928,22 +24979,22 @@ fn elemPtr( | ... | @@ -24928,22 +24979,22 @@ fn elemPtr( |
| 24928 | init: bool, | 24979 | init: bool, |
| 24929 | oob_safety: bool, | 24980 | oob_safety: bool, |
| 24930 | ) CompileError!Air.Inst.Ref { | 24981 | ) CompileError!Air.Inst.Ref { |
| 24982 | const mod = sema.mod; | ||
| 24931 | const indexable_ptr_src = src; // TODO better source location | 24983 | const indexable_ptr_src = src; // TODO better source location |
| 24932 | const indexable_ptr_ty = sema.typeOf(indexable_ptr); | 24984 | const indexable_ptr_ty = sema.typeOf(indexable_ptr); |
| 24933 | const target = sema.mod.getTarget(); | ||
| 24934 | 24985 | ||
| 24935 | const indexable_ty = switch (indexable_ptr_ty.zigTypeTag()) { | 24986 | const indexable_ty = switch (indexable_ptr_ty.zigTypeTag(mod)) { |
| 24936 | .Pointer => indexable_ptr_ty.elemType(), | 24987 | .Pointer => indexable_ptr_ty.elemType(), |
| 24937 | else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(sema.mod)}), | 24988 | else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(sema.mod)}), |
| 24938 | }; | 24989 | }; |
| 24939 | try checkIndexable(sema, block, src, indexable_ty); | 24990 | try checkIndexable(sema, block, src, indexable_ty); |
| 24940 | 24991 | ||
| 24941 | switch (indexable_ty.zigTypeTag()) { | 24992 | switch (indexable_ty.zigTypeTag(mod)) { |
| 24942 | .Array, .Vector => return sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety), | 24993 | .Array, .Vector => return sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety), |
| 24943 | .Struct => { | 24994 | .Struct => { |
| 24944 | // Tuple field access. | 24995 | // Tuple field access. |
| 24945 | const index_val = try sema.resolveConstValue(block, elem_index_src, elem_index, "tuple field access index must be comptime-known"); | 24996 | const index_val = try sema.resolveConstValue(block, elem_index_src, elem_index, "tuple field access index must be comptime-known"); |
| 24946 | const index = @intCast(u32, index_val.toUnsignedInt(target)); | 24997 | const index = @intCast(u32, index_val.toUnsignedInt(mod)); |
| 24947 | return sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init); | 24998 | return sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init); |
| 24948 | }, | 24999 | }, |
| 24949 | else => { | 25000 | else => { |
| ... | @@ -24966,7 +25017,7 @@ fn elemPtrOneLayerOnly( | ... | @@ -24966,7 +25017,7 @@ fn elemPtrOneLayerOnly( |
| 24966 | ) CompileError!Air.Inst.Ref { | 25017 | ) CompileError!Air.Inst.Ref { |
| 24967 | const indexable_src = src; // TODO better source location | 25018 | const indexable_src = src; // TODO better source location |
| 24968 | const indexable_ty = sema.typeOf(indexable); | 25019 | const indexable_ty = sema.typeOf(indexable); |
| 24969 | const target = sema.mod.getTarget(); | 25020 | const mod = sema.mod; |
| 24970 | 25021 | ||
| 24971 | try checkIndexable(sema, block, src, indexable_ty); | 25022 | try checkIndexable(sema, block, src, indexable_ty); |
| 24972 | 25023 | ||
| ... | @@ -24978,7 +25029,7 @@ fn elemPtrOneLayerOnly( | ... | @@ -24978,7 +25029,7 @@ fn elemPtrOneLayerOnly( |
| 24978 | const runtime_src = rs: { | 25029 | const runtime_src = rs: { |
| 24979 | const ptr_val = maybe_ptr_val orelse break :rs indexable_src; | 25030 | const ptr_val = maybe_ptr_val orelse break :rs indexable_src; |
| 24980 | const index_val = maybe_index_val orelse break :rs elem_index_src; | 25031 | const index_val = maybe_index_val orelse break :rs elem_index_src; |
| 24981 | const index = @intCast(usize, index_val.toUnsignedInt(target)); | 25032 | const index = @intCast(usize, index_val.toUnsignedInt(mod)); |
| 24982 | const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, sema.mod); | 25033 | const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, sema.mod); |
| 24983 | const result_ty = try sema.elemPtrType(indexable_ty, index); | 25034 | const result_ty = try sema.elemPtrType(indexable_ty, index); |
| 24984 | return sema.addConstant(result_ty, elem_ptr); | 25035 | return sema.addConstant(result_ty, elem_ptr); |
| ... | @@ -24989,7 +25040,7 @@ fn elemPtrOneLayerOnly( | ... | @@ -24989,7 +25040,7 @@ fn elemPtrOneLayerOnly( |
| 24989 | return block.addPtrElemPtr(indexable, elem_index, result_ty); | 25040 | return block.addPtrElemPtr(indexable, elem_index, result_ty); |
| 24990 | }, | 25041 | }, |
| 24991 | .One => { | 25042 | .One => { |
| 24992 | assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by checkIndexable | 25043 | assert(indexable_ty.childType().zigTypeTag(mod) == .Array); // Guaranteed by checkIndexable |
| 24993 | return sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety); | 25044 | return sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety); |
| 24994 | }, | 25045 | }, |
| 24995 | } | 25046 | } |
| ... | @@ -25006,7 +25057,7 @@ fn elemVal( | ... | @@ -25006,7 +25057,7 @@ fn elemVal( |
| 25006 | ) CompileError!Air.Inst.Ref { | 25057 | ) CompileError!Air.Inst.Ref { |
| 25007 | const indexable_src = src; // TODO better source location | 25058 | const indexable_src = src; // TODO better source location |
| 25008 | const indexable_ty = sema.typeOf(indexable); | 25059 | const indexable_ty = sema.typeOf(indexable); |
| 25009 | const target = sema.mod.getTarget(); | 25060 | const mod = sema.mod; |
| 25010 | 25061 | ||
| 25011 | try checkIndexable(sema, block, src, indexable_ty); | 25062 | try checkIndexable(sema, block, src, indexable_ty); |
| 25012 | 25063 | ||
| ... | @@ -25014,7 +25065,7 @@ fn elemVal( | ... | @@ -25014,7 +25065,7 @@ fn elemVal( |
| 25014 | // index is a scalar or vector instead of unconditionally casting to usize. | 25065 | // index is a scalar or vector instead of unconditionally casting to usize. |
| 25015 | const elem_index = try sema.coerce(block, Type.usize, elem_index_uncasted, elem_index_src); | 25066 | const elem_index = try sema.coerce(block, Type.usize, elem_index_uncasted, elem_index_src); |
| 25016 | 25067 | ||
| 25017 | switch (indexable_ty.zigTypeTag()) { | 25068 | switch (indexable_ty.zigTypeTag(mod)) { |
| 25018 | .Pointer => switch (indexable_ty.ptrSize()) { | 25069 | .Pointer => switch (indexable_ty.ptrSize()) { |
| 25019 | .Slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), | 25070 | .Slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), |
| 25020 | .Many, .C => { | 25071 | .Many, .C => { |
| ... | @@ -25024,10 +25075,10 @@ fn elemVal( | ... | @@ -25024,10 +25075,10 @@ fn elemVal( |
| 25024 | const runtime_src = rs: { | 25075 | const runtime_src = rs: { |
| 25025 | const indexable_val = maybe_indexable_val orelse break :rs indexable_src; | 25076 | const indexable_val = maybe_indexable_val orelse break :rs indexable_src; |
| 25026 | const index_val = maybe_index_val orelse break :rs elem_index_src; | 25077 | const index_val = maybe_index_val orelse break :rs elem_index_src; |
| 25027 | const index = @intCast(usize, index_val.toUnsignedInt(target)); | 25078 | const index = @intCast(usize, index_val.toUnsignedInt(mod)); |
| 25028 | const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, sema.arena, index, sema.mod); | 25079 | const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, sema.arena, index, sema.mod); |
| 25029 | if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, indexable_ty)) |elem_val| { | 25080 | if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, indexable_ty)) |elem_val| { |
| 25030 | return sema.addConstant(indexable_ty.elemType2(), elem_val); | 25081 | return sema.addConstant(indexable_ty.elemType2(mod), elem_val); |
| 25031 | } | 25082 | } |
| 25032 | break :rs indexable_src; | 25083 | break :rs indexable_src; |
| 25033 | }; | 25084 | }; |
| ... | @@ -25036,7 +25087,7 @@ fn elemVal( | ... | @@ -25036,7 +25087,7 @@ fn elemVal( |
| 25036 | return block.addBinOp(.ptr_elem_val, indexable, elem_index); | 25087 | return block.addBinOp(.ptr_elem_val, indexable, elem_index); |
| 25037 | }, | 25088 | }, |
| 25038 | .One => { | 25089 | .One => { |
| 25039 | assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by checkIndexable | 25090 | assert(indexable_ty.childType().zigTypeTag(mod) == .Array); // Guaranteed by checkIndexable |
| 25040 | const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety); | 25091 | const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety); |
| 25041 | return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src); | 25092 | return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src); |
| 25042 | }, | 25093 | }, |
| ... | @@ -25049,7 +25100,7 @@ fn elemVal( | ... | @@ -25049,7 +25100,7 @@ fn elemVal( |
| 25049 | .Struct => { | 25100 | .Struct => { |
| 25050 | // Tuple field access. | 25101 | // Tuple field access. |
| 25051 | const index_val = try sema.resolveConstValue(block, elem_index_src, elem_index, "tuple field access index must be comptime-known"); | 25102 | const index_val = try sema.resolveConstValue(block, elem_index_src, elem_index, "tuple field access index must be comptime-known"); |
| 25052 | const index = @intCast(u32, index_val.toUnsignedInt(target)); | 25103 | const index = @intCast(u32, index_val.toUnsignedInt(mod)); |
| 25053 | return sema.tupleField(block, indexable_src, indexable, elem_index_src, index); | 25104 | return sema.tupleField(block, indexable_src, indexable, elem_index_src, index); |
| 25054 | }, | 25105 | }, |
| 25055 | else => unreachable, | 25106 | else => unreachable, |
| ... | @@ -25093,6 +25144,7 @@ fn tupleFieldPtr( | ... | @@ -25093,6 +25144,7 @@ fn tupleFieldPtr( |
| 25093 | field_index: u32, | 25144 | field_index: u32, |
| 25094 | init: bool, | 25145 | init: bool, |
| 25095 | ) CompileError!Air.Inst.Ref { | 25146 | ) CompileError!Air.Inst.Ref { |
| 25147 | const mod = sema.mod; | ||
| 25096 | const tuple_ptr_ty = sema.typeOf(tuple_ptr); | 25148 | const tuple_ptr_ty = sema.typeOf(tuple_ptr); |
| 25097 | const tuple_ty = tuple_ptr_ty.childType(); | 25149 | const tuple_ty = tuple_ptr_ty.childType(); |
| 25098 | _ = try sema.resolveTypeFields(tuple_ty); | 25150 | _ = try sema.resolveTypeFields(tuple_ty); |
| ... | @@ -25116,7 +25168,7 @@ fn tupleFieldPtr( | ... | @@ -25116,7 +25168,7 @@ fn tupleFieldPtr( |
| 25116 | .@"addrspace" = tuple_ptr_ty.ptrAddressSpace(), | 25168 | .@"addrspace" = tuple_ptr_ty.ptrAddressSpace(), |
| 25117 | }); | 25169 | }); |
| 25118 | 25170 | ||
| 25119 | if (tuple_ty.structFieldValueComptime(field_index)) |default_val| { | 25171 | if (tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| { |
| 25120 | const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{ | 25172 | const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{ |
| 25121 | .field_ty = field_ty, | 25173 | .field_ty = field_ty, |
| 25122 | .field_val = default_val, | 25174 | .field_val = default_val, |
| ... | @@ -25151,6 +25203,7 @@ fn tupleField( | ... | @@ -25151,6 +25203,7 @@ fn tupleField( |
| 25151 | field_index_src: LazySrcLoc, | 25203 | field_index_src: LazySrcLoc, |
| 25152 | field_index: u32, | 25204 | field_index: u32, |
| 25153 | ) CompileError!Air.Inst.Ref { | 25205 | ) CompileError!Air.Inst.Ref { |
| 25206 | const mod = sema.mod; | ||
| 25154 | const tuple_ty = try sema.resolveTypeFields(sema.typeOf(tuple)); | 25207 | const tuple_ty = try sema.resolveTypeFields(sema.typeOf(tuple)); |
| 25155 | const field_count = tuple_ty.structFieldCount(); | 25208 | const field_count = tuple_ty.structFieldCount(); |
| 25156 | 25209 | ||
| ... | @@ -25166,13 +25219,13 @@ fn tupleField( | ... | @@ -25166,13 +25219,13 @@ fn tupleField( |
| 25166 | 25219 | ||
| 25167 | const field_ty = tuple_ty.structFieldType(field_index); | 25220 | const field_ty = tuple_ty.structFieldType(field_index); |
| 25168 | 25221 | ||
| 25169 | if (tuple_ty.structFieldValueComptime(field_index)) |default_value| { | 25222 | if (tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| { |
| 25170 | return sema.addConstant(field_ty, default_value); // comptime field | 25223 | return sema.addConstant(field_ty, default_value); // comptime field |
| 25171 | } | 25224 | } |
| 25172 | 25225 | ||
| 25173 | if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| { | 25226 | if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| { |
| 25174 | if (tuple_val.isUndef()) return sema.addConstUndef(field_ty); | 25227 | if (tuple_val.isUndef()) return sema.addConstUndef(field_ty); |
| 25175 | return sema.addConstant(field_ty, tuple_val.fieldValue(tuple_ty, field_index)); | 25228 | return sema.addConstant(field_ty, tuple_val.fieldValue(tuple_ty, mod, field_index)); |
| 25176 | } | 25229 | } |
| 25177 | 25230 | ||
| 25178 | try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src); | 25231 | try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src); |
| ... | @@ -25191,6 +25244,7 @@ fn elemValArray( | ... | @@ -25191,6 +25244,7 @@ fn elemValArray( |
| 25191 | elem_index: Air.Inst.Ref, | 25244 | elem_index: Air.Inst.Ref, |
| 25192 | oob_safety: bool, | 25245 | oob_safety: bool, |
| 25193 | ) CompileError!Air.Inst.Ref { | 25246 | ) CompileError!Air.Inst.Ref { |
| 25247 | const mod = sema.mod; | ||
| 25194 | const array_ty = sema.typeOf(array); | 25248 | const array_ty = sema.typeOf(array); |
| 25195 | const array_sent = array_ty.sentinel(); | 25249 | const array_sent = array_ty.sentinel(); |
| 25196 | const array_len = array_ty.arrayLen(); | 25250 | const array_len = array_ty.arrayLen(); |
| ... | @@ -25204,10 +25258,9 @@ fn elemValArray( | ... | @@ -25204,10 +25258,9 @@ fn elemValArray( |
| 25204 | const maybe_undef_array_val = try sema.resolveMaybeUndefVal(array); | 25258 | const maybe_undef_array_val = try sema.resolveMaybeUndefVal(array); |
| 25205 | // index must be defined since it can access out of bounds | 25259 | // index must be defined since it can access out of bounds |
| 25206 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); | 25260 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 25207 | const target = sema.mod.getTarget(); | ||
| 25208 | 25261 | ||
| 25209 | if (maybe_index_val) |index_val| { | 25262 | if (maybe_index_val) |index_val| { |
| 25210 | const index = @intCast(usize, index_val.toUnsignedInt(target)); | 25263 | const index = @intCast(usize, index_val.toUnsignedInt(mod)); |
| 25211 | if (array_sent) |s| { | 25264 | if (array_sent) |s| { |
| 25212 | if (index == array_len) { | 25265 | if (index == array_len) { |
| 25213 | return sema.addConstant(elem_ty, s); | 25266 | return sema.addConstant(elem_ty, s); |
| ... | @@ -25223,7 +25276,7 @@ fn elemValArray( | ... | @@ -25223,7 +25276,7 @@ fn elemValArray( |
| 25223 | return sema.addConstUndef(elem_ty); | 25276 | return sema.addConstUndef(elem_ty); |
| 25224 | } | 25277 | } |
| 25225 | if (maybe_index_val) |index_val| { | 25278 | if (maybe_index_val) |index_val| { |
| 25226 | const index = @intCast(usize, index_val.toUnsignedInt(target)); | 25279 | const index = @intCast(usize, index_val.toUnsignedInt(mod)); |
| 25227 | const elem_val = try array_val.elemValue(sema.mod, sema.arena, index); | 25280 | const elem_val = try array_val.elemValue(sema.mod, sema.arena, index); |
| 25228 | return sema.addConstant(elem_ty, elem_val); | 25281 | return sema.addConstant(elem_ty, elem_val); |
| 25229 | } | 25282 | } |
| ... | @@ -25255,7 +25308,7 @@ fn elemPtrArray( | ... | @@ -25255,7 +25308,7 @@ fn elemPtrArray( |
| 25255 | init: bool, | 25308 | init: bool, |
| 25256 | oob_safety: bool, | 25309 | oob_safety: bool, |
| 25257 | ) CompileError!Air.Inst.Ref { | 25310 | ) CompileError!Air.Inst.Ref { |
| 25258 | const target = sema.mod.getTarget(); | 25311 | const mod = sema.mod; |
| 25259 | const array_ptr_ty = sema.typeOf(array_ptr); | 25312 | const array_ptr_ty = sema.typeOf(array_ptr); |
| 25260 | const array_ty = array_ptr_ty.childType(); | 25313 | const array_ty = array_ptr_ty.childType(); |
| 25261 | const array_sent = array_ty.sentinel() != null; | 25314 | const array_sent = array_ty.sentinel() != null; |
| ... | @@ -25269,7 +25322,7 @@ fn elemPtrArray( | ... | @@ -25269,7 +25322,7 @@ fn elemPtrArray( |
| 25269 | const maybe_undef_array_ptr_val = try sema.resolveMaybeUndefVal(array_ptr); | 25322 | const maybe_undef_array_ptr_val = try sema.resolveMaybeUndefVal(array_ptr); |
| 25270 | // The index must not be undefined since it can be out of bounds. | 25323 | // The index must not be undefined since it can be out of bounds. |
| 25271 | const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { | 25324 | const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { |
| 25272 | const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(target)); | 25325 | const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(mod)); |
| 25273 | if (index >= array_len_s) { | 25326 | if (index >= array_len_s) { |
| 25274 | const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else ""; | 25327 | const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else ""; |
| 25275 | return sema.fail(block, elem_index_src, "index {d} outside array of length {d}{s}", .{ index, array_len, sentinel_label }); | 25328 | return sema.fail(block, elem_index_src, "index {d} outside array of length {d}{s}", .{ index, array_len, sentinel_label }); |
| ... | @@ -25290,7 +25343,7 @@ fn elemPtrArray( | ... | @@ -25290,7 +25343,7 @@ fn elemPtrArray( |
| 25290 | } | 25343 | } |
| 25291 | 25344 | ||
| 25292 | if (!init) { | 25345 | if (!init) { |
| 25293 | try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.elemType2(), array_ty, array_ptr_src); | 25346 | try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.elemType2(mod), array_ty, array_ptr_src); |
| 25294 | } | 25347 | } |
| 25295 | 25348 | ||
| 25296 | const runtime_src = if (maybe_undef_array_ptr_val != null) elem_index_src else array_ptr_src; | 25349 | const runtime_src = if (maybe_undef_array_ptr_val != null) elem_index_src else array_ptr_src; |
| ... | @@ -25316,16 +25369,16 @@ fn elemValSlice( | ... | @@ -25316,16 +25369,16 @@ fn elemValSlice( |
| 25316 | elem_index: Air.Inst.Ref, | 25369 | elem_index: Air.Inst.Ref, |
| 25317 | oob_safety: bool, | 25370 | oob_safety: bool, |
| 25318 | ) CompileError!Air.Inst.Ref { | 25371 | ) CompileError!Air.Inst.Ref { |
| 25372 | const mod = sema.mod; | ||
| 25319 | const slice_ty = sema.typeOf(slice); | 25373 | const slice_ty = sema.typeOf(slice); |
| 25320 | const slice_sent = slice_ty.sentinel() != null; | 25374 | const slice_sent = slice_ty.sentinel() != null; |
| 25321 | const elem_ty = slice_ty.elemType2(); | 25375 | const elem_ty = slice_ty.elemType2(mod); |
| 25322 | var runtime_src = slice_src; | 25376 | var runtime_src = slice_src; |
| 25323 | 25377 | ||
| 25324 | // slice must be defined since it can dereferenced as null | 25378 | // slice must be defined since it can dereferenced as null |
| 25325 | const maybe_slice_val = try sema.resolveDefinedValue(block, slice_src, slice); | 25379 | const maybe_slice_val = try sema.resolveDefinedValue(block, slice_src, slice); |
| 25326 | // index must be defined since it can index out of bounds | 25380 | // index must be defined since it can index out of bounds |
| 25327 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); | 25381 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 25328 | const target = sema.mod.getTarget(); | ||
| 25329 | 25382 | ||
| 25330 | if (maybe_slice_val) |slice_val| { | 25383 | if (maybe_slice_val) |slice_val| { |
| 25331 | runtime_src = elem_index_src; | 25384 | runtime_src = elem_index_src; |
| ... | @@ -25335,7 +25388,7 @@ fn elemValSlice( | ... | @@ -25335,7 +25388,7 @@ fn elemValSlice( |
| 25335 | return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{}); | 25388 | return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{}); |
| 25336 | } | 25389 | } |
| 25337 | if (maybe_index_val) |index_val| { | 25390 | if (maybe_index_val) |index_val| { |
| 25338 | const index = @intCast(usize, index_val.toUnsignedInt(target)); | 25391 | const index = @intCast(usize, index_val.toUnsignedInt(mod)); |
| 25339 | if (index >= slice_len_s) { | 25392 | if (index >= slice_len_s) { |
| 25340 | const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; | 25393 | const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; |
| 25341 | return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); | 25394 | return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); |
| ... | @@ -25373,14 +25426,14 @@ fn elemPtrSlice( | ... | @@ -25373,14 +25426,14 @@ fn elemPtrSlice( |
| 25373 | elem_index: Air.Inst.Ref, | 25426 | elem_index: Air.Inst.Ref, |
| 25374 | oob_safety: bool, | 25427 | oob_safety: bool, |
| 25375 | ) CompileError!Air.Inst.Ref { | 25428 | ) CompileError!Air.Inst.Ref { |
| 25376 | const target = sema.mod.getTarget(); | 25429 | const mod = sema.mod; |
| 25377 | const slice_ty = sema.typeOf(slice); | 25430 | const slice_ty = sema.typeOf(slice); |
| 25378 | const slice_sent = slice_ty.sentinel() != null; | 25431 | const slice_sent = slice_ty.sentinel() != null; |
| 25379 | 25432 | ||
| 25380 | const maybe_undef_slice_val = try sema.resolveMaybeUndefVal(slice); | 25433 | const maybe_undef_slice_val = try sema.resolveMaybeUndefVal(slice); |
| 25381 | // The index must not be undefined since it can be out of bounds. | 25434 | // The index must not be undefined since it can be out of bounds. |
| 25382 | const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { | 25435 | const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { |
| 25383 | const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(target)); | 25436 | const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(mod)); |
| 25384 | break :o index; | 25437 | break :o index; |
| 25385 | } else null; | 25438 | } else null; |
| 25386 | 25439 | ||
| ... | @@ -25484,6 +25537,7 @@ fn coerceExtra( | ... | @@ -25484,6 +25537,7 @@ fn coerceExtra( |
| 25484 | const dest_ty_src = inst_src; // TODO better source location | 25537 | const dest_ty_src = inst_src; // TODO better source location |
| 25485 | const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved); | 25538 | const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved); |
| 25486 | const inst_ty = try sema.resolveTypeFields(sema.typeOf(inst)); | 25539 | const inst_ty = try sema.resolveTypeFields(sema.typeOf(inst)); |
| 25540 | const mod = sema.mod; | ||
| 25487 | const target = sema.mod.getTarget(); | 25541 | const target = sema.mod.getTarget(); |
| 25488 | // If the types are the same, we can return the operand. | 25542 | // If the types are the same, we can return the operand. |
| 25489 | if (dest_ty.eql(inst_ty, sema.mod)) | 25543 | if (dest_ty.eql(inst_ty, sema.mod)) |
| ... | @@ -25502,9 +25556,9 @@ fn coerceExtra( | ... | @@ -25502,9 +25556,9 @@ fn coerceExtra( |
| 25502 | return block.addBitCast(dest_ty, inst); | 25556 | return block.addBitCast(dest_ty, inst); |
| 25503 | } | 25557 | } |
| 25504 | 25558 | ||
| 25505 | const is_undef = inst_ty.zigTypeTag() == .Undefined; | 25559 | const is_undef = inst_ty.zigTypeTag(mod) == .Undefined; |
| 25506 | 25560 | ||
| 25507 | switch (dest_ty.zigTypeTag()) { | 25561 | switch (dest_ty.zigTypeTag(mod)) { |
| 25508 | .Optional => optional: { | 25562 | .Optional => optional: { |
| 25509 | // undefined sets the optional bit also to undefined. | 25563 | // undefined sets the optional bit also to undefined. |
| 25510 | if (is_undef) { | 25564 | if (is_undef) { |
| ... | @@ -25512,18 +25566,18 @@ fn coerceExtra( | ... | @@ -25512,18 +25566,18 @@ fn coerceExtra( |
| 25512 | } | 25566 | } |
| 25513 | 25567 | ||
| 25514 | // null to ?T | 25568 | // null to ?T |
| 25515 | if (inst_ty.zigTypeTag() == .Null) { | 25569 | if (inst_ty.zigTypeTag(mod) == .Null) { |
| 25516 | return sema.addConstant(dest_ty, Value.null); | 25570 | return sema.addConstant(dest_ty, Value.null); |
| 25517 | } | 25571 | } |
| 25518 | 25572 | ||
| 25519 | // cast from ?*T and ?[*]T to ?*anyopaque | 25573 | // cast from ?*T and ?[*]T to ?*anyopaque |
| 25520 | // but don't do it if the source type is a double pointer | 25574 | // but don't do it if the source type is a double pointer |
| 25521 | if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and | 25575 | if (dest_ty.isPtrLikeOptional(mod) and dest_ty.elemType2(mod).tag() == .anyopaque and |
| 25522 | inst_ty.isPtrAtRuntime()) | 25576 | inst_ty.isPtrAtRuntime(mod)) |
| 25523 | anyopaque_check: { | 25577 | anyopaque_check: { |
| 25524 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional; | 25578 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional; |
| 25525 | const elem_ty = inst_ty.elemType2(); | 25579 | const elem_ty = inst_ty.elemType2(mod); |
| 25526 | if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) { | 25580 | if (elem_ty.zigTypeTag(mod) == .Pointer or elem_ty.isPtrLikeOptional(mod)) { |
| 25527 | in_memory_result = .{ .double_ptr_to_anyopaque = .{ | 25581 | in_memory_result = .{ .double_ptr_to_anyopaque = .{ |
| 25528 | .actual = inst_ty, | 25582 | .actual = inst_ty, |
| 25529 | .wanted = dest_ty, | 25583 | .wanted = dest_ty, |
| ... | @@ -25532,7 +25586,7 @@ fn coerceExtra( | ... | @@ -25532,7 +25586,7 @@ fn coerceExtra( |
| 25532 | } | 25586 | } |
| 25533 | // Let the logic below handle wrapping the optional now that | 25587 | // Let the logic below handle wrapping the optional now that |
| 25534 | // it has been checked to correctly coerce. | 25588 | // it has been checked to correctly coerce. |
| 25535 | if (!inst_ty.isPtrLikeOptional()) break :anyopaque_check; | 25589 | if (!inst_ty.isPtrLikeOptional(mod)) break :anyopaque_check; |
| 25536 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); | 25590 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| 25537 | } | 25591 | } |
| 25538 | 25592 | ||
| ... | @@ -25554,7 +25608,7 @@ fn coerceExtra( | ... | @@ -25554,7 +25608,7 @@ fn coerceExtra( |
| 25554 | const dest_info = dest_ty.ptrInfo().data; | 25608 | const dest_info = dest_ty.ptrInfo().data; |
| 25555 | 25609 | ||
| 25556 | // Function body to function pointer. | 25610 | // Function body to function pointer. |
| 25557 | if (inst_ty.zigTypeTag() == .Fn) { | 25611 | if (inst_ty.zigTypeTag(mod) == .Fn) { |
| 25558 | const fn_val = try sema.resolveConstValue(block, .unneeded, inst, ""); | 25612 | const fn_val = try sema.resolveConstValue(block, .unneeded, inst, ""); |
| 25559 | const fn_decl = fn_val.pointerDecl().?; | 25613 | const fn_decl = fn_val.pointerDecl().?; |
| 25560 | const inst_as_ptr = try sema.analyzeDeclRef(fn_decl); | 25614 | const inst_as_ptr = try sema.analyzeDeclRef(fn_decl); |
| ... | @@ -25568,7 +25622,7 @@ fn coerceExtra( | ... | @@ -25568,7 +25622,7 @@ fn coerceExtra( |
| 25568 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; | 25622 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; |
| 25569 | const ptr_elem_ty = inst_ty.childType(); | 25623 | const ptr_elem_ty = inst_ty.childType(); |
| 25570 | const array_ty = dest_info.pointee_type; | 25624 | const array_ty = dest_info.pointee_type; |
| 25571 | if (array_ty.zigTypeTag() != .Array) break :single_item; | 25625 | if (array_ty.zigTypeTag(mod) != .Array) break :single_item; |
| 25572 | const array_elem_ty = array_ty.childType(); | 25626 | const array_elem_ty = array_ty.childType(); |
| 25573 | if (array_ty.arrayLen() != 1) break :single_item; | 25627 | if (array_ty.arrayLen() != 1) break :single_item; |
| 25574 | const dest_is_mut = dest_info.mutable; | 25628 | const dest_is_mut = dest_info.mutable; |
| ... | @@ -25584,7 +25638,7 @@ fn coerceExtra( | ... | @@ -25584,7 +25638,7 @@ fn coerceExtra( |
| 25584 | if (!inst_ty.isSinglePointer()) break :src_array_ptr; | 25638 | if (!inst_ty.isSinglePointer()) break :src_array_ptr; |
| 25585 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; | 25639 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; |
| 25586 | const array_ty = inst_ty.childType(); | 25640 | const array_ty = inst_ty.childType(); |
| 25587 | if (array_ty.zigTypeTag() != .Array) break :src_array_ptr; | 25641 | if (array_ty.zigTypeTag(mod) != .Array) break :src_array_ptr; |
| 25588 | const array_elem_type = array_ty.childType(); | 25642 | const array_elem_type = array_ty.childType(); |
| 25589 | const dest_is_mut = dest_info.mutable; | 25643 | const dest_is_mut = dest_info.mutable; |
| 25590 | 25644 | ||
| ... | @@ -25656,10 +25710,10 @@ fn coerceExtra( | ... | @@ -25656,10 +25710,10 @@ fn coerceExtra( |
| 25656 | 25710 | ||
| 25657 | // cast from *T and [*]T to *anyopaque | 25711 | // cast from *T and [*]T to *anyopaque |
| 25658 | // but don't do it if the source type is a double pointer | 25712 | // but don't do it if the source type is a double pointer |
| 25659 | if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer) to_anyopaque: { | 25713 | if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag(mod) == .Pointer) to_anyopaque: { |
| 25660 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; | 25714 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; |
| 25661 | const elem_ty = inst_ty.elemType2(); | 25715 | const elem_ty = inst_ty.elemType2(mod); |
| 25662 | if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) { | 25716 | if (elem_ty.zigTypeTag(mod) == .Pointer or elem_ty.isPtrLikeOptional(mod)) { |
| 25663 | in_memory_result = .{ .double_ptr_to_anyopaque = .{ | 25717 | in_memory_result = .{ .double_ptr_to_anyopaque = .{ |
| 25664 | .actual = inst_ty, | 25718 | .actual = inst_ty, |
| 25665 | .wanted = dest_ty, | 25719 | .wanted = dest_ty, |
| ... | @@ -25679,7 +25733,7 @@ fn coerceExtra( | ... | @@ -25679,7 +25733,7 @@ fn coerceExtra( |
| 25679 | 25733 | ||
| 25680 | switch (dest_info.size) { | 25734 | switch (dest_info.size) { |
| 25681 | // coercion to C pointer | 25735 | // coercion to C pointer |
| 25682 | .C => switch (inst_ty.zigTypeTag()) { | 25736 | .C => switch (inst_ty.zigTypeTag(mod)) { |
| 25683 | .Null => { | 25737 | .Null => { |
| 25684 | return sema.addConstant(dest_ty, Value.null); | 25738 | return sema.addConstant(dest_ty, Value.null); |
| 25685 | }, | 25739 | }, |
| ... | @@ -25691,7 +25745,7 @@ fn coerceExtra( | ... | @@ -25691,7 +25745,7 @@ fn coerceExtra( |
| 25691 | return try sema.coerceCompatiblePtrs(block, dest_ty, addr, inst_src); | 25745 | return try sema.coerceCompatiblePtrs(block, dest_ty, addr, inst_src); |
| 25692 | }, | 25746 | }, |
| 25693 | .Int => { | 25747 | .Int => { |
| 25694 | const ptr_size_ty = switch (inst_ty.intInfo(target).signedness) { | 25748 | const ptr_size_ty = switch (inst_ty.intInfo(mod).signedness) { |
| 25695 | .signed => Type.isize, | 25749 | .signed => Type.isize, |
| 25696 | .unsigned => Type.usize, | 25750 | .unsigned => Type.usize, |
| 25697 | }; | 25751 | }; |
| ... | @@ -25733,7 +25787,7 @@ fn coerceExtra( | ... | @@ -25733,7 +25787,7 @@ fn coerceExtra( |
| 25733 | }, | 25787 | }, |
| 25734 | else => {}, | 25788 | else => {}, |
| 25735 | }, | 25789 | }, |
| 25736 | .One => switch (dest_info.pointee_type.zigTypeTag()) { | 25790 | .One => switch (dest_info.pointee_type.zigTypeTag(mod)) { |
| 25737 | .Union => { | 25791 | .Union => { |
| 25738 | // pointer to anonymous struct to pointer to union | 25792 | // pointer to anonymous struct to pointer to union |
| 25739 | if (inst_ty.isSinglePointer() and | 25793 | if (inst_ty.isSinglePointer() and |
| ... | @@ -25767,7 +25821,7 @@ fn coerceExtra( | ... | @@ -25767,7 +25821,7 @@ fn coerceExtra( |
| 25767 | else => {}, | 25821 | else => {}, |
| 25768 | }, | 25822 | }, |
| 25769 | .Slice => to_slice: { | 25823 | .Slice => to_slice: { |
| 25770 | if (inst_ty.zigTypeTag() == .Array) { | 25824 | if (inst_ty.zigTypeTag(mod) == .Array) { |
| 25771 | return sema.fail( | 25825 | return sema.fail( |
| 25772 | block, | 25826 | block, |
| 25773 | inst_src, | 25827 | inst_src, |
| ... | @@ -25789,7 +25843,7 @@ fn coerceExtra( | ... | @@ -25789,7 +25843,7 @@ fn coerceExtra( |
| 25789 | .ptr = if (dest_info.@"align" != 0) | 25843 | .ptr = if (dest_info.@"align" != 0) |
| 25790 | try Value.Tag.int_u64.create(sema.arena, dest_info.@"align") | 25844 | try Value.Tag.int_u64.create(sema.arena, dest_info.@"align") |
| 25791 | else | 25845 | else |
| 25792 | try dest_info.pointee_type.lazyAbiAlignment(target, sema.arena), | 25846 | try dest_info.pointee_type.lazyAbiAlignment(mod, sema.arena), |
| 25793 | .len = Value.zero, | 25847 | .len = Value.zero, |
| 25794 | }); | 25848 | }); |
| 25795 | return sema.addConstant(dest_ty, slice_val); | 25849 | return sema.addConstant(dest_ty, slice_val); |
| ... | @@ -25834,13 +25888,13 @@ fn coerceExtra( | ... | @@ -25834,13 +25888,13 @@ fn coerceExtra( |
| 25834 | }, | 25888 | }, |
| 25835 | } | 25889 | } |
| 25836 | }, | 25890 | }, |
| 25837 | .Int, .ComptimeInt => switch (inst_ty.zigTypeTag()) { | 25891 | .Int, .ComptimeInt => switch (inst_ty.zigTypeTag(mod)) { |
| 25838 | .Float, .ComptimeFloat => float: { | 25892 | .Float, .ComptimeFloat => float: { |
| 25839 | if (is_undef) { | 25893 | if (is_undef) { |
| 25840 | return sema.addConstUndef(dest_ty); | 25894 | return sema.addConstUndef(dest_ty); |
| 25841 | } | 25895 | } |
| 25842 | const val = (try sema.resolveMaybeUndefVal(inst)) orelse { | 25896 | const val = (try sema.resolveMaybeUndefVal(inst)) orelse { |
| 25843 | if (dest_ty.zigTypeTag() == .ComptimeInt) { | 25897 | if (dest_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 25844 | if (!opts.report_err) return error.NotCoercible; | 25898 | if (!opts.report_err) return error.NotCoercible; |
| 25845 | return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known"); | 25899 | return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known"); |
| 25846 | } | 25900 | } |
| ... | @@ -25870,15 +25924,15 @@ fn coerceExtra( | ... | @@ -25870,15 +25924,15 @@ fn coerceExtra( |
| 25870 | } | 25924 | } |
| 25871 | return try sema.addConstant(dest_ty, val); | 25925 | return try sema.addConstant(dest_ty, val); |
| 25872 | } | 25926 | } |
| 25873 | if (dest_ty.zigTypeTag() == .ComptimeInt) { | 25927 | if (dest_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 25874 | if (!opts.report_err) return error.NotCoercible; | 25928 | if (!opts.report_err) return error.NotCoercible; |
| 25875 | if (opts.no_cast_to_comptime_int) return inst; | 25929 | if (opts.no_cast_to_comptime_int) return inst; |
| 25876 | return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known"); | 25930 | return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known"); |
| 25877 | } | 25931 | } |
| 25878 | 25932 | ||
| 25879 | // integer widening | 25933 | // integer widening |
| 25880 | const dst_info = dest_ty.intInfo(target); | 25934 | const dst_info = dest_ty.intInfo(mod); |
| 25881 | const src_info = inst_ty.intInfo(target); | 25935 | const src_info = inst_ty.intInfo(mod); |
| 25882 | if ((src_info.signedness == dst_info.signedness and dst_info.bits >= src_info.bits) or | 25936 | if ((src_info.signedness == dst_info.signedness and dst_info.bits >= src_info.bits) or |
| 25883 | // small enough unsigned ints can get casted to large enough signed ints | 25937 | // small enough unsigned ints can get casted to large enough signed ints |
| 25884 | (dst_info.signedness == .signed and dst_info.bits > src_info.bits)) | 25938 | (dst_info.signedness == .signed and dst_info.bits > src_info.bits)) |
| ... | @@ -25892,7 +25946,7 @@ fn coerceExtra( | ... | @@ -25892,7 +25946,7 @@ fn coerceExtra( |
| 25892 | }, | 25946 | }, |
| 25893 | else => {}, | 25947 | else => {}, |
| 25894 | }, | 25948 | }, |
| 25895 | .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) { | 25949 | .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag(mod)) { |
| 25896 | .ComptimeFloat => { | 25950 | .ComptimeFloat => { |
| 25897 | const val = try sema.resolveConstValue(block, .unneeded, inst, ""); | 25951 | const val = try sema.resolveConstValue(block, .unneeded, inst, ""); |
| 25898 | const result_val = try val.floatCast(sema.arena, dest_ty, target); | 25952 | const result_val = try val.floatCast(sema.arena, dest_ty, target); |
| ... | @@ -25913,7 +25967,7 @@ fn coerceExtra( | ... | @@ -25913,7 +25967,7 @@ fn coerceExtra( |
| 25913 | ); | 25967 | ); |
| 25914 | } | 25968 | } |
| 25915 | return try sema.addConstant(dest_ty, result_val); | 25969 | return try sema.addConstant(dest_ty, result_val); |
| 25916 | } else if (dest_ty.zigTypeTag() == .ComptimeFloat) { | 25970 | } else if (dest_ty.zigTypeTag(mod) == .ComptimeFloat) { |
| 25917 | if (!opts.report_err) return error.NotCoercible; | 25971 | if (!opts.report_err) return error.NotCoercible; |
| 25918 | return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known"); | 25972 | return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known"); |
| 25919 | } | 25973 | } |
| ... | @@ -25931,7 +25985,7 @@ fn coerceExtra( | ... | @@ -25931,7 +25985,7 @@ fn coerceExtra( |
| 25931 | return sema.addConstUndef(dest_ty); | 25985 | return sema.addConstUndef(dest_ty); |
| 25932 | } | 25986 | } |
| 25933 | const val = (try sema.resolveMaybeUndefVal(inst)) orelse { | 25987 | const val = (try sema.resolveMaybeUndefVal(inst)) orelse { |
| 25934 | if (dest_ty.zigTypeTag() == .ComptimeFloat) { | 25988 | if (dest_ty.zigTypeTag(mod) == .ComptimeFloat) { |
| 25935 | if (!opts.report_err) return error.NotCoercible; | 25989 | if (!opts.report_err) return error.NotCoercible; |
| 25936 | return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known"); | 25990 | return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known"); |
| 25937 | } | 25991 | } |
| ... | @@ -25955,7 +26009,7 @@ fn coerceExtra( | ... | @@ -25955,7 +26009,7 @@ fn coerceExtra( |
| 25955 | }, | 26009 | }, |
| 25956 | else => {}, | 26010 | else => {}, |
| 25957 | }, | 26011 | }, |
| 25958 | .Enum => switch (inst_ty.zigTypeTag()) { | 26012 | .Enum => switch (inst_ty.zigTypeTag(mod)) { |
| 25959 | .EnumLiteral => { | 26013 | .EnumLiteral => { |
| 25960 | // enum literal to enum | 26014 | // enum literal to enum |
| 25961 | const val = try sema.resolveConstValue(block, .unneeded, inst, ""); | 26015 | const val = try sema.resolveConstValue(block, .unneeded, inst, ""); |
| ... | @@ -25991,7 +26045,7 @@ fn coerceExtra( | ... | @@ -25991,7 +26045,7 @@ fn coerceExtra( |
| 25991 | }, | 26045 | }, |
| 25992 | else => {}, | 26046 | else => {}, |
| 25993 | }, | 26047 | }, |
| 25994 | .ErrorUnion => switch (inst_ty.zigTypeTag()) { | 26048 | .ErrorUnion => switch (inst_ty.zigTypeTag(mod)) { |
| 25995 | .ErrorUnion => eu: { | 26049 | .ErrorUnion => eu: { |
| 25996 | if (maybe_inst_val) |inst_val| { | 26050 | if (maybe_inst_val) |inst_val| { |
| 25997 | switch (inst_val.tag()) { | 26051 | switch (inst_val.tag()) { |
| ... | @@ -26031,7 +26085,7 @@ fn coerceExtra( | ... | @@ -26031,7 +26085,7 @@ fn coerceExtra( |
| 26031 | }; | 26085 | }; |
| 26032 | }, | 26086 | }, |
| 26033 | }, | 26087 | }, |
| 26034 | .Union => switch (inst_ty.zigTypeTag()) { | 26088 | .Union => switch (inst_ty.zigTypeTag(mod)) { |
| 26035 | .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src), | 26089 | .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src), |
| 26036 | .Struct => { | 26090 | .Struct => { |
| 26037 | if (inst_ty.isAnonStruct()) { | 26091 | if (inst_ty.isAnonStruct()) { |
| ... | @@ -26043,7 +26097,7 @@ fn coerceExtra( | ... | @@ -26043,7 +26097,7 @@ fn coerceExtra( |
| 26043 | }, | 26097 | }, |
| 26044 | else => {}, | 26098 | else => {}, |
| 26045 | }, | 26099 | }, |
| 26046 | .Array => switch (inst_ty.zigTypeTag()) { | 26100 | .Array => switch (inst_ty.zigTypeTag(mod)) { |
| 26047 | .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src), | 26101 | .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src), |
| 26048 | .Struct => { | 26102 | .Struct => { |
| 26049 | if (inst == .empty_struct) { | 26103 | if (inst == .empty_struct) { |
| ... | @@ -26058,7 +26112,7 @@ fn coerceExtra( | ... | @@ -26058,7 +26112,7 @@ fn coerceExtra( |
| 26058 | }, | 26112 | }, |
| 26059 | else => {}, | 26113 | else => {}, |
| 26060 | }, | 26114 | }, |
| 26061 | .Vector => switch (inst_ty.zigTypeTag()) { | 26115 | .Vector => switch (inst_ty.zigTypeTag(mod)) { |
| 26062 | .Array, .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src), | 26116 | .Array, .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src), |
| 26063 | .Struct => { | 26117 | .Struct => { |
| 26064 | if (inst_ty.isTuple()) { | 26118 | if (inst_ty.isTuple()) { |
| ... | @@ -26093,7 +26147,7 @@ fn coerceExtra( | ... | @@ -26093,7 +26147,7 @@ fn coerceExtra( |
| 26093 | 26147 | ||
| 26094 | if (!opts.report_err) return error.NotCoercible; | 26148 | if (!opts.report_err) return error.NotCoercible; |
| 26095 | 26149 | ||
| 26096 | if (opts.is_ret and dest_ty.zigTypeTag() == .NoReturn) { | 26150 | if (opts.is_ret and dest_ty.zigTypeTag(mod) == .NoReturn) { |
| 26097 | const msg = msg: { | 26151 | const msg = msg: { |
| 26098 | const msg = try sema.errMsg(block, inst_src, "function declared 'noreturn' returns", .{}); | 26152 | const msg = try sema.errMsg(block, inst_src, "function declared 'noreturn' returns", .{}); |
| 26099 | errdefer msg.destroy(sema.gpa); | 26153 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -26111,7 +26165,7 @@ fn coerceExtra( | ... | @@ -26111,7 +26165,7 @@ fn coerceExtra( |
| 26111 | errdefer msg.destroy(sema.gpa); | 26165 | errdefer msg.destroy(sema.gpa); |
| 26112 | 26166 | ||
| 26113 | // E!T to T | 26167 | // E!T to T |
| 26114 | if (inst_ty.zigTypeTag() == .ErrorUnion and | 26168 | if (inst_ty.zigTypeTag(mod) == .ErrorUnion and |
| 26115 | (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(), dest_ty, false, target, dest_ty_src, inst_src)) == .ok) | 26169 | (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(), dest_ty, false, target, dest_ty_src, inst_src)) == .ok) |
| 26116 | { | 26170 | { |
| 26117 | try sema.errNote(block, inst_src, msg, "cannot convert error union to payload type", .{}); | 26171 | try sema.errNote(block, inst_src, msg, "cannot convert error union to payload type", .{}); |
| ... | @@ -26120,7 +26174,7 @@ fn coerceExtra( | ... | @@ -26120,7 +26174,7 @@ fn coerceExtra( |
| 26120 | 26174 | ||
| 26121 | // ?T to T | 26175 | // ?T to T |
| 26122 | var buf: Type.Payload.ElemType = undefined; | 26176 | var buf: Type.Payload.ElemType = undefined; |
| 26123 | if (inst_ty.zigTypeTag() == .Optional and | 26177 | if (inst_ty.zigTypeTag(mod) == .Optional and |
| 26124 | (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(&buf), dest_ty, false, target, dest_ty_src, inst_src)) == .ok) | 26178 | (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(&buf), dest_ty, false, target, dest_ty_src, inst_src)) == .ok) |
| 26125 | { | 26179 | { |
| 26126 | try sema.errNote(block, inst_src, msg, "cannot convert optional to payload type", .{}); | 26180 | try sema.errNote(block, inst_src, msg, "cannot convert optional to payload type", .{}); |
| ... | @@ -26133,7 +26187,7 @@ fn coerceExtra( | ... | @@ -26133,7 +26187,7 @@ fn coerceExtra( |
| 26133 | if (opts.is_ret and sema.mod.test_functions.get(sema.func.?.owner_decl) == null) { | 26187 | if (opts.is_ret and sema.mod.test_functions.get(sema.func.?.owner_decl) == null) { |
| 26134 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; | 26188 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; |
| 26135 | const src_decl = sema.mod.declPtr(sema.func.?.owner_decl); | 26189 | const src_decl = sema.mod.declPtr(sema.func.?.owner_decl); |
| 26136 | if (inst_ty.isError() and !dest_ty.isError()) { | 26190 | if (inst_ty.isError(mod) and !dest_ty.isError(mod)) { |
| 26137 | try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "function cannot return an error", .{}); | 26191 | try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "function cannot return an error", .{}); |
| 26138 | } else { | 26192 | } else { |
| 26139 | try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "function return type declared here", .{}); | 26193 | try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "function return type declared here", .{}); |
| ... | @@ -26264,6 +26318,7 @@ const InMemoryCoercionResult = union(enum) { | ... | @@ -26264,6 +26318,7 @@ const InMemoryCoercionResult = union(enum) { |
| 26264 | } | 26318 | } |
| 26265 | 26319 | ||
| 26266 | fn report(res: *const InMemoryCoercionResult, sema: *Sema, block: *Block, src: LazySrcLoc, msg: *Module.ErrorMsg) !void { | 26320 | fn report(res: *const InMemoryCoercionResult, sema: *Sema, block: *Block, src: LazySrcLoc, msg: *Module.ErrorMsg) !void { |
| 26321 | const mod = sema.mod; | ||
| 26267 | var cur = res; | 26322 | var cur = res; |
| 26268 | while (true) switch (cur.*) { | 26323 | while (true) switch (cur.*) { |
| 26269 | .ok => unreachable, | 26324 | .ok => unreachable, |
| ... | @@ -26445,8 +26500,8 @@ const InMemoryCoercionResult = union(enum) { | ... | @@ -26445,8 +26500,8 @@ const InMemoryCoercionResult = union(enum) { |
| 26445 | break; | 26500 | break; |
| 26446 | }, | 26501 | }, |
| 26447 | .ptr_allowzero => |pair| { | 26502 | .ptr_allowzero => |pair| { |
| 26448 | const wanted_allow_zero = pair.wanted.ptrAllowsZero(); | 26503 | const wanted_allow_zero = pair.wanted.ptrAllowsZero(mod); |
| 26449 | const actual_allow_zero = pair.actual.ptrAllowsZero(); | 26504 | const actual_allow_zero = pair.actual.ptrAllowsZero(mod); |
| 26450 | if (actual_allow_zero and !wanted_allow_zero) { | 26505 | if (actual_allow_zero and !wanted_allow_zero) { |
| 26451 | try sema.errNote(block, src, msg, "'{}' could have null values which are illegal in type '{}'", .{ | 26506 | try sema.errNote(block, src, msg, "'{}' could have null values which are illegal in type '{}'", .{ |
| 26452 | pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), | 26507 | pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), |
| ... | @@ -26522,13 +26577,15 @@ fn coerceInMemoryAllowed( | ... | @@ -26522,13 +26577,15 @@ fn coerceInMemoryAllowed( |
| 26522 | dest_src: LazySrcLoc, | 26577 | dest_src: LazySrcLoc, |
| 26523 | src_src: LazySrcLoc, | 26578 | src_src: LazySrcLoc, |
| 26524 | ) CompileError!InMemoryCoercionResult { | 26579 | ) CompileError!InMemoryCoercionResult { |
| 26525 | if (dest_ty.eql(src_ty, sema.mod)) | 26580 | const mod = sema.mod; |
| 26581 | |||
| 26582 | if (dest_ty.eql(src_ty, mod)) | ||
| 26526 | return .ok; | 26583 | return .ok; |
| 26527 | 26584 | ||
| 26528 | // Differently-named integers with the same number of bits. | 26585 | // Differently-named integers with the same number of bits. |
| 26529 | if (dest_ty.zigTypeTag() == .Int and src_ty.zigTypeTag() == .Int) { | 26586 | if (dest_ty.zigTypeTag(mod) == .Int and src_ty.zigTypeTag(mod) == .Int) { |
| 26530 | const dest_info = dest_ty.intInfo(target); | 26587 | const dest_info = dest_ty.intInfo(mod); |
| 26531 | const src_info = src_ty.intInfo(target); | 26588 | const src_info = src_ty.intInfo(mod); |
| 26532 | 26589 | ||
| 26533 | if (dest_info.signedness == src_info.signedness and | 26590 | if (dest_info.signedness == src_info.signedness and |
| 26534 | dest_info.bits == src_info.bits) | 26591 | dest_info.bits == src_info.bits) |
| ... | @@ -26551,7 +26608,7 @@ fn coerceInMemoryAllowed( | ... | @@ -26551,7 +26608,7 @@ fn coerceInMemoryAllowed( |
| 26551 | } | 26608 | } |
| 26552 | 26609 | ||
| 26553 | // Differently-named floats with the same number of bits. | 26610 | // Differently-named floats with the same number of bits. |
| 26554 | if (dest_ty.zigTypeTag() == .Float and src_ty.zigTypeTag() == .Float) { | 26611 | if (dest_ty.zigTypeTag(mod) == .Float and src_ty.zigTypeTag(mod) == .Float) { |
| 26555 | const dest_bits = dest_ty.floatBits(target); | 26612 | const dest_bits = dest_ty.floatBits(target); |
| 26556 | const src_bits = src_ty.floatBits(target); | 26613 | const src_bits = src_ty.floatBits(target); |
| 26557 | if (dest_bits == src_bits) { | 26614 | if (dest_bits == src_bits) { |
| ... | @@ -26575,8 +26632,8 @@ fn coerceInMemoryAllowed( | ... | @@ -26575,8 +26632,8 @@ fn coerceInMemoryAllowed( |
| 26575 | return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src); | 26632 | return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src); |
| 26576 | } | 26633 | } |
| 26577 | 26634 | ||
| 26578 | const dest_tag = dest_ty.zigTypeTag(); | 26635 | const dest_tag = dest_ty.zigTypeTag(mod); |
| 26579 | const src_tag = src_ty.zigTypeTag(); | 26636 | const src_tag = src_ty.zigTypeTag(mod); |
| 26580 | 26637 | ||
| 26581 | // Functions | 26638 | // Functions |
| 26582 | if (dest_tag == .Fn and src_tag == .Fn) { | 26639 | if (dest_tag == .Fn and src_tag == .Fn) { |
| ... | @@ -26624,7 +26681,7 @@ fn coerceInMemoryAllowed( | ... | @@ -26624,7 +26681,7 @@ fn coerceInMemoryAllowed( |
| 26624 | } | 26681 | } |
| 26625 | const ok_sent = dest_info.sentinel == null or | 26682 | const ok_sent = dest_info.sentinel == null or |
| 26626 | (src_info.sentinel != null and | 26683 | (src_info.sentinel != null and |
| 26627 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.elem_type, sema.mod)); | 26684 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.elem_type, mod)); |
| 26628 | if (!ok_sent) { | 26685 | if (!ok_sent) { |
| 26629 | return InMemoryCoercionResult{ .array_sentinel = .{ | 26686 | return InMemoryCoercionResult{ .array_sentinel = .{ |
| 26630 | .actual = src_info.sentinel orelse Value.initTag(.unreachable_value), | 26687 | .actual = src_info.sentinel orelse Value.initTag(.unreachable_value), |
| ... | @@ -26646,8 +26703,8 @@ fn coerceInMemoryAllowed( | ... | @@ -26646,8 +26703,8 @@ fn coerceInMemoryAllowed( |
| 26646 | } }; | 26703 | } }; |
| 26647 | } | 26704 | } |
| 26648 | 26705 | ||
| 26649 | const dest_elem_ty = dest_ty.scalarType(); | 26706 | const dest_elem_ty = dest_ty.scalarType(mod); |
| 26650 | const src_elem_ty = src_ty.scalarType(); | 26707 | const src_elem_ty = src_ty.scalarType(mod); |
| 26651 | const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src); | 26708 | const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src); |
| 26652 | if (child != .ok) { | 26709 | if (child != .ok) { |
| 26653 | return InMemoryCoercionResult{ .vector_elem = .{ | 26710 | return InMemoryCoercionResult{ .vector_elem = .{ |
| ... | @@ -26923,6 +26980,7 @@ fn coerceInMemoryAllowedPtrs( | ... | @@ -26923,6 +26980,7 @@ fn coerceInMemoryAllowedPtrs( |
| 26923 | dest_src: LazySrcLoc, | 26980 | dest_src: LazySrcLoc, |
| 26924 | src_src: LazySrcLoc, | 26981 | src_src: LazySrcLoc, |
| 26925 | ) !InMemoryCoercionResult { | 26982 | ) !InMemoryCoercionResult { |
| 26983 | const mod = sema.mod; | ||
| 26926 | const dest_info = dest_ptr_ty.ptrInfo().data; | 26984 | const dest_info = dest_ptr_ty.ptrInfo().data; |
| 26927 | const src_info = src_ptr_ty.ptrInfo().data; | 26985 | const src_info = src_ptr_ty.ptrInfo().data; |
| 26928 | 26986 | ||
| ... | @@ -26964,8 +27022,8 @@ fn coerceInMemoryAllowedPtrs( | ... | @@ -26964,8 +27022,8 @@ fn coerceInMemoryAllowedPtrs( |
| 26964 | } }; | 27022 | } }; |
| 26965 | } | 27023 | } |
| 26966 | 27024 | ||
| 26967 | const dest_allow_zero = dest_ty.ptrAllowsZero(); | 27025 | const dest_allow_zero = dest_ty.ptrAllowsZero(mod); |
| 26968 | const src_allow_zero = src_ty.ptrAllowsZero(); | 27026 | const src_allow_zero = src_ty.ptrAllowsZero(mod); |
| 26969 | 27027 | ||
| 26970 | const ok_allows_zero = (dest_allow_zero and | 27028 | const ok_allows_zero = (dest_allow_zero and |
| 26971 | (src_allow_zero or !dest_is_mut)) or | 27029 | (src_allow_zero or !dest_is_mut)) or |
| ... | @@ -27013,12 +27071,12 @@ fn coerceInMemoryAllowedPtrs( | ... | @@ -27013,12 +27071,12 @@ fn coerceInMemoryAllowedPtrs( |
| 27013 | const src_align = if (src_info.@"align" != 0) | 27071 | const src_align = if (src_info.@"align" != 0) |
| 27014 | src_info.@"align" | 27072 | src_info.@"align" |
| 27015 | else | 27073 | else |
| 27016 | src_info.pointee_type.abiAlignment(target); | 27074 | src_info.pointee_type.abiAlignment(mod); |
| 27017 | 27075 | ||
| 27018 | const dest_align = if (dest_info.@"align" != 0) | 27076 | const dest_align = if (dest_info.@"align" != 0) |
| 27019 | dest_info.@"align" | 27077 | dest_info.@"align" |
| 27020 | else | 27078 | else |
| 27021 | dest_info.pointee_type.abiAlignment(target); | 27079 | dest_info.pointee_type.abiAlignment(mod); |
| 27022 | 27080 | ||
| 27023 | if (dest_align > src_align) { | 27081 | if (dest_align > src_align) { |
| 27024 | return InMemoryCoercionResult{ .ptr_alignment = .{ | 27082 | return InMemoryCoercionResult{ .ptr_alignment = .{ |
| ... | @@ -27041,8 +27099,9 @@ fn coerceVarArgParam( | ... | @@ -27041,8 +27099,9 @@ fn coerceVarArgParam( |
| 27041 | ) !Air.Inst.Ref { | 27099 | ) !Air.Inst.Ref { |
| 27042 | if (block.is_typeof) return inst; | 27100 | if (block.is_typeof) return inst; |
| 27043 | 27101 | ||
| 27102 | const mod = sema.mod; | ||
| 27044 | const uncasted_ty = sema.typeOf(inst); | 27103 | const uncasted_ty = sema.typeOf(inst); |
| 27045 | const coerced = switch (uncasted_ty.zigTypeTag()) { | 27104 | const coerced = switch (uncasted_ty.zigTypeTag(mod)) { |
| 27046 | // TODO consider casting to c_int/f64 if they fit | 27105 | // TODO consider casting to c_int/f64 if they fit |
| 27047 | .ComptimeInt, .ComptimeFloat => return sema.fail( | 27106 | .ComptimeInt, .ComptimeFloat => return sema.fail( |
| 27048 | block, | 27107 | block, |
| ... | @@ -27124,7 +27183,8 @@ fn storePtr2( | ... | @@ -27124,7 +27183,8 @@ fn storePtr2( |
| 27124 | // this code does not handle tuple-to-struct coercion which requires dealing with missing | 27183 | // this code does not handle tuple-to-struct coercion which requires dealing with missing |
| 27125 | // fields. | 27184 | // fields. |
| 27126 | const operand_ty = sema.typeOf(uncasted_operand); | 27185 | const operand_ty = sema.typeOf(uncasted_operand); |
| 27127 | if (operand_ty.isTuple() and elem_ty.zigTypeTag() == .Array) { | 27186 | const mod = sema.mod; |
| 27187 | if (operand_ty.isTuple() and elem_ty.zigTypeTag(mod) == .Array) { | ||
| 27128 | const field_count = operand_ty.structFieldCount(); | 27188 | const field_count = operand_ty.structFieldCount(); |
| 27129 | var i: u32 = 0; | 27189 | var i: u32 = 0; |
| 27130 | while (i < field_count) : (i += 1) { | 27190 | while (i < field_count) : (i += 1) { |
| ... | @@ -27225,7 +27285,8 @@ fn storePtr2( | ... | @@ -27225,7 +27285,8 @@ fn storePtr2( |
| 27225 | /// lengths match. | 27285 | /// lengths match. |
| 27226 | fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref { | 27286 | fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref { |
| 27227 | const array_ty = sema.typeOf(ptr).childType(); | 27287 | const array_ty = sema.typeOf(ptr).childType(); |
| 27228 | if (array_ty.zigTypeTag() != .Array) return null; | 27288 | const mod = sema.mod; |
| 27289 | if (array_ty.zigTypeTag(mod) != .Array) return null; | ||
| 27229 | var ptr_inst = Air.refToIndex(ptr) orelse return null; | 27290 | var ptr_inst = Air.refToIndex(ptr) orelse return null; |
| 27230 | const air_datas = sema.air_instructions.items(.data); | 27291 | const air_datas = sema.air_instructions.items(.data); |
| 27231 | const air_tags = sema.air_instructions.items(.tag); | 27292 | const air_tags = sema.air_instructions.items(.tag); |
| ... | @@ -27237,7 +27298,7 @@ fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref { | ... | @@ -27237,7 +27298,7 @@ fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref { |
| 27237 | .pointer => prev_ptr_ty.castTag(.pointer).?.data.pointee_type, | 27298 | .pointer => prev_ptr_ty.castTag(.pointer).?.data.pointee_type, |
| 27238 | else => return null, | 27299 | else => return null, |
| 27239 | }; | 27300 | }; |
| 27240 | if (prev_ptr_child_ty.zigTypeTag() == .Vector) break prev_ptr; | 27301 | if (prev_ptr_child_ty.zigTypeTag(mod) == .Vector) break prev_ptr; |
| 27241 | ptr_inst = Air.refToIndex(prev_ptr) orelse return null; | 27302 | ptr_inst = Air.refToIndex(prev_ptr) orelse return null; |
| 27242 | } else return null; | 27303 | } else return null; |
| 27243 | 27304 | ||
| ... | @@ -27263,6 +27324,7 @@ fn storePtrVal( | ... | @@ -27263,6 +27324,7 @@ fn storePtrVal( |
| 27263 | operand_val: Value, | 27324 | operand_val: Value, |
| 27264 | operand_ty: Type, | 27325 | operand_ty: Type, |
| 27265 | ) !void { | 27326 | ) !void { |
| 27327 | const mod = sema.mod; | ||
| 27266 | var mut_kit = try sema.beginComptimePtrMutation(block, src, ptr_val, operand_ty); | 27328 | var mut_kit = try sema.beginComptimePtrMutation(block, src, ptr_val, operand_ty); |
| 27267 | try sema.checkComptimeVarStore(block, src, mut_kit.decl_ref_mut); | 27329 | try sema.checkComptimeVarStore(block, src, mut_kit.decl_ref_mut); |
| 27268 | 27330 | ||
| ... | @@ -27281,8 +27343,7 @@ fn storePtrVal( | ... | @@ -27281,8 +27343,7 @@ fn storePtrVal( |
| 27281 | val_ptr.* = try operand_val.copy(arena); | 27343 | val_ptr.* = try operand_val.copy(arena); |
| 27282 | }, | 27344 | }, |
| 27283 | .reinterpret => |reinterpret| { | 27345 | .reinterpret => |reinterpret| { |
| 27284 | const target = sema.mod.getTarget(); | 27346 | const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(mod)); |
| 27285 | const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(target)); | ||
| 27286 | const buffer = try sema.gpa.alloc(u8, abi_size); | 27347 | const buffer = try sema.gpa.alloc(u8, abi_size); |
| 27287 | defer sema.gpa.free(buffer); | 27348 | defer sema.gpa.free(buffer); |
| 27288 | reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, sema.mod, buffer) catch |err| switch (err) { | 27349 | reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, sema.mod, buffer) catch |err| switch (err) { |
| ... | @@ -27354,7 +27415,7 @@ fn beginComptimePtrMutation( | ... | @@ -27354,7 +27415,7 @@ fn beginComptimePtrMutation( |
| 27354 | ptr_val: Value, | 27415 | ptr_val: Value, |
| 27355 | ptr_elem_ty: Type, | 27416 | ptr_elem_ty: Type, |
| 27356 | ) CompileError!ComptimePtrMutationKit { | 27417 | ) CompileError!ComptimePtrMutationKit { |
| 27357 | const target = sema.mod.getTarget(); | 27418 | const mod = sema.mod; |
| 27358 | switch (ptr_val.tag()) { | 27419 | switch (ptr_val.tag()) { |
| 27359 | .decl_ref_mut => { | 27420 | .decl_ref_mut => { |
| 27360 | const decl_ref_mut = ptr_val.castTag(.decl_ref_mut).?.data; | 27421 | const decl_ref_mut = ptr_val.castTag(.decl_ref_mut).?.data; |
| ... | @@ -27375,7 +27436,7 @@ fn beginComptimePtrMutation( | ... | @@ -27375,7 +27436,7 @@ fn beginComptimePtrMutation( |
| 27375 | var parent = try sema.beginComptimePtrMutation(block, src, elem_ptr.array_ptr, elem_ptr.elem_ty); | 27436 | var parent = try sema.beginComptimePtrMutation(block, src, elem_ptr.array_ptr, elem_ptr.elem_ty); |
| 27376 | 27437 | ||
| 27377 | switch (parent.pointee) { | 27438 | switch (parent.pointee) { |
| 27378 | .direct => |val_ptr| switch (parent.ty.zigTypeTag()) { | 27439 | .direct => |val_ptr| switch (parent.ty.zigTypeTag(mod)) { |
| 27379 | .Array, .Vector => { | 27440 | .Array, .Vector => { |
| 27380 | const check_len = parent.ty.arrayLenIncludingSentinel(); | 27441 | const check_len = parent.ty.arrayLenIncludingSentinel(); |
| 27381 | if (elem_ptr.index >= check_len) { | 27442 | if (elem_ptr.index >= check_len) { |
| ... | @@ -27570,7 +27631,7 @@ fn beginComptimePtrMutation( | ... | @@ -27570,7 +27631,7 @@ fn beginComptimePtrMutation( |
| 27570 | }, | 27631 | }, |
| 27571 | }, | 27632 | }, |
| 27572 | .reinterpret => |reinterpret| { | 27633 | .reinterpret => |reinterpret| { |
| 27573 | if (!elem_ptr.elem_ty.hasWellDefinedLayout()) { | 27634 | if (!elem_ptr.elem_ty.hasWellDefinedLayout(mod)) { |
| 27574 | // Even though the parent value type has well-defined memory layout, our | 27635 | // Even though the parent value type has well-defined memory layout, our |
| 27575 | // pointer type does not. | 27636 | // pointer type does not. |
| 27576 | return ComptimePtrMutationKit{ | 27637 | return ComptimePtrMutationKit{ |
| ... | @@ -27608,7 +27669,7 @@ fn beginComptimePtrMutation( | ... | @@ -27608,7 +27669,7 @@ fn beginComptimePtrMutation( |
| 27608 | const arena = parent.beginArena(sema.mod); | 27669 | const arena = parent.beginArena(sema.mod); |
| 27609 | defer parent.finishArena(sema.mod); | 27670 | defer parent.finishArena(sema.mod); |
| 27610 | 27671 | ||
| 27611 | switch (parent.ty.zigTypeTag()) { | 27672 | switch (parent.ty.zigTypeTag(mod)) { |
| 27612 | .Struct => { | 27673 | .Struct => { |
| 27613 | const fields = try arena.alloc(Value, parent.ty.structFieldCount()); | 27674 | const fields = try arena.alloc(Value, parent.ty.structFieldCount()); |
| 27614 | @memset(fields, Value.undef); | 27675 | @memset(fields, Value.undef); |
| ... | @@ -27746,7 +27807,7 @@ fn beginComptimePtrMutation( | ... | @@ -27746,7 +27807,7 @@ fn beginComptimePtrMutation( |
| 27746 | else => unreachable, | 27807 | else => unreachable, |
| 27747 | }, | 27808 | }, |
| 27748 | .reinterpret => |reinterpret| { | 27809 | .reinterpret => |reinterpret| { |
| 27749 | const field_offset_u64 = field_ptr.container_ty.structFieldOffset(field_index, target); | 27810 | const field_offset_u64 = field_ptr.container_ty.structFieldOffset(field_index, mod); |
| 27750 | const field_offset = try sema.usizeCast(block, src, field_offset_u64); | 27811 | const field_offset = try sema.usizeCast(block, src, field_offset_u64); |
| 27751 | return ComptimePtrMutationKit{ | 27812 | return ComptimePtrMutationKit{ |
| 27752 | .decl_ref_mut = parent.decl_ref_mut, | 27813 | .decl_ref_mut = parent.decl_ref_mut, |
| ... | @@ -27872,7 +27933,8 @@ fn beginComptimePtrMutationInner( | ... | @@ -27872,7 +27933,8 @@ fn beginComptimePtrMutationInner( |
| 27872 | ptr_elem_ty: Type, | 27933 | ptr_elem_ty: Type, |
| 27873 | decl_ref_mut: Value.Payload.DeclRefMut.Data, | 27934 | decl_ref_mut: Value.Payload.DeclRefMut.Data, |
| 27874 | ) CompileError!ComptimePtrMutationKit { | 27935 | ) CompileError!ComptimePtrMutationKit { |
| 27875 | const target = sema.mod.getTarget(); | 27936 | const mod = sema.mod; |
| 27937 | const target = mod.getTarget(); | ||
| 27876 | const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok; | 27938 | const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok; |
| 27877 | if (coerce_ok) { | 27939 | if (coerce_ok) { |
| 27878 | return ComptimePtrMutationKit{ | 27940 | return ComptimePtrMutationKit{ |
| ... | @@ -27883,7 +27945,7 @@ fn beginComptimePtrMutationInner( | ... | @@ -27883,7 +27945,7 @@ fn beginComptimePtrMutationInner( |
| 27883 | } | 27945 | } |
| 27884 | 27946 | ||
| 27885 | // Handle the case that the decl is an array and we're actually trying to point to an element. | 27947 | // Handle the case that the decl is an array and we're actually trying to point to an element. |
| 27886 | if (decl_ty.isArrayOrVector()) { | 27948 | if (decl_ty.isArrayOrVector(mod)) { |
| 27887 | const decl_elem_ty = decl_ty.childType(); | 27949 | const decl_elem_ty = decl_ty.childType(); |
| 27888 | if ((try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_elem_ty, true, target, src, src)) == .ok) { | 27950 | if ((try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_elem_ty, true, target, src, src)) == .ok) { |
| 27889 | return ComptimePtrMutationKit{ | 27951 | return ComptimePtrMutationKit{ |
| ... | @@ -27894,14 +27956,14 @@ fn beginComptimePtrMutationInner( | ... | @@ -27894,14 +27956,14 @@ fn beginComptimePtrMutationInner( |
| 27894 | } | 27956 | } |
| 27895 | } | 27957 | } |
| 27896 | 27958 | ||
| 27897 | if (!decl_ty.hasWellDefinedLayout()) { | 27959 | if (!decl_ty.hasWellDefinedLayout(mod)) { |
| 27898 | return ComptimePtrMutationKit{ | 27960 | return ComptimePtrMutationKit{ |
| 27899 | .decl_ref_mut = decl_ref_mut, | 27961 | .decl_ref_mut = decl_ref_mut, |
| 27900 | .pointee = .{ .bad_decl_ty = {} }, | 27962 | .pointee = .{ .bad_decl_ty = {} }, |
| 27901 | .ty = decl_ty, | 27963 | .ty = decl_ty, |
| 27902 | }; | 27964 | }; |
| 27903 | } | 27965 | } |
| 27904 | if (!ptr_elem_ty.hasWellDefinedLayout()) { | 27966 | if (!ptr_elem_ty.hasWellDefinedLayout(mod)) { |
| 27905 | return ComptimePtrMutationKit{ | 27967 | return ComptimePtrMutationKit{ |
| 27906 | .decl_ref_mut = decl_ref_mut, | 27968 | .decl_ref_mut = decl_ref_mut, |
| 27907 | .pointee = .{ .bad_ptr_ty = {} }, | 27969 | .pointee = .{ .bad_ptr_ty = {} }, |
| ... | @@ -27951,6 +28013,7 @@ fn beginComptimePtrLoad( | ... | @@ -27951,6 +28013,7 @@ fn beginComptimePtrLoad( |
| 27951 | ptr_val: Value, | 28013 | ptr_val: Value, |
| 27952 | maybe_array_ty: ?Type, | 28014 | maybe_array_ty: ?Type, |
| 27953 | ) ComptimePtrLoadError!ComptimePtrLoadKit { | 28015 | ) ComptimePtrLoadError!ComptimePtrLoadKit { |
| 28016 | const mod = sema.mod; | ||
| 27954 | const target = sema.mod.getTarget(); | 28017 | const target = sema.mod.getTarget(); |
| 27955 | var deref: ComptimePtrLoadKit = switch (ptr_val.tag()) { | 28018 | var deref: ComptimePtrLoadKit = switch (ptr_val.tag()) { |
| 27956 | .decl_ref, | 28019 | .decl_ref, |
| ... | @@ -27966,7 +28029,7 @@ fn beginComptimePtrLoad( | ... | @@ -27966,7 +28029,7 @@ fn beginComptimePtrLoad( |
| 27966 | const decl_tv = try decl.typedValue(); | 28029 | const decl_tv = try decl.typedValue(); |
| 27967 | if (decl_tv.val.tag() == .variable) return error.RuntimeLoad; | 28030 | if (decl_tv.val.tag() == .variable) return error.RuntimeLoad; |
| 27968 | 28031 | ||
| 27969 | const layout_defined = decl.ty.hasWellDefinedLayout(); | 28032 | const layout_defined = decl.ty.hasWellDefinedLayout(mod); |
| 27970 | break :blk ComptimePtrLoadKit{ | 28033 | break :blk ComptimePtrLoadKit{ |
| 27971 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, | 28034 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, |
| 27972 | .pointee = decl_tv, | 28035 | .pointee = decl_tv, |
| ... | @@ -27988,7 +28051,7 @@ fn beginComptimePtrLoad( | ... | @@ -27988,7 +28051,7 @@ fn beginComptimePtrLoad( |
| 27988 | } | 28051 | } |
| 27989 | 28052 | ||
| 27990 | if (elem_ptr.index != 0) { | 28053 | if (elem_ptr.index != 0) { |
| 27991 | if (elem_ty.hasWellDefinedLayout()) { | 28054 | if (elem_ty.hasWellDefinedLayout(mod)) { |
| 27992 | if (deref.parent) |*parent| { | 28055 | if (deref.parent) |*parent| { |
| 27993 | // Update the byte offset (in-place) | 28056 | // Update the byte offset (in-place) |
| 27994 | const elem_size = try sema.typeAbiSize(elem_ty); | 28057 | const elem_size = try sema.typeAbiSize(elem_ty); |
| ... | @@ -28003,7 +28066,7 @@ fn beginComptimePtrLoad( | ... | @@ -28003,7 +28066,7 @@ fn beginComptimePtrLoad( |
| 28003 | 28066 | ||
| 28004 | // If we're loading an elem_ptr that was derived from a different type | 28067 | // If we're loading an elem_ptr that was derived from a different type |
| 28005 | // than the true type of the underlying decl, we cannot deref directly | 28068 | // than the true type of the underlying decl, we cannot deref directly |
| 28006 | const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector()) x: { | 28069 | const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: { |
| 28007 | const deref_elem_ty = deref.pointee.?.ty.childType(); | 28070 | const deref_elem_ty = deref.pointee.?.ty.childType(); |
| 28008 | break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or | 28071 | break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or |
| 28009 | (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok; | 28072 | (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok; |
| ... | @@ -28018,7 +28081,7 @@ fn beginComptimePtrLoad( | ... | @@ -28018,7 +28081,7 @@ fn beginComptimePtrLoad( |
| 28018 | if (maybe_array_ty) |load_ty| { | 28081 | if (maybe_array_ty) |load_ty| { |
| 28019 | // It's possible that we're loading a [N]T, in which case we'd like to slice | 28082 | // It's possible that we're loading a [N]T, in which case we'd like to slice |
| 28020 | // the pointee array directly from our parent array. | 28083 | // the pointee array directly from our parent array. |
| 28021 | if (load_ty.isArrayOrVector() and load_ty.childType().eql(elem_ty, sema.mod)) { | 28084 | if (load_ty.isArrayOrVector(mod) and load_ty.childType().eql(elem_ty, sema.mod)) { |
| 28022 | const N = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel()); | 28085 | const N = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel()); |
| 28023 | deref.pointee = if (elem_ptr.index + N <= check_len) TypedValue{ | 28086 | deref.pointee = if (elem_ptr.index + N <= check_len) TypedValue{ |
| 28024 | .ty = try Type.array(sema.arena, N, null, elem_ty, sema.mod), | 28087 | .ty = try Type.array(sema.arena, N, null, elem_ty, sema.mod), |
| ... | @@ -28058,7 +28121,7 @@ fn beginComptimePtrLoad( | ... | @@ -28058,7 +28121,7 @@ fn beginComptimePtrLoad( |
| 28058 | const field_index = @intCast(u32, field_ptr.field_index); | 28121 | const field_index = @intCast(u32, field_ptr.field_index); |
| 28059 | var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty); | 28122 | var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty); |
| 28060 | 28123 | ||
| 28061 | if (field_ptr.container_ty.hasWellDefinedLayout()) { | 28124 | if (field_ptr.container_ty.hasWellDefinedLayout(mod)) { |
| 28062 | const struct_ty = field_ptr.container_ty.castTag(.@"struct"); | 28125 | const struct_ty = field_ptr.container_ty.castTag(.@"struct"); |
| 28063 | if (struct_ty != null and struct_ty.?.data.layout == .Packed) { | 28126 | if (struct_ty != null and struct_ty.?.data.layout == .Packed) { |
| 28064 | // packed structs are not byte addressable | 28127 | // packed structs are not byte addressable |
| ... | @@ -28066,7 +28129,7 @@ fn beginComptimePtrLoad( | ... | @@ -28066,7 +28129,7 @@ fn beginComptimePtrLoad( |
| 28066 | } else if (deref.parent) |*parent| { | 28129 | } else if (deref.parent) |*parent| { |
| 28067 | // Update the byte offset (in-place) | 28130 | // Update the byte offset (in-place) |
| 28068 | try sema.resolveTypeLayout(field_ptr.container_ty); | 28131 | try sema.resolveTypeLayout(field_ptr.container_ty); |
| 28069 | const field_offset = field_ptr.container_ty.structFieldOffset(field_index, target); | 28132 | const field_offset = field_ptr.container_ty.structFieldOffset(field_index, mod); |
| 28070 | parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset); | 28133 | parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset); |
| 28071 | } | 28134 | } |
| 28072 | } else { | 28135 | } else { |
| ... | @@ -28103,7 +28166,7 @@ fn beginComptimePtrLoad( | ... | @@ -28103,7 +28166,7 @@ fn beginComptimePtrLoad( |
| 28103 | const field_ty = field_ptr.container_ty.structFieldType(field_index); | 28166 | const field_ty = field_ptr.container_ty.structFieldType(field_index); |
| 28104 | deref.pointee = TypedValue{ | 28167 | deref.pointee = TypedValue{ |
| 28105 | .ty = field_ty, | 28168 | .ty = field_ty, |
| 28106 | .val = tv.val.fieldValue(tv.ty, field_index), | 28169 | .val = tv.val.fieldValue(tv.ty, mod, field_index), |
| 28107 | }; | 28170 | }; |
| 28108 | } | 28171 | } |
| 28109 | break :blk deref; | 28172 | break :blk deref; |
| ... | @@ -28146,7 +28209,7 @@ fn beginComptimePtrLoad( | ... | @@ -28146,7 +28209,7 @@ fn beginComptimePtrLoad( |
| 28146 | return sema.fail(block, src, "attempt to unwrap error: {s}", .{tv.val.castTag(.@"error").?.data.name}); | 28209 | return sema.fail(block, src, "attempt to unwrap error: {s}", .{tv.val.castTag(.@"error").?.data.name}); |
| 28147 | }, | 28210 | }, |
| 28148 | .opt_payload_ptr => if (tv.val.castTag(.opt_payload)) |some| some.data else opt: { | 28211 | .opt_payload_ptr => if (tv.val.castTag(.opt_payload)) |some| some.data else opt: { |
| 28149 | if (tv.val.isNull()) return sema.fail(block, src, "attempt to use null value", .{}); | 28212 | if (tv.val.isNull(mod)) return sema.fail(block, src, "attempt to use null value", .{}); |
| 28150 | break :opt tv.val; | 28213 | break :opt tv.val; |
| 28151 | }, | 28214 | }, |
| 28152 | else => unreachable, | 28215 | else => unreachable, |
| ... | @@ -28181,7 +28244,7 @@ fn beginComptimePtrLoad( | ... | @@ -28181,7 +28244,7 @@ fn beginComptimePtrLoad( |
| 28181 | }; | 28244 | }; |
| 28182 | 28245 | ||
| 28183 | if (deref.pointee) |tv| { | 28246 | if (deref.pointee) |tv| { |
| 28184 | if (deref.parent == null and tv.ty.hasWellDefinedLayout()) { | 28247 | if (deref.parent == null and tv.ty.hasWellDefinedLayout(mod)) { |
| 28185 | deref.parent = .{ .tv = tv, .byte_offset = 0 }; | 28248 | deref.parent = .{ .tv = tv, .byte_offset = 0 }; |
| 28186 | } | 28249 | } |
| 28187 | } | 28250 | } |
| ... | @@ -28196,15 +28259,15 @@ fn bitCast( | ... | @@ -28196,15 +28259,15 @@ fn bitCast( |
| 28196 | inst_src: LazySrcLoc, | 28259 | inst_src: LazySrcLoc, |
| 28197 | operand_src: ?LazySrcLoc, | 28260 | operand_src: ?LazySrcLoc, |
| 28198 | ) CompileError!Air.Inst.Ref { | 28261 | ) CompileError!Air.Inst.Ref { |
| 28262 | const mod = sema.mod; | ||
| 28199 | const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved); | 28263 | const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved); |
| 28200 | try sema.resolveTypeLayout(dest_ty); | 28264 | try sema.resolveTypeLayout(dest_ty); |
| 28201 | 28265 | ||
| 28202 | const old_ty = try sema.resolveTypeFields(sema.typeOf(inst)); | 28266 | const old_ty = try sema.resolveTypeFields(sema.typeOf(inst)); |
| 28203 | try sema.resolveTypeLayout(old_ty); | 28267 | try sema.resolveTypeLayout(old_ty); |
| 28204 | 28268 | ||
| 28205 | const target = sema.mod.getTarget(); | 28269 | const dest_bits = dest_ty.bitSize(mod); |
| 28206 | const dest_bits = dest_ty.bitSize(target); | 28270 | const old_bits = old_ty.bitSize(mod); |
| 28207 | const old_bits = old_ty.bitSize(target); | ||
| 28208 | 28271 | ||
| 28209 | if (old_bits != dest_bits) { | 28272 | if (old_bits != dest_bits) { |
| 28210 | return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{}' has {d} bits but source type '{}' has {d} bits", .{ | 28273 | return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{}' has {d} bits but source type '{}' has {d} bits", .{ |
| ... | @@ -28233,20 +28296,20 @@ fn bitCastVal( | ... | @@ -28233,20 +28296,20 @@ fn bitCastVal( |
| 28233 | new_ty: Type, | 28296 | new_ty: Type, |
| 28234 | buffer_offset: usize, | 28297 | buffer_offset: usize, |
| 28235 | ) !?Value { | 28298 | ) !?Value { |
| 28236 | const target = sema.mod.getTarget(); | 28299 | const mod = sema.mod; |
| 28237 | if (old_ty.eql(new_ty, sema.mod)) return val; | 28300 | if (old_ty.eql(new_ty, mod)) return val; |
| 28238 | 28301 | ||
| 28239 | // For types with well-defined memory layouts, we serialize them a byte buffer, | 28302 | // For types with well-defined memory layouts, we serialize them a byte buffer, |
| 28240 | // then deserialize to the new type. | 28303 | // then deserialize to the new type. |
| 28241 | const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target)); | 28304 | const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(mod)); |
| 28242 | const buffer = try sema.gpa.alloc(u8, abi_size); | 28305 | const buffer = try sema.gpa.alloc(u8, abi_size); |
| 28243 | defer sema.gpa.free(buffer); | 28306 | defer sema.gpa.free(buffer); |
| 28244 | val.writeToMemory(old_ty, sema.mod, buffer) catch |err| switch (err) { | 28307 | val.writeToMemory(old_ty, mod, buffer) catch |err| switch (err) { |
| 28245 | error.ReinterpretDeclRef => return null, | 28308 | error.ReinterpretDeclRef => return null, |
| 28246 | error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already | 28309 | error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already |
| 28247 | error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{old_ty.fmt(sema.mod)}), | 28310 | error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{old_ty.fmt(mod)}), |
| 28248 | }; | 28311 | }; |
| 28249 | return try Value.readFromMemory(new_ty, sema.mod, buffer[buffer_offset..], sema.arena); | 28312 | return try Value.readFromMemory(new_ty, mod, buffer[buffer_offset..], sema.arena); |
| 28250 | } | 28313 | } |
| 28251 | 28314 | ||
| 28252 | fn coerceArrayPtrToSlice( | 28315 | fn coerceArrayPtrToSlice( |
| ... | @@ -28272,7 +28335,8 @@ fn coerceArrayPtrToSlice( | ... | @@ -28272,7 +28335,8 @@ fn coerceArrayPtrToSlice( |
| 28272 | fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_result: *InMemoryCoercionResult) bool { | 28335 | fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_result: *InMemoryCoercionResult) bool { |
| 28273 | const dest_info = dest_ty.ptrInfo().data; | 28336 | const dest_info = dest_ty.ptrInfo().data; |
| 28274 | const inst_info = inst_ty.ptrInfo().data; | 28337 | const inst_info = inst_ty.ptrInfo().data; |
| 28275 | const len0 = (inst_info.pointee_type.zigTypeTag() == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel() == 0 or | 28338 | const mod = sema.mod; |
| 28339 | const len0 = (inst_info.pointee_type.zigTypeTag(mod) == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel() == 0 or | ||
| 28276 | (inst_info.pointee_type.arrayLen() == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or | 28340 | (inst_info.pointee_type.arrayLen() == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or |
| 28277 | (inst_info.pointee_type.isTuple() and inst_info.pointee_type.structFieldCount() == 0); | 28341 | (inst_info.pointee_type.isTuple() and inst_info.pointee_type.structFieldCount() == 0); |
| 28278 | 28342 | ||
| ... | @@ -28298,17 +28362,16 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul | ... | @@ -28298,17 +28362,16 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul |
| 28298 | } | 28362 | } |
| 28299 | if (inst_info.@"align" == 0 and dest_info.@"align" == 0) return true; | 28363 | if (inst_info.@"align" == 0 and dest_info.@"align" == 0) return true; |
| 28300 | if (len0) return true; | 28364 | if (len0) return true; |
| 28301 | const target = sema.mod.getTarget(); | ||
| 28302 | 28365 | ||
| 28303 | const inst_align = if (inst_info.@"align" != 0) | 28366 | const inst_align = if (inst_info.@"align" != 0) |
| 28304 | inst_info.@"align" | 28367 | inst_info.@"align" |
| 28305 | else | 28368 | else |
| 28306 | inst_info.pointee_type.abiAlignment(target); | 28369 | inst_info.pointee_type.abiAlignment(mod); |
| 28307 | 28370 | ||
| 28308 | const dest_align = if (dest_info.@"align" != 0) | 28371 | const dest_align = if (dest_info.@"align" != 0) |
| 28309 | dest_info.@"align" | 28372 | dest_info.@"align" |
| 28310 | else | 28373 | else |
| 28311 | dest_info.pointee_type.abiAlignment(target); | 28374 | dest_info.pointee_type.abiAlignment(mod); |
| 28312 | 28375 | ||
| 28313 | if (dest_align > inst_align) { | 28376 | if (dest_align > inst_align) { |
| 28314 | in_memory_result.* = .{ .ptr_alignment = .{ | 28377 | in_memory_result.* = .{ .ptr_alignment = .{ |
| ... | @@ -28327,18 +28390,19 @@ fn coerceCompatiblePtrs( | ... | @@ -28327,18 +28390,19 @@ fn coerceCompatiblePtrs( |
| 28327 | inst: Air.Inst.Ref, | 28390 | inst: Air.Inst.Ref, |
| 28328 | inst_src: LazySrcLoc, | 28391 | inst_src: LazySrcLoc, |
| 28329 | ) !Air.Inst.Ref { | 28392 | ) !Air.Inst.Ref { |
| 28393 | const mod = sema.mod; | ||
| 28330 | const inst_ty = sema.typeOf(inst); | 28394 | const inst_ty = sema.typeOf(inst); |
| 28331 | if (try sema.resolveMaybeUndefVal(inst)) |val| { | 28395 | if (try sema.resolveMaybeUndefVal(inst)) |val| { |
| 28332 | if (!val.isUndef() and val.isNull() and !dest_ty.isAllowzeroPtr()) { | 28396 | if (!val.isUndef() and val.isNull(mod) and !dest_ty.isAllowzeroPtr(mod)) { |
| 28333 | return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)}); | 28397 | return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)}); |
| 28334 | } | 28398 | } |
| 28335 | // The comptime Value representation is compatible with both types. | 28399 | // The comptime Value representation is compatible with both types. |
| 28336 | return sema.addConstant(dest_ty, val); | 28400 | return sema.addConstant(dest_ty, val); |
| 28337 | } | 28401 | } |
| 28338 | try sema.requireRuntimeBlock(block, inst_src, null); | 28402 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 28339 | const inst_allows_zero = inst_ty.zigTypeTag() != .Pointer or inst_ty.ptrAllowsZero(); | 28403 | const inst_allows_zero = inst_ty.zigTypeTag(mod) != .Pointer or inst_ty.ptrAllowsZero(mod); |
| 28340 | if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero() and | 28404 | if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(mod) and |
| 28341 | (try sema.typeHasRuntimeBits(dest_ty.elemType2()) or dest_ty.elemType2().zigTypeTag() == .Fn)) | 28405 | (try sema.typeHasRuntimeBits(dest_ty.elemType2(mod)) or dest_ty.elemType2(mod).zigTypeTag(mod) == .Fn)) |
| 28342 | { | 28406 | { |
| 28343 | const actual_ptr = if (inst_ty.isSlice()) | 28407 | const actual_ptr = if (inst_ty.isSlice()) |
| 28344 | try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty) | 28408 | try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty) |
| ... | @@ -28364,6 +28428,7 @@ fn coerceEnumToUnion( | ... | @@ -28364,6 +28428,7 @@ fn coerceEnumToUnion( |
| 28364 | inst: Air.Inst.Ref, | 28428 | inst: Air.Inst.Ref, |
| 28365 | inst_src: LazySrcLoc, | 28429 | inst_src: LazySrcLoc, |
| 28366 | ) !Air.Inst.Ref { | 28430 | ) !Air.Inst.Ref { |
| 28431 | const mod = sema.mod; | ||
| 28367 | const inst_ty = sema.typeOf(inst); | 28432 | const inst_ty = sema.typeOf(inst); |
| 28368 | 28433 | ||
| 28369 | const tag_ty = union_ty.unionTagType() orelse { | 28434 | const tag_ty = union_ty.unionTagType() orelse { |
| ... | @@ -28396,7 +28461,7 @@ fn coerceEnumToUnion( | ... | @@ -28396,7 +28461,7 @@ fn coerceEnumToUnion( |
| 28396 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | 28461 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 28397 | const field = union_obj.fields.values()[field_index]; | 28462 | const field = union_obj.fields.values()[field_index]; |
| 28398 | const field_ty = try sema.resolveTypeFields(field.ty); | 28463 | const field_ty = try sema.resolveTypeFields(field.ty); |
| 28399 | if (field_ty.zigTypeTag() == .NoReturn) { | 28464 | if (field_ty.zigTypeTag(mod) == .NoReturn) { |
| 28400 | const msg = msg: { | 28465 | const msg = msg: { |
| 28401 | const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{}); | 28466 | const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{}); |
| 28402 | errdefer msg.destroy(sema.gpa); | 28467 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -28449,7 +28514,7 @@ fn coerceEnumToUnion( | ... | @@ -28449,7 +28514,7 @@ fn coerceEnumToUnion( |
| 28449 | errdefer if (msg) |some| some.destroy(sema.gpa); | 28514 | errdefer if (msg) |some| some.destroy(sema.gpa); |
| 28450 | 28515 | ||
| 28451 | for (union_obj.fields.values(), 0..) |field, i| { | 28516 | for (union_obj.fields.values(), 0..) |field, i| { |
| 28452 | if (field.ty.zigTypeTag() == .NoReturn) { | 28517 | if (field.ty.zigTypeTag(mod) == .NoReturn) { |
| 28453 | const err_msg = msg orelse try sema.errMsg( | 28518 | const err_msg = msg orelse try sema.errMsg( |
| 28454 | block, | 28519 | block, |
| 28455 | inst_src, | 28520 | inst_src, |
| ... | @@ -28469,7 +28534,7 @@ fn coerceEnumToUnion( | ... | @@ -28469,7 +28534,7 @@ fn coerceEnumToUnion( |
| 28469 | } | 28534 | } |
| 28470 | 28535 | ||
| 28471 | // If the union has all fields 0 bits, the union value is just the enum value. | 28536 | // If the union has all fields 0 bits, the union value is just the enum value. |
| 28472 | if (union_ty.unionHasAllZeroBitFieldTypes()) { | 28537 | if (union_ty.unionHasAllZeroBitFieldTypes(mod)) { |
| 28473 | return block.addBitCast(union_ty, enum_tag); | 28538 | return block.addBitCast(union_ty, enum_tag); |
| 28474 | } | 28539 | } |
| 28475 | 28540 | ||
| ... | @@ -28487,7 +28552,7 @@ fn coerceEnumToUnion( | ... | @@ -28487,7 +28552,7 @@ fn coerceEnumToUnion( |
| 28487 | while (it.next()) |field| : (field_index += 1) { | 28552 | while (it.next()) |field| : (field_index += 1) { |
| 28488 | const field_name = field.key_ptr.*; | 28553 | const field_name = field.key_ptr.*; |
| 28489 | const field_ty = field.value_ptr.ty; | 28554 | const field_ty = field.value_ptr.ty; |
| 28490 | if (!field_ty.hasRuntimeBits()) continue; | 28555 | if (!(try sema.typeHasRuntimeBits(field_ty))) continue; |
| 28491 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{s}' has type '{}'", .{ field_name, field_ty.fmt(sema.mod) }); | 28556 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{s}' has type '{}'", .{ field_name, field_ty.fmt(sema.mod) }); |
| 28492 | } | 28557 | } |
| 28493 | try sema.addDeclaredHereNote(msg, union_ty); | 28558 | try sema.addDeclaredHereNote(msg, union_ty); |
| ... | @@ -29066,12 +29131,13 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: boo | ... | @@ -29066,12 +29131,13 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: boo |
| 29066 | } | 29131 | } |
| 29067 | 29132 | ||
| 29068 | fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void { | 29133 | fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void { |
| 29069 | const decl = sema.mod.declPtr(decl_index); | 29134 | const mod = sema.mod; |
| 29135 | const decl = mod.declPtr(decl_index); | ||
| 29070 | const tv = try decl.typedValue(); | 29136 | const tv = try decl.typedValue(); |
| 29071 | if (tv.ty.zigTypeTag() != .Fn) return; | 29137 | if (tv.ty.zigTypeTag(mod) != .Fn) return; |
| 29072 | if (!try sema.fnHasRuntimeBits(tv.ty)) return; | 29138 | if (!try sema.fnHasRuntimeBits(tv.ty)) return; |
| 29073 | const func = tv.val.castTag(.function) orelse return; // undef or extern_fn | 29139 | const func = tv.val.castTag(.function) orelse return; // undef or extern_fn |
| 29074 | try sema.mod.ensureFuncBodyAnalysisQueued(func.data); | 29140 | try mod.ensureFuncBodyAnalysisQueued(func.data); |
| 29075 | } | 29141 | } |
| 29076 | 29142 | ||
| 29077 | fn analyzeRef( | 29143 | fn analyzeRef( |
| ... | @@ -29124,8 +29190,9 @@ fn analyzeLoad( | ... | @@ -29124,8 +29190,9 @@ fn analyzeLoad( |
| 29124 | ptr: Air.Inst.Ref, | 29190 | ptr: Air.Inst.Ref, |
| 29125 | ptr_src: LazySrcLoc, | 29191 | ptr_src: LazySrcLoc, |
| 29126 | ) CompileError!Air.Inst.Ref { | 29192 | ) CompileError!Air.Inst.Ref { |
| 29193 | const mod = sema.mod; | ||
| 29127 | const ptr_ty = sema.typeOf(ptr); | 29194 | const ptr_ty = sema.typeOf(ptr); |
| 29128 | const elem_ty = switch (ptr_ty.zigTypeTag()) { | 29195 | const elem_ty = switch (ptr_ty.zigTypeTag(mod)) { |
| 29129 | .Pointer => ptr_ty.childType(), | 29196 | .Pointer => ptr_ty.childType(), |
| 29130 | else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)}), | 29197 | else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)}), |
| 29131 | }; | 29198 | }; |
| ... | @@ -29196,12 +29263,13 @@ fn analyzeIsNull( | ... | @@ -29196,12 +29263,13 @@ fn analyzeIsNull( |
| 29196 | operand: Air.Inst.Ref, | 29263 | operand: Air.Inst.Ref, |
| 29197 | invert_logic: bool, | 29264 | invert_logic: bool, |
| 29198 | ) CompileError!Air.Inst.Ref { | 29265 | ) CompileError!Air.Inst.Ref { |
| 29266 | const mod = sema.mod; | ||
| 29199 | const result_ty = Type.bool; | 29267 | const result_ty = Type.bool; |
| 29200 | if (try sema.resolveMaybeUndefVal(operand)) |opt_val| { | 29268 | if (try sema.resolveMaybeUndefVal(operand)) |opt_val| { |
| 29201 | if (opt_val.isUndef()) { | 29269 | if (opt_val.isUndef()) { |
| 29202 | return sema.addConstUndef(result_ty); | 29270 | return sema.addConstUndef(result_ty); |
| 29203 | } | 29271 | } |
| 29204 | const is_null = opt_val.isNull(); | 29272 | const is_null = opt_val.isNull(mod); |
| 29205 | const bool_value = if (invert_logic) !is_null else is_null; | 29273 | const bool_value = if (invert_logic) !is_null else is_null; |
| 29206 | if (bool_value) { | 29274 | if (bool_value) { |
| 29207 | return Air.Inst.Ref.bool_true; | 29275 | return Air.Inst.Ref.bool_true; |
| ... | @@ -29213,10 +29281,10 @@ fn analyzeIsNull( | ... | @@ -29213,10 +29281,10 @@ fn analyzeIsNull( |
| 29213 | const inverted_non_null_res = if (invert_logic) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false; | 29281 | const inverted_non_null_res = if (invert_logic) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false; |
| 29214 | const operand_ty = sema.typeOf(operand); | 29282 | const operand_ty = sema.typeOf(operand); |
| 29215 | var buf: Type.Payload.ElemType = undefined; | 29283 | var buf: Type.Payload.ElemType = undefined; |
| 29216 | if (operand_ty.zigTypeTag() == .Optional and operand_ty.optionalChild(&buf).zigTypeTag() == .NoReturn) { | 29284 | if (operand_ty.zigTypeTag(mod) == .Optional and operand_ty.optionalChild(&buf).zigTypeTag(mod) == .NoReturn) { |
| 29217 | return inverted_non_null_res; | 29285 | return inverted_non_null_res; |
| 29218 | } | 29286 | } |
| 29219 | if (operand_ty.zigTypeTag() != .Optional and !operand_ty.isPtrLikeOptional()) { | 29287 | if (operand_ty.zigTypeTag(mod) != .Optional and !operand_ty.isPtrLikeOptional(mod)) { |
| 29220 | return inverted_non_null_res; | 29288 | return inverted_non_null_res; |
| 29221 | } | 29289 | } |
| 29222 | try sema.requireRuntimeBlock(block, src, null); | 29290 | try sema.requireRuntimeBlock(block, src, null); |
| ... | @@ -29230,11 +29298,12 @@ fn analyzePtrIsNonErrComptimeOnly( | ... | @@ -29230,11 +29298,12 @@ fn analyzePtrIsNonErrComptimeOnly( |
| 29230 | src: LazySrcLoc, | 29298 | src: LazySrcLoc, |
| 29231 | operand: Air.Inst.Ref, | 29299 | operand: Air.Inst.Ref, |
| 29232 | ) CompileError!Air.Inst.Ref { | 29300 | ) CompileError!Air.Inst.Ref { |
| 29301 | const mod = sema.mod; | ||
| 29233 | const ptr_ty = sema.typeOf(operand); | 29302 | const ptr_ty = sema.typeOf(operand); |
| 29234 | assert(ptr_ty.zigTypeTag() == .Pointer); | 29303 | assert(ptr_ty.zigTypeTag(mod) == .Pointer); |
| 29235 | const child_ty = ptr_ty.childType(); | 29304 | const child_ty = ptr_ty.childType(); |
| 29236 | 29305 | ||
| 29237 | const child_tag = child_ty.zigTypeTag(); | 29306 | const child_tag = child_ty.zigTypeTag(mod); |
| 29238 | if (child_tag != .ErrorSet and child_tag != .ErrorUnion) return Air.Inst.Ref.bool_true; | 29307 | if (child_tag != .ErrorSet and child_tag != .ErrorUnion) return Air.Inst.Ref.bool_true; |
| 29239 | if (child_tag == .ErrorSet) return Air.Inst.Ref.bool_false; | 29308 | if (child_tag == .ErrorSet) return Air.Inst.Ref.bool_false; |
| 29240 | assert(child_tag == .ErrorUnion); | 29309 | assert(child_tag == .ErrorUnion); |
| ... | @@ -29251,14 +29320,15 @@ fn analyzeIsNonErrComptimeOnly( | ... | @@ -29251,14 +29320,15 @@ fn analyzeIsNonErrComptimeOnly( |
| 29251 | src: LazySrcLoc, | 29320 | src: LazySrcLoc, |
| 29252 | operand: Air.Inst.Ref, | 29321 | operand: Air.Inst.Ref, |
| 29253 | ) CompileError!Air.Inst.Ref { | 29322 | ) CompileError!Air.Inst.Ref { |
| 29323 | const mod = sema.mod; | ||
| 29254 | const operand_ty = sema.typeOf(operand); | 29324 | const operand_ty = sema.typeOf(operand); |
| 29255 | const ot = operand_ty.zigTypeTag(); | 29325 | const ot = operand_ty.zigTypeTag(mod); |
| 29256 | if (ot != .ErrorSet and ot != .ErrorUnion) return Air.Inst.Ref.bool_true; | 29326 | if (ot != .ErrorSet and ot != .ErrorUnion) return Air.Inst.Ref.bool_true; |
| 29257 | if (ot == .ErrorSet) return Air.Inst.Ref.bool_false; | 29327 | if (ot == .ErrorSet) return Air.Inst.Ref.bool_false; |
| 29258 | assert(ot == .ErrorUnion); | 29328 | assert(ot == .ErrorUnion); |
| 29259 | 29329 | ||
| 29260 | const payload_ty = operand_ty.errorUnionPayload(); | 29330 | const payload_ty = operand_ty.errorUnionPayload(); |
| 29261 | if (payload_ty.zigTypeTag() == .NoReturn) { | 29331 | if (payload_ty.zigTypeTag(mod) == .NoReturn) { |
| 29262 | return Air.Inst.Ref.bool_false; | 29332 | return Air.Inst.Ref.bool_false; |
| 29263 | } | 29333 | } |
| 29264 | 29334 | ||
| ... | @@ -29375,22 +29445,21 @@ fn analyzeSlice( | ... | @@ -29375,22 +29445,21 @@ fn analyzeSlice( |
| 29375 | end_src: LazySrcLoc, | 29445 | end_src: LazySrcLoc, |
| 29376 | by_length: bool, | 29446 | by_length: bool, |
| 29377 | ) CompileError!Air.Inst.Ref { | 29447 | ) CompileError!Air.Inst.Ref { |
| 29448 | const mod = sema.mod; | ||
| 29378 | // Slice expressions can operate on a variable whose type is an array. This requires | 29449 | // Slice expressions can operate on a variable whose type is an array. This requires |
| 29379 | // the slice operand to be a pointer. In the case of a non-array, it will be a double pointer. | 29450 | // the slice operand to be a pointer. In the case of a non-array, it will be a double pointer. |
| 29380 | const ptr_ptr_ty = sema.typeOf(ptr_ptr); | 29451 | const ptr_ptr_ty = sema.typeOf(ptr_ptr); |
| 29381 | const target = sema.mod.getTarget(); | 29452 | const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(mod)) { |
| 29382 | const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag()) { | ||
| 29383 | .Pointer => ptr_ptr_ty.elemType(), | 29453 | .Pointer => ptr_ptr_ty.elemType(), |
| 29384 | else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(sema.mod)}), | 29454 | else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(sema.mod)}), |
| 29385 | }; | 29455 | }; |
| 29386 | const mod = sema.mod; | ||
| 29387 | 29456 | ||
| 29388 | var array_ty = ptr_ptr_child_ty; | 29457 | var array_ty = ptr_ptr_child_ty; |
| 29389 | var slice_ty = ptr_ptr_ty; | 29458 | var slice_ty = ptr_ptr_ty; |
| 29390 | var ptr_or_slice = ptr_ptr; | 29459 | var ptr_or_slice = ptr_ptr; |
| 29391 | var elem_ty: Type = undefined; | 29460 | var elem_ty: Type = undefined; |
| 29392 | var ptr_sentinel: ?Value = null; | 29461 | var ptr_sentinel: ?Value = null; |
| 29393 | switch (ptr_ptr_child_ty.zigTypeTag()) { | 29462 | switch (ptr_ptr_child_ty.zigTypeTag(mod)) { |
| 29394 | .Array => { | 29463 | .Array => { |
| 29395 | ptr_sentinel = ptr_ptr_child_ty.sentinel(); | 29464 | ptr_sentinel = ptr_ptr_child_ty.sentinel(); |
| 29396 | elem_ty = ptr_ptr_child_ty.childType(); | 29465 | elem_ty = ptr_ptr_child_ty.childType(); |
| ... | @@ -29398,7 +29467,7 @@ fn analyzeSlice( | ... | @@ -29398,7 +29467,7 @@ fn analyzeSlice( |
| 29398 | .Pointer => switch (ptr_ptr_child_ty.ptrSize()) { | 29467 | .Pointer => switch (ptr_ptr_child_ty.ptrSize()) { |
| 29399 | .One => { | 29468 | .One => { |
| 29400 | const double_child_ty = ptr_ptr_child_ty.childType(); | 29469 | const double_child_ty = ptr_ptr_child_ty.childType(); |
| 29401 | if (double_child_ty.zigTypeTag() == .Array) { | 29470 | if (double_child_ty.zigTypeTag(mod) == .Array) { |
| 29402 | ptr_sentinel = double_child_ty.sentinel(); | 29471 | ptr_sentinel = double_child_ty.sentinel(); |
| 29403 | ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src); | 29472 | ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src); |
| 29404 | slice_ty = ptr_ptr_child_ty; | 29473 | slice_ty = ptr_ptr_child_ty; |
| ... | @@ -29417,7 +29486,7 @@ fn analyzeSlice( | ... | @@ -29417,7 +29486,7 @@ fn analyzeSlice( |
| 29417 | 29486 | ||
| 29418 | if (ptr_ptr_child_ty.ptrSize() == .C) { | 29487 | if (ptr_ptr_child_ty.ptrSize() == .C) { |
| 29419 | if (try sema.resolveDefinedValue(block, ptr_src, ptr_or_slice)) |ptr_val| { | 29488 | if (try sema.resolveDefinedValue(block, ptr_src, ptr_or_slice)) |ptr_val| { |
| 29420 | if (ptr_val.isNull()) { | 29489 | if (ptr_val.isNull(mod)) { |
| 29421 | return sema.fail(block, src, "slice of null pointer", .{}); | 29490 | return sema.fail(block, src, "slice of null pointer", .{}); |
| 29422 | } | 29491 | } |
| 29423 | } | 29492 | } |
| ... | @@ -29448,7 +29517,7 @@ fn analyzeSlice( | ... | @@ -29448,7 +29517,7 @@ fn analyzeSlice( |
| 29448 | // we might learn of the length because it is a comptime-known slice value. | 29517 | // we might learn of the length because it is a comptime-known slice value. |
| 29449 | var end_is_len = uncasted_end_opt == .none; | 29518 | var end_is_len = uncasted_end_opt == .none; |
| 29450 | const end = e: { | 29519 | const end = e: { |
| 29451 | if (array_ty.zigTypeTag() == .Array) { | 29520 | if (array_ty.zigTypeTag(mod) == .Array) { |
| 29452 | const len_val = try Value.Tag.int_u64.create(sema.arena, array_ty.arrayLen()); | 29521 | const len_val = try Value.Tag.int_u64.create(sema.arena, array_ty.arrayLen()); |
| 29453 | 29522 | ||
| 29454 | if (!end_is_len) { | 29523 | if (!end_is_len) { |
| ... | @@ -29587,8 +29656,8 @@ fn analyzeSlice( | ... | @@ -29587,8 +29656,8 @@ fn analyzeSlice( |
| 29587 | } | 29656 | } |
| 29588 | if (try sema.resolveMaybeUndefVal(new_ptr)) |ptr_val| sentinel_check: { | 29657 | if (try sema.resolveMaybeUndefVal(new_ptr)) |ptr_val| sentinel_check: { |
| 29589 | const expected_sentinel = sentinel orelse break :sentinel_check; | 29658 | const expected_sentinel = sentinel orelse break :sentinel_check; |
| 29590 | const start_int = start_val.getUnsignedInt(sema.mod.getTarget()).?; | 29659 | const start_int = start_val.getUnsignedInt(mod).?; |
| 29591 | const end_int = end_val.getUnsignedInt(sema.mod.getTarget()).?; | 29660 | const end_int = end_val.getUnsignedInt(mod).?; |
| 29592 | const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int); | 29661 | const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int); |
| 29593 | 29662 | ||
| 29594 | const elem_ptr = try ptr_val.elemPtr(sema.typeOf(new_ptr), sema.arena, sentinel_index, sema.mod); | 29663 | const elem_ptr = try ptr_val.elemPtr(sema.typeOf(new_ptr), sema.arena, sentinel_index, sema.mod); |
| ... | @@ -29641,7 +29710,7 @@ fn analyzeSlice( | ... | @@ -29641,7 +29710,7 @@ fn analyzeSlice( |
| 29641 | const new_allowzero = new_ptr_ty_info.@"allowzero" and sema.typeOf(ptr).ptrSize() != .C; | 29710 | const new_allowzero = new_ptr_ty_info.@"allowzero" and sema.typeOf(ptr).ptrSize() != .C; |
| 29642 | 29711 | ||
| 29643 | if (opt_new_len_val) |new_len_val| { | 29712 | if (opt_new_len_val) |new_len_val| { |
| 29644 | const new_len_int = new_len_val.toUnsignedInt(target); | 29713 | const new_len_int = new_len_val.toUnsignedInt(mod); |
| 29645 | 29714 | ||
| 29646 | const return_ty = try Type.ptr(sema.arena, mod, .{ | 29715 | const return_ty = try Type.ptr(sema.arena, mod, .{ |
| 29647 | .pointee_type = try Type.array(sema.arena, new_len_int, sentinel, elem_ty, mod), | 29716 | .pointee_type = try Type.array(sema.arena, new_len_int, sentinel, elem_ty, mod), |
| ... | @@ -29724,7 +29793,7 @@ fn analyzeSlice( | ... | @@ -29724,7 +29793,7 @@ fn analyzeSlice( |
| 29724 | } | 29793 | } |
| 29725 | 29794 | ||
| 29726 | // requirement: end <= len | 29795 | // requirement: end <= len |
| 29727 | const opt_len_inst = if (array_ty.zigTypeTag() == .Array) | 29796 | const opt_len_inst = if (array_ty.zigTypeTag(mod) == .Array) |
| 29728 | try sema.addIntUnsigned(Type.usize, array_ty.arrayLenIncludingSentinel()) | 29797 | try sema.addIntUnsigned(Type.usize, array_ty.arrayLenIncludingSentinel()) |
| 29729 | else if (slice_ty.isSlice()) blk: { | 29798 | else if (slice_ty.isSlice()) blk: { |
| 29730 | if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| { | 29799 | if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| { |
| ... | @@ -29778,14 +29847,15 @@ fn cmpNumeric( | ... | @@ -29778,14 +29847,15 @@ fn cmpNumeric( |
| 29778 | lhs_src: LazySrcLoc, | 29847 | lhs_src: LazySrcLoc, |
| 29779 | rhs_src: LazySrcLoc, | 29848 | rhs_src: LazySrcLoc, |
| 29780 | ) CompileError!Air.Inst.Ref { | 29849 | ) CompileError!Air.Inst.Ref { |
| 29850 | const mod = sema.mod; | ||
| 29781 | const lhs_ty = sema.typeOf(uncasted_lhs); | 29851 | const lhs_ty = sema.typeOf(uncasted_lhs); |
| 29782 | const rhs_ty = sema.typeOf(uncasted_rhs); | 29852 | const rhs_ty = sema.typeOf(uncasted_rhs); |
| 29783 | 29853 | ||
| 29784 | assert(lhs_ty.isNumeric()); | 29854 | assert(lhs_ty.isNumeric(mod)); |
| 29785 | assert(rhs_ty.isNumeric()); | 29855 | assert(rhs_ty.isNumeric(mod)); |
| 29786 | 29856 | ||
| 29787 | const lhs_ty_tag = lhs_ty.zigTypeTag(); | 29857 | const lhs_ty_tag = lhs_ty.zigTypeTag(mod); |
| 29788 | const rhs_ty_tag = rhs_ty.zigTypeTag(); | 29858 | const rhs_ty_tag = rhs_ty.zigTypeTag(mod); |
| 29789 | const target = sema.mod.getTarget(); | 29859 | const target = sema.mod.getTarget(); |
| 29790 | 29860 | ||
| 29791 | // One exception to heterogeneous comparison: comptime_float needs to | 29861 | // One exception to heterogeneous comparison: comptime_float needs to |
| ... | @@ -29805,14 +29875,14 @@ fn cmpNumeric( | ... | @@ -29805,14 +29875,14 @@ fn cmpNumeric( |
| 29805 | if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| { | 29875 | if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| { |
| 29806 | if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| { | 29876 | if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| { |
| 29807 | // Compare ints: const vs. undefined (or vice versa) | 29877 | // Compare ints: const vs. undefined (or vice versa) |
| 29808 | if (!lhs_val.isUndef() and (lhs_ty.isInt() or lhs_ty_tag == .ComptimeInt) and rhs_ty.isInt() and rhs_val.isUndef()) { | 29878 | if (!lhs_val.isUndef() and (lhs_ty.isInt(mod) or lhs_ty_tag == .ComptimeInt) and rhs_ty.isInt(mod) and rhs_val.isUndef()) { |
| 29809 | try sema.resolveLazyValue(lhs_val); | 29879 | try sema.resolveLazyValue(lhs_val); |
| 29810 | if (sema.compareIntsOnlyPossibleResult(target, lhs_val, op, rhs_ty)) |res| { | 29880 | if (try sema.compareIntsOnlyPossibleResult(lhs_val, op, rhs_ty)) |res| { |
| 29811 | return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false; | 29881 | return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false; |
| 29812 | } | 29882 | } |
| 29813 | } else if (!rhs_val.isUndef() and (rhs_ty.isInt() or rhs_ty_tag == .ComptimeInt) and lhs_ty.isInt() and lhs_val.isUndef()) { | 29883 | } else if (!rhs_val.isUndef() and (rhs_ty.isInt(mod) or rhs_ty_tag == .ComptimeInt) and lhs_ty.isInt(mod) and lhs_val.isUndef()) { |
| 29814 | try sema.resolveLazyValue(rhs_val); | 29884 | try sema.resolveLazyValue(rhs_val); |
| 29815 | if (sema.compareIntsOnlyPossibleResult(target, rhs_val, op.reverse(), lhs_ty)) |res| { | 29885 | if (try sema.compareIntsOnlyPossibleResult(rhs_val, op.reverse(), lhs_ty)) |res| { |
| 29816 | return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false; | 29886 | return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false; |
| 29817 | } | 29887 | } |
| 29818 | } | 29888 | } |
| ... | @@ -29827,16 +29897,16 @@ fn cmpNumeric( | ... | @@ -29827,16 +29897,16 @@ fn cmpNumeric( |
| 29827 | return Air.Inst.Ref.bool_false; | 29897 | return Air.Inst.Ref.bool_false; |
| 29828 | } | 29898 | } |
| 29829 | } | 29899 | } |
| 29830 | if (try Value.compareHeteroAdvanced(lhs_val, op, rhs_val, target, sema)) { | 29900 | if (try Value.compareHeteroAdvanced(lhs_val, op, rhs_val, mod, sema)) { |
| 29831 | return Air.Inst.Ref.bool_true; | 29901 | return Air.Inst.Ref.bool_true; |
| 29832 | } else { | 29902 | } else { |
| 29833 | return Air.Inst.Ref.bool_false; | 29903 | return Air.Inst.Ref.bool_false; |
| 29834 | } | 29904 | } |
| 29835 | } else { | 29905 | } else { |
| 29836 | if (!lhs_val.isUndef() and (lhs_ty.isInt() or lhs_ty_tag == .ComptimeInt) and rhs_ty.isInt()) { | 29906 | if (!lhs_val.isUndef() and (lhs_ty.isInt(mod) or lhs_ty_tag == .ComptimeInt) and rhs_ty.isInt(mod)) { |
| 29837 | // Compare ints: const vs. var | 29907 | // Compare ints: const vs. var |
| 29838 | try sema.resolveLazyValue(lhs_val); | 29908 | try sema.resolveLazyValue(lhs_val); |
| 29839 | if (sema.compareIntsOnlyPossibleResult(target, lhs_val, op, rhs_ty)) |res| { | 29909 | if (try sema.compareIntsOnlyPossibleResult(lhs_val, op, rhs_ty)) |res| { |
| 29840 | return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false; | 29910 | return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false; |
| 29841 | } | 29911 | } |
| 29842 | } | 29912 | } |
| ... | @@ -29844,10 +29914,10 @@ fn cmpNumeric( | ... | @@ -29844,10 +29914,10 @@ fn cmpNumeric( |
| 29844 | } | 29914 | } |
| 29845 | } else { | 29915 | } else { |
| 29846 | if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| { | 29916 | if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| { |
| 29847 | if (!rhs_val.isUndef() and (rhs_ty.isInt() or rhs_ty_tag == .ComptimeInt) and lhs_ty.isInt()) { | 29917 | if (!rhs_val.isUndef() and (rhs_ty.isInt(mod) or rhs_ty_tag == .ComptimeInt) and lhs_ty.isInt(mod)) { |
| 29848 | // Compare ints: var vs. const | 29918 | // Compare ints: var vs. const |
| 29849 | try sema.resolveLazyValue(rhs_val); | 29919 | try sema.resolveLazyValue(rhs_val); |
| 29850 | if (sema.compareIntsOnlyPossibleResult(target, rhs_val, op.reverse(), lhs_ty)) |res| { | 29920 | if (try sema.compareIntsOnlyPossibleResult(rhs_val, op.reverse(), lhs_ty)) |res| { |
| 29851 | return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false; | 29921 | return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false; |
| 29852 | } | 29922 | } |
| 29853 | } | 29923 | } |
| ... | @@ -29901,11 +29971,11 @@ fn cmpNumeric( | ... | @@ -29901,11 +29971,11 @@ fn cmpNumeric( |
| 29901 | const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| | 29971 | const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| |
| 29902 | !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema)) | 29972 | !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema)) |
| 29903 | else | 29973 | else |
| 29904 | (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt()); | 29974 | (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt(mod)); |
| 29905 | const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| | 29975 | const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| |
| 29906 | !(try rhs_val.compareAllWithZeroAdvanced(.gte, sema)) | 29976 | !(try rhs_val.compareAllWithZeroAdvanced(.gte, sema)) |
| 29907 | else | 29977 | else |
| 29908 | (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt()); | 29978 | (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt(mod)); |
| 29909 | const dest_int_is_signed = lhs_is_signed or rhs_is_signed; | 29979 | const dest_int_is_signed = lhs_is_signed or rhs_is_signed; |
| 29910 | 29980 | ||
| 29911 | var dest_float_type: ?Type = null; | 29981 | var dest_float_type: ?Type = null; |
| ... | @@ -29926,7 +29996,7 @@ fn cmpNumeric( | ... | @@ -29926,7 +29996,7 @@ fn cmpNumeric( |
| 29926 | .lt, .lte => return if (lhs_val.isNegativeInf()) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false, | 29996 | .lt, .lte => return if (lhs_val.isNegativeInf()) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false, |
| 29927 | }; | 29997 | }; |
| 29928 | if (!rhs_is_signed) { | 29998 | if (!rhs_is_signed) { |
| 29929 | switch (lhs_val.orderAgainstZero()) { | 29999 | switch (lhs_val.orderAgainstZero(mod)) { |
| 29930 | .gt => {}, | 30000 | .gt => {}, |
| 29931 | .eq => switch (op) { // LHS = 0, RHS is unsigned | 30001 | .eq => switch (op) { // LHS = 0, RHS is unsigned |
| 29932 | .lte => return Air.Inst.Ref.bool_true, | 30002 | .lte => return Air.Inst.Ref.bool_true, |
| ... | @@ -29959,13 +30029,13 @@ fn cmpNumeric( | ... | @@ -29959,13 +30029,13 @@ fn cmpNumeric( |
| 29959 | } | 30029 | } |
| 29960 | lhs_bits = bigint.toConst().bitCountTwosComp(); | 30030 | lhs_bits = bigint.toConst().bitCountTwosComp(); |
| 29961 | } else { | 30031 | } else { |
| 29962 | lhs_bits = lhs_val.intBitCountTwosComp(target); | 30032 | lhs_bits = lhs_val.intBitCountTwosComp(mod); |
| 29963 | } | 30033 | } |
| 29964 | lhs_bits += @boolToInt(!lhs_is_signed and dest_int_is_signed); | 30034 | lhs_bits += @boolToInt(!lhs_is_signed and dest_int_is_signed); |
| 29965 | } else if (lhs_is_float) { | 30035 | } else if (lhs_is_float) { |
| 29966 | dest_float_type = lhs_ty; | 30036 | dest_float_type = lhs_ty; |
| 29967 | } else { | 30037 | } else { |
| 29968 | const int_info = lhs_ty.intInfo(target); | 30038 | const int_info = lhs_ty.intInfo(mod); |
| 29969 | lhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed); | 30039 | lhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed); |
| 29970 | } | 30040 | } |
| 29971 | 30041 | ||
| ... | @@ -29985,7 +30055,7 @@ fn cmpNumeric( | ... | @@ -29985,7 +30055,7 @@ fn cmpNumeric( |
| 29985 | .lt, .lte => return if (rhs_val.isNegativeInf()) Air.Inst.Ref.bool_false else Air.Inst.Ref.bool_true, | 30055 | .lt, .lte => return if (rhs_val.isNegativeInf()) Air.Inst.Ref.bool_false else Air.Inst.Ref.bool_true, |
| 29986 | }; | 30056 | }; |
| 29987 | if (!lhs_is_signed) { | 30057 | if (!lhs_is_signed) { |
| 29988 | switch (rhs_val.orderAgainstZero()) { | 30058 | switch (rhs_val.orderAgainstZero(mod)) { |
| 29989 | .gt => {}, | 30059 | .gt => {}, |
| 29990 | .eq => switch (op) { // RHS = 0, LHS is unsigned | 30060 | .eq => switch (op) { // RHS = 0, LHS is unsigned |
| 29991 | .gte => return Air.Inst.Ref.bool_true, | 30061 | .gte => return Air.Inst.Ref.bool_true, |
| ... | @@ -30018,13 +30088,13 @@ fn cmpNumeric( | ... | @@ -30018,13 +30088,13 @@ fn cmpNumeric( |
| 30018 | } | 30088 | } |
| 30019 | rhs_bits = bigint.toConst().bitCountTwosComp(); | 30089 | rhs_bits = bigint.toConst().bitCountTwosComp(); |
| 30020 | } else { | 30090 | } else { |
| 30021 | rhs_bits = rhs_val.intBitCountTwosComp(target); | 30091 | rhs_bits = rhs_val.intBitCountTwosComp(mod); |
| 30022 | } | 30092 | } |
| 30023 | rhs_bits += @boolToInt(!rhs_is_signed and dest_int_is_signed); | 30093 | rhs_bits += @boolToInt(!rhs_is_signed and dest_int_is_signed); |
| 30024 | } else if (rhs_is_float) { | 30094 | } else if (rhs_is_float) { |
| 30025 | dest_float_type = rhs_ty; | 30095 | dest_float_type = rhs_ty; |
| 30026 | } else { | 30096 | } else { |
| 30027 | const int_info = rhs_ty.intInfo(target); | 30097 | const int_info = rhs_ty.intInfo(mod); |
| 30028 | rhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed); | 30098 | rhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed); |
| 30029 | } | 30099 | } |
| 30030 | 30100 | ||
| ... | @@ -30032,7 +30102,7 @@ fn cmpNumeric( | ... | @@ -30032,7 +30102,7 @@ fn cmpNumeric( |
| 30032 | const max_bits = std.math.max(lhs_bits, rhs_bits); | 30102 | const max_bits = std.math.max(lhs_bits, rhs_bits); |
| 30033 | const casted_bits = std.math.cast(u16, max_bits) orelse return sema.fail(block, src, "{d} exceeds maximum integer bit count", .{max_bits}); | 30103 | const casted_bits = std.math.cast(u16, max_bits) orelse return sema.fail(block, src, "{d} exceeds maximum integer bit count", .{max_bits}); |
| 30034 | const signedness: std.builtin.Signedness = if (dest_int_is_signed) .signed else .unsigned; | 30104 | const signedness: std.builtin.Signedness = if (dest_int_is_signed) .signed else .unsigned; |
| 30035 | break :blk try Module.makeIntType(sema.arena, signedness, casted_bits); | 30105 | break :blk try mod.intType(signedness, casted_bits); |
| 30036 | }; | 30106 | }; |
| 30037 | const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src); | 30107 | const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src); |
| 30038 | const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src); | 30108 | const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src); |
| ... | @@ -30040,13 +30110,20 @@ fn cmpNumeric( | ... | @@ -30040,13 +30110,20 @@ fn cmpNumeric( |
| 30040 | return block.addBinOp(Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized), casted_lhs, casted_rhs); | 30110 | return block.addBinOp(Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized), casted_lhs, casted_rhs); |
| 30041 | } | 30111 | } |
| 30042 | 30112 | ||
| 30043 | /// Asserts that LHS value is an int or comptime int and not undefined, and that RHS type is an int. | 30113 | /// Asserts that LHS value is an int or comptime int and not undefined, and |
| 30044 | /// Given a const LHS and an unknown RHS, attempt to determine whether `op` has a guaranteed result. | 30114 | /// that RHS type is an int. Given a const LHS and an unknown RHS, attempt to |
| 30115 | /// determine whether `op` has a guaranteed result. | ||
| 30045 | /// If it cannot be determined, returns null. | 30116 | /// If it cannot be determined, returns null. |
| 30046 | /// Otherwise returns a bool for the guaranteed comparison operation. | 30117 | /// Otherwise returns a bool for the guaranteed comparison operation. |
| 30047 | fn compareIntsOnlyPossibleResult(sema: *Sema, target: std.Target, lhs_val: Value, op: std.math.CompareOperator, rhs_ty: Type) ?bool { | 30118 | fn compareIntsOnlyPossibleResult( |
| 30048 | const rhs_info = rhs_ty.intInfo(target); | 30119 | sema: *Sema, |
| 30049 | const vs_zero = lhs_val.orderAgainstZeroAdvanced(sema) catch unreachable; | 30120 | lhs_val: Value, |
| 30121 | op: std.math.CompareOperator, | ||
| 30122 | rhs_ty: Type, | ||
| 30123 | ) Allocator.Error!?bool { | ||
| 30124 | const mod = sema.mod; | ||
| 30125 | const rhs_info = rhs_ty.intInfo(mod); | ||
| 30126 | const vs_zero = lhs_val.orderAgainstZeroAdvanced(mod, sema) catch unreachable; | ||
| 30050 | const is_zero = vs_zero == .eq; | 30127 | const is_zero = vs_zero == .eq; |
| 30051 | const is_negative = vs_zero == .lt; | 30128 | const is_negative = vs_zero == .lt; |
| 30052 | const is_positive = vs_zero == .gt; | 30129 | const is_positive = vs_zero == .gt; |
| ... | @@ -30078,7 +30155,7 @@ fn compareIntsOnlyPossibleResult(sema: *Sema, target: std.Target, lhs_val: Value | ... | @@ -30078,7 +30155,7 @@ fn compareIntsOnlyPossibleResult(sema: *Sema, target: std.Target, lhs_val: Value |
| 30078 | }; | 30155 | }; |
| 30079 | 30156 | ||
| 30080 | const sign_adj = @boolToInt(!is_negative and rhs_info.signedness == .signed); | 30157 | const sign_adj = @boolToInt(!is_negative and rhs_info.signedness == .signed); |
| 30081 | const req_bits = lhs_val.intBitCountTwosComp(target) + sign_adj; | 30158 | const req_bits = lhs_val.intBitCountTwosComp(mod) + sign_adj; |
| 30082 | 30159 | ||
| 30083 | // No sized type can have more than 65535 bits. | 30160 | // No sized type can have more than 65535 bits. |
| 30084 | // The RHS type operand is either a runtime value or sized (but undefined) constant. | 30161 | // The RHS type operand is either a runtime value or sized (but undefined) constant. |
| ... | @@ -30111,12 +30188,11 @@ fn compareIntsOnlyPossibleResult(sema: *Sema, target: std.Target, lhs_val: Value | ... | @@ -30111,12 +30188,11 @@ fn compareIntsOnlyPossibleResult(sema: *Sema, target: std.Target, lhs_val: Value |
| 30111 | .max = false, | 30188 | .max = false, |
| 30112 | }; | 30189 | }; |
| 30113 | 30190 | ||
| 30114 | var ty_buffer: Type.Payload.Bits = .{ | 30191 | const ty = try mod.intType( |
| 30115 | .base = .{ .tag = if (is_negative) .int_signed else .int_unsigned }, | 30192 | if (is_negative) .signed else .unsigned, |
| 30116 | .data = @intCast(u16, req_bits), | 30193 | @intCast(u16, req_bits), |
| 30117 | }; | 30194 | ); |
| 30118 | const ty = Type.initPayload(&ty_buffer.base); | 30195 | const pop_count = lhs_val.popCount(ty, mod); |
| 30119 | const pop_count = lhs_val.popCount(ty, target); | ||
| 30120 | 30196 | ||
| 30121 | if (is_negative) { | 30197 | if (is_negative) { |
| 30122 | break :edge .{ | 30198 | break :edge .{ |
| ... | @@ -30152,10 +30228,11 @@ fn cmpVector( | ... | @@ -30152,10 +30228,11 @@ fn cmpVector( |
| 30152 | lhs_src: LazySrcLoc, | 30228 | lhs_src: LazySrcLoc, |
| 30153 | rhs_src: LazySrcLoc, | 30229 | rhs_src: LazySrcLoc, |
| 30154 | ) CompileError!Air.Inst.Ref { | 30230 | ) CompileError!Air.Inst.Ref { |
| 30231 | const mod = sema.mod; | ||
| 30155 | const lhs_ty = sema.typeOf(lhs); | 30232 | const lhs_ty = sema.typeOf(lhs); |
| 30156 | const rhs_ty = sema.typeOf(rhs); | 30233 | const rhs_ty = sema.typeOf(rhs); |
| 30157 | assert(lhs_ty.zigTypeTag() == .Vector); | 30234 | assert(lhs_ty.zigTypeTag(mod) == .Vector); |
| 30158 | assert(rhs_ty.zigTypeTag() == .Vector); | 30235 | assert(rhs_ty.zigTypeTag(mod) == .Vector); |
| 30159 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | 30236 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 30160 | 30237 | ||
| 30161 | const resolved_ty = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{ .override = &.{ lhs_src, rhs_src } }); | 30238 | const resolved_ty = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{ .override = &.{ lhs_src, rhs_src } }); |
| ... | @@ -30296,16 +30373,17 @@ fn resolvePeerTypes( | ... | @@ -30296,16 +30373,17 @@ fn resolvePeerTypes( |
| 30296 | instructions: []const Air.Inst.Ref, | 30373 | instructions: []const Air.Inst.Ref, |
| 30297 | candidate_srcs: Module.PeerTypeCandidateSrc, | 30374 | candidate_srcs: Module.PeerTypeCandidateSrc, |
| 30298 | ) !Type { | 30375 | ) !Type { |
| 30376 | const mod = sema.mod; | ||
| 30299 | switch (instructions.len) { | 30377 | switch (instructions.len) { |
| 30300 | 0 => return Type.initTag(.noreturn), | 30378 | 0 => return Type.initTag(.noreturn), |
| 30301 | 1 => return sema.typeOf(instructions[0]), | 30379 | 1 => return sema.typeOf(instructions[0]), |
| 30302 | else => {}, | 30380 | else => {}, |
| 30303 | } | 30381 | } |
| 30304 | 30382 | ||
| 30305 | const target = sema.mod.getTarget(); | 30383 | const target = mod.getTarget(); |
| 30306 | 30384 | ||
| 30307 | var chosen = instructions[0]; | 30385 | var chosen = instructions[0]; |
| 30308 | // If this is non-null then it does the following thing, depending on the chosen zigTypeTag(). | 30386 | // If this is non-null then it does the following thing, depending on the chosen zigTypeTag(mod). |
| 30309 | // * ErrorSet: this is an override | 30387 | // * ErrorSet: this is an override |
| 30310 | // * ErrorUnion: this is an override of the error set only | 30388 | // * ErrorUnion: this is an override of the error set only |
| 30311 | // * other: at the end we make an ErrorUnion with the other thing and this | 30389 | // * other: at the end we make an ErrorUnion with the other thing and this |
| ... | @@ -30318,8 +30396,8 @@ fn resolvePeerTypes( | ... | @@ -30318,8 +30396,8 @@ fn resolvePeerTypes( |
| 30318 | const candidate_ty = sema.typeOf(candidate); | 30396 | const candidate_ty = sema.typeOf(candidate); |
| 30319 | const chosen_ty = sema.typeOf(chosen); | 30397 | const chosen_ty = sema.typeOf(chosen); |
| 30320 | 30398 | ||
| 30321 | const candidate_ty_tag = try candidate_ty.zigTypeTagOrPoison(); | 30399 | const candidate_ty_tag = try candidate_ty.zigTypeTagOrPoison(mod); |
| 30322 | const chosen_ty_tag = try chosen_ty.zigTypeTagOrPoison(); | 30400 | const chosen_ty_tag = try chosen_ty.zigTypeTagOrPoison(mod); |
| 30323 | 30401 | ||
| 30324 | // If the candidate can coerce into our chosen type, we're done. | 30402 | // If the candidate can coerce into our chosen type, we're done. |
| 30325 | // If the chosen type can coerce into the candidate, use that. | 30403 | // If the chosen type can coerce into the candidate, use that. |
| ... | @@ -30347,8 +30425,8 @@ fn resolvePeerTypes( | ... | @@ -30347,8 +30425,8 @@ fn resolvePeerTypes( |
| 30347 | continue; | 30425 | continue; |
| 30348 | }, | 30426 | }, |
| 30349 | .Int => { | 30427 | .Int => { |
| 30350 | const chosen_info = chosen_ty.intInfo(target); | 30428 | const chosen_info = chosen_ty.intInfo(mod); |
| 30351 | const candidate_info = candidate_ty.intInfo(target); | 30429 | const candidate_info = candidate_ty.intInfo(mod); |
| 30352 | 30430 | ||
| 30353 | if (chosen_info.bits < candidate_info.bits) { | 30431 | if (chosen_info.bits < candidate_info.bits) { |
| 30354 | chosen = candidate; | 30432 | chosen = candidate; |
| ... | @@ -30537,7 +30615,7 @@ fn resolvePeerTypes( | ... | @@ -30537,7 +30615,7 @@ fn resolvePeerTypes( |
| 30537 | // *[N]T to []T | 30615 | // *[N]T to []T |
| 30538 | if ((cand_info.size == .Many or cand_info.size == .Slice) and | 30616 | if ((cand_info.size == .Many or cand_info.size == .Slice) and |
| 30539 | chosen_info.size == .One and | 30617 | chosen_info.size == .One and |
| 30540 | chosen_info.pointee_type.zigTypeTag() == .Array) | 30618 | chosen_info.pointee_type.zigTypeTag(mod) == .Array) |
| 30541 | { | 30619 | { |
| 30542 | // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T` | 30620 | // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T` |
| 30543 | convert_to_slice = false; | 30621 | convert_to_slice = false; |
| ... | @@ -30546,7 +30624,7 @@ fn resolvePeerTypes( | ... | @@ -30546,7 +30624,7 @@ fn resolvePeerTypes( |
| 30546 | continue; | 30624 | continue; |
| 30547 | } | 30625 | } |
| 30548 | if (cand_info.size == .One and | 30626 | if (cand_info.size == .One and |
| 30549 | cand_info.pointee_type.zigTypeTag() == .Array and | 30627 | cand_info.pointee_type.zigTypeTag(mod) == .Array and |
| 30550 | (chosen_info.size == .Many or chosen_info.size == .Slice)) | 30628 | (chosen_info.size == .Many or chosen_info.size == .Slice)) |
| 30551 | { | 30629 | { |
| 30552 | // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T` | 30630 | // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T` |
| ... | @@ -30559,8 +30637,8 @@ fn resolvePeerTypes( | ... | @@ -30559,8 +30637,8 @@ fn resolvePeerTypes( |
| 30559 | // Keep the one whose element type can be coerced into. | 30637 | // Keep the one whose element type can be coerced into. |
| 30560 | if (chosen_info.size == .One and | 30638 | if (chosen_info.size == .One and |
| 30561 | cand_info.size == .One and | 30639 | cand_info.size == .One and |
| 30562 | chosen_info.pointee_type.zigTypeTag() == .Array and | 30640 | chosen_info.pointee_type.zigTypeTag(mod) == .Array and |
| 30563 | cand_info.pointee_type.zigTypeTag() == .Array) | 30641 | cand_info.pointee_type.zigTypeTag(mod) == .Array) |
| 30564 | { | 30642 | { |
| 30565 | const chosen_elem_ty = chosen_info.pointee_type.childType(); | 30643 | const chosen_elem_ty = chosen_info.pointee_type.childType(); |
| 30566 | const cand_elem_ty = cand_info.pointee_type.childType(); | 30644 | const cand_elem_ty = cand_info.pointee_type.childType(); |
| ... | @@ -30631,7 +30709,7 @@ fn resolvePeerTypes( | ... | @@ -30631,7 +30709,7 @@ fn resolvePeerTypes( |
| 30631 | .Optional => { | 30709 | .Optional => { |
| 30632 | var opt_child_buf: Type.Payload.ElemType = undefined; | 30710 | var opt_child_buf: Type.Payload.ElemType = undefined; |
| 30633 | const chosen_ptr_ty = chosen_ty.optionalChild(&opt_child_buf); | 30711 | const chosen_ptr_ty = chosen_ty.optionalChild(&opt_child_buf); |
| 30634 | if (chosen_ptr_ty.zigTypeTag() == .Pointer) { | 30712 | if (chosen_ptr_ty.zigTypeTag(mod) == .Pointer) { |
| 30635 | const chosen_info = chosen_ptr_ty.ptrInfo().data; | 30713 | const chosen_info = chosen_ptr_ty.ptrInfo().data; |
| 30636 | 30714 | ||
| 30637 | seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable; | 30715 | seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable; |
| ... | @@ -30639,7 +30717,7 @@ fn resolvePeerTypes( | ... | @@ -30639,7 +30717,7 @@ fn resolvePeerTypes( |
| 30639 | // *[N]T to ?![*]T | 30717 | // *[N]T to ?![*]T |
| 30640 | // *[N]T to ?![]T | 30718 | // *[N]T to ?![]T |
| 30641 | if (cand_info.size == .One and | 30719 | if (cand_info.size == .One and |
| 30642 | cand_info.pointee_type.zigTypeTag() == .Array and | 30720 | cand_info.pointee_type.zigTypeTag(mod) == .Array and |
| 30643 | (chosen_info.size == .Many or chosen_info.size == .Slice)) | 30721 | (chosen_info.size == .Many or chosen_info.size == .Slice)) |
| 30644 | { | 30722 | { |
| 30645 | continue; | 30723 | continue; |
| ... | @@ -30648,7 +30726,7 @@ fn resolvePeerTypes( | ... | @@ -30648,7 +30726,7 @@ fn resolvePeerTypes( |
| 30648 | }, | 30726 | }, |
| 30649 | .ErrorUnion => { | 30727 | .ErrorUnion => { |
| 30650 | const chosen_ptr_ty = chosen_ty.errorUnionPayload(); | 30728 | const chosen_ptr_ty = chosen_ty.errorUnionPayload(); |
| 30651 | if (chosen_ptr_ty.zigTypeTag() == .Pointer) { | 30729 | if (chosen_ptr_ty.zigTypeTag(mod) == .Pointer) { |
| 30652 | const chosen_info = chosen_ptr_ty.ptrInfo().data; | 30730 | const chosen_info = chosen_ptr_ty.ptrInfo().data; |
| 30653 | 30731 | ||
| 30654 | seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable; | 30732 | seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable; |
| ... | @@ -30656,7 +30734,7 @@ fn resolvePeerTypes( | ... | @@ -30656,7 +30734,7 @@ fn resolvePeerTypes( |
| 30656 | // *[N]T to E![*]T | 30734 | // *[N]T to E![*]T |
| 30657 | // *[N]T to E![]T | 30735 | // *[N]T to E![]T |
| 30658 | if (cand_info.size == .One and | 30736 | if (cand_info.size == .One and |
| 30659 | cand_info.pointee_type.zigTypeTag() == .Array and | 30737 | cand_info.pointee_type.zigTypeTag(mod) == .Array and |
| 30660 | (chosen_info.size == .Many or chosen_info.size == .Slice)) | 30738 | (chosen_info.size == .Many or chosen_info.size == .Slice)) |
| 30661 | { | 30739 | { |
| 30662 | continue; | 30740 | continue; |
| ... | @@ -30664,7 +30742,7 @@ fn resolvePeerTypes( | ... | @@ -30664,7 +30742,7 @@ fn resolvePeerTypes( |
| 30664 | } | 30742 | } |
| 30665 | }, | 30743 | }, |
| 30666 | .Fn => { | 30744 | .Fn => { |
| 30667 | if (!cand_info.mutable and cand_info.pointee_type.zigTypeTag() == .Fn and .ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty, cand_info.pointee_type, target, src, src)) { | 30745 | if (!cand_info.mutable and cand_info.pointee_type.zigTypeTag(mod) == .Fn and .ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty, cand_info.pointee_type, target, src, src)) { |
| 30668 | chosen = candidate; | 30746 | chosen = candidate; |
| 30669 | chosen_i = candidate_i + 1; | 30747 | chosen_i = candidate_i + 1; |
| 30670 | continue; | 30748 | continue; |
| ... | @@ -30697,16 +30775,16 @@ fn resolvePeerTypes( | ... | @@ -30697,16 +30775,16 @@ fn resolvePeerTypes( |
| 30697 | 30775 | ||
| 30698 | const chosen_child_ty = chosen_ty.childType(); | 30776 | const chosen_child_ty = chosen_ty.childType(); |
| 30699 | const candidate_child_ty = candidate_ty.childType(); | 30777 | const candidate_child_ty = candidate_ty.childType(); |
| 30700 | if (chosen_child_ty.zigTypeTag() == .Int and candidate_child_ty.zigTypeTag() == .Int) { | 30778 | if (chosen_child_ty.zigTypeTag(mod) == .Int and candidate_child_ty.zigTypeTag(mod) == .Int) { |
| 30701 | const chosen_info = chosen_child_ty.intInfo(target); | 30779 | const chosen_info = chosen_child_ty.intInfo(mod); |
| 30702 | const candidate_info = candidate_child_ty.intInfo(target); | 30780 | const candidate_info = candidate_child_ty.intInfo(mod); |
| 30703 | if (chosen_info.bits < candidate_info.bits) { | 30781 | if (chosen_info.bits < candidate_info.bits) { |
| 30704 | chosen = candidate; | 30782 | chosen = candidate; |
| 30705 | chosen_i = candidate_i + 1; | 30783 | chosen_i = candidate_i + 1; |
| 30706 | } | 30784 | } |
| 30707 | continue; | 30785 | continue; |
| 30708 | } | 30786 | } |
| 30709 | if (chosen_child_ty.zigTypeTag() == .Float and candidate_child_ty.zigTypeTag() == .Float) { | 30787 | if (chosen_child_ty.zigTypeTag(mod) == .Float and candidate_child_ty.zigTypeTag(mod) == .Float) { |
| 30710 | if (chosen_ty.floatBits(target) < candidate_ty.floatBits(target)) { | 30788 | if (chosen_ty.floatBits(target) < candidate_ty.floatBits(target)) { |
| 30711 | chosen = candidate; | 30789 | chosen = candidate; |
| 30712 | chosen_i = candidate_i + 1; | 30790 | chosen_i = candidate_i + 1; |
| ... | @@ -30725,7 +30803,7 @@ fn resolvePeerTypes( | ... | @@ -30725,7 +30803,7 @@ fn resolvePeerTypes( |
| 30725 | .Vector => continue, | 30803 | .Vector => continue, |
| 30726 | else => {}, | 30804 | else => {}, |
| 30727 | }, | 30805 | }, |
| 30728 | .Fn => if (chosen_ty.isSinglePointer() and chosen_ty.isConstPtr() and chosen_ty.childType().zigTypeTag() == .Fn) { | 30806 | .Fn => if (chosen_ty.isSinglePointer() and chosen_ty.isConstPtr() and chosen_ty.childType().zigTypeTag(mod) == .Fn) { |
| 30729 | if (.ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty.childType(), candidate_ty, target, src, src)) { | 30807 | if (.ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty.childType(), candidate_ty, target, src, src)) { |
| 30730 | continue; | 30808 | continue; |
| 30731 | } | 30809 | } |
| ... | @@ -30790,27 +30868,27 @@ fn resolvePeerTypes( | ... | @@ -30790,27 +30868,27 @@ fn resolvePeerTypes( |
| 30790 | // the source locations. | 30868 | // the source locations. |
| 30791 | const chosen_src = candidate_srcs.resolve( | 30869 | const chosen_src = candidate_srcs.resolve( |
| 30792 | sema.gpa, | 30870 | sema.gpa, |
| 30793 | sema.mod.declPtr(block.src_decl), | 30871 | mod.declPtr(block.src_decl), |
| 30794 | chosen_i, | 30872 | chosen_i, |
| 30795 | ); | 30873 | ); |
| 30796 | const candidate_src = candidate_srcs.resolve( | 30874 | const candidate_src = candidate_srcs.resolve( |
| 30797 | sema.gpa, | 30875 | sema.gpa, |
| 30798 | sema.mod.declPtr(block.src_decl), | 30876 | mod.declPtr(block.src_decl), |
| 30799 | candidate_i + 1, | 30877 | candidate_i + 1, |
| 30800 | ); | 30878 | ); |
| 30801 | 30879 | ||
| 30802 | const msg = msg: { | 30880 | const msg = msg: { |
| 30803 | const msg = try sema.errMsg(block, src, "incompatible types: '{}' and '{}'", .{ | 30881 | const msg = try sema.errMsg(block, src, "incompatible types: '{}' and '{}'", .{ |
| 30804 | chosen_ty.fmt(sema.mod), | 30882 | chosen_ty.fmt(mod), |
| 30805 | candidate_ty.fmt(sema.mod), | 30883 | candidate_ty.fmt(mod), |
| 30806 | }); | 30884 | }); |
| 30807 | errdefer msg.destroy(sema.gpa); | 30885 | errdefer msg.destroy(sema.gpa); |
| 30808 | 30886 | ||
| 30809 | if (chosen_src) |src_loc| | 30887 | if (chosen_src) |src_loc| |
| 30810 | try sema.errNote(block, src_loc, msg, "type '{}' here", .{chosen_ty.fmt(sema.mod)}); | 30888 | try sema.errNote(block, src_loc, msg, "type '{}' here", .{chosen_ty.fmt(mod)}); |
| 30811 | 30889 | ||
| 30812 | if (candidate_src) |src_loc| | 30890 | if (candidate_src) |src_loc| |
| 30813 | try sema.errNote(block, src_loc, msg, "type '{}' here", .{candidate_ty.fmt(sema.mod)}); | 30891 | try sema.errNote(block, src_loc, msg, "type '{}' here", .{candidate_ty.fmt(mod)}); |
| 30814 | 30892 | ||
| 30815 | break :msg msg; | 30893 | break :msg msg; |
| 30816 | }; | 30894 | }; |
| ... | @@ -30826,72 +30904,73 @@ fn resolvePeerTypes( | ... | @@ -30826,72 +30904,73 @@ fn resolvePeerTypes( |
| 30826 | info.data.sentinel = chosen_child_ty.sentinel(); | 30904 | info.data.sentinel = chosen_child_ty.sentinel(); |
| 30827 | info.data.size = .Slice; | 30905 | info.data.size = .Slice; |
| 30828 | info.data.mutable = !(seen_const or chosen_child_ty.isConstPtr()); | 30906 | info.data.mutable = !(seen_const or chosen_child_ty.isConstPtr()); |
| 30829 | info.data.pointee_type = chosen_child_ty.elemType2(); | 30907 | info.data.pointee_type = chosen_child_ty.elemType2(mod); |
| 30830 | 30908 | ||
| 30831 | const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data); | 30909 | const new_ptr_ty = try Type.ptr(sema.arena, mod, info.data); |
| 30832 | const opt_ptr_ty = if (any_are_null) | 30910 | const opt_ptr_ty = if (any_are_null) |
| 30833 | try Type.optional(sema.arena, new_ptr_ty) | 30911 | try Type.optional(sema.arena, new_ptr_ty) |
| 30834 | else | 30912 | else |
| 30835 | new_ptr_ty; | 30913 | new_ptr_ty; |
| 30836 | const set_ty = err_set_ty orelse return opt_ptr_ty; | 30914 | const set_ty = err_set_ty orelse return opt_ptr_ty; |
| 30837 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, sema.mod); | 30915 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, mod); |
| 30838 | } | 30916 | } |
| 30839 | 30917 | ||
| 30840 | if (seen_const) { | 30918 | if (seen_const) { |
| 30841 | // turn []T => []const T | 30919 | // turn []T => []const T |
| 30842 | switch (chosen_ty.zigTypeTag()) { | 30920 | switch (chosen_ty.zigTypeTag(mod)) { |
| 30843 | .ErrorUnion => { | 30921 | .ErrorUnion => { |
| 30844 | const ptr_ty = chosen_ty.errorUnionPayload(); | 30922 | const ptr_ty = chosen_ty.errorUnionPayload(); |
| 30845 | var info = ptr_ty.ptrInfo(); | 30923 | var info = ptr_ty.ptrInfo(); |
| 30846 | info.data.mutable = false; | 30924 | info.data.mutable = false; |
| 30847 | const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data); | 30925 | const new_ptr_ty = try Type.ptr(sema.arena, mod, info.data); |
| 30848 | const opt_ptr_ty = if (any_are_null) | 30926 | const opt_ptr_ty = if (any_are_null) |
| 30849 | try Type.optional(sema.arena, new_ptr_ty) | 30927 | try Type.optional(sema.arena, new_ptr_ty) |
| 30850 | else | 30928 | else |
| 30851 | new_ptr_ty; | 30929 | new_ptr_ty; |
| 30852 | const set_ty = err_set_ty orelse chosen_ty.errorUnionSet(); | 30930 | const set_ty = err_set_ty orelse chosen_ty.errorUnionSet(); |
| 30853 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, sema.mod); | 30931 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, mod); |
| 30854 | }, | 30932 | }, |
| 30855 | .Pointer => { | 30933 | .Pointer => { |
| 30856 | var info = chosen_ty.ptrInfo(); | 30934 | var info = chosen_ty.ptrInfo(); |
| 30857 | info.data.mutable = false; | 30935 | info.data.mutable = false; |
| 30858 | const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data); | 30936 | const new_ptr_ty = try Type.ptr(sema.arena, mod, info.data); |
| 30859 | const opt_ptr_ty = if (any_are_null) | 30937 | const opt_ptr_ty = if (any_are_null) |
| 30860 | try Type.optional(sema.arena, new_ptr_ty) | 30938 | try Type.optional(sema.arena, new_ptr_ty) |
| 30861 | else | 30939 | else |
| 30862 | new_ptr_ty; | 30940 | new_ptr_ty; |
| 30863 | const set_ty = err_set_ty orelse return opt_ptr_ty; | 30941 | const set_ty = err_set_ty orelse return opt_ptr_ty; |
| 30864 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, sema.mod); | 30942 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, mod); |
| 30865 | }, | 30943 | }, |
| 30866 | else => return chosen_ty, | 30944 | else => return chosen_ty, |
| 30867 | } | 30945 | } |
| 30868 | } | 30946 | } |
| 30869 | 30947 | ||
| 30870 | if (any_are_null) { | 30948 | if (any_are_null) { |
| 30871 | const opt_ty = switch (chosen_ty.zigTypeTag()) { | 30949 | const opt_ty = switch (chosen_ty.zigTypeTag(mod)) { |
| 30872 | .Null, .Optional => chosen_ty, | 30950 | .Null, .Optional => chosen_ty, |
| 30873 | else => try Type.optional(sema.arena, chosen_ty), | 30951 | else => try Type.optional(sema.arena, chosen_ty), |
| 30874 | }; | 30952 | }; |
| 30875 | const set_ty = err_set_ty orelse return opt_ty; | 30953 | const set_ty = err_set_ty orelse return opt_ty; |
| 30876 | return try Type.errorUnion(sema.arena, set_ty, opt_ty, sema.mod); | 30954 | return try Type.errorUnion(sema.arena, set_ty, opt_ty, mod); |
| 30877 | } | 30955 | } |
| 30878 | 30956 | ||
| 30879 | if (err_set_ty) |ty| switch (chosen_ty.zigTypeTag()) { | 30957 | if (err_set_ty) |ty| switch (chosen_ty.zigTypeTag(mod)) { |
| 30880 | .ErrorSet => return ty, | 30958 | .ErrorSet => return ty, |
| 30881 | .ErrorUnion => { | 30959 | .ErrorUnion => { |
| 30882 | const payload_ty = chosen_ty.errorUnionPayload(); | 30960 | const payload_ty = chosen_ty.errorUnionPayload(); |
| 30883 | return try Type.errorUnion(sema.arena, ty, payload_ty, sema.mod); | 30961 | return try Type.errorUnion(sema.arena, ty, payload_ty, mod); |
| 30884 | }, | 30962 | }, |
| 30885 | else => return try Type.errorUnion(sema.arena, ty, chosen_ty, sema.mod), | 30963 | else => return try Type.errorUnion(sema.arena, ty, chosen_ty, mod), |
| 30886 | }; | 30964 | }; |
| 30887 | 30965 | ||
| 30888 | return chosen_ty; | 30966 | return chosen_ty; |
| 30889 | } | 30967 | } |
| 30890 | 30968 | ||
| 30891 | pub fn resolveFnTypes(sema: *Sema, fn_info: Type.Payload.Function.Data) CompileError!void { | 30969 | pub fn resolveFnTypes(sema: *Sema, fn_info: Type.Payload.Function.Data) CompileError!void { |
| 30970 | const mod = sema.mod; | ||
| 30892 | try sema.resolveTypeFully(fn_info.return_type); | 30971 | try sema.resolveTypeFully(fn_info.return_type); |
| 30893 | 30972 | ||
| 30894 | if (sema.mod.comp.bin_file.options.error_return_tracing and fn_info.return_type.isError()) { | 30973 | if (mod.comp.bin_file.options.error_return_tracing and fn_info.return_type.isError(mod)) { |
| 30895 | // Ensure the type exists so that backends can assume that. | 30974 | // Ensure the type exists so that backends can assume that. |
| 30896 | _ = try sema.getBuiltinType("StackTrace"); | 30975 | _ = try sema.getBuiltinType("StackTrace"); |
| 30897 | } | 30976 | } |
| ... | @@ -30943,7 +31022,8 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!void { | ... | @@ -30943,7 +31022,8 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!void { |
| 30943 | } | 31022 | } |
| 30944 | 31023 | ||
| 30945 | pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void { | 31024 | pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void { |
| 30946 | switch (ty.zigTypeTag()) { | 31025 | const mod = sema.mod; |
| 31026 | switch (ty.zigTypeTag(mod)) { | ||
| 30947 | .Struct => return sema.resolveStructLayout(ty), | 31027 | .Struct => return sema.resolveStructLayout(ty), |
| 30948 | .Union => return sema.resolveUnionLayout(ty), | 31028 | .Union => return sema.resolveUnionLayout(ty), |
| 30949 | .Array => { | 31029 | .Array => { |
| ... | @@ -31021,7 +31101,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -31021,7 +31101,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31021 | struct_obj.status = .have_layout; | 31101 | struct_obj.status = .have_layout; |
| 31022 | _ = try sema.resolveTypeRequiresComptime(resolved_ty); | 31102 | _ = try sema.resolveTypeRequiresComptime(resolved_ty); |
| 31023 | 31103 | ||
| 31024 | if (struct_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) { | 31104 | if (struct_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) { |
| 31025 | const msg = try Module.ErrorMsg.create( | 31105 | const msg = try Module.ErrorMsg.create( |
| 31026 | sema.gpa, | 31106 | sema.gpa, |
| 31027 | struct_obj.srcLoc(sema.mod), | 31107 | struct_obj.srcLoc(sema.mod), |
| ... | @@ -31043,7 +31123,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -31043,7 +31123,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31043 | }; | 31123 | }; |
| 31044 | 31124 | ||
| 31045 | for (struct_obj.fields.values(), 0..) |field, i| { | 31125 | for (struct_obj.fields.values(), 0..) |field, i| { |
| 31046 | optimized_order[i] = if (field.ty.hasRuntimeBits()) | 31126 | optimized_order[i] = if (!(try sema.typeHasRuntimeBits(field.ty))) |
| 31047 | @intCast(u32, i) | 31127 | @intCast(u32, i) |
| 31048 | else | 31128 | else |
| 31049 | Module.Struct.omitted_field; | 31129 | Module.Struct.omitted_field; |
| ... | @@ -31054,11 +31134,11 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -31054,11 +31134,11 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31054 | sema: *Sema, | 31134 | sema: *Sema, |
| 31055 | 31135 | ||
| 31056 | fn lessThan(ctx: @This(), a: u32, b: u32) bool { | 31136 | fn lessThan(ctx: @This(), a: u32, b: u32) bool { |
| 31137 | const m = ctx.sema.mod; | ||
| 31057 | if (a == Module.Struct.omitted_field) return false; | 31138 | if (a == Module.Struct.omitted_field) return false; |
| 31058 | if (b == Module.Struct.omitted_field) return true; | 31139 | if (b == Module.Struct.omitted_field) return true; |
| 31059 | const target = ctx.sema.mod.getTarget(); | 31140 | return ctx.struct_obj.fields.values()[a].ty.abiAlignment(m) > |
| 31060 | return ctx.struct_obj.fields.values()[a].ty.abiAlignment(target) > | 31141 | ctx.struct_obj.fields.values()[b].ty.abiAlignment(m); |
| 31061 | ctx.struct_obj.fields.values()[b].ty.abiAlignment(target); | ||
| 31062 | } | 31142 | } |
| 31063 | }; | 31143 | }; |
| 31064 | mem.sort(u32, optimized_order, AlignSortContext{ | 31144 | mem.sort(u32, optimized_order, AlignSortContext{ |
| ... | @@ -31073,11 +31153,10 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -31073,11 +31153,10 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31073 | 31153 | ||
| 31074 | fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!void { | 31154 | fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!void { |
| 31075 | const gpa = mod.gpa; | 31155 | const gpa = mod.gpa; |
| 31076 | const target = mod.getTarget(); | ||
| 31077 | 31156 | ||
| 31078 | var fields_bit_sum: u64 = 0; | 31157 | var fields_bit_sum: u64 = 0; |
| 31079 | for (struct_obj.fields.values()) |field| { | 31158 | for (struct_obj.fields.values()) |field| { |
| 31080 | fields_bit_sum += field.ty.bitSize(target); | 31159 | fields_bit_sum += field.ty.bitSize(mod); |
| 31081 | } | 31160 | } |
| 31082 | 31161 | ||
| 31083 | const decl_index = struct_obj.owner_decl; | 31162 | const decl_index = struct_obj.owner_decl; |
| ... | @@ -31178,32 +31257,29 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi | ... | @@ -31178,32 +31257,29 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi |
| 31178 | }; | 31257 | }; |
| 31179 | return sema.fail(&block, LazySrcLoc.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); | 31258 | return sema.fail(&block, LazySrcLoc.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); |
| 31180 | } | 31259 | } |
| 31181 | var buf: Type.Payload.Bits = .{ | 31260 | struct_obj.backing_int_ty = try mod.intType(.unsigned, @intCast(u16, fields_bit_sum)); |
| 31182 | .base = .{ .tag = .int_unsigned }, | ||
| 31183 | .data = @intCast(u16, fields_bit_sum), | ||
| 31184 | }; | ||
| 31185 | struct_obj.backing_int_ty = try Type.initPayload(&buf.base).copy(decl_arena_allocator); | ||
| 31186 | } | 31261 | } |
| 31187 | } | 31262 | } |
| 31188 | 31263 | ||
| 31189 | fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void { | 31264 | fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void { |
| 31190 | const target = sema.mod.getTarget(); | 31265 | const mod = sema.mod; |
| 31191 | 31266 | ||
| 31192 | if (!backing_int_ty.isInt()) { | 31267 | if (!backing_int_ty.isInt(mod)) { |
| 31193 | return sema.fail(block, src, "expected backing integer type, found '{}'", .{backing_int_ty.fmt(sema.mod)}); | 31268 | return sema.fail(block, src, "expected backing integer type, found '{}'", .{backing_int_ty.fmt(sema.mod)}); |
| 31194 | } | 31269 | } |
| 31195 | if (backing_int_ty.bitSize(target) != fields_bit_sum) { | 31270 | if (backing_int_ty.bitSize(mod) != fields_bit_sum) { |
| 31196 | return sema.fail( | 31271 | return sema.fail( |
| 31197 | block, | 31272 | block, |
| 31198 | src, | 31273 | src, |
| 31199 | "backing integer type '{}' has bit size {} but the struct fields have a total bit size of {}", | 31274 | "backing integer type '{}' has bit size {} but the struct fields have a total bit size of {}", |
| 31200 | .{ backing_int_ty.fmt(sema.mod), backing_int_ty.bitSize(target), fields_bit_sum }, | 31275 | .{ backing_int_ty.fmt(sema.mod), backing_int_ty.bitSize(mod), fields_bit_sum }, |
| 31201 | ); | 31276 | ); |
| 31202 | } | 31277 | } |
| 31203 | } | 31278 | } |
| 31204 | 31279 | ||
| 31205 | fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | 31280 | fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { |
| 31206 | if (!ty.isIndexable()) { | 31281 | const mod = sema.mod; |
| 31282 | if (!ty.isIndexable(mod)) { | ||
| 31207 | const msg = msg: { | 31283 | const msg = msg: { |
| 31208 | const msg = try sema.errMsg(block, src, "type '{}' does not support indexing", .{ty.fmt(sema.mod)}); | 31284 | const msg = try sema.errMsg(block, src, "type '{}' does not support indexing", .{ty.fmt(sema.mod)}); |
| 31209 | errdefer msg.destroy(sema.gpa); | 31285 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -31215,12 +31291,13 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | ... | @@ -31215,12 +31291,13 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { |
| 31215 | } | 31291 | } |
| 31216 | 31292 | ||
| 31217 | fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | 31293 | fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { |
| 31218 | if (ty.zigTypeTag() == .Pointer) { | 31294 | const mod = sema.mod; |
| 31295 | if (ty.zigTypeTag(mod) == .Pointer) { | ||
| 31219 | switch (ty.ptrSize()) { | 31296 | switch (ty.ptrSize()) { |
| 31220 | .Slice, .Many, .C => return, | 31297 | .Slice, .Many, .C => return, |
| 31221 | .One => { | 31298 | .One => { |
| 31222 | const elem_ty = ty.childType(); | 31299 | const elem_ty = ty.childType(); |
| 31223 | if (elem_ty.zigTypeTag() == .Array) return; | 31300 | if (elem_ty.zigTypeTag(mod) == .Array) return; |
| 31224 | // TODO https://github.com/ziglang/zig/issues/15479 | 31301 | // TODO https://github.com/ziglang/zig/issues/15479 |
| 31225 | // if (elem_ty.isTuple()) return; | 31302 | // if (elem_ty.isTuple()) return; |
| 31226 | }, | 31303 | }, |
| ... | @@ -31270,7 +31347,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -31270,7 +31347,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31270 | union_obj.status = .have_layout; | 31347 | union_obj.status = .have_layout; |
| 31271 | _ = try sema.resolveTypeRequiresComptime(resolved_ty); | 31348 | _ = try sema.resolveTypeRequiresComptime(resolved_ty); |
| 31272 | 31349 | ||
| 31273 | if (union_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) { | 31350 | if (union_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) { |
| 31274 | const msg = try Module.ErrorMsg.create( | 31351 | const msg = try Module.ErrorMsg.create( |
| 31275 | sema.gpa, | 31352 | sema.gpa, |
| 31276 | union_obj.srcLoc(sema.mod), | 31353 | union_obj.srcLoc(sema.mod), |
| ... | @@ -31285,6 +31362,23 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -31285,6 +31362,23 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31285 | // for hasRuntimeBits() of each field, so we need "requires comptime" | 31362 | // for hasRuntimeBits() of each field, so we need "requires comptime" |
| 31286 | // to be known already before this function returns. | 31363 | // to be known already before this function returns. |
| 31287 | pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | 31364 | pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31365 | const mod = sema.mod; | ||
| 31366 | |||
| 31367 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 31368 | .int_type => return false, | ||
| 31369 | .ptr_type => @panic("TODO"), | ||
| 31370 | .array_type => @panic("TODO"), | ||
| 31371 | .vector_type => @panic("TODO"), | ||
| 31372 | .optional_type => @panic("TODO"), | ||
| 31373 | .error_union_type => @panic("TODO"), | ||
| 31374 | .simple_type => @panic("TODO"), | ||
| 31375 | .struct_type => @panic("TODO"), | ||
| 31376 | .simple_value => unreachable, | ||
| 31377 | .extern_func => unreachable, | ||
| 31378 | .int => unreachable, | ||
| 31379 | .enum_tag => unreachable, // it's a value, not a type | ||
| 31380 | }; | ||
| 31381 | |||
| 31288 | return switch (ty.tag()) { | 31382 | return switch (ty.tag()) { |
| 31289 | .u1, | 31383 | .u1, |
| 31290 | .u8, | 31384 | .u8, |
| ... | @@ -31349,8 +31443,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -31349,8 +31443,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31349 | .generic_poison, | 31443 | .generic_poison, |
| 31350 | .array_u8, | 31444 | .array_u8, |
| 31351 | .array_u8_sentinel_0, | 31445 | .array_u8_sentinel_0, |
| 31352 | .int_signed, | ||
| 31353 | .int_unsigned, | ||
| 31354 | .enum_simple, | 31446 | .enum_simple, |
| 31355 | => false, | 31447 | => false, |
| 31356 | 31448 | ||
| ... | @@ -31360,11 +31452,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -31360,11 +31452,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31360 | .comptime_float, | 31452 | .comptime_float, |
| 31361 | .enum_literal, | 31453 | .enum_literal, |
| 31362 | .type_info, | 31454 | .type_info, |
| 31363 | // These are function bodies, not function pointers. | ||
| 31364 | .fn_noreturn_no_args, | ||
| 31365 | .fn_void_no_args, | ||
| 31366 | .fn_naked_noreturn_no_args, | ||
| 31367 | .fn_ccc_void_no_args, | ||
| 31368 | .function, | 31455 | .function, |
| 31369 | => true, | 31456 | => true, |
| 31370 | 31457 | ||
| ... | @@ -31387,7 +31474,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -31387,7 +31474,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31387 | .mut_slice, | 31474 | .mut_slice, |
| 31388 | => { | 31475 | => { |
| 31389 | const child_ty = ty.childType(); | 31476 | const child_ty = ty.childType(); |
| 31390 | if (child_ty.zigTypeTag() == .Fn) { | 31477 | if (child_ty.zigTypeTag(mod) == .Fn) { |
| 31391 | return child_ty.fnInfo().is_generic; | 31478 | return child_ty.fnInfo().is_generic; |
| 31392 | } else { | 31479 | } else { |
| 31393 | return sema.resolveTypeRequiresComptime(child_ty); | 31480 | return sema.resolveTypeRequiresComptime(child_ty); |
| ... | @@ -31474,7 +31561,8 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -31474,7 +31561,8 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31474 | /// Returns `error.AnalysisFail` if any of the types (recursively) failed to | 31561 | /// Returns `error.AnalysisFail` if any of the types (recursively) failed to |
| 31475 | /// be resolved. | 31562 | /// be resolved. |
| 31476 | pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void { | 31563 | pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void { |
| 31477 | switch (ty.zigTypeTag()) { | 31564 | const mod = sema.mod; |
| 31565 | switch (ty.zigTypeTag(mod)) { | ||
| 31478 | .Pointer => { | 31566 | .Pointer => { |
| 31479 | const child_ty = try sema.resolveTypeFields(ty.childType()); | 31567 | const child_ty = try sema.resolveTypeFields(ty.childType()); |
| 31480 | return sema.resolveTypeFully(child_ty); | 31568 | return sema.resolveTypeFully(child_ty); |
| ... | @@ -31840,7 +31928,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -31840,7 +31928,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 31840 | type_body_len: u32 = 0, | 31928 | type_body_len: u32 = 0, |
| 31841 | align_body_len: u32 = 0, | 31929 | align_body_len: u32 = 0, |
| 31842 | init_body_len: u32 = 0, | 31930 | init_body_len: u32 = 0, |
| 31843 | type_ref: Air.Inst.Ref = .none, | 31931 | type_ref: Zir.Inst.Ref = .none, |
| 31844 | }; | 31932 | }; |
| 31845 | const fields = try sema.arena.alloc(Field, fields_len); | 31933 | const fields = try sema.arena.alloc(Field, fields_len); |
| 31846 | var any_inits = false; | 31934 | var any_inits = false; |
| ... | @@ -31967,7 +32055,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -31967,7 +32055,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 31967 | const field = &struct_obj.fields.values()[field_i]; | 32055 | const field = &struct_obj.fields.values()[field_i]; |
| 31968 | field.ty = try field_ty.copy(decl_arena_allocator); | 32056 | field.ty = try field_ty.copy(decl_arena_allocator); |
| 31969 | 32057 | ||
| 31970 | if (field_ty.zigTypeTag() == .Opaque) { | 32058 | if (field_ty.zigTypeTag(mod) == .Opaque) { |
| 31971 | const msg = msg: { | 32059 | const msg = msg: { |
| 31972 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ | 32060 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 31973 | .index = field_i, | 32061 | .index = field_i, |
| ... | @@ -31981,7 +32069,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -31981,7 +32069,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 31981 | }; | 32069 | }; |
| 31982 | return sema.failWithOwnedErrorMsg(msg); | 32070 | return sema.failWithOwnedErrorMsg(msg); |
| 31983 | } | 32071 | } |
| 31984 | if (field_ty.zigTypeTag() == .NoReturn) { | 32072 | if (field_ty.zigTypeTag(mod) == .NoReturn) { |
| 31985 | const msg = msg: { | 32073 | const msg = msg: { |
| 31986 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ | 32074 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 31987 | .index = field_i, | 32075 | .index = field_i, |
| ... | @@ -32010,7 +32098,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -32010,7 +32098,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 32010 | break :msg msg; | 32098 | break :msg msg; |
| 32011 | }; | 32099 | }; |
| 32012 | return sema.failWithOwnedErrorMsg(msg); | 32100 | return sema.failWithOwnedErrorMsg(msg); |
| 32013 | } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) { | 32101 | } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty, mod))) { |
| 32014 | const msg = msg: { | 32102 | const msg = msg: { |
| 32015 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ | 32103 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 32016 | .index = field_i, | 32104 | .index = field_i, |
| ... | @@ -32191,7 +32279,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -32191,7 +32279,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 32191 | if (small.auto_enum_tag) { | 32279 | if (small.auto_enum_tag) { |
| 32192 | // The provided type is an integer type and we must construct the enum tag type here. | 32280 | // The provided type is an integer type and we must construct the enum tag type here. |
| 32193 | int_tag_ty = provided_ty; | 32281 | int_tag_ty = provided_ty; |
| 32194 | if (int_tag_ty.zigTypeTag() != .Int and int_tag_ty.zigTypeTag() != .ComptimeInt) { | 32282 | if (int_tag_ty.zigTypeTag(mod) != .Int and int_tag_ty.zigTypeTag(mod) != .ComptimeInt) { |
| 32195 | return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(sema.mod)}); | 32283 | return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(sema.mod)}); |
| 32196 | } | 32284 | } |
| 32197 | 32285 | ||
| ... | @@ -32220,7 +32308,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -32220,7 +32308,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 32220 | } else { | 32308 | } else { |
| 32221 | // The provided type is the enum tag type. | 32309 | // The provided type is the enum tag type. |
| 32222 | union_obj.tag_ty = try provided_ty.copy(decl_arena_allocator); | 32310 | union_obj.tag_ty = try provided_ty.copy(decl_arena_allocator); |
| 32223 | if (union_obj.tag_ty.zigTypeTag() != .Enum) { | 32311 | if (union_obj.tag_ty.zigTypeTag(mod) != .Enum) { |
| 32224 | return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{union_obj.tag_ty.fmt(sema.mod)}); | 32312 | return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{union_obj.tag_ty.fmt(sema.mod)}); |
| 32225 | } | 32313 | } |
| 32226 | // The fields of the union must match the enum exactly. | 32314 | // The fields of the union must match the enum exactly. |
| ... | @@ -32281,7 +32369,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -32281,7 +32369,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 32281 | break :blk align_ref; | 32369 | break :blk align_ref; |
| 32282 | } else .none; | 32370 | } else .none; |
| 32283 | 32371 | ||
| 32284 | const tag_ref: Zir.Inst.Ref = if (has_tag) blk: { | 32372 | const tag_ref: Air.Inst.Ref = if (has_tag) blk: { |
| 32285 | const tag_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]); | 32373 | const tag_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]); |
| 32286 | extra_index += 1; | 32374 | extra_index += 1; |
| 32287 | break :blk try sema.resolveInst(tag_ref); | 32375 | break :blk try sema.resolveInst(tag_ref); |
| ... | @@ -32391,7 +32479,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -32391,7 +32479,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 32391 | } | 32479 | } |
| 32392 | } | 32480 | } |
| 32393 | 32481 | ||
| 32394 | if (field_ty.zigTypeTag() == .Opaque) { | 32482 | if (field_ty.zigTypeTag(mod) == .Opaque) { |
| 32395 | const msg = msg: { | 32483 | const msg = msg: { |
| 32396 | const ty_src = union_obj.fieldSrcLoc(sema.mod, .{ | 32484 | const ty_src = union_obj.fieldSrcLoc(sema.mod, .{ |
| 32397 | .index = field_i, | 32485 | .index = field_i, |
| ... | @@ -32420,7 +32508,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -32420,7 +32508,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 32420 | break :msg msg; | 32508 | break :msg msg; |
| 32421 | }; | 32509 | }; |
| 32422 | return sema.failWithOwnedErrorMsg(msg); | 32510 | return sema.failWithOwnedErrorMsg(msg); |
| 32423 | } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) { | 32511 | } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) { |
| 32424 | const msg = msg: { | 32512 | const msg = msg: { |
| 32425 | const ty_src = union_obj.fieldSrcLoc(sema.mod, .{ | 32513 | const ty_src = union_obj.fieldSrcLoc(sema.mod, .{ |
| 32426 | .index = field_i, | 32514 | .index = field_i, |
| ... | @@ -32673,6 +32761,29 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { | ... | @@ -32673,6 +32761,29 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { |
| 32673 | /// that the types are already resolved. | 32761 | /// that the types are already resolved. |
| 32674 | /// TODO assert the return value matches `ty.onePossibleValue` | 32762 | /// TODO assert the return value matches `ty.onePossibleValue` |
| 32675 | pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | 32763 | pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 32764 | const mod = sema.mod; | ||
| 32765 | |||
| 32766 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 32767 | .int_type => |int_type| { | ||
| 32768 | if (int_type.bits == 0) { | ||
| 32769 | return Value.zero; | ||
| 32770 | } else { | ||
| 32771 | return null; | ||
| 32772 | } | ||
| 32773 | }, | ||
| 32774 | .ptr_type => @panic("TODO"), | ||
| 32775 | .array_type => @panic("TODO"), | ||
| 32776 | .vector_type => @panic("TODO"), | ||
| 32777 | .optional_type => @panic("TODO"), | ||
| 32778 | .error_union_type => @panic("TODO"), | ||
| 32779 | .simple_type => @panic("TODO"), | ||
| 32780 | .struct_type => @panic("TODO"), | ||
| 32781 | .simple_value => unreachable, | ||
| 32782 | .extern_func => unreachable, | ||
| 32783 | .int => unreachable, | ||
| 32784 | .enum_tag => unreachable, // it's a value, not a type | ||
| 32785 | }; | ||
| 32786 | |||
| 32676 | switch (ty.tag()) { | 32787 | switch (ty.tag()) { |
| 32677 | .f16, | 32788 | .f16, |
| 32678 | .f32, | 32789 | .f32, |
| ... | @@ -32712,10 +32823,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -32712,10 +32823,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 32712 | .error_set, | 32823 | .error_set, |
| 32713 | .error_set_merged, | 32824 | .error_set_merged, |
| 32714 | .error_union, | 32825 | .error_union, |
| 32715 | .fn_noreturn_no_args, | ||
| 32716 | .fn_void_no_args, | ||
| 32717 | .fn_naked_noreturn_no_args, | ||
| 32718 | .fn_ccc_void_no_args, | ||
| 32719 | .function, | 32826 | .function, |
| 32720 | .single_const_pointer_to_comptime_int, | 32827 | .single_const_pointer_to_comptime_int, |
| 32721 | .array_sentinel, | 32828 | .array_sentinel, |
| ... | @@ -32803,7 +32910,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -32803,7 +32910,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 32803 | const resolved_ty = try sema.resolveTypeFields(ty); | 32910 | const resolved_ty = try sema.resolveTypeFields(ty); |
| 32804 | const enum_obj = resolved_ty.castTag(.enum_numbered).?.data; | 32911 | const enum_obj = resolved_ty.castTag(.enum_numbered).?.data; |
| 32805 | // An explicit tag type is always provided for enum_numbered. | 32912 | // An explicit tag type is always provided for enum_numbered. |
| 32806 | if (enum_obj.tag_ty.hasRuntimeBits()) { | 32913 | if (!(try sema.typeHasRuntimeBits(enum_obj.tag_ty))) { |
| 32807 | return null; | 32914 | return null; |
| 32808 | } | 32915 | } |
| 32809 | if (enum_obj.fields.count() == 1) { | 32916 | if (enum_obj.fields.count() == 1) { |
| ... | @@ -32819,7 +32926,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -32819,7 +32926,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 32819 | .enum_full => { | 32926 | .enum_full => { |
| 32820 | const resolved_ty = try sema.resolveTypeFields(ty); | 32927 | const resolved_ty = try sema.resolveTypeFields(ty); |
| 32821 | const enum_obj = resolved_ty.castTag(.enum_full).?.data; | 32928 | const enum_obj = resolved_ty.castTag(.enum_full).?.data; |
| 32822 | if (enum_obj.tag_ty.hasRuntimeBits()) { | 32929 | if (!(try sema.typeHasRuntimeBits(enum_obj.tag_ty))) { |
| 32823 | return null; | 32930 | return null; |
| 32824 | } | 32931 | } |
| 32825 | switch (enum_obj.fields.count()) { | 32932 | switch (enum_obj.fields.count()) { |
| ... | @@ -32843,7 +32950,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -32843,7 +32950,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 32843 | }, | 32950 | }, |
| 32844 | .enum_nonexhaustive => { | 32951 | .enum_nonexhaustive => { |
| 32845 | const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty; | 32952 | const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty; |
| 32846 | if (tag_ty.zigTypeTag() != .ComptimeInt and !(try sema.typeHasRuntimeBits(tag_ty))) { | 32953 | if (tag_ty.zigTypeTag(mod) != .ComptimeInt and !(try sema.typeHasRuntimeBits(tag_ty))) { |
| 32847 | return Value.zero; | 32954 | return Value.zero; |
| 32848 | } else { | 32955 | } else { |
| 32849 | return null; | 32956 | return null; |
| ... | @@ -32883,13 +32990,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -32883,13 +32990,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 32883 | .null => return Value.null, | 32990 | .null => return Value.null, |
| 32884 | .undefined => return Value.initTag(.undef), | 32991 | .undefined => return Value.initTag(.undef), |
| 32885 | 32992 | ||
| 32886 | .int_unsigned, .int_signed => { | ||
| 32887 | if (ty.cast(Type.Payload.Bits).?.data == 0) { | ||
| 32888 | return Value.zero; | ||
| 32889 | } else { | ||
| 32890 | return null; | ||
| 32891 | } | ||
| 32892 | }, | ||
| 32893 | .vector, .array, .array_u8 => { | 32993 | .vector, .array, .array_u8 => { |
| 32894 | if (ty.arrayLen() == 0) | 32994 | if (ty.arrayLen() == 0) |
| 32895 | return Value.initTag(.empty_array); | 32995 | return Value.initTag(.empty_array); |
| ... | @@ -32919,6 +33019,89 @@ pub fn getTmpAir(sema: Sema) Air { | ... | @@ -32919,6 +33019,89 @@ pub fn getTmpAir(sema: Sema) Air { |
| 32919 | } | 33019 | } |
| 32920 | 33020 | ||
| 32921 | pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { | 33021 | pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { |
| 33022 | switch (ty.ip_index) { | ||
| 33023 | .u1_type => return .u1_type, | ||
| 33024 | .u8_type => return .u8_type, | ||
| 33025 | .i8_type => return .i8_type, | ||
| 33026 | .u16_type => return .u16_type, | ||
| 33027 | .i16_type => return .i16_type, | ||
| 33028 | .u29_type => return .u29_type, | ||
| 33029 | .u32_type => return .u32_type, | ||
| 33030 | .i32_type => return .i32_type, | ||
| 33031 | .u64_type => return .u64_type, | ||
| 33032 | .i64_type => return .i64_type, | ||
| 33033 | .u80_type => return .u80_type, | ||
| 33034 | .u128_type => return .u128_type, | ||
| 33035 | .i128_type => return .i128_type, | ||
| 33036 | .usize_type => return .usize_type, | ||
| 33037 | .isize_type => return .isize_type, | ||
| 33038 | .c_char_type => return .c_char_type, | ||
| 33039 | .c_short_type => return .c_short_type, | ||
| 33040 | .c_ushort_type => return .c_ushort_type, | ||
| 33041 | .c_int_type => return .c_int_type, | ||
| 33042 | .c_uint_type => return .c_uint_type, | ||
| 33043 | .c_long_type => return .c_long_type, | ||
| 33044 | .c_ulong_type => return .c_ulong_type, | ||
| 33045 | .c_longlong_type => return .c_longlong_type, | ||
| 33046 | .c_ulonglong_type => return .c_ulonglong_type, | ||
| 33047 | .c_longdouble_type => return .c_longdouble_type, | ||
| 33048 | .f16_type => return .f16_type, | ||
| 33049 | .f32_type => return .f32_type, | ||
| 33050 | .f64_type => return .f64_type, | ||
| 33051 | .f80_type => return .f80_type, | ||
| 33052 | .f128_type => return .f128_type, | ||
| 33053 | .anyopaque_type => return .anyopaque_type, | ||
| 33054 | .bool_type => return .bool_type, | ||
| 33055 | .void_type => return .void_type, | ||
| 33056 | .type_type => return .type_type, | ||
| 33057 | .anyerror_type => return .anyerror_type, | ||
| 33058 | .comptime_int_type => return .comptime_int_type, | ||
| 33059 | .comptime_float_type => return .comptime_float_type, | ||
| 33060 | .noreturn_type => return .noreturn_type, | ||
| 33061 | .anyframe_type => return .anyframe_type, | ||
| 33062 | .null_type => return .null_type, | ||
| 33063 | .undefined_type => return .undefined_type, | ||
| 33064 | .enum_literal_type => return .enum_literal_type, | ||
| 33065 | .atomic_order_type => return .atomic_order_type, | ||
| 33066 | .atomic_rmw_op_type => return .atomic_rmw_op_type, | ||
| 33067 | .calling_convention_type => return .calling_convention_type, | ||
| 33068 | .address_space_type => return .address_space_type, | ||
| 33069 | .float_mode_type => return .float_mode_type, | ||
| 33070 | .reduce_op_type => return .reduce_op_type, | ||
| 33071 | .call_modifier_type => return .call_modifier_type, | ||
| 33072 | .prefetch_options_type => return .prefetch_options_type, | ||
| 33073 | .export_options_type => return .export_options_type, | ||
| 33074 | .extern_options_type => return .extern_options_type, | ||
| 33075 | .type_info_type => return .type_info_type, | ||
| 33076 | .manyptr_u8_type => return .manyptr_u8_type, | ||
| 33077 | .manyptr_const_u8_type => return .manyptr_const_u8_type, | ||
| 33078 | .single_const_pointer_to_comptime_int_type => return .single_const_pointer_to_comptime_int_type, | ||
| 33079 | .const_slice_u8_type => return .const_slice_u8_type, | ||
| 33080 | .anyerror_void_error_union_type => return .anyerror_void_error_union_type, | ||
| 33081 | .generic_poison_type => return .generic_poison_type, | ||
| 33082 | .var_args_param_type => return .var_args_param_type, | ||
| 33083 | .empty_struct_type => return .empty_struct_type, | ||
| 33084 | |||
| 33085 | // values | ||
| 33086 | .undef => unreachable, | ||
| 33087 | .zero => unreachable, | ||
| 33088 | .zero_usize => unreachable, | ||
| 33089 | .one => unreachable, | ||
| 33090 | .one_usize => unreachable, | ||
| 33091 | .calling_convention_c => unreachable, | ||
| 33092 | .calling_convention_inline => unreachable, | ||
| 33093 | .void_value => unreachable, | ||
| 33094 | .unreachable_value => unreachable, | ||
| 33095 | .null_value => unreachable, | ||
| 33096 | .bool_true => unreachable, | ||
| 33097 | .bool_false => unreachable, | ||
| 33098 | .empty_struct => unreachable, | ||
| 33099 | .generic_poison => unreachable, | ||
| 33100 | |||
| 33101 | _ => {}, | ||
| 33102 | |||
| 33103 | .none => unreachable, | ||
| 33104 | } | ||
| 32922 | switch (ty.tag()) { | 33105 | switch (ty.tag()) { |
| 32923 | .u1 => return .u1_type, | 33106 | .u1 => return .u1_type, |
| 32924 | .u8 => return .u8_type, | 33107 | .u8 => return .u8_type, |
| ... | @@ -32934,6 +33117,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { | ... | @@ -32934,6 +33117,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { |
| 32934 | .i128 => return .i128_type, | 33117 | .i128 => return .i128_type, |
| 32935 | .usize => return .usize_type, | 33118 | .usize => return .usize_type, |
| 32936 | .isize => return .isize_type, | 33119 | .isize => return .isize_type, |
| 33120 | .c_char => return .c_char_type, | ||
| 32937 | .c_short => return .c_short_type, | 33121 | .c_short => return .c_short_type, |
| 32938 | .c_ushort => return .c_ushort_type, | 33122 | .c_ushort => return .c_ushort_type, |
| 32939 | .c_int => return .c_int_type, | 33123 | .c_int => return .c_int_type, |
| ... | @@ -32966,17 +33150,13 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { | ... | @@ -32966,17 +33150,13 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { |
| 32966 | .address_space => return .address_space_type, | 33150 | .address_space => return .address_space_type, |
| 32967 | .float_mode => return .float_mode_type, | 33151 | .float_mode => return .float_mode_type, |
| 32968 | .reduce_op => return .reduce_op_type, | 33152 | .reduce_op => return .reduce_op_type, |
| 32969 | .modifier => return .modifier_type, | 33153 | .modifier => return .call_modifier_type, |
| 32970 | .prefetch_options => return .prefetch_options_type, | 33154 | .prefetch_options => return .prefetch_options_type, |
| 32971 | .export_options => return .export_options_type, | 33155 | .export_options => return .export_options_type, |
| 32972 | .extern_options => return .extern_options_type, | 33156 | .extern_options => return .extern_options_type, |
| 32973 | .type_info => return .type_info_type, | 33157 | .type_info => return .type_info_type, |
| 32974 | .manyptr_u8 => return .manyptr_u8_type, | 33158 | .manyptr_u8 => return .manyptr_u8_type, |
| 32975 | .manyptr_const_u8 => return .manyptr_const_u8_type, | 33159 | .manyptr_const_u8 => return .manyptr_const_u8_type, |
| 32976 | .fn_noreturn_no_args => return .fn_noreturn_no_args_type, | ||
| 32977 | .fn_void_no_args => return .fn_void_no_args_type, | ||
| 32978 | .fn_naked_noreturn_no_args => return .fn_naked_noreturn_no_args_type, | ||
| 32979 | .fn_ccc_void_no_args => return .fn_ccc_void_no_args_type, | ||
| 32980 | .single_const_pointer_to_comptime_int => return .single_const_pointer_to_comptime_int_type, | 33160 | .single_const_pointer_to_comptime_int => return .single_const_pointer_to_comptime_int_type, |
| 32981 | .const_slice_u8 => return .const_slice_u8_type, | 33161 | .const_slice_u8 => return .const_slice_u8_type, |
| 32982 | .anyerror_void_error_union => return .anyerror_void_error_union_type, | 33162 | .anyerror_void_error_union => return .anyerror_void_error_union_type, |
| ... | @@ -33186,7 +33366,8 @@ const DerefResult = union(enum) { | ... | @@ -33186,7 +33366,8 @@ const DerefResult = union(enum) { |
| 33186 | }; | 33366 | }; |
| 33187 | 33367 | ||
| 33188 | fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, load_ty: Type, want_mutable: bool) CompileError!DerefResult { | 33368 | fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, load_ty: Type, want_mutable: bool) CompileError!DerefResult { |
| 33189 | const target = sema.mod.getTarget(); | 33369 | const mod = sema.mod; |
| 33370 | const target = mod.getTarget(); | ||
| 33190 | const deref = sema.beginComptimePtrLoad(block, src, ptr_val, load_ty) catch |err| switch (err) { | 33371 | const deref = sema.beginComptimePtrLoad(block, src, ptr_val, load_ty) catch |err| switch (err) { |
| 33191 | error.RuntimeLoad => return DerefResult{ .runtime_load = {} }, | 33372 | error.RuntimeLoad => return DerefResult{ .runtime_load = {} }, |
| 33192 | else => |e| return e, | 33373 | else => |e| return e, |
| ... | @@ -33211,7 +33392,7 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value | ... | @@ -33211,7 +33392,7 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value |
| 33211 | 33392 | ||
| 33212 | // The type is not in-memory coercible or the direct dereference failed, so it must | 33393 | // The type is not in-memory coercible or the direct dereference failed, so it must |
| 33213 | // be bitcast according to the pointer type we are performing the load through. | 33394 | // be bitcast according to the pointer type we are performing the load through. |
| 33214 | if (!load_ty.hasWellDefinedLayout()) { | 33395 | if (!load_ty.hasWellDefinedLayout(mod)) { |
| 33215 | return DerefResult{ .needed_well_defined = load_ty }; | 33396 | return DerefResult{ .needed_well_defined = load_ty }; |
| 33216 | } | 33397 | } |
| 33217 | 33398 | ||
| ... | @@ -33253,6 +33434,7 @@ fn typePtrOrOptionalPtrTy( | ... | @@ -33253,6 +33434,7 @@ fn typePtrOrOptionalPtrTy( |
| 33253 | ty: Type, | 33434 | ty: Type, |
| 33254 | buf: *Type.Payload.ElemType, | 33435 | buf: *Type.Payload.ElemType, |
| 33255 | ) !?Type { | 33436 | ) !?Type { |
| 33437 | const mod = sema.mod; | ||
| 33256 | switch (ty.tag()) { | 33438 | switch (ty.tag()) { |
| 33257 | .optional_single_const_pointer, | 33439 | .optional_single_const_pointer, |
| 33258 | .optional_single_mut_pointer, | 33440 | .optional_single_mut_pointer, |
| ... | @@ -33281,7 +33463,7 @@ fn typePtrOrOptionalPtrTy( | ... | @@ -33281,7 +33463,7 @@ fn typePtrOrOptionalPtrTy( |
| 33281 | 33463 | ||
| 33282 | .optional => { | 33464 | .optional => { |
| 33283 | const child_type = ty.optionalChild(buf); | 33465 | const child_type = ty.optionalChild(buf); |
| 33284 | if (child_type.zigTypeTag() != .Pointer) return null; | 33466 | if (child_type.zigTypeTag(mod) != .Pointer) return null; |
| 33285 | 33467 | ||
| 33286 | const info = child_type.ptrInfo().data; | 33468 | const info = child_type.ptrInfo().data; |
| 33287 | switch (info.size) { | 33469 | switch (info.size) { |
| ... | @@ -33310,6 +33492,23 @@ fn typePtrOrOptionalPtrTy( | ... | @@ -33310,6 +33492,23 @@ fn typePtrOrOptionalPtrTy( |
| 33310 | /// TODO merge these implementations together with the "advanced"/opt_sema pattern seen | 33492 | /// TODO merge these implementations together with the "advanced"/opt_sema pattern seen |
| 33311 | /// elsewhere in value.zig | 33493 | /// elsewhere in value.zig |
| 33312 | pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | 33494 | pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33495 | const mod = sema.mod; | ||
| 33496 | if (ty.ip_index != .none) { | ||
| 33497 | switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 33498 | .int_type => return false, | ||
| 33499 | .ptr_type => @panic("TODO"), | ||
| 33500 | .array_type => @panic("TODO"), | ||
| 33501 | .vector_type => @panic("TODO"), | ||
| 33502 | .optional_type => @panic("TODO"), | ||
| 33503 | .error_union_type => @panic("TODO"), | ||
| 33504 | .simple_type => @panic("TODO"), | ||
| 33505 | .struct_type => @panic("TODO"), | ||
| 33506 | .simple_value => unreachable, | ||
| 33507 | .extern_func => unreachable, | ||
| 33508 | .int => unreachable, | ||
| 33509 | .enum_tag => unreachable, // it's a value, not a type | ||
| 33510 | } | ||
| 33511 | } | ||
| 33313 | return switch (ty.tag()) { | 33512 | return switch (ty.tag()) { |
| 33314 | .u1, | 33513 | .u1, |
| 33315 | .u8, | 33514 | .u8, |
| ... | @@ -33374,8 +33573,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -33374,8 +33573,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33374 | .generic_poison, | 33573 | .generic_poison, |
| 33375 | .array_u8, | 33574 | .array_u8, |
| 33376 | .array_u8_sentinel_0, | 33575 | .array_u8_sentinel_0, |
| 33377 | .int_signed, | ||
| 33378 | .int_unsigned, | ||
| 33379 | .enum_simple, | 33576 | .enum_simple, |
| 33380 | => false, | 33577 | => false, |
| 33381 | 33578 | ||
| ... | @@ -33385,11 +33582,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -33385,11 +33582,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33385 | .comptime_float, | 33582 | .comptime_float, |
| 33386 | .enum_literal, | 33583 | .enum_literal, |
| 33387 | .type_info, | 33584 | .type_info, |
| 33388 | // These are function bodies, not function pointers. | ||
| 33389 | .fn_noreturn_no_args, | ||
| 33390 | .fn_void_no_args, | ||
| 33391 | .fn_naked_noreturn_no_args, | ||
| 33392 | .fn_ccc_void_no_args, | ||
| 33393 | .function, | 33585 | .function, |
| 33394 | => true, | 33586 | => true, |
| 33395 | 33587 | ||
| ... | @@ -33412,7 +33604,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -33412,7 +33604,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33412 | .mut_slice, | 33604 | .mut_slice, |
| 33413 | => { | 33605 | => { |
| 33414 | const child_ty = ty.childType(); | 33606 | const child_ty = ty.childType(); |
| 33415 | if (child_ty.zigTypeTag() == .Fn) { | 33607 | if (child_ty.zigTypeTag(mod) == .Fn) { |
| 33416 | return child_ty.fnInfo().is_generic; | 33608 | return child_ty.fnInfo().is_generic; |
| 33417 | } else { | 33609 | } else { |
| 33418 | return sema.typeRequiresComptime(child_ty); | 33610 | return sema.typeRequiresComptime(child_ty); |
| ... | @@ -33504,7 +33696,8 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -33504,7 +33696,8 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33504 | } | 33696 | } |
| 33505 | 33697 | ||
| 33506 | pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool { | 33698 | pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool { |
| 33507 | return ty.hasRuntimeBitsAdvanced(false, .{ .sema = sema }) catch |err| switch (err) { | 33699 | const mod = sema.mod; |
| 33700 | return ty.hasRuntimeBitsAdvanced(mod, false, .{ .sema = sema }) catch |err| switch (err) { | ||
| 33508 | error.NeedLazy => unreachable, | 33701 | error.NeedLazy => unreachable, |
| 33509 | else => |e| return e, | 33702 | else => |e| return e, |
| 33510 | }; | 33703 | }; |
| ... | @@ -33512,19 +33705,18 @@ pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -33512,19 +33705,18 @@ pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool { |
| 33512 | 33705 | ||
| 33513 | fn typeAbiSize(sema: *Sema, ty: Type) !u64 { | 33706 | fn typeAbiSize(sema: *Sema, ty: Type) !u64 { |
| 33514 | try sema.resolveTypeLayout(ty); | 33707 | try sema.resolveTypeLayout(ty); |
| 33515 | const target = sema.mod.getTarget(); | 33708 | return ty.abiSize(sema.mod); |
| 33516 | return ty.abiSize(target); | ||
| 33517 | } | 33709 | } |
| 33518 | 33710 | ||
| 33519 | fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!u32 { | 33711 | fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!u32 { |
| 33520 | const target = sema.mod.getTarget(); | 33712 | return (try ty.abiAlignmentAdvanced(sema.mod, .{ .sema = sema })).scalar; |
| 33521 | return (try ty.abiAlignmentAdvanced(target, .{ .sema = sema })).scalar; | ||
| 33522 | } | 33713 | } |
| 33523 | 33714 | ||
| 33524 | /// Not valid to call for packed unions. | 33715 | /// Not valid to call for packed unions. |
| 33525 | /// Keep implementation in sync with `Module.Union.Field.normalAlignment`. | 33716 | /// Keep implementation in sync with `Module.Union.Field.normalAlignment`. |
| 33526 | fn unionFieldAlignment(sema: *Sema, field: Module.Union.Field) !u32 { | 33717 | fn unionFieldAlignment(sema: *Sema, field: Module.Union.Field) !u32 { |
| 33527 | if (field.ty.zigTypeTag() == .NoReturn) { | 33718 | const mod = sema.mod; |
| 33719 | if (field.ty.zigTypeTag(mod) == .NoReturn) { | ||
| 33528 | return @as(u32, 0); | 33720 | return @as(u32, 0); |
| 33529 | } else if (field.abi_align == 0) { | 33721 | } else if (field.abi_align == 0) { |
| 33530 | return sema.typeAbiAlignment(field.ty); | 33722 | return sema.typeAbiAlignment(field.ty); |
| ... | @@ -33605,13 +33797,14 @@ fn queueFullTypeResolution(sema: *Sema, ty: Type) !void { | ... | @@ -33605,13 +33797,14 @@ fn queueFullTypeResolution(sema: *Sema, ty: Type) !void { |
| 33605 | } | 33797 | } |
| 33606 | 33798 | ||
| 33607 | fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { | 33799 | fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 33608 | if (ty.zigTypeTag() == .Vector) { | 33800 | const mod = sema.mod; |
| 33801 | if (ty.zigTypeTag(mod) == .Vector) { | ||
| 33609 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); | 33802 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 33610 | for (result_data, 0..) |*scalar, i| { | 33803 | for (result_data, 0..) |*scalar, i| { |
| 33611 | var lhs_buf: Value.ElemValueBuffer = undefined; | 33804 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 33612 | var rhs_buf: Value.ElemValueBuffer = undefined; | 33805 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 33613 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); | 33806 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 33614 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); | 33807 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 33615 | scalar.* = try sema.intAddScalar(lhs_elem, rhs_elem); | 33808 | scalar.* = try sema.intAddScalar(lhs_elem, rhs_elem); |
| 33616 | } | 33809 | } |
| 33617 | return Value.Tag.aggregate.create(sema.arena, result_data); | 33810 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| ... | @@ -33620,13 +33813,13 @@ fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { | ... | @@ -33620,13 +33813,13 @@ fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 33620 | } | 33813 | } |
| 33621 | 33814 | ||
| 33622 | fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value) !Value { | 33815 | fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 33816 | const mod = sema.mod; | ||
| 33623 | // TODO is this a performance issue? maybe we should try the operation without | 33817 | // TODO is this a performance issue? maybe we should try the operation without |
| 33624 | // resorting to BigInt first. | 33818 | // resorting to BigInt first. |
| 33625 | var lhs_space: Value.BigIntSpace = undefined; | 33819 | var lhs_space: Value.BigIntSpace = undefined; |
| 33626 | var rhs_space: Value.BigIntSpace = undefined; | 33820 | var rhs_space: Value.BigIntSpace = undefined; |
| 33627 | const target = sema.mod.getTarget(); | 33821 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema); |
| 33628 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema); | 33822 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema); |
| 33629 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema); | ||
| 33630 | const limbs = try sema.arena.alloc( | 33823 | const limbs = try sema.arena.alloc( |
| 33631 | std.math.big.Limb, | 33824 | std.math.big.Limb, |
| 33632 | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1, | 33825 | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1, |
| ... | @@ -33645,7 +33838,8 @@ fn numberAddWrapScalar( | ... | @@ -33645,7 +33838,8 @@ fn numberAddWrapScalar( |
| 33645 | ) !Value { | 33838 | ) !Value { |
| 33646 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 33839 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 33647 | 33840 | ||
| 33648 | if (ty.zigTypeTag() == .ComptimeInt) { | 33841 | const mod = sema.mod; |
| 33842 | if (ty.zigTypeTag(mod) == .ComptimeInt) { | ||
| 33649 | return sema.intAdd(lhs, rhs, ty); | 33843 | return sema.intAdd(lhs, rhs, ty); |
| 33650 | } | 33844 | } |
| 33651 | 33845 | ||
| ... | @@ -33663,7 +33857,8 @@ fn intSub( | ... | @@ -33663,7 +33857,8 @@ fn intSub( |
| 33663 | rhs: Value, | 33857 | rhs: Value, |
| 33664 | ty: Type, | 33858 | ty: Type, |
| 33665 | ) !Value { | 33859 | ) !Value { |
| 33666 | if (ty.zigTypeTag() == .Vector) { | 33860 | const mod = sema.mod; |
| 33861 | if (ty.zigTypeTag(mod) == .Vector) { | ||
| 33667 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); | 33862 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 33668 | for (result_data, 0..) |*scalar, i| { | 33863 | for (result_data, 0..) |*scalar, i| { |
| 33669 | var lhs_buf: Value.ElemValueBuffer = undefined; | 33864 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| ... | @@ -33678,13 +33873,13 @@ fn intSub( | ... | @@ -33678,13 +33873,13 @@ fn intSub( |
| 33678 | } | 33873 | } |
| 33679 | 33874 | ||
| 33680 | fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value) !Value { | 33875 | fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 33876 | const mod = sema.mod; | ||
| 33681 | // TODO is this a performance issue? maybe we should try the operation without | 33877 | // TODO is this a performance issue? maybe we should try the operation without |
| 33682 | // resorting to BigInt first. | 33878 | // resorting to BigInt first. |
| 33683 | var lhs_space: Value.BigIntSpace = undefined; | 33879 | var lhs_space: Value.BigIntSpace = undefined; |
| 33684 | var rhs_space: Value.BigIntSpace = undefined; | 33880 | var rhs_space: Value.BigIntSpace = undefined; |
| 33685 | const target = sema.mod.getTarget(); | 33881 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema); |
| 33686 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema); | 33882 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema); |
| 33687 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema); | ||
| 33688 | const limbs = try sema.arena.alloc( | 33883 | const limbs = try sema.arena.alloc( |
| 33689 | std.math.big.Limb, | 33884 | std.math.big.Limb, |
| 33690 | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1, | 33885 | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1, |
| ... | @@ -33703,7 +33898,8 @@ fn numberSubWrapScalar( | ... | @@ -33703,7 +33898,8 @@ fn numberSubWrapScalar( |
| 33703 | ) !Value { | 33898 | ) !Value { |
| 33704 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 33899 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 33705 | 33900 | ||
| 33706 | if (ty.zigTypeTag() == .ComptimeInt) { | 33901 | const mod = sema.mod; |
| 33902 | if (ty.zigTypeTag(mod) == .ComptimeInt) { | ||
| 33707 | return sema.intSub(lhs, rhs, ty); | 33903 | return sema.intSub(lhs, rhs, ty); |
| 33708 | } | 33904 | } |
| 33709 | 33905 | ||
| ... | @@ -33721,14 +33917,15 @@ fn floatAdd( | ... | @@ -33721,14 +33917,15 @@ fn floatAdd( |
| 33721 | rhs: Value, | 33917 | rhs: Value, |
| 33722 | float_type: Type, | 33918 | float_type: Type, |
| 33723 | ) !Value { | 33919 | ) !Value { |
| 33724 | if (float_type.zigTypeTag() == .Vector) { | 33920 | const mod = sema.mod; |
| 33921 | if (float_type.zigTypeTag(mod) == .Vector) { | ||
| 33725 | const result_data = try sema.arena.alloc(Value, float_type.vectorLen()); | 33922 | const result_data = try sema.arena.alloc(Value, float_type.vectorLen()); |
| 33726 | for (result_data, 0..) |*scalar, i| { | 33923 | for (result_data, 0..) |*scalar, i| { |
| 33727 | var lhs_buf: Value.ElemValueBuffer = undefined; | 33924 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 33728 | var rhs_buf: Value.ElemValueBuffer = undefined; | 33925 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 33729 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); | 33926 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); |
| 33730 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); | 33927 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); |
| 33731 | scalar.* = try sema.floatAddScalar(lhs_elem, rhs_elem, float_type.scalarType()); | 33928 | scalar.* = try sema.floatAddScalar(lhs_elem, rhs_elem, float_type.scalarType(mod)); |
| 33732 | } | 33929 | } |
| 33733 | return Value.Tag.aggregate.create(sema.arena, result_data); | 33930 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 33734 | } | 33931 | } |
| ... | @@ -33778,14 +33975,15 @@ fn floatSub( | ... | @@ -33778,14 +33975,15 @@ fn floatSub( |
| 33778 | rhs: Value, | 33975 | rhs: Value, |
| 33779 | float_type: Type, | 33976 | float_type: Type, |
| 33780 | ) !Value { | 33977 | ) !Value { |
| 33781 | if (float_type.zigTypeTag() == .Vector) { | 33978 | const mod = sema.mod; |
| 33979 | if (float_type.zigTypeTag(mod) == .Vector) { | ||
| 33782 | const result_data = try sema.arena.alloc(Value, float_type.vectorLen()); | 33980 | const result_data = try sema.arena.alloc(Value, float_type.vectorLen()); |
| 33783 | for (result_data, 0..) |*scalar, i| { | 33981 | for (result_data, 0..) |*scalar, i| { |
| 33784 | var lhs_buf: Value.ElemValueBuffer = undefined; | 33982 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 33785 | var rhs_buf: Value.ElemValueBuffer = undefined; | 33983 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 33786 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); | 33984 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); |
| 33787 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); | 33985 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); |
| 33788 | scalar.* = try sema.floatSubScalar(lhs_elem, rhs_elem, float_type.scalarType()); | 33986 | scalar.* = try sema.floatSubScalar(lhs_elem, rhs_elem, float_type.scalarType(mod)); |
| 33789 | } | 33987 | } |
| 33790 | return Value.Tag.aggregate.create(sema.arena, result_data); | 33988 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 33791 | } | 33989 | } |
| ... | @@ -33835,7 +34033,8 @@ fn intSubWithOverflow( | ... | @@ -33835,7 +34033,8 @@ fn intSubWithOverflow( |
| 33835 | rhs: Value, | 34033 | rhs: Value, |
| 33836 | ty: Type, | 34034 | ty: Type, |
| 33837 | ) !Value.OverflowArithmeticResult { | 34035 | ) !Value.OverflowArithmeticResult { |
| 33838 | if (ty.zigTypeTag() == .Vector) { | 34036 | const mod = sema.mod; |
| 34037 | if (ty.zigTypeTag(mod) == .Vector) { | ||
| 33839 | const overflowed_data = try sema.arena.alloc(Value, ty.vectorLen()); | 34038 | const overflowed_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 33840 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); | 34039 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 33841 | for (result_data, 0..) |*scalar, i| { | 34040 | for (result_data, 0..) |*scalar, i| { |
| ... | @@ -33843,7 +34042,7 @@ fn intSubWithOverflow( | ... | @@ -33843,7 +34042,7 @@ fn intSubWithOverflow( |
| 33843 | var rhs_buf: Value.ElemValueBuffer = undefined; | 34042 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 33844 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); | 34043 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); |
| 33845 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); | 34044 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); |
| 33846 | const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType()); | 34045 | const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(mod)); |
| 33847 | overflowed_data[i] = of_math_result.overflow_bit; | 34046 | overflowed_data[i] = of_math_result.overflow_bit; |
| 33848 | scalar.* = of_math_result.wrapped_result; | 34047 | scalar.* = of_math_result.wrapped_result; |
| 33849 | } | 34048 | } |
| ... | @@ -33861,13 +34060,13 @@ fn intSubWithOverflowScalar( | ... | @@ -33861,13 +34060,13 @@ fn intSubWithOverflowScalar( |
| 33861 | rhs: Value, | 34060 | rhs: Value, |
| 33862 | ty: Type, | 34061 | ty: Type, |
| 33863 | ) !Value.OverflowArithmeticResult { | 34062 | ) !Value.OverflowArithmeticResult { |
| 33864 | const target = sema.mod.getTarget(); | 34063 | const mod = sema.mod; |
| 33865 | const info = ty.intInfo(target); | 34064 | const info = ty.intInfo(mod); |
| 33866 | 34065 | ||
| 33867 | var lhs_space: Value.BigIntSpace = undefined; | 34066 | var lhs_space: Value.BigIntSpace = undefined; |
| 33868 | var rhs_space: Value.BigIntSpace = undefined; | 34067 | var rhs_space: Value.BigIntSpace = undefined; |
| 33869 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema); | 34068 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema); |
| 33870 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema); | 34069 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema); |
| 33871 | const limbs = try sema.arena.alloc( | 34070 | const limbs = try sema.arena.alloc( |
| 33872 | std.math.big.Limb, | 34071 | std.math.big.Limb, |
| 33873 | std.math.big.int.calcTwosCompLimbCount(info.bits), | 34072 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| ... | @@ -33889,13 +34088,14 @@ fn floatToInt( | ... | @@ -33889,13 +34088,14 @@ fn floatToInt( |
| 33889 | float_ty: Type, | 34088 | float_ty: Type, |
| 33890 | int_ty: Type, | 34089 | int_ty: Type, |
| 33891 | ) CompileError!Value { | 34090 | ) CompileError!Value { |
| 33892 | if (float_ty.zigTypeTag() == .Vector) { | 34091 | const mod = sema.mod; |
| 34092 | if (float_ty.zigTypeTag(mod) == .Vector) { | ||
| 33893 | const elem_ty = float_ty.childType(); | 34093 | const elem_ty = float_ty.childType(); |
| 33894 | const result_data = try sema.arena.alloc(Value, float_ty.vectorLen()); | 34094 | const result_data = try sema.arena.alloc(Value, float_ty.vectorLen()); |
| 33895 | for (result_data, 0..) |*scalar, i| { | 34095 | for (result_data, 0..) |*scalar, i| { |
| 33896 | var buf: Value.ElemValueBuffer = undefined; | 34096 | var buf: Value.ElemValueBuffer = undefined; |
| 33897 | const elem_val = val.elemValueBuffer(sema.mod, i, &buf); | 34097 | const elem_val = val.elemValueBuffer(sema.mod, i, &buf); |
| 33898 | scalar.* = try sema.floatToIntScalar(block, src, elem_val, elem_ty, int_ty.scalarType()); | 34098 | scalar.* = try sema.floatToIntScalar(block, src, elem_val, elem_ty, int_ty.scalarType(mod)); |
| 33899 | } | 34099 | } |
| 33900 | return Value.Tag.aggregate.create(sema.arena, result_data); | 34100 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 33901 | } | 34101 | } |
| ... | @@ -33976,7 +34176,8 @@ fn intFitsInType( | ... | @@ -33976,7 +34176,8 @@ fn intFitsInType( |
| 33976 | ty: Type, | 34176 | ty: Type, |
| 33977 | vector_index: ?*usize, | 34177 | vector_index: ?*usize, |
| 33978 | ) CompileError!bool { | 34178 | ) CompileError!bool { |
| 33979 | const target = sema.mod.getTarget(); | 34179 | const mod = sema.mod; |
| 34180 | const target = mod.getTarget(); | ||
| 33980 | switch (val.tag()) { | 34181 | switch (val.tag()) { |
| 33981 | .zero, | 34182 | .zero, |
| 33982 | .undef, | 34183 | .undef, |
| ... | @@ -33985,9 +34186,9 @@ fn intFitsInType( | ... | @@ -33985,9 +34186,9 @@ fn intFitsInType( |
| 33985 | 34186 | ||
| 33986 | .one, | 34187 | .one, |
| 33987 | .bool_true, | 34188 | .bool_true, |
| 33988 | => switch (ty.zigTypeTag()) { | 34189 | => switch (ty.zigTypeTag(mod)) { |
| 33989 | .Int => { | 34190 | .Int => { |
| 33990 | const info = ty.intInfo(target); | 34191 | const info = ty.intInfo(mod); |
| 33991 | return switch (info.signedness) { | 34192 | return switch (info.signedness) { |
| 33992 | .signed => info.bits >= 2, | 34193 | .signed => info.bits >= 2, |
| 33993 | .unsigned => info.bits >= 1, | 34194 | .unsigned => info.bits >= 1, |
| ... | @@ -33997,9 +34198,9 @@ fn intFitsInType( | ... | @@ -33997,9 +34198,9 @@ fn intFitsInType( |
| 33997 | else => unreachable, | 34198 | else => unreachable, |
| 33998 | }, | 34199 | }, |
| 33999 | 34200 | ||
| 34000 | .lazy_align => switch (ty.zigTypeTag()) { | 34201 | .lazy_align => switch (ty.zigTypeTag(mod)) { |
| 34001 | .Int => { | 34202 | .Int => { |
| 34002 | const info = ty.intInfo(target); | 34203 | const info = ty.intInfo(mod); |
| 34003 | const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed); | 34204 | const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed); |
| 34004 | // If it is u16 or bigger we know the alignment fits without resolving it. | 34205 | // If it is u16 or bigger we know the alignment fits without resolving it. |
| 34005 | if (info.bits >= max_needed_bits) return true; | 34206 | if (info.bits >= max_needed_bits) return true; |
| ... | @@ -34011,9 +34212,9 @@ fn intFitsInType( | ... | @@ -34011,9 +34212,9 @@ fn intFitsInType( |
| 34011 | .ComptimeInt => return true, | 34212 | .ComptimeInt => return true, |
| 34012 | else => unreachable, | 34213 | else => unreachable, |
| 34013 | }, | 34214 | }, |
| 34014 | .lazy_size => switch (ty.zigTypeTag()) { | 34215 | .lazy_size => switch (ty.zigTypeTag(mod)) { |
| 34015 | .Int => { | 34216 | .Int => { |
| 34016 | const info = ty.intInfo(target); | 34217 | const info = ty.intInfo(mod); |
| 34017 | const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed); | 34218 | const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed); |
| 34018 | // If it is u64 or bigger we know the size fits without resolving it. | 34219 | // If it is u64 or bigger we know the size fits without resolving it. |
| 34019 | if (info.bits >= max_needed_bits) return true; | 34220 | if (info.bits >= max_needed_bits) return true; |
| ... | @@ -34026,41 +34227,41 @@ fn intFitsInType( | ... | @@ -34026,41 +34227,41 @@ fn intFitsInType( |
| 34026 | else => unreachable, | 34227 | else => unreachable, |
| 34027 | }, | 34228 | }, |
| 34028 | 34229 | ||
| 34029 | .int_u64 => switch (ty.zigTypeTag()) { | 34230 | .int_u64 => switch (ty.zigTypeTag(mod)) { |
| 34030 | .Int => { | 34231 | .Int => { |
| 34031 | const x = val.castTag(.int_u64).?.data; | 34232 | const x = val.castTag(.int_u64).?.data; |
| 34032 | if (x == 0) return true; | 34233 | if (x == 0) return true; |
| 34033 | const info = ty.intInfo(target); | 34234 | const info = ty.intInfo(mod); |
| 34034 | const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed); | 34235 | const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed); |
| 34035 | return info.bits >= needed_bits; | 34236 | return info.bits >= needed_bits; |
| 34036 | }, | 34237 | }, |
| 34037 | .ComptimeInt => return true, | 34238 | .ComptimeInt => return true, |
| 34038 | else => unreachable, | 34239 | else => unreachable, |
| 34039 | }, | 34240 | }, |
| 34040 | .int_i64 => switch (ty.zigTypeTag()) { | 34241 | .int_i64 => switch (ty.zigTypeTag(mod)) { |
| 34041 | .Int => { | 34242 | .Int => { |
| 34042 | const x = val.castTag(.int_i64).?.data; | 34243 | const x = val.castTag(.int_i64).?.data; |
| 34043 | if (x == 0) return true; | 34244 | if (x == 0) return true; |
| 34044 | const info = ty.intInfo(target); | 34245 | const info = ty.intInfo(mod); |
| 34045 | if (info.signedness == .unsigned and x < 0) | 34246 | if (info.signedness == .unsigned and x < 0) |
| 34046 | return false; | 34247 | return false; |
| 34047 | var buffer: Value.BigIntSpace = undefined; | 34248 | var buffer: Value.BigIntSpace = undefined; |
| 34048 | return (try val.toBigIntAdvanced(&buffer, target, sema)).fitsInTwosComp(info.signedness, info.bits); | 34249 | return (try val.toBigIntAdvanced(&buffer, mod, sema)).fitsInTwosComp(info.signedness, info.bits); |
| 34049 | }, | 34250 | }, |
| 34050 | .ComptimeInt => return true, | 34251 | .ComptimeInt => return true, |
| 34051 | else => unreachable, | 34252 | else => unreachable, |
| 34052 | }, | 34253 | }, |
| 34053 | .int_big_positive => switch (ty.zigTypeTag()) { | 34254 | .int_big_positive => switch (ty.zigTypeTag(mod)) { |
| 34054 | .Int => { | 34255 | .Int => { |
| 34055 | const info = ty.intInfo(target); | 34256 | const info = ty.intInfo(mod); |
| 34056 | return val.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits); | 34257 | return val.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits); |
| 34057 | }, | 34258 | }, |
| 34058 | .ComptimeInt => return true, | 34259 | .ComptimeInt => return true, |
| 34059 | else => unreachable, | 34260 | else => unreachable, |
| 34060 | }, | 34261 | }, |
| 34061 | .int_big_negative => switch (ty.zigTypeTag()) { | 34262 | .int_big_negative => switch (ty.zigTypeTag(mod)) { |
| 34062 | .Int => { | 34263 | .Int => { |
| 34063 | const info = ty.intInfo(target); | 34264 | const info = ty.intInfo(mod); |
| 34064 | return val.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits); | 34265 | return val.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits); |
| 34065 | }, | 34266 | }, |
| 34066 | .ComptimeInt => return true, | 34267 | .ComptimeInt => return true, |
| ... | @@ -34068,7 +34269,7 @@ fn intFitsInType( | ... | @@ -34068,7 +34269,7 @@ fn intFitsInType( |
| 34068 | }, | 34269 | }, |
| 34069 | 34270 | ||
| 34070 | .the_only_possible_value => { | 34271 | .the_only_possible_value => { |
| 34071 | assert(ty.intInfo(target).bits == 0); | 34272 | assert(ty.intInfo(mod).bits == 0); |
| 34072 | return true; | 34273 | return true; |
| 34073 | }, | 34274 | }, |
| 34074 | 34275 | ||
| ... | @@ -34077,9 +34278,9 @@ fn intFitsInType( | ... | @@ -34077,9 +34278,9 @@ fn intFitsInType( |
| 34077 | .decl_ref, | 34278 | .decl_ref, |
| 34078 | .function, | 34279 | .function, |
| 34079 | .variable, | 34280 | .variable, |
| 34080 | => switch (ty.zigTypeTag()) { | 34281 | => switch (ty.zigTypeTag(mod)) { |
| 34081 | .Int => { | 34282 | .Int => { |
| 34082 | const info = ty.intInfo(target); | 34283 | const info = ty.intInfo(mod); |
| 34083 | const ptr_bits = target.ptrBitWidth(); | 34284 | const ptr_bits = target.ptrBitWidth(); |
| 34084 | return switch (info.signedness) { | 34285 | return switch (info.signedness) { |
| 34085 | .signed => info.bits > ptr_bits, | 34286 | .signed => info.bits > ptr_bits, |
| ... | @@ -34091,9 +34292,9 @@ fn intFitsInType( | ... | @@ -34091,9 +34292,9 @@ fn intFitsInType( |
| 34091 | }, | 34292 | }, |
| 34092 | 34293 | ||
| 34093 | .aggregate => { | 34294 | .aggregate => { |
| 34094 | assert(ty.zigTypeTag() == .Vector); | 34295 | assert(ty.zigTypeTag(mod) == .Vector); |
| 34095 | for (val.castTag(.aggregate).?.data, 0..) |elem, i| { | 34296 | for (val.castTag(.aggregate).?.data, 0..) |elem, i| { |
| 34096 | if (!(try sema.intFitsInType(elem, ty.scalarType(), null))) { | 34297 | if (!(try sema.intFitsInType(elem, ty.scalarType(mod), null))) { |
| 34097 | if (vector_index) |some| some.* = i; | 34298 | if (vector_index) |some| some.* = i; |
| 34098 | return false; | 34299 | return false; |
| 34099 | } | 34300 | } |
| ... | @@ -34122,11 +34323,8 @@ fn intInRange( | ... | @@ -34122,11 +34323,8 @@ fn intInRange( |
| 34122 | } | 34323 | } |
| 34123 | 34324 | ||
| 34124 | /// Asserts the type is an enum. | 34325 | /// Asserts the type is an enum. |
| 34125 | fn enumHasInt( | 34326 | fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool { |
| 34126 | sema: *Sema, | 34327 | const mod = sema.mod; |
| 34127 | ty: Type, | ||
| 34128 | int: Value, | ||
| 34129 | ) CompileError!bool { | ||
| 34130 | switch (ty.tag()) { | 34328 | switch (ty.tag()) { |
| 34131 | .enum_nonexhaustive => unreachable, | 34329 | .enum_nonexhaustive => unreachable, |
| 34132 | .enum_full => { | 34330 | .enum_full => { |
| ... | @@ -34157,11 +34355,7 @@ fn enumHasInt( | ... | @@ -34157,11 +34355,7 @@ fn enumHasInt( |
| 34157 | const enum_simple = ty.castTag(.enum_simple).?.data; | 34355 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 34158 | const fields_len = enum_simple.fields.count(); | 34356 | const fields_len = enum_simple.fields.count(); |
| 34159 | const bits = std.math.log2_int_ceil(usize, fields_len); | 34357 | const bits = std.math.log2_int_ceil(usize, fields_len); |
| 34160 | var buffer: Type.Payload.Bits = .{ | 34358 | const tag_ty = try mod.intType(.unsigned, bits); |
| 34161 | .base = .{ .tag = .int_unsigned }, | ||
| 34162 | .data = bits, | ||
| 34163 | }; | ||
| 34164 | const tag_ty = Type.initPayload(&buffer.base); | ||
| 34165 | return sema.intInRange(tag_ty, int, fields_len); | 34359 | return sema.intInRange(tag_ty, int, fields_len); |
| 34166 | }, | 34360 | }, |
| 34167 | .atomic_order, | 34361 | .atomic_order, |
| ... | @@ -34186,7 +34380,8 @@ fn intAddWithOverflow( | ... | @@ -34186,7 +34380,8 @@ fn intAddWithOverflow( |
| 34186 | rhs: Value, | 34380 | rhs: Value, |
| 34187 | ty: Type, | 34381 | ty: Type, |
| 34188 | ) !Value.OverflowArithmeticResult { | 34382 | ) !Value.OverflowArithmeticResult { |
| 34189 | if (ty.zigTypeTag() == .Vector) { | 34383 | const mod = sema.mod; |
| 34384 | if (ty.zigTypeTag(mod) == .Vector) { | ||
| 34190 | const overflowed_data = try sema.arena.alloc(Value, ty.vectorLen()); | 34385 | const overflowed_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 34191 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); | 34386 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 34192 | for (result_data, 0..) |*scalar, i| { | 34387 | for (result_data, 0..) |*scalar, i| { |
| ... | @@ -34194,7 +34389,7 @@ fn intAddWithOverflow( | ... | @@ -34194,7 +34389,7 @@ fn intAddWithOverflow( |
| 34194 | var rhs_buf: Value.ElemValueBuffer = undefined; | 34389 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 34195 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); | 34390 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); |
| 34196 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); | 34391 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); |
| 34197 | const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType()); | 34392 | const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(mod)); |
| 34198 | overflowed_data[i] = of_math_result.overflow_bit; | 34393 | overflowed_data[i] = of_math_result.overflow_bit; |
| 34199 | scalar.* = of_math_result.wrapped_result; | 34394 | scalar.* = of_math_result.wrapped_result; |
| 34200 | } | 34395 | } |
| ... | @@ -34212,13 +34407,13 @@ fn intAddWithOverflowScalar( | ... | @@ -34212,13 +34407,13 @@ fn intAddWithOverflowScalar( |
| 34212 | rhs: Value, | 34407 | rhs: Value, |
| 34213 | ty: Type, | 34408 | ty: Type, |
| 34214 | ) !Value.OverflowArithmeticResult { | 34409 | ) !Value.OverflowArithmeticResult { |
| 34215 | const target = sema.mod.getTarget(); | 34410 | const mod = sema.mod; |
| 34216 | const info = ty.intInfo(target); | 34411 | const info = ty.intInfo(mod); |
| 34217 | 34412 | ||
| 34218 | var lhs_space: Value.BigIntSpace = undefined; | 34413 | var lhs_space: Value.BigIntSpace = undefined; |
| 34219 | var rhs_space: Value.BigIntSpace = undefined; | 34414 | var rhs_space: Value.BigIntSpace = undefined; |
| 34220 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema); | 34415 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema); |
| 34221 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema); | 34416 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema); |
| 34222 | const limbs = try sema.arena.alloc( | 34417 | const limbs = try sema.arena.alloc( |
| 34223 | std.math.big.Limb, | 34418 | std.math.big.Limb, |
| 34224 | std.math.big.int.calcTwosCompLimbCount(info.bits), | 34419 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| ... | @@ -34243,14 +34438,15 @@ fn compareAll( | ... | @@ -34243,14 +34438,15 @@ fn compareAll( |
| 34243 | rhs: Value, | 34438 | rhs: Value, |
| 34244 | ty: Type, | 34439 | ty: Type, |
| 34245 | ) CompileError!bool { | 34440 | ) CompileError!bool { |
| 34246 | if (ty.zigTypeTag() == .Vector) { | 34441 | const mod = sema.mod; |
| 34442 | if (ty.zigTypeTag(mod) == .Vector) { | ||
| 34247 | var i: usize = 0; | 34443 | var i: usize = 0; |
| 34248 | while (i < ty.vectorLen()) : (i += 1) { | 34444 | while (i < ty.vectorLen()) : (i += 1) { |
| 34249 | var lhs_buf: Value.ElemValueBuffer = undefined; | 34445 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 34250 | var rhs_buf: Value.ElemValueBuffer = undefined; | 34446 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 34251 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); | 34447 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); |
| 34252 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); | 34448 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); |
| 34253 | if (!(try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType()))) { | 34449 | if (!(try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(mod)))) { |
| 34254 | return false; | 34450 | return false; |
| 34255 | } | 34451 | } |
| 34256 | } | 34452 | } |
| ... | @@ -34270,7 +34466,7 @@ fn compareScalar( | ... | @@ -34270,7 +34466,7 @@ fn compareScalar( |
| 34270 | switch (op) { | 34466 | switch (op) { |
| 34271 | .eq => return sema.valuesEqual(lhs, rhs, ty), | 34467 | .eq => return sema.valuesEqual(lhs, rhs, ty), |
| 34272 | .neq => return !(try sema.valuesEqual(lhs, rhs, ty)), | 34468 | .neq => return !(try sema.valuesEqual(lhs, rhs, ty)), |
| 34273 | else => return Value.compareHeteroAdvanced(lhs, op, rhs, sema.mod.getTarget(), sema), | 34469 | else => return Value.compareHeteroAdvanced(lhs, op, rhs, sema.mod, sema), |
| 34274 | } | 34470 | } |
| 34275 | } | 34471 | } |
| 34276 | 34472 | ||
| ... | @@ -34291,14 +34487,15 @@ fn compareVector( | ... | @@ -34291,14 +34487,15 @@ fn compareVector( |
| 34291 | rhs: Value, | 34487 | rhs: Value, |
| 34292 | ty: Type, | 34488 | ty: Type, |
| 34293 | ) !Value { | 34489 | ) !Value { |
| 34294 | assert(ty.zigTypeTag() == .Vector); | 34490 | const mod = sema.mod; |
| 34491 | assert(ty.zigTypeTag(mod) == .Vector); | ||
| 34295 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); | 34492 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 34296 | for (result_data, 0..) |*scalar, i| { | 34493 | for (result_data, 0..) |*scalar, i| { |
| 34297 | var lhs_buf: Value.ElemValueBuffer = undefined; | 34494 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 34298 | var rhs_buf: Value.ElemValueBuffer = undefined; | 34495 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 34299 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); | 34496 | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); |
| 34300 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); | 34497 | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); |
| 34301 | const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType()); | 34498 | const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(mod)); |
| 34302 | scalar.* = Value.makeBool(res_bool); | 34499 | scalar.* = Value.makeBool(res_bool); |
| 34303 | } | 34500 | } |
| 34304 | return Value.Tag.aggregate.create(sema.arena, result_data); | 34501 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| ... | @@ -34312,10 +34509,10 @@ fn compareVector( | ... | @@ -34312,10 +34509,10 @@ fn compareVector( |
| 34312 | /// Handles const-ness and address spaces in particular. | 34509 | /// Handles const-ness and address spaces in particular. |
| 34313 | /// This code is duplicated in `analyzePtrArithmetic`. | 34510 | /// This code is duplicated in `analyzePtrArithmetic`. |
| 34314 | fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type { | 34511 | fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type { |
| 34512 | const mod = sema.mod; | ||
| 34315 | const ptr_info = ptr_ty.ptrInfo().data; | 34513 | const ptr_info = ptr_ty.ptrInfo().data; |
| 34316 | const elem_ty = ptr_ty.elemType2(); | 34514 | const elem_ty = ptr_ty.elemType2(mod); |
| 34317 | const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0; | 34515 | const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0; |
| 34318 | const target = sema.mod.getTarget(); | ||
| 34319 | const parent_ty = ptr_ty.childType(); | 34516 | const parent_ty = ptr_ty.childType(); |
| 34320 | 34517 | ||
| 34321 | const VI = Type.Payload.Pointer.Data.VectorIndex; | 34518 | const VI = Type.Payload.Pointer.Data.VectorIndex; |
| ... | @@ -34325,14 +34522,14 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type { | ... | @@ -34325,14 +34522,14 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type { |
| 34325 | alignment: u32 = 0, | 34522 | alignment: u32 = 0, |
| 34326 | vector_index: VI = .none, | 34523 | vector_index: VI = .none, |
| 34327 | } = if (parent_ty.tag() == .vector and ptr_info.size == .One) blk: { | 34524 | } = if (parent_ty.tag() == .vector and ptr_info.size == .One) blk: { |
| 34328 | const elem_bits = elem_ty.bitSize(target); | 34525 | const elem_bits = elem_ty.bitSize(mod); |
| 34329 | if (elem_bits == 0) break :blk .{}; | 34526 | if (elem_bits == 0) break :blk .{}; |
| 34330 | const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits); | 34527 | const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits); |
| 34331 | if (!is_packed) break :blk .{}; | 34528 | if (!is_packed) break :blk .{}; |
| 34332 | 34529 | ||
| 34333 | break :blk .{ | 34530 | break :blk .{ |
| 34334 | .host_size = @intCast(u16, parent_ty.arrayLen()), | 34531 | .host_size = @intCast(u16, parent_ty.arrayLen()), |
| 34335 | .alignment = @intCast(u16, parent_ty.abiAlignment(target)), | 34532 | .alignment = @intCast(u16, parent_ty.abiAlignment(mod)), |
| 34336 | .vector_index = if (offset) |some| @intToEnum(VI, some) else .runtime, | 34533 | .vector_index = if (offset) |some| @intToEnum(VI, some) else .runtime, |
| 34337 | }; | 34534 | }; |
| 34338 | } else .{}; | 34535 | } else .{}; |
src/TypedValue.zig+15-27| ... | @@ -71,7 +71,6 @@ pub fn print( | ... | @@ -71,7 +71,6 @@ pub fn print( |
| 71 | level: u8, | 71 | level: u8, |
| 72 | mod: *Module, | 72 | mod: *Module, |
| 73 | ) @TypeOf(writer).Error!void { | 73 | ) @TypeOf(writer).Error!void { |
| 74 | const target = mod.getTarget(); | ||
| 75 | var val = tv.val; | 74 | var val = tv.val; |
| 76 | var ty = tv.ty; | 75 | var ty = tv.ty; |
| 77 | if (val.isVariable(mod)) | 76 | if (val.isVariable(mod)) |
| ... | @@ -117,10 +116,6 @@ pub fn print( | ... | @@ -117,10 +116,6 @@ pub fn print( |
| 117 | .noreturn_type => return writer.writeAll("noreturn"), | 116 | .noreturn_type => return writer.writeAll("noreturn"), |
| 118 | .null_type => return writer.writeAll("@Type(.Null)"), | 117 | .null_type => return writer.writeAll("@Type(.Null)"), |
| 119 | .undefined_type => return writer.writeAll("@Type(.Undefined)"), | 118 | .undefined_type => return writer.writeAll("@Type(.Undefined)"), |
| 120 | .fn_noreturn_no_args_type => return writer.writeAll("fn() noreturn"), | ||
| 121 | .fn_void_no_args_type => return writer.writeAll("fn() void"), | ||
| 122 | .fn_naked_noreturn_no_args_type => return writer.writeAll("fn() callconv(.Naked) noreturn"), | ||
| 123 | .fn_ccc_void_no_args_type => return writer.writeAll("fn() callconv(.C) void"), | ||
| 124 | .single_const_pointer_to_comptime_int_type => return writer.writeAll("*const comptime_int"), | 119 | .single_const_pointer_to_comptime_int_type => return writer.writeAll("*const comptime_int"), |
| 125 | .anyframe_type => return writer.writeAll("anyframe"), | 120 | .anyframe_type => return writer.writeAll("anyframe"), |
| 126 | .const_slice_u8_type => return writer.writeAll("[]const u8"), | 121 | .const_slice_u8_type => return writer.writeAll("[]const u8"), |
| ... | @@ -147,7 +142,7 @@ pub fn print( | ... | @@ -147,7 +142,7 @@ pub fn print( |
| 147 | if (level == 0) { | 142 | if (level == 0) { |
| 148 | return writer.writeAll(".{ ... }"); | 143 | return writer.writeAll(".{ ... }"); |
| 149 | } | 144 | } |
| 150 | if (ty.zigTypeTag() == .Struct) { | 145 | if (ty.zigTypeTag(mod) == .Struct) { |
| 151 | try writer.writeAll(".{"); | 146 | try writer.writeAll(".{"); |
| 152 | const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items); | 147 | const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items); |
| 153 | 148 | ||
| ... | @@ -160,7 +155,7 @@ pub fn print( | ... | @@ -160,7 +155,7 @@ pub fn print( |
| 160 | } | 155 | } |
| 161 | try print(.{ | 156 | try print(.{ |
| 162 | .ty = ty.structFieldType(i), | 157 | .ty = ty.structFieldType(i), |
| 163 | .val = val.fieldValue(ty, i), | 158 | .val = val.fieldValue(ty, mod, i), |
| 164 | }, writer, level - 1, mod); | 159 | }, writer, level - 1, mod); |
| 165 | } | 160 | } |
| 166 | if (ty.structFieldCount() > max_aggregate_items) { | 161 | if (ty.structFieldCount() > max_aggregate_items) { |
| ... | @@ -168,7 +163,7 @@ pub fn print( | ... | @@ -168,7 +163,7 @@ pub fn print( |
| 168 | } | 163 | } |
| 169 | return writer.writeAll("}"); | 164 | return writer.writeAll("}"); |
| 170 | } else { | 165 | } else { |
| 171 | const elem_ty = ty.elemType2(); | 166 | const elem_ty = ty.elemType2(mod); |
| 172 | const len = ty.arrayLen(); | 167 | const len = ty.arrayLen(); |
| 173 | 168 | ||
| 174 | if (elem_ty.eql(Type.u8, mod)) str: { | 169 | if (elem_ty.eql(Type.u8, mod)) str: { |
| ... | @@ -177,9 +172,9 @@ pub fn print( | ... | @@ -177,9 +172,9 @@ pub fn print( |
| 177 | 172 | ||
| 178 | var i: u32 = 0; | 173 | var i: u32 = 0; |
| 179 | while (i < max_len) : (i += 1) { | 174 | while (i < max_len) : (i += 1) { |
| 180 | const elem = val.fieldValue(ty, i); | 175 | const elem = val.fieldValue(ty, mod, i); |
| 181 | if (elem.isUndef()) break :str; | 176 | if (elem.isUndef()) break :str; |
| 182 | buf[i] = std.math.cast(u8, elem.toUnsignedInt(target)) orelse break :str; | 177 | buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str; |
| 183 | } | 178 | } |
| 184 | 179 | ||
| 185 | const truncated = if (len > max_string_len) " (truncated)" else ""; | 180 | const truncated = if (len > max_string_len) " (truncated)" else ""; |
| ... | @@ -194,7 +189,7 @@ pub fn print( | ... | @@ -194,7 +189,7 @@ pub fn print( |
| 194 | if (i != 0) try writer.writeAll(", "); | 189 | if (i != 0) try writer.writeAll(", "); |
| 195 | try print(.{ | 190 | try print(.{ |
| 196 | .ty = elem_ty, | 191 | .ty = elem_ty, |
| 197 | .val = val.fieldValue(ty, i), | 192 | .val = val.fieldValue(ty, mod, i), |
| 198 | }, writer, level - 1, mod); | 193 | }, writer, level - 1, mod); |
| 199 | } | 194 | } |
| 200 | if (len > max_aggregate_items) { | 195 | if (len > max_aggregate_items) { |
| ... | @@ -232,25 +227,18 @@ pub fn print( | ... | @@ -232,25 +227,18 @@ pub fn print( |
| 232 | .bool_true => return writer.writeAll("true"), | 227 | .bool_true => return writer.writeAll("true"), |
| 233 | .bool_false => return writer.writeAll("false"), | 228 | .bool_false => return writer.writeAll("false"), |
| 234 | .ty => return val.castTag(.ty).?.data.print(writer, mod), | 229 | .ty => return val.castTag(.ty).?.data.print(writer, mod), |
| 235 | .int_type => { | ||
| 236 | const int_type = val.castTag(.int_type).?.data; | ||
| 237 | return writer.print("{s}{d}", .{ | ||
| 238 | if (int_type.signed) "s" else "u", | ||
| 239 | int_type.bits, | ||
| 240 | }); | ||
| 241 | }, | ||
| 242 | .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", .{}, writer), | 230 | .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", .{}, writer), |
| 243 | .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", .{}, writer), | 231 | .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", .{}, writer), |
| 244 | .int_big_positive => return writer.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}), | 232 | .int_big_positive => return writer.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}), |
| 245 | .int_big_negative => return writer.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}), | 233 | .int_big_negative => return writer.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}), |
| 246 | .lazy_align => { | 234 | .lazy_align => { |
| 247 | const sub_ty = val.castTag(.lazy_align).?.data; | 235 | const sub_ty = val.castTag(.lazy_align).?.data; |
| 248 | const x = sub_ty.abiAlignment(target); | 236 | const x = sub_ty.abiAlignment(mod); |
| 249 | return writer.print("{d}", .{x}); | 237 | return writer.print("{d}", .{x}); |
| 250 | }, | 238 | }, |
| 251 | .lazy_size => { | 239 | .lazy_size => { |
| 252 | const sub_ty = val.castTag(.lazy_size).?.data; | 240 | const sub_ty = val.castTag(.lazy_size).?.data; |
| 253 | const x = sub_ty.abiSize(target); | 241 | const x = sub_ty.abiSize(mod); |
| 254 | return writer.print("{d}", .{x}); | 242 | return writer.print("{d}", .{x}); |
| 255 | }, | 243 | }, |
| 256 | .function => return writer.print("(function '{s}')", .{ | 244 | .function => return writer.print("(function '{s}')", .{ |
| ... | @@ -315,7 +303,7 @@ pub fn print( | ... | @@ -315,7 +303,7 @@ pub fn print( |
| 315 | }, writer, level - 1, mod); | 303 | }, writer, level - 1, mod); |
| 316 | } | 304 | } |
| 317 | 305 | ||
| 318 | if (field_ptr.container_ty.zigTypeTag() == .Struct) { | 306 | if (field_ptr.container_ty.zigTypeTag(mod) == .Struct) { |
| 319 | switch (field_ptr.container_ty.tag()) { | 307 | switch (field_ptr.container_ty.tag()) { |
| 320 | .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}), | 308 | .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}), |
| 321 | else => { | 309 | else => { |
| ... | @@ -323,7 +311,7 @@ pub fn print( | ... | @@ -323,7 +311,7 @@ pub fn print( |
| 323 | return writer.print(".{s}", .{field_name}); | 311 | return writer.print(".{s}", .{field_name}); |
| 324 | }, | 312 | }, |
| 325 | } | 313 | } |
| 326 | } else if (field_ptr.container_ty.zigTypeTag() == .Union) { | 314 | } else if (field_ptr.container_ty.zigTypeTag(mod) == .Union) { |
| 327 | const field_name = field_ptr.container_ty.unionFields().keys()[field_ptr.field_index]; | 315 | const field_name = field_ptr.container_ty.unionFields().keys()[field_ptr.field_index]; |
| 328 | return writer.print(".{s}", .{field_name}); | 316 | return writer.print(".{s}", .{field_name}); |
| 329 | } else if (field_ptr.container_ty.isSlice()) { | 317 | } else if (field_ptr.container_ty.isSlice()) { |
| ... | @@ -352,7 +340,7 @@ pub fn print( | ... | @@ -352,7 +340,7 @@ pub fn print( |
| 352 | var i: u32 = 0; | 340 | var i: u32 = 0; |
| 353 | try writer.writeAll(".{ "); | 341 | try writer.writeAll(".{ "); |
| 354 | const elem_tv = TypedValue{ | 342 | const elem_tv = TypedValue{ |
| 355 | .ty = ty.elemType2(), | 343 | .ty = ty.elemType2(mod), |
| 356 | .val = val.castTag(.repeated).?.data, | 344 | .val = val.castTag(.repeated).?.data, |
| 357 | }; | 345 | }; |
| 358 | const len = ty.arrayLen(); | 346 | const len = ty.arrayLen(); |
| ... | @@ -372,7 +360,7 @@ pub fn print( | ... | @@ -372,7 +360,7 @@ pub fn print( |
| 372 | } | 360 | } |
| 373 | try writer.writeAll(".{ "); | 361 | try writer.writeAll(".{ "); |
| 374 | try print(.{ | 362 | try print(.{ |
| 375 | .ty = ty.elemType2(), | 363 | .ty = ty.elemType2(mod), |
| 376 | .val = ty.sentinel().?, | 364 | .val = ty.sentinel().?, |
| 377 | }, writer, level - 1, mod); | 365 | }, writer, level - 1, mod); |
| 378 | return writer.writeAll(" }"); | 366 | return writer.writeAll(" }"); |
| ... | @@ -382,8 +370,8 @@ pub fn print( | ... | @@ -382,8 +370,8 @@ pub fn print( |
| 382 | return writer.writeAll(".{ ... }"); | 370 | return writer.writeAll(".{ ... }"); |
| 383 | } | 371 | } |
| 384 | const payload = val.castTag(.slice).?.data; | 372 | const payload = val.castTag(.slice).?.data; |
| 385 | const elem_ty = ty.elemType2(); | 373 | const elem_ty = ty.elemType2(mod); |
| 386 | const len = payload.len.toUnsignedInt(target); | 374 | const len = payload.len.toUnsignedInt(mod); |
| 387 | 375 | ||
| 388 | if (elem_ty.eql(Type.u8, mod)) str: { | 376 | if (elem_ty.eql(Type.u8, mod)) str: { |
| 389 | const max_len = @intCast(usize, std.math.min(len, max_string_len)); | 377 | const max_len = @intCast(usize, std.math.min(len, max_string_len)); |
| ... | @@ -394,7 +382,7 @@ pub fn print( | ... | @@ -394,7 +382,7 @@ pub fn print( |
| 394 | var elem_buf: Value.ElemValueBuffer = undefined; | 382 | var elem_buf: Value.ElemValueBuffer = undefined; |
| 395 | const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf); | 383 | const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf); |
| 396 | if (elem_val.isUndef()) break :str; | 384 | if (elem_val.isUndef()) break :str; |
| 397 | buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(target)) orelse break :str; | 385 | buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(mod)) orelse break :str; |
| 398 | } | 386 | } |
| 399 | 387 | ||
| 400 | // TODO would be nice if this had a bit of unicode awareness. | 388 | // TODO would be nice if this had a bit of unicode awareness. |
src/Zir.zig+83-435| ... | @@ -19,6 +19,7 @@ const BigIntConst = std.math.big.int.Const; | ... | @@ -19,6 +19,7 @@ const BigIntConst = std.math.big.int.Const; |
| 19 | const BigIntMutable = std.math.big.int.Mutable; | 19 | const BigIntMutable = std.math.big.int.Mutable; |
| 20 | const Ast = std.zig.Ast; | 20 | const Ast = std.zig.Ast; |
| 21 | 21 | ||
| 22 | const InternPool = @import("InternPool.zig"); | ||
| 22 | const Zir = @This(); | 23 | const Zir = @This(); |
| 23 | const Type = @import("type.zig").Type; | 24 | const Type = @import("type.zig").Type; |
| 24 | const Value = @import("value.zig").Value; | 25 | const Value = @import("value.zig").Value; |
| ... | @@ -2041,448 +2042,95 @@ pub const Inst = struct { | ... | @@ -2041,448 +2042,95 @@ pub const Inst = struct { |
| 2041 | /// The position of a ZIR instruction within the `Zir` instructions array. | 2042 | /// The position of a ZIR instruction within the `Zir` instructions array. |
| 2042 | pub const Index = u32; | 2043 | pub const Index = u32; |
| 2043 | 2044 | ||
| 2044 | /// A reference to a TypedValue or ZIR instruction. | 2045 | /// A reference to ZIR instruction, or to an InternPool index, or neither. |
| 2045 | /// | 2046 | /// |
| 2046 | /// If the Ref has a tag in this enum, it refers to a TypedValue. | 2047 | /// If the integer tag value is < InternPool.static_len, then it |
| 2047 | /// | 2048 | /// corresponds to an InternPool index. Otherwise, this refers to a ZIR |
| 2048 | /// If the value of a Ref does not have a tag, it refers to a ZIR instruction. | 2049 | /// instruction. |
| 2049 | /// | ||
| 2050 | /// The first values after the the last tag refer to ZIR instructions which may | ||
| 2051 | /// be derived by subtracting `typed_value_map.len`. | ||
| 2052 | /// | ||
| 2053 | /// When adding a tag to this enum, consider adding a corresponding entry to | ||
| 2054 | /// `primitives` in astgen. | ||
| 2055 | /// | 2050 | /// |
| 2056 | /// The tag type is specified so that it is safe to bitcast between `[]u32` | 2051 | /// The tag type is specified so that it is safe to bitcast between `[]u32` |
| 2057 | /// and `[]Ref`. | 2052 | /// and `[]Ref`. |
| 2058 | pub const Ref = enum(u32) { | 2053 | pub const Ref = enum(u32) { |
| 2054 | u1_type = @enumToInt(InternPool.Index.u1_type), | ||
| 2055 | u8_type = @enumToInt(InternPool.Index.u8_type), | ||
| 2056 | i8_type = @enumToInt(InternPool.Index.i8_type), | ||
| 2057 | u16_type = @enumToInt(InternPool.Index.u16_type), | ||
| 2058 | i16_type = @enumToInt(InternPool.Index.i16_type), | ||
| 2059 | u29_type = @enumToInt(InternPool.Index.u29_type), | ||
| 2060 | u32_type = @enumToInt(InternPool.Index.u32_type), | ||
| 2061 | i32_type = @enumToInt(InternPool.Index.i32_type), | ||
| 2062 | u64_type = @enumToInt(InternPool.Index.u64_type), | ||
| 2063 | i64_type = @enumToInt(InternPool.Index.i64_type), | ||
| 2064 | u80_type = @enumToInt(InternPool.Index.u80_type), | ||
| 2065 | u128_type = @enumToInt(InternPool.Index.u128_type), | ||
| 2066 | i128_type = @enumToInt(InternPool.Index.i128_type), | ||
| 2067 | usize_type = @enumToInt(InternPool.Index.usize_type), | ||
| 2068 | isize_type = @enumToInt(InternPool.Index.isize_type), | ||
| 2069 | c_char_type = @enumToInt(InternPool.Index.c_char_type), | ||
| 2070 | c_short_type = @enumToInt(InternPool.Index.c_short_type), | ||
| 2071 | c_ushort_type = @enumToInt(InternPool.Index.c_ushort_type), | ||
| 2072 | c_int_type = @enumToInt(InternPool.Index.c_int_type), | ||
| 2073 | c_uint_type = @enumToInt(InternPool.Index.c_uint_type), | ||
| 2074 | c_long_type = @enumToInt(InternPool.Index.c_long_type), | ||
| 2075 | c_ulong_type = @enumToInt(InternPool.Index.c_ulong_type), | ||
| 2076 | c_longlong_type = @enumToInt(InternPool.Index.c_longlong_type), | ||
| 2077 | c_ulonglong_type = @enumToInt(InternPool.Index.c_ulonglong_type), | ||
| 2078 | c_longdouble_type = @enumToInt(InternPool.Index.c_longdouble_type), | ||
| 2079 | f16_type = @enumToInt(InternPool.Index.f16_type), | ||
| 2080 | f32_type = @enumToInt(InternPool.Index.f32_type), | ||
| 2081 | f64_type = @enumToInt(InternPool.Index.f64_type), | ||
| 2082 | f80_type = @enumToInt(InternPool.Index.f80_type), | ||
| 2083 | f128_type = @enumToInt(InternPool.Index.f128_type), | ||
| 2084 | anyopaque_type = @enumToInt(InternPool.Index.anyopaque_type), | ||
| 2085 | bool_type = @enumToInt(InternPool.Index.bool_type), | ||
| 2086 | void_type = @enumToInt(InternPool.Index.void_type), | ||
| 2087 | type_type = @enumToInt(InternPool.Index.type_type), | ||
| 2088 | anyerror_type = @enumToInt(InternPool.Index.anyerror_type), | ||
| 2089 | comptime_int_type = @enumToInt(InternPool.Index.comptime_int_type), | ||
| 2090 | comptime_float_type = @enumToInt(InternPool.Index.comptime_float_type), | ||
| 2091 | noreturn_type = @enumToInt(InternPool.Index.noreturn_type), | ||
| 2092 | anyframe_type = @enumToInt(InternPool.Index.anyframe_type), | ||
| 2093 | null_type = @enumToInt(InternPool.Index.null_type), | ||
| 2094 | undefined_type = @enumToInt(InternPool.Index.undefined_type), | ||
| 2095 | enum_literal_type = @enumToInt(InternPool.Index.enum_literal_type), | ||
| 2096 | atomic_order_type = @enumToInt(InternPool.Index.atomic_order_type), | ||
| 2097 | atomic_rmw_op_type = @enumToInt(InternPool.Index.atomic_rmw_op_type), | ||
| 2098 | calling_convention_type = @enumToInt(InternPool.Index.calling_convention_type), | ||
| 2099 | address_space_type = @enumToInt(InternPool.Index.address_space_type), | ||
| 2100 | float_mode_type = @enumToInt(InternPool.Index.float_mode_type), | ||
| 2101 | reduce_op_type = @enumToInt(InternPool.Index.reduce_op_type), | ||
| 2102 | call_modifier_type = @enumToInt(InternPool.Index.call_modifier_type), | ||
| 2103 | prefetch_options_type = @enumToInt(InternPool.Index.prefetch_options_type), | ||
| 2104 | export_options_type = @enumToInt(InternPool.Index.export_options_type), | ||
| 2105 | extern_options_type = @enumToInt(InternPool.Index.extern_options_type), | ||
| 2106 | type_info_type = @enumToInt(InternPool.Index.type_info_type), | ||
| 2107 | manyptr_u8_type = @enumToInt(InternPool.Index.manyptr_u8_type), | ||
| 2108 | manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type), | ||
| 2109 | single_const_pointer_to_comptime_int_type = @enumToInt(InternPool.Index.single_const_pointer_to_comptime_int_type), | ||
| 2110 | const_slice_u8_type = @enumToInt(InternPool.Index.const_slice_u8_type), | ||
| 2111 | anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type), | ||
| 2112 | generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type), | ||
| 2113 | var_args_param_type = @enumToInt(InternPool.Index.var_args_param_type), | ||
| 2114 | empty_struct_type = @enumToInt(InternPool.Index.empty_struct_type), | ||
| 2115 | undef = @enumToInt(InternPool.Index.undef), | ||
| 2116 | zero = @enumToInt(InternPool.Index.zero), | ||
| 2117 | zero_usize = @enumToInt(InternPool.Index.zero_usize), | ||
| 2118 | one = @enumToInt(InternPool.Index.one), | ||
| 2119 | one_usize = @enumToInt(InternPool.Index.one_usize), | ||
| 2120 | calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c), | ||
| 2121 | calling_convention_inline = @enumToInt(InternPool.Index.calling_convention_inline), | ||
| 2122 | void_value = @enumToInt(InternPool.Index.void_value), | ||
| 2123 | unreachable_value = @enumToInt(InternPool.Index.unreachable_value), | ||
| 2124 | null_value = @enumToInt(InternPool.Index.null_value), | ||
| 2125 | bool_true = @enumToInt(InternPool.Index.bool_true), | ||
| 2126 | bool_false = @enumToInt(InternPool.Index.bool_false), | ||
| 2127 | empty_struct = @enumToInt(InternPool.Index.empty_struct), | ||
| 2128 | generic_poison = @enumToInt(InternPool.Index.generic_poison), | ||
| 2129 | |||
| 2059 | /// This Ref does not correspond to any ZIR instruction or constant | 2130 | /// This Ref does not correspond to any ZIR instruction or constant |
| 2060 | /// value and may instead be used as a sentinel to indicate null. | 2131 | /// value and may instead be used as a sentinel to indicate null. |
| 2061 | none, | 2132 | none = std.math.maxInt(u32), |
| 2062 | |||
| 2063 | u1_type, | ||
| 2064 | u8_type, | ||
| 2065 | i8_type, | ||
| 2066 | u16_type, | ||
| 2067 | i16_type, | ||
| 2068 | u29_type, | ||
| 2069 | u32_type, | ||
| 2070 | i32_type, | ||
| 2071 | u64_type, | ||
| 2072 | i64_type, | ||
| 2073 | u128_type, | ||
| 2074 | i128_type, | ||
| 2075 | usize_type, | ||
| 2076 | isize_type, | ||
| 2077 | c_char_type, | ||
| 2078 | c_short_type, | ||
| 2079 | c_ushort_type, | ||
| 2080 | c_int_type, | ||
| 2081 | c_uint_type, | ||
| 2082 | c_long_type, | ||
| 2083 | c_ulong_type, | ||
| 2084 | c_longlong_type, | ||
| 2085 | c_ulonglong_type, | ||
| 2086 | c_longdouble_type, | ||
| 2087 | f16_type, | ||
| 2088 | f32_type, | ||
| 2089 | f64_type, | ||
| 2090 | f80_type, | ||
| 2091 | f128_type, | ||
| 2092 | anyopaque_type, | ||
| 2093 | bool_type, | ||
| 2094 | void_type, | ||
| 2095 | type_type, | ||
| 2096 | anyerror_type, | ||
| 2097 | comptime_int_type, | ||
| 2098 | comptime_float_type, | ||
| 2099 | noreturn_type, | ||
| 2100 | anyframe_type, | ||
| 2101 | null_type, | ||
| 2102 | undefined_type, | ||
| 2103 | enum_literal_type, | ||
| 2104 | atomic_order_type, | ||
| 2105 | atomic_rmw_op_type, | ||
| 2106 | calling_convention_type, | ||
| 2107 | address_space_type, | ||
| 2108 | float_mode_type, | ||
| 2109 | reduce_op_type, | ||
| 2110 | modifier_type, | ||
| 2111 | prefetch_options_type, | ||
| 2112 | export_options_type, | ||
| 2113 | extern_options_type, | ||
| 2114 | type_info_type, | ||
| 2115 | manyptr_u8_type, | ||
| 2116 | manyptr_const_u8_type, | ||
| 2117 | fn_noreturn_no_args_type, | ||
| 2118 | fn_void_no_args_type, | ||
| 2119 | fn_naked_noreturn_no_args_type, | ||
| 2120 | fn_ccc_void_no_args_type, | ||
| 2121 | single_const_pointer_to_comptime_int_type, | ||
| 2122 | const_slice_u8_type, | ||
| 2123 | anyerror_void_error_union_type, | ||
| 2124 | generic_poison_type, | ||
| 2125 | |||
| 2126 | /// `undefined` (untyped) | ||
| 2127 | undef, | ||
| 2128 | /// `0` (comptime_int) | ||
| 2129 | zero, | ||
| 2130 | /// `1` (comptime_int) | ||
| 2131 | one, | ||
| 2132 | /// `{}` | ||
| 2133 | void_value, | ||
| 2134 | /// `unreachable` (noreturn type) | ||
| 2135 | unreachable_value, | ||
| 2136 | /// `null` (untyped) | ||
| 2137 | null_value, | ||
| 2138 | /// `true` | ||
| 2139 | bool_true, | ||
| 2140 | /// `false` | ||
| 2141 | bool_false, | ||
| 2142 | /// `.{}` (untyped) | ||
| 2143 | empty_struct, | ||
| 2144 | /// `0` (usize) | ||
| 2145 | zero_usize, | ||
| 2146 | /// `1` (usize) | ||
| 2147 | one_usize, | ||
| 2148 | /// `std.builtin.CallingConvention.C` | ||
| 2149 | calling_convention_c, | ||
| 2150 | /// `std.builtin.CallingConvention.Inline` | ||
| 2151 | calling_convention_inline, | ||
| 2152 | /// Used for generic parameters where the type and value | ||
| 2153 | /// is not known until generic function instantiation. | ||
| 2154 | generic_poison, | ||
| 2155 | /// This is a special type for variadic parameters of a function call. | ||
| 2156 | /// Casts to it will validate that the type can be passed to a c | ||
| 2157 | /// calling convention function. | ||
| 2158 | var_args_param, | ||
| 2159 | |||
| 2160 | _, | 2133 | _, |
| 2161 | |||
| 2162 | pub const typed_value_map = std.enums.directEnumArray(Ref, TypedValue, 0, .{ | ||
| 2163 | .none = undefined, | ||
| 2164 | |||
| 2165 | .u1_type = .{ | ||
| 2166 | .ty = Type.initTag(.type), | ||
| 2167 | .val = Value.initTag(.u1_type), | ||
| 2168 | }, | ||
| 2169 | .u8_type = .{ | ||
| 2170 | .ty = Type.initTag(.type), | ||
| 2171 | .val = Value.initTag(.u8_type), | ||
| 2172 | }, | ||
| 2173 | .i8_type = .{ | ||
| 2174 | .ty = Type.initTag(.type), | ||
| 2175 | .val = Value.initTag(.i8_type), | ||
| 2176 | }, | ||
| 2177 | .u16_type = .{ | ||
| 2178 | .ty = Type.initTag(.type), | ||
| 2179 | .val = Value.initTag(.u16_type), | ||
| 2180 | }, | ||
| 2181 | .i16_type = .{ | ||
| 2182 | .ty = Type.initTag(.type), | ||
| 2183 | .val = Value.initTag(.i16_type), | ||
| 2184 | }, | ||
| 2185 | .u29_type = .{ | ||
| 2186 | .ty = Type.initTag(.type), | ||
| 2187 | .val = Value.initTag(.u29_type), | ||
| 2188 | }, | ||
| 2189 | .u32_type = .{ | ||
| 2190 | .ty = Type.initTag(.type), | ||
| 2191 | .val = Value.initTag(.u32_type), | ||
| 2192 | }, | ||
| 2193 | .i32_type = .{ | ||
| 2194 | .ty = Type.initTag(.type), | ||
| 2195 | .val = Value.initTag(.i32_type), | ||
| 2196 | }, | ||
| 2197 | .u64_type = .{ | ||
| 2198 | .ty = Type.initTag(.type), | ||
| 2199 | .val = Value.initTag(.u64_type), | ||
| 2200 | }, | ||
| 2201 | .i64_type = .{ | ||
| 2202 | .ty = Type.initTag(.type), | ||
| 2203 | .val = Value.initTag(.i64_type), | ||
| 2204 | }, | ||
| 2205 | .u128_type = .{ | ||
| 2206 | .ty = Type.initTag(.type), | ||
| 2207 | .val = Value.initTag(.u128_type), | ||
| 2208 | }, | ||
| 2209 | .i128_type = .{ | ||
| 2210 | .ty = Type.initTag(.type), | ||
| 2211 | .val = Value.initTag(.i128_type), | ||
| 2212 | }, | ||
| 2213 | .usize_type = .{ | ||
| 2214 | .ty = Type.initTag(.type), | ||
| 2215 | .val = Value.initTag(.usize_type), | ||
| 2216 | }, | ||
| 2217 | .isize_type = .{ | ||
| 2218 | .ty = Type.initTag(.type), | ||
| 2219 | .val = Value.initTag(.isize_type), | ||
| 2220 | }, | ||
| 2221 | .c_char_type = .{ | ||
| 2222 | .ty = Type.initTag(.type), | ||
| 2223 | .val = Value.initTag(.c_char_type), | ||
| 2224 | }, | ||
| 2225 | .c_short_type = .{ | ||
| 2226 | .ty = Type.initTag(.type), | ||
| 2227 | .val = Value.initTag(.c_short_type), | ||
| 2228 | }, | ||
| 2229 | .c_ushort_type = .{ | ||
| 2230 | .ty = Type.initTag(.type), | ||
| 2231 | .val = Value.initTag(.c_ushort_type), | ||
| 2232 | }, | ||
| 2233 | .c_int_type = .{ | ||
| 2234 | .ty = Type.initTag(.type), | ||
| 2235 | .val = Value.initTag(.c_int_type), | ||
| 2236 | }, | ||
| 2237 | .c_uint_type = .{ | ||
| 2238 | .ty = Type.initTag(.type), | ||
| 2239 | .val = Value.initTag(.c_uint_type), | ||
| 2240 | }, | ||
| 2241 | .c_long_type = .{ | ||
| 2242 | .ty = Type.initTag(.type), | ||
| 2243 | .val = Value.initTag(.c_long_type), | ||
| 2244 | }, | ||
| 2245 | .c_ulong_type = .{ | ||
| 2246 | .ty = Type.initTag(.type), | ||
| 2247 | .val = Value.initTag(.c_ulong_type), | ||
| 2248 | }, | ||
| 2249 | .c_longlong_type = .{ | ||
| 2250 | .ty = Type.initTag(.type), | ||
| 2251 | .val = Value.initTag(.c_longlong_type), | ||
| 2252 | }, | ||
| 2253 | .c_ulonglong_type = .{ | ||
| 2254 | .ty = Type.initTag(.type), | ||
| 2255 | .val = Value.initTag(.c_ulonglong_type), | ||
| 2256 | }, | ||
| 2257 | .c_longdouble_type = .{ | ||
| 2258 | .ty = Type.initTag(.type), | ||
| 2259 | .val = Value.initTag(.c_longdouble_type), | ||
| 2260 | }, | ||
| 2261 | .f16_type = .{ | ||
| 2262 | .ty = Type.initTag(.type), | ||
| 2263 | .val = Value.initTag(.f16_type), | ||
| 2264 | }, | ||
| 2265 | .f32_type = .{ | ||
| 2266 | .ty = Type.initTag(.type), | ||
| 2267 | .val = Value.initTag(.f32_type), | ||
| 2268 | }, | ||
| 2269 | .f64_type = .{ | ||
| 2270 | .ty = Type.initTag(.type), | ||
| 2271 | .val = Value.initTag(.f64_type), | ||
| 2272 | }, | ||
| 2273 | .f80_type = .{ | ||
| 2274 | .ty = Type.initTag(.type), | ||
| 2275 | .val = Value.initTag(.f80_type), | ||
| 2276 | }, | ||
| 2277 | .f128_type = .{ | ||
| 2278 | .ty = Type.initTag(.type), | ||
| 2279 | .val = Value.initTag(.f128_type), | ||
| 2280 | }, | ||
| 2281 | .anyopaque_type = .{ | ||
| 2282 | .ty = Type.initTag(.type), | ||
| 2283 | .val = Value.initTag(.anyopaque_type), | ||
| 2284 | }, | ||
| 2285 | .bool_type = .{ | ||
| 2286 | .ty = Type.initTag(.type), | ||
| 2287 | .val = Value.initTag(.bool_type), | ||
| 2288 | }, | ||
| 2289 | .void_type = .{ | ||
| 2290 | .ty = Type.initTag(.type), | ||
| 2291 | .val = Value.initTag(.void_type), | ||
| 2292 | }, | ||
| 2293 | .type_type = .{ | ||
| 2294 | .ty = Type.initTag(.type), | ||
| 2295 | .val = Value.initTag(.type_type), | ||
| 2296 | }, | ||
| 2297 | .anyerror_type = .{ | ||
| 2298 | .ty = Type.initTag(.type), | ||
| 2299 | .val = Value.initTag(.anyerror_type), | ||
| 2300 | }, | ||
| 2301 | .comptime_int_type = .{ | ||
| 2302 | .ty = Type.initTag(.type), | ||
| 2303 | .val = Value.initTag(.comptime_int_type), | ||
| 2304 | }, | ||
| 2305 | .comptime_float_type = .{ | ||
| 2306 | .ty = Type.initTag(.type), | ||
| 2307 | .val = Value.initTag(.comptime_float_type), | ||
| 2308 | }, | ||
| 2309 | .noreturn_type = .{ | ||
| 2310 | .ty = Type.initTag(.type), | ||
| 2311 | .val = Value.initTag(.noreturn_type), | ||
| 2312 | }, | ||
| 2313 | .anyframe_type = .{ | ||
| 2314 | .ty = Type.initTag(.type), | ||
| 2315 | .val = Value.initTag(.anyframe_type), | ||
| 2316 | }, | ||
| 2317 | .null_type = .{ | ||
| 2318 | .ty = Type.initTag(.type), | ||
| 2319 | .val = Value.initTag(.null_type), | ||
| 2320 | }, | ||
| 2321 | .undefined_type = .{ | ||
| 2322 | .ty = Type.initTag(.type), | ||
| 2323 | .val = Value.initTag(.undefined_type), | ||
| 2324 | }, | ||
| 2325 | .fn_noreturn_no_args_type = .{ | ||
| 2326 | .ty = Type.initTag(.type), | ||
| 2327 | .val = Value.initTag(.fn_noreturn_no_args_type), | ||
| 2328 | }, | ||
| 2329 | .fn_void_no_args_type = .{ | ||
| 2330 | .ty = Type.initTag(.type), | ||
| 2331 | .val = Value.initTag(.fn_void_no_args_type), | ||
| 2332 | }, | ||
| 2333 | .fn_naked_noreturn_no_args_type = .{ | ||
| 2334 | .ty = Type.initTag(.type), | ||
| 2335 | .val = Value.initTag(.fn_naked_noreturn_no_args_type), | ||
| 2336 | }, | ||
| 2337 | .fn_ccc_void_no_args_type = .{ | ||
| 2338 | .ty = Type.initTag(.type), | ||
| 2339 | .val = Value.initTag(.fn_ccc_void_no_args_type), | ||
| 2340 | }, | ||
| 2341 | .single_const_pointer_to_comptime_int_type = .{ | ||
| 2342 | .ty = Type.initTag(.type), | ||
| 2343 | .val = Value.initTag(.single_const_pointer_to_comptime_int_type), | ||
| 2344 | }, | ||
| 2345 | .const_slice_u8_type = .{ | ||
| 2346 | .ty = Type.initTag(.type), | ||
| 2347 | .val = Value.initTag(.const_slice_u8_type), | ||
| 2348 | }, | ||
| 2349 | .anyerror_void_error_union_type = .{ | ||
| 2350 | .ty = Type.initTag(.type), | ||
| 2351 | .val = Value.initTag(.anyerror_void_error_union_type), | ||
| 2352 | }, | ||
| 2353 | .generic_poison_type = .{ | ||
| 2354 | .ty = Type.initTag(.type), | ||
| 2355 | .val = Value.initTag(.generic_poison_type), | ||
| 2356 | }, | ||
| 2357 | .enum_literal_type = .{ | ||
| 2358 | .ty = Type.initTag(.type), | ||
| 2359 | .val = Value.initTag(.enum_literal_type), | ||
| 2360 | }, | ||
| 2361 | .manyptr_u8_type = .{ | ||
| 2362 | .ty = Type.initTag(.type), | ||
| 2363 | .val = Value.initTag(.manyptr_u8_type), | ||
| 2364 | }, | ||
| 2365 | .manyptr_const_u8_type = .{ | ||
| 2366 | .ty = Type.initTag(.type), | ||
| 2367 | .val = Value.initTag(.manyptr_const_u8_type), | ||
| 2368 | }, | ||
| 2369 | .atomic_order_type = .{ | ||
| 2370 | .ty = Type.initTag(.type), | ||
| 2371 | .val = Value.initTag(.atomic_order_type), | ||
| 2372 | }, | ||
| 2373 | .atomic_rmw_op_type = .{ | ||
| 2374 | .ty = Type.initTag(.type), | ||
| 2375 | .val = Value.initTag(.atomic_rmw_op_type), | ||
| 2376 | }, | ||
| 2377 | .calling_convention_type = .{ | ||
| 2378 | .ty = Type.initTag(.type), | ||
| 2379 | .val = Value.initTag(.calling_convention_type), | ||
| 2380 | }, | ||
| 2381 | .address_space_type = .{ | ||
| 2382 | .ty = Type.initTag(.type), | ||
| 2383 | .val = Value.initTag(.address_space_type), | ||
| 2384 | }, | ||
| 2385 | .float_mode_type = .{ | ||
| 2386 | .ty = Type.initTag(.type), | ||
| 2387 | .val = Value.initTag(.float_mode_type), | ||
| 2388 | }, | ||
| 2389 | .reduce_op_type = .{ | ||
| 2390 | .ty = Type.initTag(.type), | ||
| 2391 | .val = Value.initTag(.reduce_op_type), | ||
| 2392 | }, | ||
| 2393 | .modifier_type = .{ | ||
| 2394 | .ty = Type.initTag(.type), | ||
| 2395 | .val = Value.initTag(.modifier_type), | ||
| 2396 | }, | ||
| 2397 | .prefetch_options_type = .{ | ||
| 2398 | .ty = Type.initTag(.type), | ||
| 2399 | .val = Value.initTag(.prefetch_options_type), | ||
| 2400 | }, | ||
| 2401 | .export_options_type = .{ | ||
| 2402 | .ty = Type.initTag(.type), | ||
| 2403 | .val = Value.initTag(.export_options_type), | ||
| 2404 | }, | ||
| 2405 | .extern_options_type = .{ | ||
| 2406 | .ty = Type.initTag(.type), | ||
| 2407 | .val = Value.initTag(.extern_options_type), | ||
| 2408 | }, | ||
| 2409 | .type_info_type = .{ | ||
| 2410 | .ty = Type.initTag(.type), | ||
| 2411 | .val = Value.initTag(.type_info_type), | ||
| 2412 | }, | ||
| 2413 | |||
| 2414 | .undef = .{ | ||
| 2415 | .ty = Type.initTag(.undefined), | ||
| 2416 | .val = Value.initTag(.undef), | ||
| 2417 | }, | ||
| 2418 | .zero = .{ | ||
| 2419 | .ty = Type.initTag(.comptime_int), | ||
| 2420 | .val = Value.initTag(.zero), | ||
| 2421 | }, | ||
| 2422 | .zero_usize = .{ | ||
| 2423 | .ty = Type.initTag(.usize), | ||
| 2424 | .val = Value.initTag(.zero), | ||
| 2425 | }, | ||
| 2426 | .one = .{ | ||
| 2427 | .ty = Type.initTag(.comptime_int), | ||
| 2428 | .val = Value.initTag(.one), | ||
| 2429 | }, | ||
| 2430 | .one_usize = .{ | ||
| 2431 | .ty = Type.initTag(.usize), | ||
| 2432 | .val = Value.initTag(.one), | ||
| 2433 | }, | ||
| 2434 | .void_value = .{ | ||
| 2435 | .ty = Type.initTag(.void), | ||
| 2436 | .val = Value.initTag(.void_value), | ||
| 2437 | }, | ||
| 2438 | .unreachable_value = .{ | ||
| 2439 | .ty = Type.initTag(.noreturn), | ||
| 2440 | .val = Value.initTag(.unreachable_value), | ||
| 2441 | }, | ||
| 2442 | .null_value = .{ | ||
| 2443 | .ty = Type.initTag(.null), | ||
| 2444 | .val = Value.initTag(.null_value), | ||
| 2445 | }, | ||
| 2446 | .bool_true = .{ | ||
| 2447 | .ty = Type.initTag(.bool), | ||
| 2448 | .val = Value.initTag(.bool_true), | ||
| 2449 | }, | ||
| 2450 | .bool_false = .{ | ||
| 2451 | .ty = Type.initTag(.bool), | ||
| 2452 | .val = Value.initTag(.bool_false), | ||
| 2453 | }, | ||
| 2454 | .empty_struct = .{ | ||
| 2455 | .ty = Type.initTag(.empty_struct_literal), | ||
| 2456 | .val = Value.initTag(.empty_struct_value), | ||
| 2457 | }, | ||
| 2458 | .calling_convention_c = .{ | ||
| 2459 | .ty = Type.initTag(.calling_convention), | ||
| 2460 | .val = .{ .ptr_otherwise = &calling_convention_c_payload.base }, | ||
| 2461 | }, | ||
| 2462 | .calling_convention_inline = .{ | ||
| 2463 | .ty = Type.initTag(.calling_convention), | ||
| 2464 | .val = .{ .ptr_otherwise = &calling_convention_inline_payload.base }, | ||
| 2465 | }, | ||
| 2466 | .generic_poison = .{ | ||
| 2467 | .ty = Type.initTag(.generic_poison), | ||
| 2468 | .val = Value.initTag(.generic_poison), | ||
| 2469 | }, | ||
| 2470 | .var_args_param = undefined, | ||
| 2471 | }); | ||
| 2472 | }; | ||
| 2473 | |||
| 2474 | /// We would like this to be const but `Value` wants a mutable pointer for | ||
| 2475 | /// its payload field. Nothing should mutate this though. | ||
| 2476 | var calling_convention_c_payload: Value.Payload.U32 = .{ | ||
| 2477 | .base = .{ .tag = .enum_field_index }, | ||
| 2478 | .data = @enumToInt(std.builtin.CallingConvention.C), | ||
| 2479 | }; | ||
| 2480 | |||
| 2481 | /// We would like this to be const but `Value` wants a mutable pointer for | ||
| 2482 | /// its payload field. Nothing should mutate this though. | ||
| 2483 | var calling_convention_inline_payload: Value.Payload.U32 = .{ | ||
| 2484 | .base = .{ .tag = .enum_field_index }, | ||
| 2485 | .data = @enumToInt(std.builtin.CallingConvention.Inline), | ||
| 2486 | }; | 2134 | }; |
| 2487 | 2135 | ||
| 2488 | /// All instructions have an 8-byte payload, which is contained within | 2136 | /// All instructions have an 8-byte payload, which is contained within |
| ... | @@ -4163,7 +3811,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo { | ... | @@ -4163,7 +3811,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo { |
| 4163 | }; | 3811 | }; |
| 4164 | } | 3812 | } |
| 4165 | 3813 | ||
| 4166 | const ref_start_index: u32 = Inst.Ref.typed_value_map.len; | 3814 | const ref_start_index: u32 = InternPool.static_len; |
| 4167 | 3815 | ||
| 4168 | pub fn indexToRef(inst: Inst.Index) Inst.Ref { | 3816 | pub fn indexToRef(inst: Inst.Index) Inst.Ref { |
| 4169 | return @intToEnum(Inst.Ref, ref_start_index + inst); | 3817 | return @intToEnum(Inst.Ref, ref_start_index + inst); |
src/arch/aarch64/CodeGen.zig+191-160| ... | @@ -471,6 +471,7 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { | ... | @@ -471,6 +471,7 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { |
| 471 | } | 471 | } |
| 472 | 472 | ||
| 473 | fn gen(self: *Self) !void { | 473 | fn gen(self: *Self) !void { |
| 474 | const mod = self.bin_file.options.module.?; | ||
| 474 | const cc = self.fn_type.fnCallingConvention(); | 475 | const cc = self.fn_type.fnCallingConvention(); |
| 475 | if (cc != .Naked) { | 476 | if (cc != .Naked) { |
| 476 | // stp fp, lr, [sp, #-16]! | 477 | // stp fp, lr, [sp, #-16]! |
| ... | @@ -522,8 +523,8 @@ fn gen(self: *Self) !void { | ... | @@ -522,8 +523,8 @@ fn gen(self: *Self) !void { |
| 522 | 523 | ||
| 523 | const ty = self.air.typeOfIndex(inst); | 524 | const ty = self.air.typeOfIndex(inst); |
| 524 | 525 | ||
| 525 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 526 | const abi_size = @intCast(u32, ty.abiSize(mod)); |
| 526 | const abi_align = ty.abiAlignment(self.target.*); | 527 | const abi_align = ty.abiAlignment(mod); |
| 527 | const stack_offset = try self.allocMem(abi_size, abi_align, inst); | 528 | const stack_offset = try self.allocMem(abi_size, abi_align, inst); |
| 528 | try self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 529 | try self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 529 | 530 | ||
| ... | @@ -951,8 +952,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live | ... | @@ -951,8 +952,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live |
| 951 | tomb_bits >>= 1; | 952 | tomb_bits >>= 1; |
| 952 | if (!dies) continue; | 953 | if (!dies) continue; |
| 953 | const op_int = @enumToInt(op); | 954 | const op_int = @enumToInt(op); |
| 954 | if (op_int < Air.Inst.Ref.typed_value_map.len) continue; | 955 | if (op_int < Air.ref_start_index) continue; |
| 955 | const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len); | 956 | const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index); |
| 956 | self.processDeath(op_index); | 957 | self.processDeath(op_index); |
| 957 | } | 958 | } |
| 958 | const is_used = @truncate(u1, tomb_bits) == 0; | 959 | const is_used = @truncate(u1, tomb_bits) == 0; |
| ... | @@ -1026,31 +1027,31 @@ fn allocMem( | ... | @@ -1026,31 +1027,31 @@ fn allocMem( |
| 1026 | 1027 | ||
| 1027 | /// Use a pointer instruction as the basis for allocating stack memory. | 1028 | /// Use a pointer instruction as the basis for allocating stack memory. |
| 1028 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { | 1029 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 1030 | const mod = self.bin_file.options.module.?; | ||
| 1029 | const elem_ty = self.air.typeOfIndex(inst).elemType(); | 1031 | const elem_ty = self.air.typeOfIndex(inst).elemType(); |
| 1030 | 1032 | ||
| 1031 | if (!elem_ty.hasRuntimeBits()) { | 1033 | if (!elem_ty.hasRuntimeBits(mod)) { |
| 1032 | // return the stack offset 0. Stack offset 0 will be where all | 1034 | // return the stack offset 0. Stack offset 0 will be where all |
| 1033 | // zero-sized stack allocations live as non-zero-sized | 1035 | // zero-sized stack allocations live as non-zero-sized |
| 1034 | // allocations will always have an offset > 0. | 1036 | // allocations will always have an offset > 0. |
| 1035 | return @as(u32, 0); | 1037 | return @as(u32, 0); |
| 1036 | } | 1038 | } |
| 1037 | 1039 | ||
| 1038 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { | 1040 | const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { |
| 1039 | const mod = self.bin_file.options.module.?; | ||
| 1040 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | 1041 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 1041 | }; | 1042 | }; |
| 1042 | // TODO swap this for inst.ty.ptrAlign | 1043 | // TODO swap this for inst.ty.ptrAlign |
| 1043 | const abi_align = elem_ty.abiAlignment(self.target.*); | 1044 | const abi_align = elem_ty.abiAlignment(mod); |
| 1044 | 1045 | ||
| 1045 | return self.allocMem(abi_size, abi_align, inst); | 1046 | return self.allocMem(abi_size, abi_align, inst); |
| 1046 | } | 1047 | } |
| 1047 | 1048 | ||
| 1048 | fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue { | 1049 | fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue { |
| 1049 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { | 1050 | const mod = self.bin_file.options.module.?; |
| 1050 | const mod = self.bin_file.options.module.?; | 1051 | const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { |
| 1051 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | 1052 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 1052 | }; | 1053 | }; |
| 1053 | const abi_align = elem_ty.abiAlignment(self.target.*); | 1054 | const abi_align = elem_ty.abiAlignment(mod); |
| 1054 | 1055 | ||
| 1055 | if (reg_ok) { | 1056 | if (reg_ok) { |
| 1056 | // Make sure the type can fit in a register before we try to allocate one. | 1057 | // Make sure the type can fit in a register before we try to allocate one. |
| ... | @@ -1177,13 +1178,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1177,13 +1178,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1177 | if (self.liveness.isUnused(inst)) | 1178 | if (self.liveness.isUnused(inst)) |
| 1178 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); | 1179 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1179 | 1180 | ||
| 1181 | const mod = self.bin_file.options.module.?; | ||
| 1180 | const operand = ty_op.operand; | 1182 | const operand = ty_op.operand; |
| 1181 | const operand_mcv = try self.resolveInst(operand); | 1183 | const operand_mcv = try self.resolveInst(operand); |
| 1182 | const operand_ty = self.air.typeOf(operand); | 1184 | const operand_ty = self.air.typeOf(operand); |
| 1183 | const operand_info = operand_ty.intInfo(self.target.*); | 1185 | const operand_info = operand_ty.intInfo(mod); |
| 1184 | 1186 | ||
| 1185 | const dest_ty = self.air.typeOfIndex(inst); | 1187 | const dest_ty = self.air.typeOfIndex(inst); |
| 1186 | const dest_info = dest_ty.intInfo(self.target.*); | 1188 | const dest_info = dest_ty.intInfo(mod); |
| 1187 | 1189 | ||
| 1188 | const result: MCValue = result: { | 1190 | const result: MCValue = result: { |
| 1189 | const operand_lock: ?RegisterLock = switch (operand_mcv) { | 1191 | const operand_lock: ?RegisterLock = switch (operand_mcv) { |
| ... | @@ -1257,8 +1259,9 @@ fn trunc( | ... | @@ -1257,8 +1259,9 @@ fn trunc( |
| 1257 | operand_ty: Type, | 1259 | operand_ty: Type, |
| 1258 | dest_ty: Type, | 1260 | dest_ty: Type, |
| 1259 | ) !MCValue { | 1261 | ) !MCValue { |
| 1260 | const info_a = operand_ty.intInfo(self.target.*); | 1262 | const mod = self.bin_file.options.module.?; |
| 1261 | const info_b = dest_ty.intInfo(self.target.*); | 1263 | const info_a = operand_ty.intInfo(mod); |
| 1264 | const info_b = dest_ty.intInfo(mod); | ||
| 1262 | 1265 | ||
| 1263 | if (info_b.bits <= 64) { | 1266 | if (info_b.bits <= 64) { |
| 1264 | const operand_reg = switch (operand) { | 1267 | const operand_reg = switch (operand) { |
| ... | @@ -1319,6 +1322,7 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1319,6 +1322,7 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 1319 | 1322 | ||
| 1320 | fn airNot(self: *Self, inst: Air.Inst.Index) !void { | 1323 | fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1321 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1324 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1325 | const mod = self.bin_file.options.module.?; | ||
| 1322 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1326 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1323 | const operand = try self.resolveInst(ty_op.operand); | 1327 | const operand = try self.resolveInst(ty_op.operand); |
| 1324 | const operand_ty = self.air.typeOf(ty_op.operand); | 1328 | const operand_ty = self.air.typeOf(ty_op.operand); |
| ... | @@ -1327,7 +1331,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1327,7 +1331,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1327 | .unreach => unreachable, | 1331 | .unreach => unreachable, |
| 1328 | .compare_flags => |cond| break :result MCValue{ .compare_flags = cond.negate() }, | 1332 | .compare_flags => |cond| break :result MCValue{ .compare_flags = cond.negate() }, |
| 1329 | else => { | 1333 | else => { |
| 1330 | switch (operand_ty.zigTypeTag()) { | 1334 | switch (operand_ty.zigTypeTag(mod)) { |
| 1331 | .Bool => { | 1335 | .Bool => { |
| 1332 | // TODO convert this to mvn + and | 1336 | // TODO convert this to mvn + and |
| 1333 | const op_reg = switch (operand) { | 1337 | const op_reg = switch (operand) { |
| ... | @@ -1361,7 +1365,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1361,7 +1365,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1361 | }, | 1365 | }, |
| 1362 | .Vector => return self.fail("TODO bitwise not for vectors", .{}), | 1366 | .Vector => return self.fail("TODO bitwise not for vectors", .{}), |
| 1363 | .Int => { | 1367 | .Int => { |
| 1364 | const int_info = operand_ty.intInfo(self.target.*); | 1368 | const int_info = operand_ty.intInfo(mod); |
| 1365 | if (int_info.bits <= 64) { | 1369 | if (int_info.bits <= 64) { |
| 1366 | const op_reg = switch (operand) { | 1370 | const op_reg = switch (operand) { |
| 1367 | .register => |r| r, | 1371 | .register => |r| r, |
| ... | @@ -1413,13 +1417,13 @@ fn minMax( | ... | @@ -1413,13 +1417,13 @@ fn minMax( |
| 1413 | rhs_ty: Type, | 1417 | rhs_ty: Type, |
| 1414 | maybe_inst: ?Air.Inst.Index, | 1418 | maybe_inst: ?Air.Inst.Index, |
| 1415 | ) !MCValue { | 1419 | ) !MCValue { |
| 1416 | switch (lhs_ty.zigTypeTag()) { | 1420 | const mod = self.bin_file.options.module.?; |
| 1421 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 1417 | .Float => return self.fail("TODO ARM min/max on floats", .{}), | 1422 | .Float => return self.fail("TODO ARM min/max on floats", .{}), |
| 1418 | .Vector => return self.fail("TODO ARM min/max on vectors", .{}), | 1423 | .Vector => return self.fail("TODO ARM min/max on vectors", .{}), |
| 1419 | .Int => { | 1424 | .Int => { |
| 1420 | const mod = self.bin_file.options.module.?; | ||
| 1421 | assert(lhs_ty.eql(rhs_ty, mod)); | 1425 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 1422 | const int_info = lhs_ty.intInfo(self.target.*); | 1426 | const int_info = lhs_ty.intInfo(mod); |
| 1423 | if (int_info.bits <= 64) { | 1427 | if (int_info.bits <= 64) { |
| 1424 | var lhs_reg: Register = undefined; | 1428 | var lhs_reg: Register = undefined; |
| 1425 | var rhs_reg: Register = undefined; | 1429 | var rhs_reg: Register = undefined; |
| ... | @@ -1907,12 +1911,12 @@ fn addSub( | ... | @@ -1907,12 +1911,12 @@ fn addSub( |
| 1907 | maybe_inst: ?Air.Inst.Index, | 1911 | maybe_inst: ?Air.Inst.Index, |
| 1908 | ) InnerError!MCValue { | 1912 | ) InnerError!MCValue { |
| 1909 | const mod = self.bin_file.options.module.?; | 1913 | const mod = self.bin_file.options.module.?; |
| 1910 | switch (lhs_ty.zigTypeTag()) { | 1914 | switch (lhs_ty.zigTypeTag(mod)) { |
| 1911 | .Float => return self.fail("TODO binary operations on floats", .{}), | 1915 | .Float => return self.fail("TODO binary operations on floats", .{}), |
| 1912 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 1916 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1913 | .Int => { | 1917 | .Int => { |
| 1914 | assert(lhs_ty.eql(rhs_ty, mod)); | 1918 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 1915 | const int_info = lhs_ty.intInfo(self.target.*); | 1919 | const int_info = lhs_ty.intInfo(mod); |
| 1916 | if (int_info.bits <= 64) { | 1920 | if (int_info.bits <= 64) { |
| 1917 | const lhs_immediate = try lhs_bind.resolveToImmediate(self); | 1921 | const lhs_immediate = try lhs_bind.resolveToImmediate(self); |
| 1918 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); | 1922 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); |
| ... | @@ -1968,11 +1972,11 @@ fn mul( | ... | @@ -1968,11 +1972,11 @@ fn mul( |
| 1968 | maybe_inst: ?Air.Inst.Index, | 1972 | maybe_inst: ?Air.Inst.Index, |
| 1969 | ) InnerError!MCValue { | 1973 | ) InnerError!MCValue { |
| 1970 | const mod = self.bin_file.options.module.?; | 1974 | const mod = self.bin_file.options.module.?; |
| 1971 | switch (lhs_ty.zigTypeTag()) { | 1975 | switch (lhs_ty.zigTypeTag(mod)) { |
| 1972 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 1976 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1973 | .Int => { | 1977 | .Int => { |
| 1974 | assert(lhs_ty.eql(rhs_ty, mod)); | 1978 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 1975 | const int_info = lhs_ty.intInfo(self.target.*); | 1979 | const int_info = lhs_ty.intInfo(mod); |
| 1976 | if (int_info.bits <= 64) { | 1980 | if (int_info.bits <= 64) { |
| 1977 | // TODO add optimisations for multiplication | 1981 | // TODO add optimisations for multiplication |
| 1978 | // with immediates, for example a * 2 can be | 1982 | // with immediates, for example a * 2 can be |
| ... | @@ -1999,7 +2003,8 @@ fn divFloat( | ... | @@ -1999,7 +2003,8 @@ fn divFloat( |
| 1999 | _ = rhs_ty; | 2003 | _ = rhs_ty; |
| 2000 | _ = maybe_inst; | 2004 | _ = maybe_inst; |
| 2001 | 2005 | ||
| 2002 | switch (lhs_ty.zigTypeTag()) { | 2006 | const mod = self.bin_file.options.module.?; |
| 2007 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 2003 | .Float => return self.fail("TODO div_float", .{}), | 2008 | .Float => return self.fail("TODO div_float", .{}), |
| 2004 | .Vector => return self.fail("TODO div_float on vectors", .{}), | 2009 | .Vector => return self.fail("TODO div_float on vectors", .{}), |
| 2005 | else => unreachable, | 2010 | else => unreachable, |
| ... | @@ -2015,12 +2020,12 @@ fn divTrunc( | ... | @@ -2015,12 +2020,12 @@ fn divTrunc( |
| 2015 | maybe_inst: ?Air.Inst.Index, | 2020 | maybe_inst: ?Air.Inst.Index, |
| 2016 | ) InnerError!MCValue { | 2021 | ) InnerError!MCValue { |
| 2017 | const mod = self.bin_file.options.module.?; | 2022 | const mod = self.bin_file.options.module.?; |
| 2018 | switch (lhs_ty.zigTypeTag()) { | 2023 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2019 | .Float => return self.fail("TODO div on floats", .{}), | 2024 | .Float => return self.fail("TODO div on floats", .{}), |
| 2020 | .Vector => return self.fail("TODO div on vectors", .{}), | 2025 | .Vector => return self.fail("TODO div on vectors", .{}), |
| 2021 | .Int => { | 2026 | .Int => { |
| 2022 | assert(lhs_ty.eql(rhs_ty, mod)); | 2027 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2023 | const int_info = lhs_ty.intInfo(self.target.*); | 2028 | const int_info = lhs_ty.intInfo(mod); |
| 2024 | if (int_info.bits <= 64) { | 2029 | if (int_info.bits <= 64) { |
| 2025 | switch (int_info.signedness) { | 2030 | switch (int_info.signedness) { |
| 2026 | .signed => { | 2031 | .signed => { |
| ... | @@ -2049,12 +2054,12 @@ fn divFloor( | ... | @@ -2049,12 +2054,12 @@ fn divFloor( |
| 2049 | maybe_inst: ?Air.Inst.Index, | 2054 | maybe_inst: ?Air.Inst.Index, |
| 2050 | ) InnerError!MCValue { | 2055 | ) InnerError!MCValue { |
| 2051 | const mod = self.bin_file.options.module.?; | 2056 | const mod = self.bin_file.options.module.?; |
| 2052 | switch (lhs_ty.zigTypeTag()) { | 2057 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2053 | .Float => return self.fail("TODO div on floats", .{}), | 2058 | .Float => return self.fail("TODO div on floats", .{}), |
| 2054 | .Vector => return self.fail("TODO div on vectors", .{}), | 2059 | .Vector => return self.fail("TODO div on vectors", .{}), |
| 2055 | .Int => { | 2060 | .Int => { |
| 2056 | assert(lhs_ty.eql(rhs_ty, mod)); | 2061 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2057 | const int_info = lhs_ty.intInfo(self.target.*); | 2062 | const int_info = lhs_ty.intInfo(mod); |
| 2058 | if (int_info.bits <= 64) { | 2063 | if (int_info.bits <= 64) { |
| 2059 | switch (int_info.signedness) { | 2064 | switch (int_info.signedness) { |
| 2060 | .signed => { | 2065 | .signed => { |
| ... | @@ -2082,12 +2087,12 @@ fn divExact( | ... | @@ -2082,12 +2087,12 @@ fn divExact( |
| 2082 | maybe_inst: ?Air.Inst.Index, | 2087 | maybe_inst: ?Air.Inst.Index, |
| 2083 | ) InnerError!MCValue { | 2088 | ) InnerError!MCValue { |
| 2084 | const mod = self.bin_file.options.module.?; | 2089 | const mod = self.bin_file.options.module.?; |
| 2085 | switch (lhs_ty.zigTypeTag()) { | 2090 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2086 | .Float => return self.fail("TODO div on floats", .{}), | 2091 | .Float => return self.fail("TODO div on floats", .{}), |
| 2087 | .Vector => return self.fail("TODO div on vectors", .{}), | 2092 | .Vector => return self.fail("TODO div on vectors", .{}), |
| 2088 | .Int => { | 2093 | .Int => { |
| 2089 | assert(lhs_ty.eql(rhs_ty, mod)); | 2094 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2090 | const int_info = lhs_ty.intInfo(self.target.*); | 2095 | const int_info = lhs_ty.intInfo(mod); |
| 2091 | if (int_info.bits <= 64) { | 2096 | if (int_info.bits <= 64) { |
| 2092 | switch (int_info.signedness) { | 2097 | switch (int_info.signedness) { |
| 2093 | .signed => { | 2098 | .signed => { |
| ... | @@ -2118,12 +2123,12 @@ fn rem( | ... | @@ -2118,12 +2123,12 @@ fn rem( |
| 2118 | _ = maybe_inst; | 2123 | _ = maybe_inst; |
| 2119 | 2124 | ||
| 2120 | const mod = self.bin_file.options.module.?; | 2125 | const mod = self.bin_file.options.module.?; |
| 2121 | switch (lhs_ty.zigTypeTag()) { | 2126 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2122 | .Float => return self.fail("TODO rem/mod on floats", .{}), | 2127 | .Float => return self.fail("TODO rem/mod on floats", .{}), |
| 2123 | .Vector => return self.fail("TODO rem/mod on vectors", .{}), | 2128 | .Vector => return self.fail("TODO rem/mod on vectors", .{}), |
| 2124 | .Int => { | 2129 | .Int => { |
| 2125 | assert(lhs_ty.eql(rhs_ty, mod)); | 2130 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2126 | const int_info = lhs_ty.intInfo(self.target.*); | 2131 | const int_info = lhs_ty.intInfo(mod); |
| 2127 | if (int_info.bits <= 64) { | 2132 | if (int_info.bits <= 64) { |
| 2128 | var lhs_reg: Register = undefined; | 2133 | var lhs_reg: Register = undefined; |
| 2129 | var rhs_reg: Register = undefined; | 2134 | var rhs_reg: Register = undefined; |
| ... | @@ -2188,7 +2193,8 @@ fn modulo( | ... | @@ -2188,7 +2193,8 @@ fn modulo( |
| 2188 | _ = rhs_ty; | 2193 | _ = rhs_ty; |
| 2189 | _ = maybe_inst; | 2194 | _ = maybe_inst; |
| 2190 | 2195 | ||
| 2191 | switch (lhs_ty.zigTypeTag()) { | 2196 | const mod = self.bin_file.options.module.?; |
| 2197 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 2192 | .Float => return self.fail("TODO mod on floats", .{}), | 2198 | .Float => return self.fail("TODO mod on floats", .{}), |
| 2193 | .Vector => return self.fail("TODO mod on vectors", .{}), | 2199 | .Vector => return self.fail("TODO mod on vectors", .{}), |
| 2194 | .Int => return self.fail("TODO mod on ints", .{}), | 2200 | .Int => return self.fail("TODO mod on ints", .{}), |
| ... | @@ -2205,10 +2211,11 @@ fn wrappingArithmetic( | ... | @@ -2205,10 +2211,11 @@ fn wrappingArithmetic( |
| 2205 | rhs_ty: Type, | 2211 | rhs_ty: Type, |
| 2206 | maybe_inst: ?Air.Inst.Index, | 2212 | maybe_inst: ?Air.Inst.Index, |
| 2207 | ) InnerError!MCValue { | 2213 | ) InnerError!MCValue { |
| 2208 | switch (lhs_ty.zigTypeTag()) { | 2214 | const mod = self.bin_file.options.module.?; |
| 2215 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 2209 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2216 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 2210 | .Int => { | 2217 | .Int => { |
| 2211 | const int_info = lhs_ty.intInfo(self.target.*); | 2218 | const int_info = lhs_ty.intInfo(mod); |
| 2212 | if (int_info.bits <= 64) { | 2219 | if (int_info.bits <= 64) { |
| 2213 | // Generate an add/sub/mul | 2220 | // Generate an add/sub/mul |
| 2214 | const result: MCValue = switch (tag) { | 2221 | const result: MCValue = switch (tag) { |
| ... | @@ -2240,11 +2247,11 @@ fn bitwise( | ... | @@ -2240,11 +2247,11 @@ fn bitwise( |
| 2240 | maybe_inst: ?Air.Inst.Index, | 2247 | maybe_inst: ?Air.Inst.Index, |
| 2241 | ) InnerError!MCValue { | 2248 | ) InnerError!MCValue { |
| 2242 | const mod = self.bin_file.options.module.?; | 2249 | const mod = self.bin_file.options.module.?; |
| 2243 | switch (lhs_ty.zigTypeTag()) { | 2250 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2244 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2251 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 2245 | .Int => { | 2252 | .Int => { |
| 2246 | assert(lhs_ty.eql(rhs_ty, mod)); | 2253 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2247 | const int_info = lhs_ty.intInfo(self.target.*); | 2254 | const int_info = lhs_ty.intInfo(mod); |
| 2248 | if (int_info.bits <= 64) { | 2255 | if (int_info.bits <= 64) { |
| 2249 | // TODO implement bitwise operations with immediates | 2256 | // TODO implement bitwise operations with immediates |
| 2250 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 2257 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| ... | @@ -2274,10 +2281,11 @@ fn shiftExact( | ... | @@ -2274,10 +2281,11 @@ fn shiftExact( |
| 2274 | ) InnerError!MCValue { | 2281 | ) InnerError!MCValue { |
| 2275 | _ = rhs_ty; | 2282 | _ = rhs_ty; |
| 2276 | 2283 | ||
| 2277 | switch (lhs_ty.zigTypeTag()) { | 2284 | const mod = self.bin_file.options.module.?; |
| 2285 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 2278 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2286 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 2279 | .Int => { | 2287 | .Int => { |
| 2280 | const int_info = lhs_ty.intInfo(self.target.*); | 2288 | const int_info = lhs_ty.intInfo(mod); |
| 2281 | if (int_info.bits <= 64) { | 2289 | if (int_info.bits <= 64) { |
| 2282 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); | 2290 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); |
| 2283 | 2291 | ||
| ... | @@ -2323,10 +2331,11 @@ fn shiftNormal( | ... | @@ -2323,10 +2331,11 @@ fn shiftNormal( |
| 2323 | rhs_ty: Type, | 2331 | rhs_ty: Type, |
| 2324 | maybe_inst: ?Air.Inst.Index, | 2332 | maybe_inst: ?Air.Inst.Index, |
| 2325 | ) InnerError!MCValue { | 2333 | ) InnerError!MCValue { |
| 2326 | switch (lhs_ty.zigTypeTag()) { | 2334 | const mod = self.bin_file.options.module.?; |
| 2335 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 2327 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2336 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 2328 | .Int => { | 2337 | .Int => { |
| 2329 | const int_info = lhs_ty.intInfo(self.target.*); | 2338 | const int_info = lhs_ty.intInfo(mod); |
| 2330 | if (int_info.bits <= 64) { | 2339 | if (int_info.bits <= 64) { |
| 2331 | // Generate a shl_exact/shr_exact | 2340 | // Generate a shl_exact/shr_exact |
| 2332 | const result: MCValue = switch (tag) { | 2341 | const result: MCValue = switch (tag) { |
| ... | @@ -2362,7 +2371,8 @@ fn booleanOp( | ... | @@ -2362,7 +2371,8 @@ fn booleanOp( |
| 2362 | rhs_ty: Type, | 2371 | rhs_ty: Type, |
| 2363 | maybe_inst: ?Air.Inst.Index, | 2372 | maybe_inst: ?Air.Inst.Index, |
| 2364 | ) InnerError!MCValue { | 2373 | ) InnerError!MCValue { |
| 2365 | switch (lhs_ty.zigTypeTag()) { | 2374 | const mod = self.bin_file.options.module.?; |
| 2375 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 2366 | .Bool => { | 2376 | .Bool => { |
| 2367 | assert((try lhs_bind.resolveToImmediate(self)) == null); // should have been handled by Sema | 2377 | assert((try lhs_bind.resolveToImmediate(self)) == null); // should have been handled by Sema |
| 2368 | assert((try rhs_bind.resolveToImmediate(self)) == null); // should have been handled by Sema | 2378 | assert((try rhs_bind.resolveToImmediate(self)) == null); // should have been handled by Sema |
| ... | @@ -2388,9 +2398,9 @@ fn ptrArithmetic( | ... | @@ -2388,9 +2398,9 @@ fn ptrArithmetic( |
| 2388 | rhs_ty: Type, | 2398 | rhs_ty: Type, |
| 2389 | maybe_inst: ?Air.Inst.Index, | 2399 | maybe_inst: ?Air.Inst.Index, |
| 2390 | ) InnerError!MCValue { | 2400 | ) InnerError!MCValue { |
| 2391 | switch (lhs_ty.zigTypeTag()) { | 2401 | const mod = self.bin_file.options.module.?; |
| 2402 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 2392 | .Pointer => { | 2403 | .Pointer => { |
| 2393 | const mod = self.bin_file.options.module.?; | ||
| 2394 | assert(rhs_ty.eql(Type.usize, mod)); | 2404 | assert(rhs_ty.eql(Type.usize, mod)); |
| 2395 | 2405 | ||
| 2396 | const ptr_ty = lhs_ty; | 2406 | const ptr_ty = lhs_ty; |
| ... | @@ -2398,7 +2408,7 @@ fn ptrArithmetic( | ... | @@ -2398,7 +2408,7 @@ fn ptrArithmetic( |
| 2398 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type | 2408 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type |
| 2399 | else => ptr_ty.childType(), | 2409 | else => ptr_ty.childType(), |
| 2400 | }; | 2410 | }; |
| 2401 | const elem_size = elem_ty.abiSize(self.target.*); | 2411 | const elem_size = elem_ty.abiSize(mod); |
| 2402 | 2412 | ||
| 2403 | const base_tag: Air.Inst.Tag = switch (tag) { | 2413 | const base_tag: Air.Inst.Tag = switch (tag) { |
| 2404 | .ptr_add => .add, | 2414 | .ptr_add => .add, |
| ... | @@ -2511,6 +2521,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2511,6 +2521,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2511 | const tag = self.air.instructions.items(.tag)[inst]; | 2521 | const tag = self.air.instructions.items(.tag)[inst]; |
| 2512 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2522 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2513 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 2523 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2524 | const mod = self.bin_file.options.module.?; | ||
| 2514 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2525 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2515 | const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; | 2526 | const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; |
| 2516 | const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; | 2527 | const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; |
| ... | @@ -2518,16 +2529,15 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2518,16 +2529,15 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2518 | const rhs_ty = self.air.typeOf(extra.rhs); | 2529 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 2519 | 2530 | ||
| 2520 | const tuple_ty = self.air.typeOfIndex(inst); | 2531 | const tuple_ty = self.air.typeOfIndex(inst); |
| 2521 | const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*)); | 2532 | const tuple_size = @intCast(u32, tuple_ty.abiSize(mod)); |
| 2522 | const tuple_align = tuple_ty.abiAlignment(self.target.*); | 2533 | const tuple_align = tuple_ty.abiAlignment(mod); |
| 2523 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*)); | 2534 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod)); |
| 2524 | 2535 | ||
| 2525 | switch (lhs_ty.zigTypeTag()) { | 2536 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2526 | .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}), | 2537 | .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}), |
| 2527 | .Int => { | 2538 | .Int => { |
| 2528 | const mod = self.bin_file.options.module.?; | ||
| 2529 | assert(lhs_ty.eql(rhs_ty, mod)); | 2539 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2530 | const int_info = lhs_ty.intInfo(self.target.*); | 2540 | const int_info = lhs_ty.intInfo(mod); |
| 2531 | switch (int_info.bits) { | 2541 | switch (int_info.bits) { |
| 2532 | 1...31, 33...63 => { | 2542 | 1...31, 33...63 => { |
| 2533 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); | 2543 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); |
| ... | @@ -2639,24 +2649,23 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2639,24 +2649,23 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2639 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2649 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2640 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 2650 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2641 | if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); | 2651 | if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); |
| 2652 | const mod = self.bin_file.options.module.?; | ||
| 2642 | const result: MCValue = result: { | 2653 | const result: MCValue = result: { |
| 2643 | const mod = self.bin_file.options.module.?; | ||
| 2644 | |||
| 2645 | const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; | 2654 | const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; |
| 2646 | const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; | 2655 | const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; |
| 2647 | const lhs_ty = self.air.typeOf(extra.lhs); | 2656 | const lhs_ty = self.air.typeOf(extra.lhs); |
| 2648 | const rhs_ty = self.air.typeOf(extra.rhs); | 2657 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 2649 | 2658 | ||
| 2650 | const tuple_ty = self.air.typeOfIndex(inst); | 2659 | const tuple_ty = self.air.typeOfIndex(inst); |
| 2651 | const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*)); | 2660 | const tuple_size = @intCast(u32, tuple_ty.abiSize(mod)); |
| 2652 | const tuple_align = tuple_ty.abiAlignment(self.target.*); | 2661 | const tuple_align = tuple_ty.abiAlignment(mod); |
| 2653 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*)); | 2662 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod)); |
| 2654 | 2663 | ||
| 2655 | switch (lhs_ty.zigTypeTag()) { | 2664 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2656 | .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), | 2665 | .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), |
| 2657 | .Int => { | 2666 | .Int => { |
| 2658 | assert(lhs_ty.eql(rhs_ty, mod)); | 2667 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2659 | const int_info = lhs_ty.intInfo(self.target.*); | 2668 | const int_info = lhs_ty.intInfo(mod); |
| 2660 | if (int_info.bits <= 32) { | 2669 | if (int_info.bits <= 32) { |
| 2661 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); | 2670 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); |
| 2662 | 2671 | ||
| ... | @@ -2864,6 +2873,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2864,6 +2873,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2864 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2873 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2865 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 2874 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2866 | if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); | 2875 | if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); |
| 2876 | const mod = self.bin_file.options.module.?; | ||
| 2867 | const result: MCValue = result: { | 2877 | const result: MCValue = result: { |
| 2868 | const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; | 2878 | const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; |
| 2869 | const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; | 2879 | const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; |
| ... | @@ -2871,14 +2881,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2871,14 +2881,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2871 | const rhs_ty = self.air.typeOf(extra.rhs); | 2881 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 2872 | 2882 | ||
| 2873 | const tuple_ty = self.air.typeOfIndex(inst); | 2883 | const tuple_ty = self.air.typeOfIndex(inst); |
| 2874 | const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*)); | 2884 | const tuple_size = @intCast(u32, tuple_ty.abiSize(mod)); |
| 2875 | const tuple_align = tuple_ty.abiAlignment(self.target.*); | 2885 | const tuple_align = tuple_ty.abiAlignment(mod); |
| 2876 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*)); | 2886 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod)); |
| 2877 | 2887 | ||
| 2878 | switch (lhs_ty.zigTypeTag()) { | 2888 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2879 | .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}), | 2889 | .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}), |
| 2880 | .Int => { | 2890 | .Int => { |
| 2881 | const int_info = lhs_ty.intInfo(self.target.*); | 2891 | const int_info = lhs_ty.intInfo(mod); |
| 2882 | if (int_info.bits <= 64) { | 2892 | if (int_info.bits <= 64) { |
| 2883 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); | 2893 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); |
| 2884 | 2894 | ||
| ... | @@ -3011,10 +3021,11 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3011,10 +3021,11 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 3011 | } | 3021 | } |
| 3012 | 3022 | ||
| 3013 | fn optionalPayload(self: *Self, inst: Air.Inst.Index, mcv: MCValue, optional_ty: Type) !MCValue { | 3023 | fn optionalPayload(self: *Self, inst: Air.Inst.Index, mcv: MCValue, optional_ty: Type) !MCValue { |
| 3024 | const mod = self.bin_file.options.module.?; | ||
| 3014 | var opt_buf: Type.Payload.ElemType = undefined; | 3025 | var opt_buf: Type.Payload.ElemType = undefined; |
| 3015 | const payload_ty = optional_ty.optionalChild(&opt_buf); | 3026 | const payload_ty = optional_ty.optionalChild(&opt_buf); |
| 3016 | if (!payload_ty.hasRuntimeBits()) return MCValue.none; | 3027 | if (!payload_ty.hasRuntimeBits(mod)) return MCValue.none; |
| 3017 | if (optional_ty.isPtrLikeOptional()) { | 3028 | if (optional_ty.isPtrLikeOptional(mod)) { |
| 3018 | // TODO should we reuse the operand here? | 3029 | // TODO should we reuse the operand here? |
| 3019 | const raw_reg = try self.register_manager.allocReg(inst, gp); | 3030 | const raw_reg = try self.register_manager.allocReg(inst, gp); |
| 3020 | const reg = self.registerAlias(raw_reg, payload_ty); | 3031 | const reg = self.registerAlias(raw_reg, payload_ty); |
| ... | @@ -3055,16 +3066,17 @@ fn errUnionErr( | ... | @@ -3055,16 +3066,17 @@ fn errUnionErr( |
| 3055 | error_union_ty: Type, | 3066 | error_union_ty: Type, |
| 3056 | maybe_inst: ?Air.Inst.Index, | 3067 | maybe_inst: ?Air.Inst.Index, |
| 3057 | ) !MCValue { | 3068 | ) !MCValue { |
| 3069 | const mod = self.bin_file.options.module.?; | ||
| 3058 | const err_ty = error_union_ty.errorUnionSet(); | 3070 | const err_ty = error_union_ty.errorUnionSet(); |
| 3059 | const payload_ty = error_union_ty.errorUnionPayload(); | 3071 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 3060 | if (err_ty.errorSetIsEmpty()) { | 3072 | if (err_ty.errorSetIsEmpty()) { |
| 3061 | return MCValue{ .immediate = 0 }; | 3073 | return MCValue{ .immediate = 0 }; |
| 3062 | } | 3074 | } |
| 3063 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 3075 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3064 | return try error_union_bind.resolveToMcv(self); | 3076 | return try error_union_bind.resolveToMcv(self); |
| 3065 | } | 3077 | } |
| 3066 | 3078 | ||
| 3067 | const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, self.target.*)); | 3079 | const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, mod)); |
| 3068 | switch (try error_union_bind.resolveToMcv(self)) { | 3080 | switch (try error_union_bind.resolveToMcv(self)) { |
| 3069 | .register => { | 3081 | .register => { |
| 3070 | var operand_reg: Register = undefined; | 3082 | var operand_reg: Register = undefined; |
| ... | @@ -3086,7 +3098,7 @@ fn errUnionErr( | ... | @@ -3086,7 +3098,7 @@ fn errUnionErr( |
| 3086 | ); | 3098 | ); |
| 3087 | 3099 | ||
| 3088 | const err_bit_offset = err_offset * 8; | 3100 | const err_bit_offset = err_offset * 8; |
| 3089 | const err_bit_size = @intCast(u32, err_ty.abiSize(self.target.*)) * 8; | 3101 | const err_bit_size = @intCast(u32, err_ty.abiSize(mod)) * 8; |
| 3090 | 3102 | ||
| 3091 | _ = try self.addInst(.{ | 3103 | _ = try self.addInst(.{ |
| 3092 | .tag = .ubfx, // errors are unsigned integers | 3104 | .tag = .ubfx, // errors are unsigned integers |
| ... | @@ -3134,16 +3146,17 @@ fn errUnionPayload( | ... | @@ -3134,16 +3146,17 @@ fn errUnionPayload( |
| 3134 | error_union_ty: Type, | 3146 | error_union_ty: Type, |
| 3135 | maybe_inst: ?Air.Inst.Index, | 3147 | maybe_inst: ?Air.Inst.Index, |
| 3136 | ) !MCValue { | 3148 | ) !MCValue { |
| 3149 | const mod = self.bin_file.options.module.?; | ||
| 3137 | const err_ty = error_union_ty.errorUnionSet(); | 3150 | const err_ty = error_union_ty.errorUnionSet(); |
| 3138 | const payload_ty = error_union_ty.errorUnionPayload(); | 3151 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 3139 | if (err_ty.errorSetIsEmpty()) { | 3152 | if (err_ty.errorSetIsEmpty()) { |
| 3140 | return try error_union_bind.resolveToMcv(self); | 3153 | return try error_union_bind.resolveToMcv(self); |
| 3141 | } | 3154 | } |
| 3142 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 3155 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3143 | return MCValue.none; | 3156 | return MCValue.none; |
| 3144 | } | 3157 | } |
| 3145 | 3158 | ||
| 3146 | const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*)); | 3159 | const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod)); |
| 3147 | switch (try error_union_bind.resolveToMcv(self)) { | 3160 | switch (try error_union_bind.resolveToMcv(self)) { |
| 3148 | .register => { | 3161 | .register => { |
| 3149 | var operand_reg: Register = undefined; | 3162 | var operand_reg: Register = undefined; |
| ... | @@ -3165,10 +3178,10 @@ fn errUnionPayload( | ... | @@ -3165,10 +3178,10 @@ fn errUnionPayload( |
| 3165 | ); | 3178 | ); |
| 3166 | 3179 | ||
| 3167 | const payload_bit_offset = payload_offset * 8; | 3180 | const payload_bit_offset = payload_offset * 8; |
| 3168 | const payload_bit_size = @intCast(u32, payload_ty.abiSize(self.target.*)) * 8; | 3181 | const payload_bit_size = @intCast(u32, payload_ty.abiSize(mod)) * 8; |
| 3169 | 3182 | ||
| 3170 | _ = try self.addInst(.{ | 3183 | _ = try self.addInst(.{ |
| 3171 | .tag = if (payload_ty.isSignedInt()) Mir.Inst.Tag.sbfx else .ubfx, | 3184 | .tag = if (payload_ty.isSignedInt(mod)) Mir.Inst.Tag.sbfx else .ubfx, |
| 3172 | .data = .{ | 3185 | .data = .{ |
| 3173 | .rr_lsb_width = .{ | 3186 | .rr_lsb_width = .{ |
| 3174 | // Set both registers to the X variant to get the full width | 3187 | // Set both registers to the X variant to get the full width |
| ... | @@ -3245,6 +3258,7 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3245,6 +3258,7 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { |
| 3245 | } | 3258 | } |
| 3246 | 3259 | ||
| 3247 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | 3260 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 3261 | const mod = self.bin_file.options.module.?; | ||
| 3248 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3262 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3249 | 3263 | ||
| 3250 | if (self.liveness.isUnused(inst)) { | 3264 | if (self.liveness.isUnused(inst)) { |
| ... | @@ -3253,7 +3267,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3253,7 +3267,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 3253 | 3267 | ||
| 3254 | const result: MCValue = result: { | 3268 | const result: MCValue = result: { |
| 3255 | const payload_ty = self.air.typeOf(ty_op.operand); | 3269 | const payload_ty = self.air.typeOf(ty_op.operand); |
| 3256 | if (!payload_ty.hasRuntimeBits()) { | 3270 | if (!payload_ty.hasRuntimeBits(mod)) { |
| 3257 | break :result MCValue{ .immediate = 1 }; | 3271 | break :result MCValue{ .immediate = 1 }; |
| 3258 | } | 3272 | } |
| 3259 | 3273 | ||
| ... | @@ -3265,7 +3279,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3265,7 +3279,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 3265 | }; | 3279 | }; |
| 3266 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); | 3280 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); |
| 3267 | 3281 | ||
| 3268 | if (optional_ty.isPtrLikeOptional()) { | 3282 | if (optional_ty.isPtrLikeOptional(mod)) { |
| 3269 | // TODO should we check if we can reuse the operand? | 3283 | // TODO should we check if we can reuse the operand? |
| 3270 | const raw_reg = try self.register_manager.allocReg(inst, gp); | 3284 | const raw_reg = try self.register_manager.allocReg(inst, gp); |
| 3271 | const reg = self.registerAlias(raw_reg, payload_ty); | 3285 | const reg = self.registerAlias(raw_reg, payload_ty); |
| ... | @@ -3273,9 +3287,9 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3273,9 +3287,9 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 3273 | break :result MCValue{ .register = reg }; | 3287 | break :result MCValue{ .register = reg }; |
| 3274 | } | 3288 | } |
| 3275 | 3289 | ||
| 3276 | const optional_abi_size = @intCast(u32, optional_ty.abiSize(self.target.*)); | 3290 | const optional_abi_size = @intCast(u32, optional_ty.abiSize(mod)); |
| 3277 | const optional_abi_align = optional_ty.abiAlignment(self.target.*); | 3291 | const optional_abi_align = optional_ty.abiAlignment(mod); |
| 3278 | const offset = @intCast(u32, payload_ty.abiSize(self.target.*)); | 3292 | const offset = @intCast(u32, payload_ty.abiSize(mod)); |
| 3279 | 3293 | ||
| 3280 | const stack_offset = try self.allocMem(optional_abi_size, optional_abi_align, inst); | 3294 | const stack_offset = try self.allocMem(optional_abi_size, optional_abi_align, inst); |
| 3281 | try self.genSetStack(payload_ty, stack_offset, operand); | 3295 | try self.genSetStack(payload_ty, stack_offset, operand); |
| ... | @@ -3289,19 +3303,20 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3289,19 +3303,20 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 3289 | 3303 | ||
| 3290 | /// T to E!T | 3304 | /// T to E!T |
| 3291 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { | 3305 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 3306 | const mod = self.bin_file.options.module.?; | ||
| 3292 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3307 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3293 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 3308 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 3294 | const error_union_ty = self.air.getRefType(ty_op.ty); | 3309 | const error_union_ty = self.air.getRefType(ty_op.ty); |
| 3295 | const error_ty = error_union_ty.errorUnionSet(); | 3310 | const error_ty = error_union_ty.errorUnionSet(); |
| 3296 | const payload_ty = error_union_ty.errorUnionPayload(); | 3311 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 3297 | const operand = try self.resolveInst(ty_op.operand); | 3312 | const operand = try self.resolveInst(ty_op.operand); |
| 3298 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand; | 3313 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand; |
| 3299 | 3314 | ||
| 3300 | const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*)); | 3315 | const abi_size = @intCast(u32, error_union_ty.abiSize(mod)); |
| 3301 | const abi_align = error_union_ty.abiAlignment(self.target.*); | 3316 | const abi_align = error_union_ty.abiAlignment(mod); |
| 3302 | const stack_offset = try self.allocMem(abi_size, abi_align, inst); | 3317 | const stack_offset = try self.allocMem(abi_size, abi_align, inst); |
| 3303 | const payload_off = errUnionPayloadOffset(payload_ty, self.target.*); | 3318 | const payload_off = errUnionPayloadOffset(payload_ty, mod); |
| 3304 | const err_off = errUnionErrorOffset(payload_ty, self.target.*); | 3319 | const err_off = errUnionErrorOffset(payload_ty, mod); |
| 3305 | try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand); | 3320 | try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand); |
| 3306 | try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), .{ .immediate = 0 }); | 3321 | try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), .{ .immediate = 0 }); |
| 3307 | 3322 | ||
| ... | @@ -3314,17 +3329,18 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3314,17 +3329,18 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 3314 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | 3329 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 3315 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3330 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3316 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 3331 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 3332 | const mod = self.bin_file.options.module.?; | ||
| 3317 | const error_union_ty = self.air.getRefType(ty_op.ty); | 3333 | const error_union_ty = self.air.getRefType(ty_op.ty); |
| 3318 | const error_ty = error_union_ty.errorUnionSet(); | 3334 | const error_ty = error_union_ty.errorUnionSet(); |
| 3319 | const payload_ty = error_union_ty.errorUnionPayload(); | 3335 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 3320 | const operand = try self.resolveInst(ty_op.operand); | 3336 | const operand = try self.resolveInst(ty_op.operand); |
| 3321 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand; | 3337 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand; |
| 3322 | 3338 | ||
| 3323 | const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*)); | 3339 | const abi_size = @intCast(u32, error_union_ty.abiSize(mod)); |
| 3324 | const abi_align = error_union_ty.abiAlignment(self.target.*); | 3340 | const abi_align = error_union_ty.abiAlignment(mod); |
| 3325 | const stack_offset = try self.allocMem(abi_size, abi_align, inst); | 3341 | const stack_offset = try self.allocMem(abi_size, abi_align, inst); |
| 3326 | const payload_off = errUnionPayloadOffset(payload_ty, self.target.*); | 3342 | const payload_off = errUnionPayloadOffset(payload_ty, mod); |
| 3327 | const err_off = errUnionErrorOffset(payload_ty, self.target.*); | 3343 | const err_off = errUnionErrorOffset(payload_ty, mod); |
| 3328 | try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand); | 3344 | try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand); |
| 3329 | try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef); | 3345 | try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef); |
| 3330 | 3346 | ||
| ... | @@ -3440,8 +3456,9 @@ fn ptrElemVal( | ... | @@ -3440,8 +3456,9 @@ fn ptrElemVal( |
| 3440 | ptr_ty: Type, | 3456 | ptr_ty: Type, |
| 3441 | maybe_inst: ?Air.Inst.Index, | 3457 | maybe_inst: ?Air.Inst.Index, |
| 3442 | ) !MCValue { | 3458 | ) !MCValue { |
| 3459 | const mod = self.bin_file.options.module.?; | ||
| 3443 | const elem_ty = ptr_ty.childType(); | 3460 | const elem_ty = ptr_ty.childType(); |
| 3444 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | 3461 | const elem_size = @intCast(u32, elem_ty.abiSize(mod)); |
| 3445 | 3462 | ||
| 3446 | // TODO optimize for elem_sizes of 1, 2, 4, 8 | 3463 | // TODO optimize for elem_sizes of 1, 2, 4, 8 |
| 3447 | switch (elem_size) { | 3464 | switch (elem_size) { |
| ... | @@ -3597,8 +3614,9 @@ fn reuseOperand( | ... | @@ -3597,8 +3614,9 @@ fn reuseOperand( |
| 3597 | } | 3614 | } |
| 3598 | 3615 | ||
| 3599 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { | 3616 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 3617 | const mod = self.bin_file.options.module.?; | ||
| 3600 | const elem_ty = ptr_ty.elemType(); | 3618 | const elem_ty = ptr_ty.elemType(); |
| 3601 | const elem_size = elem_ty.abiSize(self.target.*); | 3619 | const elem_size = elem_ty.abiSize(mod); |
| 3602 | 3620 | ||
| 3603 | switch (ptr) { | 3621 | switch (ptr) { |
| 3604 | .none => unreachable, | 3622 | .none => unreachable, |
| ... | @@ -3846,9 +3864,10 @@ fn genInlineMemsetCode( | ... | @@ -3846,9 +3864,10 @@ fn genInlineMemsetCode( |
| 3846 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | 3864 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3847 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3865 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3848 | const elem_ty = self.air.typeOfIndex(inst); | 3866 | const elem_ty = self.air.typeOfIndex(inst); |
| 3849 | const elem_size = elem_ty.abiSize(self.target.*); | 3867 | const mod = self.bin_file.options.module.?; |
| 3868 | const elem_size = elem_ty.abiSize(mod); | ||
| 3850 | const result: MCValue = result: { | 3869 | const result: MCValue = result: { |
| 3851 | if (!elem_ty.hasRuntimeBits()) | 3870 | if (!elem_ty.hasRuntimeBits(mod)) |
| 3852 | break :result MCValue.none; | 3871 | break :result MCValue.none; |
| 3853 | 3872 | ||
| 3854 | const ptr = try self.resolveInst(ty_op.operand); | 3873 | const ptr = try self.resolveInst(ty_op.operand); |
| ... | @@ -3874,11 +3893,12 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3874,11 +3893,12 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3874 | } | 3893 | } |
| 3875 | 3894 | ||
| 3876 | fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type) !void { | 3895 | fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type) !void { |
| 3877 | const abi_size = ty.abiSize(self.target.*); | 3896 | const mod = self.bin_file.options.module.?; |
| 3897 | const abi_size = ty.abiSize(mod); | ||
| 3878 | 3898 | ||
| 3879 | const tag: Mir.Inst.Tag = switch (abi_size) { | 3899 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3880 | 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_immediate else .ldrb_immediate, | 3900 | 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb_immediate else .ldrb_immediate, |
| 3881 | 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_immediate else .ldrh_immediate, | 3901 | 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_immediate else .ldrh_immediate, |
| 3882 | 4 => .ldr_immediate, | 3902 | 4 => .ldr_immediate, |
| 3883 | 8 => .ldr_immediate, | 3903 | 8 => .ldr_immediate, |
| 3884 | 3, 5, 6, 7 => return self.fail("TODO: genLdrRegister for more abi_sizes", .{}), | 3904 | 3, 5, 6, 7 => return self.fail("TODO: genLdrRegister for more abi_sizes", .{}), |
| ... | @@ -3896,7 +3916,8 @@ fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type | ... | @@ -3896,7 +3916,8 @@ fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type |
| 3896 | } | 3916 | } |
| 3897 | 3917 | ||
| 3898 | fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type) !void { | 3918 | fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type) !void { |
| 3899 | const abi_size = ty.abiSize(self.target.*); | 3919 | const mod = self.bin_file.options.module.?; |
| 3920 | const abi_size = ty.abiSize(mod); | ||
| 3900 | 3921 | ||
| 3901 | const tag: Mir.Inst.Tag = switch (abi_size) { | 3922 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3902 | 1 => .strb_immediate, | 3923 | 1 => .strb_immediate, |
| ... | @@ -3917,8 +3938,9 @@ fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type | ... | @@ -3917,8 +3938,9 @@ fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type |
| 3917 | } | 3938 | } |
| 3918 | 3939 | ||
| 3919 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { | 3940 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { |
| 3941 | const mod = self.bin_file.options.module.?; | ||
| 3920 | log.debug("store: storing {} to {}", .{ value, ptr }); | 3942 | log.debug("store: storing {} to {}", .{ value, ptr }); |
| 3921 | const abi_size = value_ty.abiSize(self.target.*); | 3943 | const abi_size = value_ty.abiSize(mod); |
| 3922 | 3944 | ||
| 3923 | switch (ptr) { | 3945 | switch (ptr) { |
| 3924 | .none => unreachable, | 3946 | .none => unreachable, |
| ... | @@ -4069,10 +4091,11 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { | ... | @@ -4069,10 +4091,11 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { |
| 4069 | 4091 | ||
| 4070 | fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { | 4092 | fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { |
| 4071 | return if (self.liveness.isUnused(inst)) .dead else result: { | 4093 | return if (self.liveness.isUnused(inst)) .dead else result: { |
| 4094 | const mod = self.bin_file.options.module.?; | ||
| 4072 | const mcv = try self.resolveInst(operand); | 4095 | const mcv = try self.resolveInst(operand); |
| 4073 | const ptr_ty = self.air.typeOf(operand); | 4096 | const ptr_ty = self.air.typeOf(operand); |
| 4074 | const struct_ty = ptr_ty.childType(); | 4097 | const struct_ty = ptr_ty.childType(); |
| 4075 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); | 4098 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod)); |
| 4076 | switch (mcv) { | 4099 | switch (mcv) { |
| 4077 | .ptr_stack_offset => |off| { | 4100 | .ptr_stack_offset => |off| { |
| 4078 | break :result MCValue{ .ptr_stack_offset = off - struct_field_offset }; | 4101 | break :result MCValue{ .ptr_stack_offset = off - struct_field_offset }; |
| ... | @@ -4093,10 +4116,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4093,10 +4116,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4093 | const operand = extra.struct_operand; | 4116 | const operand = extra.struct_operand; |
| 4094 | const index = extra.field_index; | 4117 | const index = extra.field_index; |
| 4095 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 4118 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4119 | const mod = self.bin_file.options.module.?; | ||
| 4096 | const mcv = try self.resolveInst(operand); | 4120 | const mcv = try self.resolveInst(operand); |
| 4097 | const struct_ty = self.air.typeOf(operand); | 4121 | const struct_ty = self.air.typeOf(operand); |
| 4098 | const struct_field_ty = struct_ty.structFieldType(index); | 4122 | const struct_field_ty = struct_ty.structFieldType(index); |
| 4099 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); | 4123 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod)); |
| 4100 | 4124 | ||
| 4101 | switch (mcv) { | 4125 | switch (mcv) { |
| 4102 | .dead, .unreach => unreachable, | 4126 | .dead, .unreach => unreachable, |
| ... | @@ -4142,12 +4166,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4142,12 +4166,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4142 | } | 4166 | } |
| 4143 | 4167 | ||
| 4144 | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | 4168 | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4169 | const mod = self.bin_file.options.module.?; | ||
| 4145 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 4170 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 4146 | const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | 4171 | const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 4147 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 4172 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4148 | const field_ptr = try self.resolveInst(extra.field_ptr); | 4173 | const field_ptr = try self.resolveInst(extra.field_ptr); |
| 4149 | const struct_ty = self.air.getRefType(ty_pl.ty).childType(); | 4174 | const struct_ty = self.air.getRefType(ty_pl.ty).childType(); |
| 4150 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(extra.field_index, self.target.*)); | 4175 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(extra.field_index, mod)); |
| 4151 | switch (field_ptr) { | 4176 | switch (field_ptr) { |
| 4152 | .ptr_stack_offset => |off| { | 4177 | .ptr_stack_offset => |off| { |
| 4153 | break :result MCValue{ .ptr_stack_offset = off + struct_field_offset }; | 4178 | break :result MCValue{ .ptr_stack_offset = off + struct_field_offset }; |
| ... | @@ -4223,8 +4248,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4223,8 +4248,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4223 | const extra = self.air.extraData(Air.Call, pl_op.payload); | 4248 | const extra = self.air.extraData(Air.Call, pl_op.payload); |
| 4224 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); | 4249 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); |
| 4225 | const ty = self.air.typeOf(callee); | 4250 | const ty = self.air.typeOf(callee); |
| 4251 | const mod = self.bin_file.options.module.?; | ||
| 4226 | 4252 | ||
| 4227 | const fn_ty = switch (ty.zigTypeTag()) { | 4253 | const fn_ty = switch (ty.zigTypeTag(mod)) { |
| 4228 | .Fn => ty, | 4254 | .Fn => ty, |
| 4229 | .Pointer => ty.childType(), | 4255 | .Pointer => ty.childType(), |
| 4230 | else => unreachable, | 4256 | else => unreachable, |
| ... | @@ -4246,8 +4272,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4246,8 +4272,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4246 | if (info.return_value == .stack_offset) { | 4272 | if (info.return_value == .stack_offset) { |
| 4247 | log.debug("airCall: return by reference", .{}); | 4273 | log.debug("airCall: return by reference", .{}); |
| 4248 | const ret_ty = fn_ty.fnReturnType(); | 4274 | const ret_ty = fn_ty.fnReturnType(); |
| 4249 | const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 4275 | const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod)); |
| 4250 | const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*)); | 4276 | const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod)); |
| 4251 | const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst); | 4277 | const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst); |
| 4252 | 4278 | ||
| 4253 | const ret_ptr_reg = self.registerAlias(.x0, Type.usize); | 4279 | const ret_ptr_reg = self.registerAlias(.x0, Type.usize); |
| ... | @@ -4289,8 +4315,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4289,8 +4315,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4289 | 4315 | ||
| 4290 | // Due to incremental compilation, how function calls are generated depends | 4316 | // Due to incremental compilation, how function calls are generated depends |
| 4291 | // on linking. | 4317 | // on linking. |
| 4292 | const mod = self.bin_file.options.module.?; | 4318 | if (self.air.value(callee, mod)) |func_value| { |
| 4293 | if (self.air.value(callee)) |func_value| { | ||
| 4294 | if (func_value.castTag(.function)) |func_payload| { | 4319 | if (func_value.castTag(.function)) |func_payload| { |
| 4295 | const func = func_payload.data; | 4320 | const func = func_payload.data; |
| 4296 | 4321 | ||
| ... | @@ -4369,7 +4394,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4369,7 +4394,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4369 | return self.fail("TODO implement calling bitcasted functions", .{}); | 4394 | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 4370 | } | 4395 | } |
| 4371 | } else { | 4396 | } else { |
| 4372 | assert(ty.zigTypeTag() == .Pointer); | 4397 | assert(ty.zigTypeTag(mod) == .Pointer); |
| 4373 | const mcv = try self.resolveInst(callee); | 4398 | const mcv = try self.resolveInst(callee); |
| 4374 | try self.genSetReg(ty, .x30, mcv); | 4399 | try self.genSetReg(ty, .x30, mcv); |
| 4375 | 4400 | ||
| ... | @@ -4410,11 +4435,12 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4410,11 +4435,12 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 4410 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 4435 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4411 | const operand = try self.resolveInst(un_op); | 4436 | const operand = try self.resolveInst(un_op); |
| 4412 | const ret_ty = self.fn_type.fnReturnType(); | 4437 | const ret_ty = self.fn_type.fnReturnType(); |
| 4438 | const mod = self.bin_file.options.module.?; | ||
| 4413 | 4439 | ||
| 4414 | switch (self.ret_mcv) { | 4440 | switch (self.ret_mcv) { |
| 4415 | .none => {}, | 4441 | .none => {}, |
| 4416 | .immediate => { | 4442 | .immediate => { |
| 4417 | assert(ret_ty.isError()); | 4443 | assert(ret_ty.isError(mod)); |
| 4418 | }, | 4444 | }, |
| 4419 | .register => |reg| { | 4445 | .register => |reg| { |
| 4420 | // Return result by value | 4446 | // Return result by value |
| ... | @@ -4465,8 +4491,9 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4465,8 +4491,9 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 4465 | // location. | 4491 | // location. |
| 4466 | const op_inst = Air.refToIndex(un_op).?; | 4492 | const op_inst = Air.refToIndex(un_op).?; |
| 4467 | if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) { | 4493 | if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) { |
| 4468 | const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 4494 | const mod = self.bin_file.options.module.?; |
| 4469 | const abi_align = ret_ty.abiAlignment(self.target.*); | 4495 | const abi_size = @intCast(u32, ret_ty.abiSize(mod)); |
| 4496 | const abi_align = ret_ty.abiAlignment(mod); | ||
| 4470 | 4497 | ||
| 4471 | const offset = try self.allocMem(abi_size, abi_align, null); | 4498 | const offset = try self.allocMem(abi_size, abi_align, null); |
| 4472 | 4499 | ||
| ... | @@ -4501,21 +4528,21 @@ fn cmp( | ... | @@ -4501,21 +4528,21 @@ fn cmp( |
| 4501 | lhs_ty: Type, | 4528 | lhs_ty: Type, |
| 4502 | op: math.CompareOperator, | 4529 | op: math.CompareOperator, |
| 4503 | ) !MCValue { | 4530 | ) !MCValue { |
| 4504 | var int_buffer: Type.Payload.Bits = undefined; | 4531 | const mod = self.bin_file.options.module.?; |
| 4505 | const int_ty = switch (lhs_ty.zigTypeTag()) { | 4532 | const int_ty = switch (lhs_ty.zigTypeTag(mod)) { |
| 4506 | .Optional => blk: { | 4533 | .Optional => blk: { |
| 4507 | var opt_buffer: Type.Payload.ElemType = undefined; | 4534 | var opt_buffer: Type.Payload.ElemType = undefined; |
| 4508 | const payload_ty = lhs_ty.optionalChild(&opt_buffer); | 4535 | const payload_ty = lhs_ty.optionalChild(&opt_buffer); |
| 4509 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 4536 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4510 | break :blk Type.initTag(.u1); | 4537 | break :blk Type.initTag(.u1); |
| 4511 | } else if (lhs_ty.isPtrLikeOptional()) { | 4538 | } else if (lhs_ty.isPtrLikeOptional(mod)) { |
| 4512 | break :blk Type.usize; | 4539 | break :blk Type.usize; |
| 4513 | } else { | 4540 | } else { |
| 4514 | return self.fail("TODO ARM cmp non-pointer optionals", .{}); | 4541 | return self.fail("TODO ARM cmp non-pointer optionals", .{}); |
| 4515 | } | 4542 | } |
| 4516 | }, | 4543 | }, |
| 4517 | .Float => return self.fail("TODO ARM cmp floats", .{}), | 4544 | .Float => return self.fail("TODO ARM cmp floats", .{}), |
| 4518 | .Enum => lhs_ty.intTagType(&int_buffer), | 4545 | .Enum => lhs_ty.intTagType(), |
| 4519 | .Int => lhs_ty, | 4546 | .Int => lhs_ty, |
| 4520 | .Bool => Type.initTag(.u1), | 4547 | .Bool => Type.initTag(.u1), |
| 4521 | .Pointer => Type.usize, | 4548 | .Pointer => Type.usize, |
| ... | @@ -4523,7 +4550,7 @@ fn cmp( | ... | @@ -4523,7 +4550,7 @@ fn cmp( |
| 4523 | else => unreachable, | 4550 | else => unreachable, |
| 4524 | }; | 4551 | }; |
| 4525 | 4552 | ||
| 4526 | const int_info = int_ty.intInfo(self.target.*); | 4553 | const int_info = int_ty.intInfo(mod); |
| 4527 | if (int_info.bits <= 64) { | 4554 | if (int_info.bits <= 64) { |
| 4528 | try self.spillCompareFlagsIfOccupied(); | 4555 | try self.spillCompareFlagsIfOccupied(); |
| 4529 | 4556 | ||
| ... | @@ -4687,8 +4714,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4687,8 +4714,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 4687 | // whether it needs to be spilled in the branches | 4714 | // whether it needs to be spilled in the branches |
| 4688 | if (self.liveness.operandDies(inst, 0)) { | 4715 | if (self.liveness.operandDies(inst, 0)) { |
| 4689 | const op_int = @enumToInt(pl_op.operand); | 4716 | const op_int = @enumToInt(pl_op.operand); |
| 4690 | if (op_int >= Air.Inst.Ref.typed_value_map.len) { | 4717 | if (op_int >= Air.ref_start_index) { |
| 4691 | const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len); | 4718 | const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index); |
| 4692 | self.processDeath(op_index); | 4719 | self.processDeath(op_index); |
| 4693 | } | 4720 | } |
| 4694 | } | 4721 | } |
| ... | @@ -4819,13 +4846,14 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4819,13 +4846,14 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 4819 | } | 4846 | } |
| 4820 | 4847 | ||
| 4821 | fn isNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue { | 4848 | fn isNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue { |
| 4822 | const sentinel: struct { ty: Type, bind: ReadArg.Bind } = if (!operand_ty.isPtrLikeOptional()) blk: { | 4849 | const mod = self.bin_file.options.module.?; |
| 4850 | const sentinel: struct { ty: Type, bind: ReadArg.Bind } = if (!operand_ty.isPtrLikeOptional(mod)) blk: { | ||
| 4823 | var buf: Type.Payload.ElemType = undefined; | 4851 | var buf: Type.Payload.ElemType = undefined; |
| 4824 | const payload_ty = operand_ty.optionalChild(&buf); | 4852 | const payload_ty = operand_ty.optionalChild(&buf); |
| 4825 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) | 4853 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 4826 | break :blk .{ .ty = operand_ty, .bind = operand_bind }; | 4854 | break :blk .{ .ty = operand_ty, .bind = operand_bind }; |
| 4827 | 4855 | ||
| 4828 | const offset = @intCast(u32, payload_ty.abiSize(self.target.*)); | 4856 | const offset = @intCast(u32, payload_ty.abiSize(mod)); |
| 4829 | const operand_mcv = try operand_bind.resolveToMcv(self); | 4857 | const operand_mcv = try operand_bind.resolveToMcv(self); |
| 4830 | const new_mcv: MCValue = switch (operand_mcv) { | 4858 | const new_mcv: MCValue = switch (operand_mcv) { |
| 4831 | .register => |source_reg| new: { | 4859 | .register => |source_reg| new: { |
| ... | @@ -4838,7 +4866,7 @@ fn isNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue { | ... | @@ -4838,7 +4866,7 @@ fn isNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue { |
| 4838 | try self.genSetReg(payload_ty, dest_reg, operand_mcv); | 4866 | try self.genSetReg(payload_ty, dest_reg, operand_mcv); |
| 4839 | } else { | 4867 | } else { |
| 4840 | _ = try self.addInst(.{ | 4868 | _ = try self.addInst(.{ |
| 4841 | .tag = if (payload_ty.isSignedInt()) | 4869 | .tag = if (payload_ty.isSignedInt(mod)) |
| 4842 | Mir.Inst.Tag.asr_immediate | 4870 | Mir.Inst.Tag.asr_immediate |
| 4843 | else | 4871 | else |
| 4844 | Mir.Inst.Tag.lsr_immediate, | 4872 | Mir.Inst.Tag.lsr_immediate, |
| ... | @@ -5210,9 +5238,10 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5210,9 +5238,10 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 5210 | } | 5238 | } |
| 5211 | 5239 | ||
| 5212 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { | 5240 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 5241 | const mod = self.bin_file.options.module.?; | ||
| 5213 | const block_data = self.blocks.getPtr(block).?; | 5242 | const block_data = self.blocks.getPtr(block).?; |
| 5214 | 5243 | ||
| 5215 | if (self.air.typeOf(operand).hasRuntimeBits()) { | 5244 | if (self.air.typeOf(operand).hasRuntimeBits(mod)) { |
| 5216 | const operand_mcv = try self.resolveInst(operand); | 5245 | const operand_mcv = try self.resolveInst(operand); |
| 5217 | const block_mcv = block_data.mcv; | 5246 | const block_mcv = block_data.mcv; |
| 5218 | if (block_mcv == .none) { | 5247 | if (block_mcv == .none) { |
| ... | @@ -5386,7 +5415,8 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { | ... | @@ -5386,7 +5415,8 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { |
| 5386 | } | 5415 | } |
| 5387 | 5416 | ||
| 5388 | fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { | 5417 | fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { |
| 5389 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 5418 | const mod = self.bin_file.options.module.?; |
| 5419 | const abi_size = @intCast(u32, ty.abiSize(mod)); | ||
| 5390 | switch (mcv) { | 5420 | switch (mcv) { |
| 5391 | .dead => unreachable, | 5421 | .dead => unreachable, |
| 5392 | .unreach, .none => return, // Nothing to do. | 5422 | .unreach, .none => return, // Nothing to do. |
| ... | @@ -5445,7 +5475,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -5445,7 +5475,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5445 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg }); | 5475 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg }); |
| 5446 | 5476 | ||
| 5447 | const overflow_bit_ty = ty.structFieldType(1); | 5477 | const overflow_bit_ty = ty.structFieldType(1); |
| 5448 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*)); | 5478 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); |
| 5449 | const raw_cond_reg = try self.register_manager.allocReg(null, gp); | 5479 | const raw_cond_reg = try self.register_manager.allocReg(null, gp); |
| 5450 | const cond_reg = self.registerAlias(raw_cond_reg, overflow_bit_ty); | 5480 | const cond_reg = self.registerAlias(raw_cond_reg, overflow_bit_ty); |
| 5451 | 5481 | ||
| ... | @@ -5559,6 +5589,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -5559,6 +5589,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5559 | } | 5589 | } |
| 5560 | 5590 | ||
| 5561 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { | 5591 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { |
| 5592 | const mod = self.bin_file.options.module.?; | ||
| 5562 | switch (mcv) { | 5593 | switch (mcv) { |
| 5563 | .dead => unreachable, | 5594 | .dead => unreachable, |
| 5564 | .unreach, .none => return, // Nothing to do. | 5595 | .unreach, .none => return, // Nothing to do. |
| ... | @@ -5669,13 +5700,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -5669,13 +5700,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5669 | try self.genLdrRegister(reg, reg.toX(), ty); | 5700 | try self.genLdrRegister(reg, reg.toX(), ty); |
| 5670 | }, | 5701 | }, |
| 5671 | .stack_offset => |off| { | 5702 | .stack_offset => |off| { |
| 5672 | const abi_size = ty.abiSize(self.target.*); | 5703 | const abi_size = ty.abiSize(mod); |
| 5673 | 5704 | ||
| 5674 | switch (abi_size) { | 5705 | switch (abi_size) { |
| 5675 | 1, 2, 4, 8 => { | 5706 | 1, 2, 4, 8 => { |
| 5676 | const tag: Mir.Inst.Tag = switch (abi_size) { | 5707 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 5677 | 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack else .ldrb_stack, | 5708 | 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb_stack else .ldrb_stack, |
| 5678 | 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_stack else .ldrh_stack, | 5709 | 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_stack else .ldrh_stack, |
| 5679 | 4, 8 => .ldr_stack, | 5710 | 4, 8 => .ldr_stack, |
| 5680 | else => unreachable, // unexpected abi size | 5711 | else => unreachable, // unexpected abi size |
| 5681 | }; | 5712 | }; |
| ... | @@ -5693,13 +5724,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -5693,13 +5724,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5693 | } | 5724 | } |
| 5694 | }, | 5725 | }, |
| 5695 | .stack_argument_offset => |off| { | 5726 | .stack_argument_offset => |off| { |
| 5696 | const abi_size = ty.abiSize(self.target.*); | 5727 | const abi_size = ty.abiSize(mod); |
| 5697 | 5728 | ||
| 5698 | switch (abi_size) { | 5729 | switch (abi_size) { |
| 5699 | 1, 2, 4, 8 => { | 5730 | 1, 2, 4, 8 => { |
| 5700 | const tag: Mir.Inst.Tag = switch (abi_size) { | 5731 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 5701 | 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument, | 5732 | 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument, |
| 5702 | 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument, | 5733 | 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument, |
| 5703 | 4, 8 => .ldr_stack_argument, | 5734 | 4, 8 => .ldr_stack_argument, |
| 5704 | else => unreachable, // unexpected abi size | 5735 | else => unreachable, // unexpected abi size |
| 5705 | }; | 5736 | }; |
| ... | @@ -5720,7 +5751,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -5720,7 +5751,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5720 | } | 5751 | } |
| 5721 | 5752 | ||
| 5722 | fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { | 5753 | fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { |
| 5723 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 5754 | const mod = self.bin_file.options.module.?; |
| 5755 | const abi_size = @intCast(u32, ty.abiSize(mod)); | ||
| 5724 | switch (mcv) { | 5756 | switch (mcv) { |
| 5725 | .dead => unreachable, | 5757 | .dead => unreachable, |
| 5726 | .none, .unreach => return, | 5758 | .none, .unreach => return, |
| ... | @@ -5728,7 +5760,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I | ... | @@ -5728,7 +5760,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 5728 | if (!self.wantSafety()) | 5760 | if (!self.wantSafety()) |
| 5729 | return; // The already existing value will do just fine. | 5761 | return; // The already existing value will do just fine. |
| 5730 | // TODO Upgrade this to a memset call when we have that available. | 5762 | // TODO Upgrade this to a memset call when we have that available. |
| 5731 | switch (ty.abiSize(self.target.*)) { | 5763 | switch (ty.abiSize(mod)) { |
| 5732 | 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }), | 5764 | 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }), |
| 5733 | 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }), | 5765 | 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }), |
| 5734 | 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }), | 5766 | 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }), |
| ... | @@ -6087,14 +6119,15 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6087,14 +6119,15 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 6087 | } | 6119 | } |
| 6088 | 6120 | ||
| 6089 | fn airTry(self: *Self, inst: Air.Inst.Index) !void { | 6121 | fn airTry(self: *Self, inst: Air.Inst.Index) !void { |
| 6122 | const mod = self.bin_file.options.module.?; | ||
| 6090 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 6123 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 6091 | const extra = self.air.extraData(Air.Try, pl_op.payload); | 6124 | const extra = self.air.extraData(Air.Try, pl_op.payload); |
| 6092 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; | 6125 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 6093 | const result: MCValue = result: { | 6126 | const result: MCValue = result: { |
| 6094 | const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand }; | 6127 | const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand }; |
| 6095 | const error_union_ty = self.air.typeOf(pl_op.operand); | 6128 | const error_union_ty = self.air.typeOf(pl_op.operand); |
| 6096 | const error_union_size = @intCast(u32, error_union_ty.abiSize(self.target.*)); | 6129 | const error_union_size = @intCast(u32, error_union_ty.abiSize(mod)); |
| 6097 | const error_union_align = error_union_ty.abiAlignment(self.target.*); | 6130 | const error_union_align = error_union_ty.abiAlignment(mod); |
| 6098 | 6131 | ||
| 6099 | // The error union will die in the body. However, we need the | 6132 | // The error union will die in the body. However, we need the |
| 6100 | // error union after the body in order to extract the payload | 6133 | // error union after the body in order to extract the payload |
| ... | @@ -6123,22 +6156,18 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6123,22 +6156,18 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6123 | } | 6156 | } |
| 6124 | 6157 | ||
| 6125 | fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { | 6158 | fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { |
| 6126 | // First section of indexes correspond to a set number of constant values. | 6159 | const mod = self.bin_file.options.module.?; |
| 6127 | const ref_int = @enumToInt(inst); | ||
| 6128 | if (ref_int < Air.Inst.Ref.typed_value_map.len) { | ||
| 6129 | const tv = Air.Inst.Ref.typed_value_map[ref_int]; | ||
| 6130 | if (!tv.ty.hasRuntimeBitsIgnoreComptime() and !tv.ty.isError()) { | ||
| 6131 | return MCValue{ .none = {} }; | ||
| 6132 | } | ||
| 6133 | return self.genTypedValue(tv); | ||
| 6134 | } | ||
| 6135 | 6160 | ||
| 6136 | // If the type has no codegen bits, no need to store it. | 6161 | // If the type has no codegen bits, no need to store it. |
| 6137 | const inst_ty = self.air.typeOf(inst); | 6162 | const inst_ty = self.air.typeOf(inst); |
| 6138 | if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError()) | 6163 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod)) |
| 6139 | return MCValue{ .none = {} }; | 6164 | return MCValue{ .none = {} }; |
| 6140 | 6165 | ||
| 6141 | const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len); | 6166 | const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{ |
| 6167 | .ty = inst_ty, | ||
| 6168 | .val = self.air.value(inst, mod).?, | ||
| 6169 | }); | ||
| 6170 | |||
| 6142 | switch (self.air.instructions.items(.tag)[inst_index]) { | 6171 | switch (self.air.instructions.items(.tag)[inst_index]) { |
| 6143 | .constant => { | 6172 | .constant => { |
| 6144 | // Constants have static lifetimes, so they are always memoized in the outer most table. | 6173 | // Constants have static lifetimes, so they are always memoized in the outer most table. |
| ... | @@ -6222,6 +6251,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6222,6 +6251,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6222 | errdefer self.gpa.free(result.args); | 6251 | errdefer self.gpa.free(result.args); |
| 6223 | 6252 | ||
| 6224 | const ret_ty = fn_ty.fnReturnType(); | 6253 | const ret_ty = fn_ty.fnReturnType(); |
| 6254 | const mod = self.bin_file.options.module.?; | ||
| 6225 | 6255 | ||
| 6226 | switch (cc) { | 6256 | switch (cc) { |
| 6227 | .Naked => { | 6257 | .Naked => { |
| ... | @@ -6236,14 +6266,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6236,14 +6266,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6236 | var ncrn: usize = 0; // Next Core Register Number | 6266 | var ncrn: usize = 0; // Next Core Register Number |
| 6237 | var nsaa: u32 = 0; // Next stacked argument address | 6267 | var nsaa: u32 = 0; // Next stacked argument address |
| 6238 | 6268 | ||
| 6239 | if (ret_ty.zigTypeTag() == .NoReturn) { | 6269 | if (ret_ty.zigTypeTag(mod) == .NoReturn) { |
| 6240 | result.return_value = .{ .unreach = {} }; | 6270 | result.return_value = .{ .unreach = {} }; |
| 6241 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) { | 6271 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and !ret_ty.isError(mod)) { |
| 6242 | result.return_value = .{ .none = {} }; | 6272 | result.return_value = .{ .none = {} }; |
| 6243 | } else { | 6273 | } else { |
| 6244 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 6274 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod)); |
| 6245 | if (ret_ty_size == 0) { | 6275 | if (ret_ty_size == 0) { |
| 6246 | assert(ret_ty.isError()); | 6276 | assert(ret_ty.isError(mod)); |
| 6247 | result.return_value = .{ .immediate = 0 }; | 6277 | result.return_value = .{ .immediate = 0 }; |
| 6248 | } else if (ret_ty_size <= 8) { | 6278 | } else if (ret_ty_size <= 8) { |
| 6249 | result.return_value = .{ .register = self.registerAlias(c_abi_int_return_regs[0], ret_ty) }; | 6279 | result.return_value = .{ .register = self.registerAlias(c_abi_int_return_regs[0], ret_ty) }; |
| ... | @@ -6253,7 +6283,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6253,7 +6283,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6253 | } | 6283 | } |
| 6254 | 6284 | ||
| 6255 | for (param_types, 0..) |ty, i| { | 6285 | for (param_types, 0..) |ty, i| { |
| 6256 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); | 6286 | const param_size = @intCast(u32, ty.abiSize(mod)); |
| 6257 | if (param_size == 0) { | 6287 | if (param_size == 0) { |
| 6258 | result.args[i] = .{ .none = {} }; | 6288 | result.args[i] = .{ .none = {} }; |
| 6259 | continue; | 6289 | continue; |
| ... | @@ -6261,7 +6291,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6261,7 +6291,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6261 | 6291 | ||
| 6262 | // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned | 6292 | // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned |
| 6263 | // values to spread across odd-numbered registers. | 6293 | // values to spread across odd-numbered registers. |
| 6264 | if (ty.abiAlignment(self.target.*) == 16 and !self.target.isDarwin()) { | 6294 | if (ty.abiAlignment(mod) == 16 and !self.target.isDarwin()) { |
| 6265 | // Round up NCRN to the next even number | 6295 | // Round up NCRN to the next even number |
| 6266 | ncrn += ncrn % 2; | 6296 | ncrn += ncrn % 2; |
| 6267 | } | 6297 | } |
| ... | @@ -6279,7 +6309,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6279,7 +6309,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6279 | ncrn = 8; | 6309 | ncrn = 8; |
| 6280 | // TODO Apple allows the arguments on the stack to be non-8-byte aligned provided | 6310 | // TODO Apple allows the arguments on the stack to be non-8-byte aligned provided |
| 6281 | // that the entire stack space consumed by the arguments is 8-byte aligned. | 6311 | // that the entire stack space consumed by the arguments is 8-byte aligned. |
| 6282 | if (ty.abiAlignment(self.target.*) == 8) { | 6312 | if (ty.abiAlignment(mod) == 8) { |
| 6283 | if (nsaa % 8 != 0) { | 6313 | if (nsaa % 8 != 0) { |
| 6284 | nsaa += 8 - (nsaa % 8); | 6314 | nsaa += 8 - (nsaa % 8); |
| 6285 | } | 6315 | } |
| ... | @@ -6294,14 +6324,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6294,14 +6324,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6294 | result.stack_align = 16; | 6324 | result.stack_align = 16; |
| 6295 | }, | 6325 | }, |
| 6296 | .Unspecified => { | 6326 | .Unspecified => { |
| 6297 | if (ret_ty.zigTypeTag() == .NoReturn) { | 6327 | if (ret_ty.zigTypeTag(mod) == .NoReturn) { |
| 6298 | result.return_value = .{ .unreach = {} }; | 6328 | result.return_value = .{ .unreach = {} }; |
| 6299 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) { | 6329 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and !ret_ty.isError(mod)) { |
| 6300 | result.return_value = .{ .none = {} }; | 6330 | result.return_value = .{ .none = {} }; |
| 6301 | } else { | 6331 | } else { |
| 6302 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 6332 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod)); |
| 6303 | if (ret_ty_size == 0) { | 6333 | if (ret_ty_size == 0) { |
| 6304 | assert(ret_ty.isError()); | 6334 | assert(ret_ty.isError(mod)); |
| 6305 | result.return_value = .{ .immediate = 0 }; | 6335 | result.return_value = .{ .immediate = 0 }; |
| 6306 | } else if (ret_ty_size <= 8) { | 6336 | } else if (ret_ty_size <= 8) { |
| 6307 | result.return_value = .{ .register = self.registerAlias(.x0, ret_ty) }; | 6337 | result.return_value = .{ .register = self.registerAlias(.x0, ret_ty) }; |
| ... | @@ -6318,9 +6348,9 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6318,9 +6348,9 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6318 | var stack_offset: u32 = 0; | 6348 | var stack_offset: u32 = 0; |
| 6319 | 6349 | ||
| 6320 | for (param_types, 0..) |ty, i| { | 6350 | for (param_types, 0..) |ty, i| { |
| 6321 | if (ty.abiSize(self.target.*) > 0) { | 6351 | if (ty.abiSize(mod) > 0) { |
| 6322 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); | 6352 | const param_size = @intCast(u32, ty.abiSize(mod)); |
| 6323 | const param_alignment = ty.abiAlignment(self.target.*); | 6353 | const param_alignment = ty.abiAlignment(mod); |
| 6324 | 6354 | ||
| 6325 | stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment); | 6355 | stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment); |
| 6326 | result.args[i] = .{ .stack_argument_offset = stack_offset }; | 6356 | result.args[i] = .{ .stack_argument_offset = stack_offset }; |
| ... | @@ -6371,7 +6401,8 @@ fn parseRegName(name: []const u8) ?Register { | ... | @@ -6371,7 +6401,8 @@ fn parseRegName(name: []const u8) ?Register { |
| 6371 | } | 6401 | } |
| 6372 | 6402 | ||
| 6373 | fn registerAlias(self: *Self, reg: Register, ty: Type) Register { | 6403 | fn registerAlias(self: *Self, reg: Register, ty: Type) Register { |
| 6374 | const abi_size = ty.abiSize(self.target.*); | 6404 | const mod = self.bin_file.options.module.?; |
| 6405 | const abi_size = ty.abiSize(mod); | ||
| 6375 | 6406 | ||
| 6376 | switch (reg.class()) { | 6407 | switch (reg.class()) { |
| 6377 | .general_purpose => { | 6408 | .general_purpose => { |
src/arch/aarch64/abi.zig+19-17| ... | @@ -4,6 +4,7 @@ const bits = @import("bits.zig"); | ... | @@ -4,6 +4,7 @@ const bits = @import("bits.zig"); |
| 4 | const Register = bits.Register; | 4 | const Register = bits.Register; |
| 5 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; | 5 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; |
| 6 | const Type = @import("../../type.zig").Type; | 6 | const Type = @import("../../type.zig").Type; |
| 7 | const Module = @import("../../Module.zig"); | ||
| 7 | 8 | ||
| 8 | pub const Class = union(enum) { | 9 | pub const Class = union(enum) { |
| 9 | memory, | 10 | memory, |
| ... | @@ -14,40 +15,40 @@ pub const Class = union(enum) { | ... | @@ -14,40 +15,40 @@ pub const Class = union(enum) { |
| 14 | }; | 15 | }; |
| 15 | 16 | ||
| 16 | /// For `float_array` the second element will be the amount of floats. | 17 | /// For `float_array` the second element will be the amount of floats. |
| 17 | pub fn classifyType(ty: Type, target: std.Target) Class { | 18 | pub fn classifyType(ty: Type, mod: *const Module) Class { |
| 18 | std.debug.assert(ty.hasRuntimeBitsIgnoreComptime()); | 19 | std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(mod)); |
| 19 | 20 | ||
| 20 | var maybe_float_bits: ?u16 = null; | 21 | var maybe_float_bits: ?u16 = null; |
| 21 | switch (ty.zigTypeTag()) { | 22 | switch (ty.zigTypeTag(mod)) { |
| 22 | .Struct => { | 23 | .Struct => { |
| 23 | if (ty.containerLayout() == .Packed) return .byval; | 24 | if (ty.containerLayout() == .Packed) return .byval; |
| 24 | const float_count = countFloats(ty, target, &maybe_float_bits); | 25 | const float_count = countFloats(ty, mod, &maybe_float_bits); |
| 25 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; | 26 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; |
| 26 | 27 | ||
| 27 | const bit_size = ty.bitSize(target); | 28 | const bit_size = ty.bitSize(mod); |
| 28 | if (bit_size > 128) return .memory; | 29 | if (bit_size > 128) return .memory; |
| 29 | if (bit_size > 64) return .double_integer; | 30 | if (bit_size > 64) return .double_integer; |
| 30 | return .integer; | 31 | return .integer; |
| 31 | }, | 32 | }, |
| 32 | .Union => { | 33 | .Union => { |
| 33 | if (ty.containerLayout() == .Packed) return .byval; | 34 | if (ty.containerLayout() == .Packed) return .byval; |
| 34 | const float_count = countFloats(ty, target, &maybe_float_bits); | 35 | const float_count = countFloats(ty, mod, &maybe_float_bits); |
| 35 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; | 36 | if (float_count <= sret_float_count) return .{ .float_array = float_count }; |
| 36 | 37 | ||
| 37 | const bit_size = ty.bitSize(target); | 38 | const bit_size = ty.bitSize(mod); |
| 38 | if (bit_size > 128) return .memory; | 39 | if (bit_size > 128) return .memory; |
| 39 | if (bit_size > 64) return .double_integer; | 40 | if (bit_size > 64) return .double_integer; |
| 40 | return .integer; | 41 | return .integer; |
| 41 | }, | 42 | }, |
| 42 | .Int, .Enum, .ErrorSet, .Float, .Bool => return .byval, | 43 | .Int, .Enum, .ErrorSet, .Float, .Bool => return .byval, |
| 43 | .Vector => { | 44 | .Vector => { |
| 44 | const bit_size = ty.bitSize(target); | 45 | const bit_size = ty.bitSize(mod); |
| 45 | // TODO is this controlled by a cpu feature? | 46 | // TODO is this controlled by a cpu feature? |
| 46 | if (bit_size > 128) return .memory; | 47 | if (bit_size > 128) return .memory; |
| 47 | return .byval; | 48 | return .byval; |
| 48 | }, | 49 | }, |
| 49 | .Optional => { | 50 | .Optional => { |
| 50 | std.debug.assert(ty.isPtrLikeOptional()); | 51 | std.debug.assert(ty.isPtrLikeOptional(mod)); |
| 51 | return .byval; | 52 | return .byval; |
| 52 | }, | 53 | }, |
| 53 | .Pointer => { | 54 | .Pointer => { |
| ... | @@ -73,14 +74,15 @@ pub fn classifyType(ty: Type, target: std.Target) Class { | ... | @@ -73,14 +74,15 @@ pub fn classifyType(ty: Type, target: std.Target) Class { |
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | const sret_float_count = 4; | 76 | const sret_float_count = 4; |
| 76 | fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 { | 77 | fn countFloats(ty: Type, mod: *const Module, maybe_float_bits: *?u16) u8 { |
| 78 | const target = mod.getTarget(); | ||
| 77 | const invalid = std.math.maxInt(u8); | 79 | const invalid = std.math.maxInt(u8); |
| 78 | switch (ty.zigTypeTag()) { | 80 | switch (ty.zigTypeTag(mod)) { |
| 79 | .Union => { | 81 | .Union => { |
| 80 | const fields = ty.unionFields(); | 82 | const fields = ty.unionFields(); |
| 81 | var max_count: u8 = 0; | 83 | var max_count: u8 = 0; |
| 82 | for (fields.values()) |field| { | 84 | for (fields.values()) |field| { |
| 83 | const field_count = countFloats(field.ty, target, maybe_float_bits); | 85 | const field_count = countFloats(field.ty, mod, maybe_float_bits); |
| 84 | if (field_count == invalid) return invalid; | 86 | if (field_count == invalid) return invalid; |
| 85 | if (field_count > max_count) max_count = field_count; | 87 | if (field_count > max_count) max_count = field_count; |
| 86 | if (max_count > sret_float_count) return invalid; | 88 | if (max_count > sret_float_count) return invalid; |
| ... | @@ -93,7 +95,7 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 { | ... | @@ -93,7 +95,7 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 { |
| 93 | var i: u32 = 0; | 95 | var i: u32 = 0; |
| 94 | while (i < fields_len) : (i += 1) { | 96 | while (i < fields_len) : (i += 1) { |
| 95 | const field_ty = ty.structFieldType(i); | 97 | const field_ty = ty.structFieldType(i); |
| 96 | const field_count = countFloats(field_ty, target, maybe_float_bits); | 98 | const field_count = countFloats(field_ty, mod, maybe_float_bits); |
| 97 | if (field_count == invalid) return invalid; | 99 | if (field_count == invalid) return invalid; |
| 98 | count += field_count; | 100 | count += field_count; |
| 99 | if (count > sret_float_count) return invalid; | 101 | if (count > sret_float_count) return invalid; |
| ... | @@ -113,12 +115,12 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 { | ... | @@ -113,12 +115,12 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 { |
| 113 | } | 115 | } |
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | pub fn getFloatArrayType(ty: Type) ?Type { | 118 | pub fn getFloatArrayType(ty: Type, mod: *const Module) ?Type { |
| 117 | switch (ty.zigTypeTag()) { | 119 | switch (ty.zigTypeTag(mod)) { |
| 118 | .Union => { | 120 | .Union => { |
| 119 | const fields = ty.unionFields(); | 121 | const fields = ty.unionFields(); |
| 120 | for (fields.values()) |field| { | 122 | for (fields.values()) |field| { |
| 121 | if (getFloatArrayType(field.ty)) |some| return some; | 123 | if (getFloatArrayType(field.ty, mod)) |some| return some; |
| 122 | } | 124 | } |
| 123 | return null; | 125 | return null; |
| 124 | }, | 126 | }, |
| ... | @@ -127,7 +129,7 @@ pub fn getFloatArrayType(ty: Type) ?Type { | ... | @@ -127,7 +129,7 @@ pub fn getFloatArrayType(ty: Type) ?Type { |
| 127 | var i: u32 = 0; | 129 | var i: u32 = 0; |
| 128 | while (i < fields_len) : (i += 1) { | 130 | while (i < fields_len) : (i += 1) { |
| 129 | const field_ty = ty.structFieldType(i); | 131 | const field_ty = ty.structFieldType(i); |
| 130 | if (getFloatArrayType(field_ty)) |some| return some; | 132 | if (getFloatArrayType(field_ty, mod)) |some| return some; |
| 131 | } | 133 | } |
| 132 | return null; | 134 | return null; |
| 133 | }, | 135 | }, |
src/arch/arm/CodeGen.zig+187-155| ... | @@ -520,8 +520,9 @@ fn gen(self: *Self) !void { | ... | @@ -520,8 +520,9 @@ fn gen(self: *Self) !void { |
| 520 | 520 | ||
| 521 | const ty = self.air.typeOfIndex(inst); | 521 | const ty = self.air.typeOfIndex(inst); |
| 522 | 522 | ||
| 523 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 523 | const mod = self.bin_file.options.module.?; |
| 524 | const abi_align = ty.abiAlignment(self.target.*); | 524 | const abi_size = @intCast(u32, ty.abiSize(mod)); |
| 525 | const abi_align = ty.abiAlignment(mod); | ||
| 525 | const stack_offset = try self.allocMem(abi_size, abi_align, inst); | 526 | const stack_offset = try self.allocMem(abi_size, abi_align, inst); |
| 526 | try self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 527 | try self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 527 | 528 | ||
| ... | @@ -937,8 +938,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live | ... | @@ -937,8 +938,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live |
| 937 | tomb_bits >>= 1; | 938 | tomb_bits >>= 1; |
| 938 | if (!dies) continue; | 939 | if (!dies) continue; |
| 939 | const op_int = @enumToInt(op); | 940 | const op_int = @enumToInt(op); |
| 940 | if (op_int < Air.Inst.Ref.typed_value_map.len) continue; | 941 | if (op_int < Air.ref_start_index) continue; |
| 941 | const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len); | 942 | const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index); |
| 942 | self.processDeath(op_index); | 943 | self.processDeath(op_index); |
| 943 | } | 944 | } |
| 944 | const is_used = @truncate(u1, tomb_bits) == 0; | 945 | const is_used = @truncate(u1, tomb_bits) == 0; |
| ... | @@ -1006,9 +1007,10 @@ fn allocMem( | ... | @@ -1006,9 +1007,10 @@ fn allocMem( |
| 1006 | 1007 | ||
| 1007 | /// Use a pointer instruction as the basis for allocating stack memory. | 1008 | /// Use a pointer instruction as the basis for allocating stack memory. |
| 1008 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { | 1009 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 1010 | const mod = self.bin_file.options.module.?; | ||
| 1009 | const elem_ty = self.air.typeOfIndex(inst).elemType(); | 1011 | const elem_ty = self.air.typeOfIndex(inst).elemType(); |
| 1010 | 1012 | ||
| 1011 | if (!elem_ty.hasRuntimeBits()) { | 1013 | if (!elem_ty.hasRuntimeBits(mod)) { |
| 1012 | // As this stack item will never be dereferenced at runtime, | 1014 | // As this stack item will never be dereferenced at runtime, |
| 1013 | // return the stack offset 0. Stack offset 0 will be where all | 1015 | // return the stack offset 0. Stack offset 0 will be where all |
| 1014 | // zero-sized stack allocations live as non-zero-sized | 1016 | // zero-sized stack allocations live as non-zero-sized |
| ... | @@ -1016,22 +1018,21 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { | ... | @@ -1016,22 +1018,21 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 1016 | return @as(u32, 0); | 1018 | return @as(u32, 0); |
| 1017 | } | 1019 | } |
| 1018 | 1020 | ||
| 1019 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { | 1021 | const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { |
| 1020 | const mod = self.bin_file.options.module.?; | ||
| 1021 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | 1022 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 1022 | }; | 1023 | }; |
| 1023 | // TODO swap this for inst.ty.ptrAlign | 1024 | // TODO swap this for inst.ty.ptrAlign |
| 1024 | const abi_align = elem_ty.abiAlignment(self.target.*); | 1025 | const abi_align = elem_ty.abiAlignment(mod); |
| 1025 | 1026 | ||
| 1026 | return self.allocMem(abi_size, abi_align, inst); | 1027 | return self.allocMem(abi_size, abi_align, inst); |
| 1027 | } | 1028 | } |
| 1028 | 1029 | ||
| 1029 | fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue { | 1030 | fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue { |
| 1030 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { | 1031 | const mod = self.bin_file.options.module.?; |
| 1031 | const mod = self.bin_file.options.module.?; | 1032 | const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { |
| 1032 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | 1033 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 1033 | }; | 1034 | }; |
| 1034 | const abi_align = elem_ty.abiAlignment(self.target.*); | 1035 | const abi_align = elem_ty.abiAlignment(mod); |
| 1035 | 1036 | ||
| 1036 | if (reg_ok) { | 1037 | if (reg_ok) { |
| 1037 | // Make sure the type can fit in a register before we try to allocate one. | 1038 | // Make sure the type can fit in a register before we try to allocate one. |
| ... | @@ -1158,10 +1159,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1158,10 +1159,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1158 | const operand_ty = self.air.typeOf(ty_op.operand); | 1159 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 1159 | const dest_ty = self.air.typeOfIndex(inst); | 1160 | const dest_ty = self.air.typeOfIndex(inst); |
| 1160 | 1161 | ||
| 1161 | const operand_abi_size = operand_ty.abiSize(self.target.*); | 1162 | const mod = self.bin_file.options.module.?; |
| 1162 | const dest_abi_size = dest_ty.abiSize(self.target.*); | 1163 | const operand_abi_size = operand_ty.abiSize(mod); |
| 1163 | const info_a = operand_ty.intInfo(self.target.*); | 1164 | const dest_abi_size = dest_ty.abiSize(mod); |
| 1164 | const info_b = dest_ty.intInfo(self.target.*); | 1165 | const info_a = operand_ty.intInfo(mod); |
| 1166 | const info_b = dest_ty.intInfo(mod); | ||
| 1165 | 1167 | ||
| 1166 | const dst_mcv: MCValue = blk: { | 1168 | const dst_mcv: MCValue = blk: { |
| 1167 | if (info_a.bits == info_b.bits) { | 1169 | if (info_a.bits == info_b.bits) { |
| ... | @@ -1215,8 +1217,9 @@ fn trunc( | ... | @@ -1215,8 +1217,9 @@ fn trunc( |
| 1215 | operand_ty: Type, | 1217 | operand_ty: Type, |
| 1216 | dest_ty: Type, | 1218 | dest_ty: Type, |
| 1217 | ) !MCValue { | 1219 | ) !MCValue { |
| 1218 | const info_a = operand_ty.intInfo(self.target.*); | 1220 | const mod = self.bin_file.options.module.?; |
| 1219 | const info_b = dest_ty.intInfo(self.target.*); | 1221 | const info_a = operand_ty.intInfo(mod); |
| 1222 | const info_b = dest_ty.intInfo(mod); | ||
| 1220 | 1223 | ||
| 1221 | if (info_b.bits <= 32) { | 1224 | if (info_b.bits <= 32) { |
| 1222 | if (info_a.bits > 32) { | 1225 | if (info_a.bits > 32) { |
| ... | @@ -1278,6 +1281,7 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1278,6 +1281,7 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 1278 | 1281 | ||
| 1279 | fn airNot(self: *Self, inst: Air.Inst.Index) !void { | 1282 | fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1280 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1283 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1284 | const mod = self.bin_file.options.module.?; | ||
| 1281 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1285 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1282 | const operand_bind: ReadArg.Bind = .{ .inst = ty_op.operand }; | 1286 | const operand_bind: ReadArg.Bind = .{ .inst = ty_op.operand }; |
| 1283 | const operand_ty = self.air.typeOf(ty_op.operand); | 1287 | const operand_ty = self.air.typeOf(ty_op.operand); |
| ... | @@ -1286,7 +1290,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1286,7 +1290,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1286 | .unreach => unreachable, | 1290 | .unreach => unreachable, |
| 1287 | .cpsr_flags => |cond| break :result MCValue{ .cpsr_flags = cond.negate() }, | 1291 | .cpsr_flags => |cond| break :result MCValue{ .cpsr_flags = cond.negate() }, |
| 1288 | else => { | 1292 | else => { |
| 1289 | switch (operand_ty.zigTypeTag()) { | 1293 | switch (operand_ty.zigTypeTag(mod)) { |
| 1290 | .Bool => { | 1294 | .Bool => { |
| 1291 | var op_reg: Register = undefined; | 1295 | var op_reg: Register = undefined; |
| 1292 | var dest_reg: Register = undefined; | 1296 | var dest_reg: Register = undefined; |
| ... | @@ -1319,7 +1323,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1319,7 +1323,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1319 | }, | 1323 | }, |
| 1320 | .Vector => return self.fail("TODO bitwise not for vectors", .{}), | 1324 | .Vector => return self.fail("TODO bitwise not for vectors", .{}), |
| 1321 | .Int => { | 1325 | .Int => { |
| 1322 | const int_info = operand_ty.intInfo(self.target.*); | 1326 | const int_info = operand_ty.intInfo(mod); |
| 1323 | if (int_info.bits <= 32) { | 1327 | if (int_info.bits <= 32) { |
| 1324 | var op_reg: Register = undefined; | 1328 | var op_reg: Register = undefined; |
| 1325 | var dest_reg: Register = undefined; | 1329 | var dest_reg: Register = undefined; |
| ... | @@ -1373,13 +1377,13 @@ fn minMax( | ... | @@ -1373,13 +1377,13 @@ fn minMax( |
| 1373 | rhs_ty: Type, | 1377 | rhs_ty: Type, |
| 1374 | maybe_inst: ?Air.Inst.Index, | 1378 | maybe_inst: ?Air.Inst.Index, |
| 1375 | ) !MCValue { | 1379 | ) !MCValue { |
| 1376 | switch (lhs_ty.zigTypeTag()) { | 1380 | const mod = self.bin_file.options.module.?; |
| 1381 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 1377 | .Float => return self.fail("TODO ARM min/max on floats", .{}), | 1382 | .Float => return self.fail("TODO ARM min/max on floats", .{}), |
| 1378 | .Vector => return self.fail("TODO ARM min/max on vectors", .{}), | 1383 | .Vector => return self.fail("TODO ARM min/max on vectors", .{}), |
| 1379 | .Int => { | 1384 | .Int => { |
| 1380 | const mod = self.bin_file.options.module.?; | ||
| 1381 | assert(lhs_ty.eql(rhs_ty, mod)); | 1385 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 1382 | const int_info = lhs_ty.intInfo(self.target.*); | 1386 | const int_info = lhs_ty.intInfo(mod); |
| 1383 | if (int_info.bits <= 32) { | 1387 | if (int_info.bits <= 32) { |
| 1384 | var lhs_reg: Register = undefined; | 1388 | var lhs_reg: Register = undefined; |
| 1385 | var rhs_reg: Register = undefined; | 1389 | var rhs_reg: Register = undefined; |
| ... | @@ -1582,6 +1586,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1582,6 +1586,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1582 | const tag = self.air.instructions.items(.tag)[inst]; | 1586 | const tag = self.air.instructions.items(.tag)[inst]; |
| 1583 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1587 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1584 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 1588 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 1589 | const mod = self.bin_file.options.module.?; | ||
| 1585 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1590 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1586 | const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; | 1591 | const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; |
| 1587 | const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; | 1592 | const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; |
| ... | @@ -1589,16 +1594,15 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1589,16 +1594,15 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1589 | const rhs_ty = self.air.typeOf(extra.rhs); | 1594 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 1590 | 1595 | ||
| 1591 | const tuple_ty = self.air.typeOfIndex(inst); | 1596 | const tuple_ty = self.air.typeOfIndex(inst); |
| 1592 | const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*)); | 1597 | const tuple_size = @intCast(u32, tuple_ty.abiSize(mod)); |
| 1593 | const tuple_align = tuple_ty.abiAlignment(self.target.*); | 1598 | const tuple_align = tuple_ty.abiAlignment(mod); |
| 1594 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*)); | 1599 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod)); |
| 1595 | 1600 | ||
| 1596 | switch (lhs_ty.zigTypeTag()) { | 1601 | switch (lhs_ty.zigTypeTag(mod)) { |
| 1597 | .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}), | 1602 | .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}), |
| 1598 | .Int => { | 1603 | .Int => { |
| 1599 | const mod = self.bin_file.options.module.?; | ||
| 1600 | assert(lhs_ty.eql(rhs_ty, mod)); | 1604 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 1601 | const int_info = lhs_ty.intInfo(self.target.*); | 1605 | const int_info = lhs_ty.intInfo(mod); |
| 1602 | if (int_info.bits < 32) { | 1606 | if (int_info.bits < 32) { |
| 1603 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); | 1607 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); |
| 1604 | 1608 | ||
| ... | @@ -1695,6 +1699,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1695,6 +1699,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1695 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1699 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1696 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 1700 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 1697 | if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); | 1701 | if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); |
| 1702 | const mod = self.bin_file.options.module.?; | ||
| 1698 | const result: MCValue = result: { | 1703 | const result: MCValue = result: { |
| 1699 | const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; | 1704 | const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; |
| 1700 | const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; | 1705 | const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; |
| ... | @@ -1702,16 +1707,15 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1702,16 +1707,15 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1702 | const rhs_ty = self.air.typeOf(extra.rhs); | 1707 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 1703 | 1708 | ||
| 1704 | const tuple_ty = self.air.typeOfIndex(inst); | 1709 | const tuple_ty = self.air.typeOfIndex(inst); |
| 1705 | const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*)); | 1710 | const tuple_size = @intCast(u32, tuple_ty.abiSize(mod)); |
| 1706 | const tuple_align = tuple_ty.abiAlignment(self.target.*); | 1711 | const tuple_align = tuple_ty.abiAlignment(mod); |
| 1707 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*)); | 1712 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod)); |
| 1708 | 1713 | ||
| 1709 | switch (lhs_ty.zigTypeTag()) { | 1714 | switch (lhs_ty.zigTypeTag(mod)) { |
| 1710 | .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), | 1715 | .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), |
| 1711 | .Int => { | 1716 | .Int => { |
| 1712 | const mod = self.bin_file.options.module.?; | ||
| 1713 | assert(lhs_ty.eql(rhs_ty, mod)); | 1717 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 1714 | const int_info = lhs_ty.intInfo(self.target.*); | 1718 | const int_info = lhs_ty.intInfo(mod); |
| 1715 | if (int_info.bits <= 16) { | 1719 | if (int_info.bits <= 16) { |
| 1716 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); | 1720 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); |
| 1717 | 1721 | ||
| ... | @@ -1859,19 +1863,20 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1859,19 +1863,20 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1859 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1863 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1860 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 1864 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 1861 | if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); | 1865 | if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); |
| 1866 | const mod = self.bin_file.options.module.?; | ||
| 1862 | const result: MCValue = result: { | 1867 | const result: MCValue = result: { |
| 1863 | const lhs_ty = self.air.typeOf(extra.lhs); | 1868 | const lhs_ty = self.air.typeOf(extra.lhs); |
| 1864 | const rhs_ty = self.air.typeOf(extra.rhs); | 1869 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 1865 | 1870 | ||
| 1866 | const tuple_ty = self.air.typeOfIndex(inst); | 1871 | const tuple_ty = self.air.typeOfIndex(inst); |
| 1867 | const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*)); | 1872 | const tuple_size = @intCast(u32, tuple_ty.abiSize(mod)); |
| 1868 | const tuple_align = tuple_ty.abiAlignment(self.target.*); | 1873 | const tuple_align = tuple_ty.abiAlignment(mod); |
| 1869 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*)); | 1874 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod)); |
| 1870 | 1875 | ||
| 1871 | switch (lhs_ty.zigTypeTag()) { | 1876 | switch (lhs_ty.zigTypeTag(mod)) { |
| 1872 | .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}), | 1877 | .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}), |
| 1873 | .Int => { | 1878 | .Int => { |
| 1874 | const int_info = lhs_ty.intInfo(self.target.*); | 1879 | const int_info = lhs_ty.intInfo(mod); |
| 1875 | if (int_info.bits <= 32) { | 1880 | if (int_info.bits <= 32) { |
| 1876 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); | 1881 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); |
| 1877 | 1882 | ||
| ... | @@ -2017,7 +2022,8 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2017,7 +2022,8 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 2017 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2022 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2018 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2023 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2019 | const optional_ty = self.air.typeOfIndex(inst); | 2024 | const optional_ty = self.air.typeOfIndex(inst); |
| 2020 | const abi_size = @intCast(u32, optional_ty.abiSize(self.target.*)); | 2025 | const mod = self.bin_file.options.module.?; |
| 2026 | const abi_size = @intCast(u32, optional_ty.abiSize(mod)); | ||
| 2021 | 2027 | ||
| 2022 | // Optional with a zero-bit payload type is just a boolean true | 2028 | // Optional with a zero-bit payload type is just a boolean true |
| 2023 | if (abi_size == 1) { | 2029 | if (abi_size == 1) { |
| ... | @@ -2036,16 +2042,17 @@ fn errUnionErr( | ... | @@ -2036,16 +2042,17 @@ fn errUnionErr( |
| 2036 | error_union_ty: Type, | 2042 | error_union_ty: Type, |
| 2037 | maybe_inst: ?Air.Inst.Index, | 2043 | maybe_inst: ?Air.Inst.Index, |
| 2038 | ) !MCValue { | 2044 | ) !MCValue { |
| 2045 | const mod = self.bin_file.options.module.?; | ||
| 2039 | const err_ty = error_union_ty.errorUnionSet(); | 2046 | const err_ty = error_union_ty.errorUnionSet(); |
| 2040 | const payload_ty = error_union_ty.errorUnionPayload(); | 2047 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 2041 | if (err_ty.errorSetIsEmpty()) { | 2048 | if (err_ty.errorSetIsEmpty()) { |
| 2042 | return MCValue{ .immediate = 0 }; | 2049 | return MCValue{ .immediate = 0 }; |
| 2043 | } | 2050 | } |
| 2044 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 2051 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2045 | return try error_union_bind.resolveToMcv(self); | 2052 | return try error_union_bind.resolveToMcv(self); |
| 2046 | } | 2053 | } |
| 2047 | 2054 | ||
| 2048 | const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, self.target.*)); | 2055 | const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, mod)); |
| 2049 | switch (try error_union_bind.resolveToMcv(self)) { | 2056 | switch (try error_union_bind.resolveToMcv(self)) { |
| 2050 | .register => { | 2057 | .register => { |
| 2051 | var operand_reg: Register = undefined; | 2058 | var operand_reg: Register = undefined; |
| ... | @@ -2067,7 +2074,7 @@ fn errUnionErr( | ... | @@ -2067,7 +2074,7 @@ fn errUnionErr( |
| 2067 | ); | 2074 | ); |
| 2068 | 2075 | ||
| 2069 | const err_bit_offset = err_offset * 8; | 2076 | const err_bit_offset = err_offset * 8; |
| 2070 | const err_bit_size = @intCast(u32, err_ty.abiSize(self.target.*)) * 8; | 2077 | const err_bit_size = @intCast(u32, err_ty.abiSize(mod)) * 8; |
| 2071 | 2078 | ||
| 2072 | _ = try self.addInst(.{ | 2079 | _ = try self.addInst(.{ |
| 2073 | .tag = .ubfx, // errors are unsigned integers | 2080 | .tag = .ubfx, // errors are unsigned integers |
| ... | @@ -2112,16 +2119,17 @@ fn errUnionPayload( | ... | @@ -2112,16 +2119,17 @@ fn errUnionPayload( |
| 2112 | error_union_ty: Type, | 2119 | error_union_ty: Type, |
| 2113 | maybe_inst: ?Air.Inst.Index, | 2120 | maybe_inst: ?Air.Inst.Index, |
| 2114 | ) !MCValue { | 2121 | ) !MCValue { |
| 2122 | const mod = self.bin_file.options.module.?; | ||
| 2115 | const err_ty = error_union_ty.errorUnionSet(); | 2123 | const err_ty = error_union_ty.errorUnionSet(); |
| 2116 | const payload_ty = error_union_ty.errorUnionPayload(); | 2124 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 2117 | if (err_ty.errorSetIsEmpty()) { | 2125 | if (err_ty.errorSetIsEmpty()) { |
| 2118 | return try error_union_bind.resolveToMcv(self); | 2126 | return try error_union_bind.resolveToMcv(self); |
| 2119 | } | 2127 | } |
| 2120 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 2128 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2121 | return MCValue.none; | 2129 | return MCValue.none; |
| 2122 | } | 2130 | } |
| 2123 | 2131 | ||
| 2124 | const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*)); | 2132 | const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod)); |
| 2125 | switch (try error_union_bind.resolveToMcv(self)) { | 2133 | switch (try error_union_bind.resolveToMcv(self)) { |
| 2126 | .register => { | 2134 | .register => { |
| 2127 | var operand_reg: Register = undefined; | 2135 | var operand_reg: Register = undefined; |
| ... | @@ -2143,10 +2151,10 @@ fn errUnionPayload( | ... | @@ -2143,10 +2151,10 @@ fn errUnionPayload( |
| 2143 | ); | 2151 | ); |
| 2144 | 2152 | ||
| 2145 | const payload_bit_offset = payload_offset * 8; | 2153 | const payload_bit_offset = payload_offset * 8; |
| 2146 | const payload_bit_size = @intCast(u32, payload_ty.abiSize(self.target.*)) * 8; | 2154 | const payload_bit_size = @intCast(u32, payload_ty.abiSize(mod)) * 8; |
| 2147 | 2155 | ||
| 2148 | _ = try self.addInst(.{ | 2156 | _ = try self.addInst(.{ |
| 2149 | .tag = if (payload_ty.isSignedInt()) Mir.Inst.Tag.sbfx else .ubfx, | 2157 | .tag = if (payload_ty.isSignedInt(mod)) Mir.Inst.Tag.sbfx else .ubfx, |
| 2150 | .data = .{ .rr_lsb_width = .{ | 2158 | .data = .{ .rr_lsb_width = .{ |
| 2151 | .rd = dest_reg, | 2159 | .rd = dest_reg, |
| 2152 | .rn = operand_reg, | 2160 | .rn = operand_reg, |
| ... | @@ -2221,19 +2229,20 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2221,19 +2229,20 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { |
| 2221 | 2229 | ||
| 2222 | /// T to E!T | 2230 | /// T to E!T |
| 2223 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { | 2231 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 2232 | const mod = self.bin_file.options.module.?; | ||
| 2224 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2233 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2225 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2234 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2226 | const error_union_ty = self.air.getRefType(ty_op.ty); | 2235 | const error_union_ty = self.air.getRefType(ty_op.ty); |
| 2227 | const error_ty = error_union_ty.errorUnionSet(); | 2236 | const error_ty = error_union_ty.errorUnionSet(); |
| 2228 | const payload_ty = error_union_ty.errorUnionPayload(); | 2237 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 2229 | const operand = try self.resolveInst(ty_op.operand); | 2238 | const operand = try self.resolveInst(ty_op.operand); |
| 2230 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand; | 2239 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand; |
| 2231 | 2240 | ||
| 2232 | const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*)); | 2241 | const abi_size = @intCast(u32, error_union_ty.abiSize(mod)); |
| 2233 | const abi_align = error_union_ty.abiAlignment(self.target.*); | 2242 | const abi_align = error_union_ty.abiAlignment(mod); |
| 2234 | const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst)); | 2243 | const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst)); |
| 2235 | const payload_off = errUnionPayloadOffset(payload_ty, self.target.*); | 2244 | const payload_off = errUnionPayloadOffset(payload_ty, mod); |
| 2236 | const err_off = errUnionErrorOffset(payload_ty, self.target.*); | 2245 | const err_off = errUnionErrorOffset(payload_ty, mod); |
| 2237 | try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand); | 2246 | try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand); |
| 2238 | try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), .{ .immediate = 0 }); | 2247 | try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), .{ .immediate = 0 }); |
| 2239 | 2248 | ||
| ... | @@ -2244,19 +2253,20 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2244,19 +2253,20 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 2244 | 2253 | ||
| 2245 | /// E to E!T | 2254 | /// E to E!T |
| 2246 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | 2255 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 2256 | const mod = self.bin_file.options.module.?; | ||
| 2247 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2257 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2248 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2258 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2249 | const error_union_ty = self.air.getRefType(ty_op.ty); | 2259 | const error_union_ty = self.air.getRefType(ty_op.ty); |
| 2250 | const error_ty = error_union_ty.errorUnionSet(); | 2260 | const error_ty = error_union_ty.errorUnionSet(); |
| 2251 | const payload_ty = error_union_ty.errorUnionPayload(); | 2261 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 2252 | const operand = try self.resolveInst(ty_op.operand); | 2262 | const operand = try self.resolveInst(ty_op.operand); |
| 2253 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand; | 2263 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand; |
| 2254 | 2264 | ||
| 2255 | const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*)); | 2265 | const abi_size = @intCast(u32, error_union_ty.abiSize(mod)); |
| 2256 | const abi_align = error_union_ty.abiAlignment(self.target.*); | 2266 | const abi_align = error_union_ty.abiAlignment(mod); |
| 2257 | const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst)); | 2267 | const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst)); |
| 2258 | const payload_off = errUnionPayloadOffset(payload_ty, self.target.*); | 2268 | const payload_off = errUnionPayloadOffset(payload_ty, mod); |
| 2259 | const err_off = errUnionErrorOffset(payload_ty, self.target.*); | 2269 | const err_off = errUnionErrorOffset(payload_ty, mod); |
| 2260 | try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand); | 2270 | try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand); |
| 2261 | try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef); | 2271 | try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef); |
| 2262 | 2272 | ||
| ... | @@ -2361,7 +2371,8 @@ fn ptrElemVal( | ... | @@ -2361,7 +2371,8 @@ fn ptrElemVal( |
| 2361 | maybe_inst: ?Air.Inst.Index, | 2371 | maybe_inst: ?Air.Inst.Index, |
| 2362 | ) !MCValue { | 2372 | ) !MCValue { |
| 2363 | const elem_ty = ptr_ty.childType(); | 2373 | const elem_ty = ptr_ty.childType(); |
| 2364 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | 2374 | const mod = self.bin_file.options.module.?; |
| 2375 | const elem_size = @intCast(u32, elem_ty.abiSize(mod)); | ||
| 2365 | 2376 | ||
| 2366 | switch (elem_size) { | 2377 | switch (elem_size) { |
| 2367 | 1, 4 => { | 2378 | 1, 4 => { |
| ... | @@ -2647,7 +2658,8 @@ fn reuseOperand( | ... | @@ -2647,7 +2658,8 @@ fn reuseOperand( |
| 2647 | 2658 | ||
| 2648 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { | 2659 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 2649 | const elem_ty = ptr_ty.elemType(); | 2660 | const elem_ty = ptr_ty.elemType(); |
| 2650 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | 2661 | const mod = self.bin_file.options.module.?; |
| 2662 | const elem_size = @intCast(u32, elem_ty.abiSize(mod)); | ||
| 2651 | 2663 | ||
| 2652 | switch (ptr) { | 2664 | switch (ptr) { |
| 2653 | .none => unreachable, | 2665 | .none => unreachable, |
| ... | @@ -2722,10 +2734,11 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -2722,10 +2734,11 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2722 | } | 2734 | } |
| 2723 | 2735 | ||
| 2724 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | 2736 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 2737 | const mod = self.bin_file.options.module.?; | ||
| 2725 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2738 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2726 | const elem_ty = self.air.typeOfIndex(inst); | 2739 | const elem_ty = self.air.typeOfIndex(inst); |
| 2727 | const result: MCValue = result: { | 2740 | const result: MCValue = result: { |
| 2728 | if (!elem_ty.hasRuntimeBits()) | 2741 | if (!elem_ty.hasRuntimeBits(mod)) |
| 2729 | break :result MCValue.none; | 2742 | break :result MCValue.none; |
| 2730 | 2743 | ||
| 2731 | const ptr = try self.resolveInst(ty_op.operand); | 2744 | const ptr = try self.resolveInst(ty_op.operand); |
| ... | @@ -2734,7 +2747,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2734,7 +2747,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 2734 | break :result MCValue.dead; | 2747 | break :result MCValue.dead; |
| 2735 | 2748 | ||
| 2736 | const dest_mcv: MCValue = blk: { | 2749 | const dest_mcv: MCValue = blk: { |
| 2737 | const ptr_fits_dest = elem_ty.abiSize(self.target.*) <= 4; | 2750 | const ptr_fits_dest = elem_ty.abiSize(mod) <= 4; |
| 2738 | if (ptr_fits_dest and self.reuseOperand(inst, ty_op.operand, 0, ptr)) { | 2751 | if (ptr_fits_dest and self.reuseOperand(inst, ty_op.operand, 0, ptr)) { |
| 2739 | // The MCValue that holds the pointer can be re-used as the value. | 2752 | // The MCValue that holds the pointer can be re-used as the value. |
| 2740 | break :blk ptr; | 2753 | break :blk ptr; |
| ... | @@ -2750,7 +2763,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2750,7 +2763,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 2750 | } | 2763 | } |
| 2751 | 2764 | ||
| 2752 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { | 2765 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { |
| 2753 | const elem_size = @intCast(u32, value_ty.abiSize(self.target.*)); | 2766 | const mod = self.bin_file.options.module.?; |
| 2767 | const elem_size = @intCast(u32, value_ty.abiSize(mod)); | ||
| 2754 | 2768 | ||
| 2755 | switch (ptr) { | 2769 | switch (ptr) { |
| 2756 | .none => unreachable, | 2770 | .none => unreachable, |
| ... | @@ -2869,10 +2883,11 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { | ... | @@ -2869,10 +2883,11 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { |
| 2869 | 2883 | ||
| 2870 | fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { | 2884 | fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { |
| 2871 | return if (self.liveness.isUnused(inst)) .dead else result: { | 2885 | return if (self.liveness.isUnused(inst)) .dead else result: { |
| 2886 | const mod = self.bin_file.options.module.?; | ||
| 2872 | const mcv = try self.resolveInst(operand); | 2887 | const mcv = try self.resolveInst(operand); |
| 2873 | const ptr_ty = self.air.typeOf(operand); | 2888 | const ptr_ty = self.air.typeOf(operand); |
| 2874 | const struct_ty = ptr_ty.childType(); | 2889 | const struct_ty = ptr_ty.childType(); |
| 2875 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); | 2890 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod)); |
| 2876 | switch (mcv) { | 2891 | switch (mcv) { |
| 2877 | .ptr_stack_offset => |off| { | 2892 | .ptr_stack_offset => |off| { |
| 2878 | break :result MCValue{ .ptr_stack_offset = off - struct_field_offset }; | 2893 | break :result MCValue{ .ptr_stack_offset = off - struct_field_offset }; |
| ... | @@ -2892,10 +2907,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2892,10 +2907,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2892 | const extra = self.air.extraData(Air.StructField, ty_pl.payload).data; | 2907 | const extra = self.air.extraData(Air.StructField, ty_pl.payload).data; |
| 2893 | const operand = extra.struct_operand; | 2908 | const operand = extra.struct_operand; |
| 2894 | const index = extra.field_index; | 2909 | const index = extra.field_index; |
| 2910 | const mod = self.bin_file.options.module.?; | ||
| 2895 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2911 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2896 | const mcv = try self.resolveInst(operand); | 2912 | const mcv = try self.resolveInst(operand); |
| 2897 | const struct_ty = self.air.typeOf(operand); | 2913 | const struct_ty = self.air.typeOf(operand); |
| 2898 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); | 2914 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod)); |
| 2899 | const struct_field_ty = struct_ty.structFieldType(index); | 2915 | const struct_field_ty = struct_ty.structFieldType(index); |
| 2900 | 2916 | ||
| 2901 | switch (mcv) { | 2917 | switch (mcv) { |
| ... | @@ -2959,10 +2975,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2959,10 +2975,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2959 | ); | 2975 | ); |
| 2960 | 2976 | ||
| 2961 | const field_bit_offset = struct_field_offset * 8; | 2977 | const field_bit_offset = struct_field_offset * 8; |
| 2962 | const field_bit_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)) * 8; | 2978 | const field_bit_size = @intCast(u32, struct_field_ty.abiSize(mod)) * 8; |
| 2963 | 2979 | ||
| 2964 | _ = try self.addInst(.{ | 2980 | _ = try self.addInst(.{ |
| 2965 | .tag = if (struct_field_ty.isSignedInt()) Mir.Inst.Tag.sbfx else .ubfx, | 2981 | .tag = if (struct_field_ty.isSignedInt(mod)) Mir.Inst.Tag.sbfx else .ubfx, |
| 2966 | .data = .{ .rr_lsb_width = .{ | 2982 | .data = .{ .rr_lsb_width = .{ |
| 2967 | .rd = dest_reg, | 2983 | .rd = dest_reg, |
| 2968 | .rn = operand_reg, | 2984 | .rn = operand_reg, |
| ... | @@ -2981,17 +2997,18 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2981,17 +2997,18 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2981 | } | 2997 | } |
| 2982 | 2998 | ||
| 2983 | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | 2999 | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3000 | const mod = self.bin_file.options.module.?; | ||
| 2984 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 3001 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2985 | const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | 3002 | const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 2986 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 3003 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2987 | const field_ptr = try self.resolveInst(extra.field_ptr); | 3004 | const field_ptr = try self.resolveInst(extra.field_ptr); |
| 2988 | const struct_ty = self.air.getRefType(ty_pl.ty).childType(); | 3005 | const struct_ty = self.air.getRefType(ty_pl.ty).childType(); |
| 2989 | 3006 | ||
| 2990 | if (struct_ty.zigTypeTag() == .Union) { | 3007 | if (struct_ty.zigTypeTag(mod) == .Union) { |
| 2991 | return self.fail("TODO implement @fieldParentPtr codegen for unions", .{}); | 3008 | return self.fail("TODO implement @fieldParentPtr codegen for unions", .{}); |
| 2992 | } | 3009 | } |
| 2993 | 3010 | ||
| 2994 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(extra.field_index, self.target.*)); | 3011 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(extra.field_index, mod)); |
| 2995 | switch (field_ptr) { | 3012 | switch (field_ptr) { |
| 2996 | .ptr_stack_offset => |off| { | 3013 | .ptr_stack_offset => |off| { |
| 2997 | break :result MCValue{ .ptr_stack_offset = off + struct_field_offset }; | 3014 | break :result MCValue{ .ptr_stack_offset = off + struct_field_offset }; |
| ... | @@ -3375,12 +3392,12 @@ fn addSub( | ... | @@ -3375,12 +3392,12 @@ fn addSub( |
| 3375 | maybe_inst: ?Air.Inst.Index, | 3392 | maybe_inst: ?Air.Inst.Index, |
| 3376 | ) InnerError!MCValue { | 3393 | ) InnerError!MCValue { |
| 3377 | const mod = self.bin_file.options.module.?; | 3394 | const mod = self.bin_file.options.module.?; |
| 3378 | switch (lhs_ty.zigTypeTag()) { | 3395 | switch (lhs_ty.zigTypeTag(mod)) { |
| 3379 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | 3396 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 3380 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3397 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3381 | .Int => { | 3398 | .Int => { |
| 3382 | assert(lhs_ty.eql(rhs_ty, mod)); | 3399 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 3383 | const int_info = lhs_ty.intInfo(self.target.*); | 3400 | const int_info = lhs_ty.intInfo(mod); |
| 3384 | if (int_info.bits <= 32) { | 3401 | if (int_info.bits <= 32) { |
| 3385 | const lhs_immediate = try lhs_bind.resolveToImmediate(self); | 3402 | const lhs_immediate = try lhs_bind.resolveToImmediate(self); |
| 3386 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); | 3403 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); |
| ... | @@ -3431,12 +3448,12 @@ fn mul( | ... | @@ -3431,12 +3448,12 @@ fn mul( |
| 3431 | maybe_inst: ?Air.Inst.Index, | 3448 | maybe_inst: ?Air.Inst.Index, |
| 3432 | ) InnerError!MCValue { | 3449 | ) InnerError!MCValue { |
| 3433 | const mod = self.bin_file.options.module.?; | 3450 | const mod = self.bin_file.options.module.?; |
| 3434 | switch (lhs_ty.zigTypeTag()) { | 3451 | switch (lhs_ty.zigTypeTag(mod)) { |
| 3435 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | 3452 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 3436 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3453 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3437 | .Int => { | 3454 | .Int => { |
| 3438 | assert(lhs_ty.eql(rhs_ty, mod)); | 3455 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 3439 | const int_info = lhs_ty.intInfo(self.target.*); | 3456 | const int_info = lhs_ty.intInfo(mod); |
| 3440 | if (int_info.bits <= 32) { | 3457 | if (int_info.bits <= 32) { |
| 3441 | // TODO add optimisations for multiplication | 3458 | // TODO add optimisations for multiplication |
| 3442 | // with immediates, for example a * 2 can be | 3459 | // with immediates, for example a * 2 can be |
| ... | @@ -3463,7 +3480,8 @@ fn divFloat( | ... | @@ -3463,7 +3480,8 @@ fn divFloat( |
| 3463 | _ = rhs_ty; | 3480 | _ = rhs_ty; |
| 3464 | _ = maybe_inst; | 3481 | _ = maybe_inst; |
| 3465 | 3482 | ||
| 3466 | switch (lhs_ty.zigTypeTag()) { | 3483 | const mod = self.bin_file.options.module.?; |
| 3484 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 3467 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | 3485 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 3468 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3486 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3469 | else => unreachable, | 3487 | else => unreachable, |
| ... | @@ -3479,12 +3497,12 @@ fn divTrunc( | ... | @@ -3479,12 +3497,12 @@ fn divTrunc( |
| 3479 | maybe_inst: ?Air.Inst.Index, | 3497 | maybe_inst: ?Air.Inst.Index, |
| 3480 | ) InnerError!MCValue { | 3498 | ) InnerError!MCValue { |
| 3481 | const mod = self.bin_file.options.module.?; | 3499 | const mod = self.bin_file.options.module.?; |
| 3482 | switch (lhs_ty.zigTypeTag()) { | 3500 | switch (lhs_ty.zigTypeTag(mod)) { |
| 3483 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | 3501 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 3484 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3502 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3485 | .Int => { | 3503 | .Int => { |
| 3486 | assert(lhs_ty.eql(rhs_ty, mod)); | 3504 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 3487 | const int_info = lhs_ty.intInfo(self.target.*); | 3505 | const int_info = lhs_ty.intInfo(mod); |
| 3488 | if (int_info.bits <= 32) { | 3506 | if (int_info.bits <= 32) { |
| 3489 | switch (int_info.signedness) { | 3507 | switch (int_info.signedness) { |
| 3490 | .signed => { | 3508 | .signed => { |
| ... | @@ -3522,12 +3540,12 @@ fn divFloor( | ... | @@ -3522,12 +3540,12 @@ fn divFloor( |
| 3522 | maybe_inst: ?Air.Inst.Index, | 3540 | maybe_inst: ?Air.Inst.Index, |
| 3523 | ) InnerError!MCValue { | 3541 | ) InnerError!MCValue { |
| 3524 | const mod = self.bin_file.options.module.?; | 3542 | const mod = self.bin_file.options.module.?; |
| 3525 | switch (lhs_ty.zigTypeTag()) { | 3543 | switch (lhs_ty.zigTypeTag(mod)) { |
| 3526 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | 3544 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 3527 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3545 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3528 | .Int => { | 3546 | .Int => { |
| 3529 | assert(lhs_ty.eql(rhs_ty, mod)); | 3547 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 3530 | const int_info = lhs_ty.intInfo(self.target.*); | 3548 | const int_info = lhs_ty.intInfo(mod); |
| 3531 | if (int_info.bits <= 32) { | 3549 | if (int_info.bits <= 32) { |
| 3532 | switch (int_info.signedness) { | 3550 | switch (int_info.signedness) { |
| 3533 | .signed => { | 3551 | .signed => { |
| ... | @@ -3569,7 +3587,8 @@ fn divExact( | ... | @@ -3569,7 +3587,8 @@ fn divExact( |
| 3569 | _ = rhs_ty; | 3587 | _ = rhs_ty; |
| 3570 | _ = maybe_inst; | 3588 | _ = maybe_inst; |
| 3571 | 3589 | ||
| 3572 | switch (lhs_ty.zigTypeTag()) { | 3590 | const mod = self.bin_file.options.module.?; |
| 3591 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 3573 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | 3592 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 3574 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3593 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3575 | .Int => return self.fail("TODO ARM div_exact", .{}), | 3594 | .Int => return self.fail("TODO ARM div_exact", .{}), |
| ... | @@ -3586,12 +3605,12 @@ fn rem( | ... | @@ -3586,12 +3605,12 @@ fn rem( |
| 3586 | maybe_inst: ?Air.Inst.Index, | 3605 | maybe_inst: ?Air.Inst.Index, |
| 3587 | ) InnerError!MCValue { | 3606 | ) InnerError!MCValue { |
| 3588 | const mod = self.bin_file.options.module.?; | 3607 | const mod = self.bin_file.options.module.?; |
| 3589 | switch (lhs_ty.zigTypeTag()) { | 3608 | switch (lhs_ty.zigTypeTag(mod)) { |
| 3590 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | 3609 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 3591 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3610 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3592 | .Int => { | 3611 | .Int => { |
| 3593 | assert(lhs_ty.eql(rhs_ty, mod)); | 3612 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 3594 | const int_info = lhs_ty.intInfo(self.target.*); | 3613 | const int_info = lhs_ty.intInfo(mod); |
| 3595 | if (int_info.bits <= 32) { | 3614 | if (int_info.bits <= 32) { |
| 3596 | switch (int_info.signedness) { | 3615 | switch (int_info.signedness) { |
| 3597 | .signed => { | 3616 | .signed => { |
| ... | @@ -3654,7 +3673,8 @@ fn modulo( | ... | @@ -3654,7 +3673,8 @@ fn modulo( |
| 3654 | _ = rhs_ty; | 3673 | _ = rhs_ty; |
| 3655 | _ = maybe_inst; | 3674 | _ = maybe_inst; |
| 3656 | 3675 | ||
| 3657 | switch (lhs_ty.zigTypeTag()) { | 3676 | const mod = self.bin_file.options.module.?; |
| 3677 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 3658 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | 3678 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 3659 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3679 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3660 | .Int => return self.fail("TODO ARM mod", .{}), | 3680 | .Int => return self.fail("TODO ARM mod", .{}), |
| ... | @@ -3671,10 +3691,11 @@ fn wrappingArithmetic( | ... | @@ -3671,10 +3691,11 @@ fn wrappingArithmetic( |
| 3671 | rhs_ty: Type, | 3691 | rhs_ty: Type, |
| 3672 | maybe_inst: ?Air.Inst.Index, | 3692 | maybe_inst: ?Air.Inst.Index, |
| 3673 | ) InnerError!MCValue { | 3693 | ) InnerError!MCValue { |
| 3674 | switch (lhs_ty.zigTypeTag()) { | 3694 | const mod = self.bin_file.options.module.?; |
| 3695 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 3675 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3696 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3676 | .Int => { | 3697 | .Int => { |
| 3677 | const int_info = lhs_ty.intInfo(self.target.*); | 3698 | const int_info = lhs_ty.intInfo(mod); |
| 3678 | if (int_info.bits <= 32) { | 3699 | if (int_info.bits <= 32) { |
| 3679 | // Generate an add/sub/mul | 3700 | // Generate an add/sub/mul |
| 3680 | const result: MCValue = switch (tag) { | 3701 | const result: MCValue = switch (tag) { |
| ... | @@ -3708,12 +3729,12 @@ fn bitwise( | ... | @@ -3708,12 +3729,12 @@ fn bitwise( |
| 3708 | rhs_ty: Type, | 3729 | rhs_ty: Type, |
| 3709 | maybe_inst: ?Air.Inst.Index, | 3730 | maybe_inst: ?Air.Inst.Index, |
| 3710 | ) InnerError!MCValue { | 3731 | ) InnerError!MCValue { |
| 3711 | switch (lhs_ty.zigTypeTag()) { | 3732 | const mod = self.bin_file.options.module.?; |
| 3733 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 3712 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3734 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3713 | .Int => { | 3735 | .Int => { |
| 3714 | const mod = self.bin_file.options.module.?; | ||
| 3715 | assert(lhs_ty.eql(rhs_ty, mod)); | 3736 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 3716 | const int_info = lhs_ty.intInfo(self.target.*); | 3737 | const int_info = lhs_ty.intInfo(mod); |
| 3717 | if (int_info.bits <= 32) { | 3738 | if (int_info.bits <= 32) { |
| 3718 | const lhs_immediate = try lhs_bind.resolveToImmediate(self); | 3739 | const lhs_immediate = try lhs_bind.resolveToImmediate(self); |
| 3719 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); | 3740 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); |
| ... | @@ -3753,16 +3774,17 @@ fn shiftExact( | ... | @@ -3753,16 +3774,17 @@ fn shiftExact( |
| 3753 | rhs_ty: Type, | 3774 | rhs_ty: Type, |
| 3754 | maybe_inst: ?Air.Inst.Index, | 3775 | maybe_inst: ?Air.Inst.Index, |
| 3755 | ) InnerError!MCValue { | 3776 | ) InnerError!MCValue { |
| 3756 | switch (lhs_ty.zigTypeTag()) { | 3777 | const mod = self.bin_file.options.module.?; |
| 3778 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 3757 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3779 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3758 | .Int => { | 3780 | .Int => { |
| 3759 | const int_info = lhs_ty.intInfo(self.target.*); | 3781 | const int_info = lhs_ty.intInfo(mod); |
| 3760 | if (int_info.bits <= 32) { | 3782 | if (int_info.bits <= 32) { |
| 3761 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); | 3783 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); |
| 3762 | 3784 | ||
| 3763 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 3785 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 3764 | .shl_exact => .lsl, | 3786 | .shl_exact => .lsl, |
| 3765 | .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) { | 3787 | .shr_exact => switch (lhs_ty.intInfo(mod).signedness) { |
| 3766 | .signed => Mir.Inst.Tag.asr, | 3788 | .signed => Mir.Inst.Tag.asr, |
| 3767 | .unsigned => Mir.Inst.Tag.lsr, | 3789 | .unsigned => Mir.Inst.Tag.lsr, |
| 3768 | }, | 3790 | }, |
| ... | @@ -3791,10 +3813,11 @@ fn shiftNormal( | ... | @@ -3791,10 +3813,11 @@ fn shiftNormal( |
| 3791 | rhs_ty: Type, | 3813 | rhs_ty: Type, |
| 3792 | maybe_inst: ?Air.Inst.Index, | 3814 | maybe_inst: ?Air.Inst.Index, |
| 3793 | ) InnerError!MCValue { | 3815 | ) InnerError!MCValue { |
| 3794 | switch (lhs_ty.zigTypeTag()) { | 3816 | const mod = self.bin_file.options.module.?; |
| 3817 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 3795 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 3818 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 3796 | .Int => { | 3819 | .Int => { |
| 3797 | const int_info = lhs_ty.intInfo(self.target.*); | 3820 | const int_info = lhs_ty.intInfo(mod); |
| 3798 | if (int_info.bits <= 32) { | 3821 | if (int_info.bits <= 32) { |
| 3799 | // Generate a shl_exact/shr_exact | 3822 | // Generate a shl_exact/shr_exact |
| 3800 | const result: MCValue = switch (tag) { | 3823 | const result: MCValue = switch (tag) { |
| ... | @@ -3833,7 +3856,8 @@ fn booleanOp( | ... | @@ -3833,7 +3856,8 @@ fn booleanOp( |
| 3833 | rhs_ty: Type, | 3856 | rhs_ty: Type, |
| 3834 | maybe_inst: ?Air.Inst.Index, | 3857 | maybe_inst: ?Air.Inst.Index, |
| 3835 | ) InnerError!MCValue { | 3858 | ) InnerError!MCValue { |
| 3836 | switch (lhs_ty.zigTypeTag()) { | 3859 | const mod = self.bin_file.options.module.?; |
| 3860 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 3837 | .Bool => { | 3861 | .Bool => { |
| 3838 | const lhs_immediate = try lhs_bind.resolveToImmediate(self); | 3862 | const lhs_immediate = try lhs_bind.resolveToImmediate(self); |
| 3839 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); | 3863 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); |
| ... | @@ -3866,9 +3890,9 @@ fn ptrArithmetic( | ... | @@ -3866,9 +3890,9 @@ fn ptrArithmetic( |
| 3866 | rhs_ty: Type, | 3890 | rhs_ty: Type, |
| 3867 | maybe_inst: ?Air.Inst.Index, | 3891 | maybe_inst: ?Air.Inst.Index, |
| 3868 | ) InnerError!MCValue { | 3892 | ) InnerError!MCValue { |
| 3869 | switch (lhs_ty.zigTypeTag()) { | 3893 | const mod = self.bin_file.options.module.?; |
| 3894 | switch (lhs_ty.zigTypeTag(mod)) { | ||
| 3870 | .Pointer => { | 3895 | .Pointer => { |
| 3871 | const mod = self.bin_file.options.module.?; | ||
| 3872 | assert(rhs_ty.eql(Type.usize, mod)); | 3896 | assert(rhs_ty.eql(Type.usize, mod)); |
| 3873 | 3897 | ||
| 3874 | const ptr_ty = lhs_ty; | 3898 | const ptr_ty = lhs_ty; |
| ... | @@ -3876,7 +3900,7 @@ fn ptrArithmetic( | ... | @@ -3876,7 +3900,7 @@ fn ptrArithmetic( |
| 3876 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type | 3900 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type |
| 3877 | else => ptr_ty.childType(), | 3901 | else => ptr_ty.childType(), |
| 3878 | }; | 3902 | }; |
| 3879 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | 3903 | const elem_size = @intCast(u32, elem_ty.abiSize(mod)); |
| 3880 | 3904 | ||
| 3881 | const base_tag: Air.Inst.Tag = switch (tag) { | 3905 | const base_tag: Air.Inst.Tag = switch (tag) { |
| 3882 | .ptr_add => .add, | 3906 | .ptr_add => .add, |
| ... | @@ -3903,11 +3927,12 @@ fn ptrArithmetic( | ... | @@ -3903,11 +3927,12 @@ fn ptrArithmetic( |
| 3903 | } | 3927 | } |
| 3904 | 3928 | ||
| 3905 | fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void { | 3929 | fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void { |
| 3906 | const abi_size = ty.abiSize(self.target.*); | 3930 | const mod = self.bin_file.options.module.?; |
| 3931 | const abi_size = ty.abiSize(mod); | ||
| 3907 | 3932 | ||
| 3908 | const tag: Mir.Inst.Tag = switch (abi_size) { | 3933 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3909 | 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb else .ldrb, | 3934 | 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb else .ldrb, |
| 3910 | 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh else .ldrh, | 3935 | 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh else .ldrh, |
| 3911 | 3, 4 => .ldr, | 3936 | 3, 4 => .ldr, |
| 3912 | else => unreachable, | 3937 | else => unreachable, |
| 3913 | }; | 3938 | }; |
| ... | @@ -3924,7 +3949,7 @@ fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) | ... | @@ -3924,7 +3949,7 @@ fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) |
| 3924 | } }; | 3949 | } }; |
| 3925 | 3950 | ||
| 3926 | const data: Mir.Inst.Data = switch (abi_size) { | 3951 | const data: Mir.Inst.Data = switch (abi_size) { |
| 3927 | 1 => if (ty.isSignedInt()) rr_extra_offset else rr_offset, | 3952 | 1 => if (ty.isSignedInt(mod)) rr_extra_offset else rr_offset, |
| 3928 | 2 => rr_extra_offset, | 3953 | 2 => rr_extra_offset, |
| 3929 | 3, 4 => rr_offset, | 3954 | 3, 4 => rr_offset, |
| 3930 | else => unreachable, | 3955 | else => unreachable, |
| ... | @@ -3937,7 +3962,8 @@ fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) | ... | @@ -3937,7 +3962,8 @@ fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) |
| 3937 | } | 3962 | } |
| 3938 | 3963 | ||
| 3939 | fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Type) !void { | 3964 | fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Type) !void { |
| 3940 | const abi_size = ty.abiSize(self.target.*); | 3965 | const mod = self.bin_file.options.module.?; |
| 3966 | const abi_size = ty.abiSize(mod); | ||
| 3941 | 3967 | ||
| 3942 | const tag: Mir.Inst.Tag = switch (abi_size) { | 3968 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3943 | 1 => .strb, | 3969 | 1 => .strb, |
| ... | @@ -4197,8 +4223,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4197,8 +4223,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4197 | const extra = self.air.extraData(Air.Call, pl_op.payload); | 4223 | const extra = self.air.extraData(Air.Call, pl_op.payload); |
| 4198 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); | 4224 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); |
| 4199 | const ty = self.air.typeOf(callee); | 4225 | const ty = self.air.typeOf(callee); |
| 4226 | const mod = self.bin_file.options.module.?; | ||
| 4200 | 4227 | ||
| 4201 | const fn_ty = switch (ty.zigTypeTag()) { | 4228 | const fn_ty = switch (ty.zigTypeTag(mod)) { |
| 4202 | .Fn => ty, | 4229 | .Fn => ty, |
| 4203 | .Pointer => ty.childType(), | 4230 | .Pointer => ty.childType(), |
| 4204 | else => unreachable, | 4231 | else => unreachable, |
| ... | @@ -4226,8 +4253,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4226,8 +4253,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4226 | const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: { | 4253 | const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: { |
| 4227 | log.debug("airCall: return by reference", .{}); | 4254 | log.debug("airCall: return by reference", .{}); |
| 4228 | const ret_ty = fn_ty.fnReturnType(); | 4255 | const ret_ty = fn_ty.fnReturnType(); |
| 4229 | const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 4256 | const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod)); |
| 4230 | const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*)); | 4257 | const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod)); |
| 4231 | const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst); | 4258 | const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst); |
| 4232 | 4259 | ||
| 4233 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 4260 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| ... | @@ -4270,7 +4297,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4270,7 +4297,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4270 | 4297 | ||
| 4271 | // Due to incremental compilation, how function calls are generated depends | 4298 | // Due to incremental compilation, how function calls are generated depends |
| 4272 | // on linking. | 4299 | // on linking. |
| 4273 | if (self.air.value(callee)) |func_value| { | 4300 | if (self.air.value(callee, mod)) |func_value| { |
| 4274 | if (func_value.castTag(.function)) |func_payload| { | 4301 | if (func_value.castTag(.function)) |func_payload| { |
| 4275 | const func = func_payload.data; | 4302 | const func = func_payload.data; |
| 4276 | 4303 | ||
| ... | @@ -4294,7 +4321,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4294,7 +4321,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4294 | return self.fail("TODO implement calling bitcasted functions", .{}); | 4321 | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 4295 | } | 4322 | } |
| 4296 | } else { | 4323 | } else { |
| 4297 | assert(ty.zigTypeTag() == .Pointer); | 4324 | assert(ty.zigTypeTag(mod) == .Pointer); |
| 4298 | const mcv = try self.resolveInst(callee); | 4325 | const mcv = try self.resolveInst(callee); |
| 4299 | 4326 | ||
| 4300 | try self.genSetReg(Type.initTag(.usize), .lr, mcv); | 4327 | try self.genSetReg(Type.initTag(.usize), .lr, mcv); |
| ... | @@ -4356,11 +4383,12 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4356,11 +4383,12 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 4356 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 4383 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4357 | const operand = try self.resolveInst(un_op); | 4384 | const operand = try self.resolveInst(un_op); |
| 4358 | const ret_ty = self.fn_type.fnReturnType(); | 4385 | const ret_ty = self.fn_type.fnReturnType(); |
| 4386 | const mod = self.bin_file.options.module.?; | ||
| 4359 | 4387 | ||
| 4360 | switch (self.ret_mcv) { | 4388 | switch (self.ret_mcv) { |
| 4361 | .none => {}, | 4389 | .none => {}, |
| 4362 | .immediate => { | 4390 | .immediate => { |
| 4363 | assert(ret_ty.isError()); | 4391 | assert(ret_ty.isError(mod)); |
| 4364 | }, | 4392 | }, |
| 4365 | .register => |reg| { | 4393 | .register => |reg| { |
| 4366 | // Return result by value | 4394 | // Return result by value |
| ... | @@ -4411,8 +4439,9 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4411,8 +4439,9 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 4411 | // location. | 4439 | // location. |
| 4412 | const op_inst = Air.refToIndex(un_op).?; | 4440 | const op_inst = Air.refToIndex(un_op).?; |
| 4413 | if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) { | 4441 | if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) { |
| 4414 | const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 4442 | const mod = self.bin_file.options.module.?; |
| 4415 | const abi_align = ret_ty.abiAlignment(self.target.*); | 4443 | const abi_size = @intCast(u32, ret_ty.abiSize(mod)); |
| 4444 | const abi_align = ret_ty.abiAlignment(mod); | ||
| 4416 | 4445 | ||
| 4417 | const offset = try self.allocMem(abi_size, abi_align, null); | 4446 | const offset = try self.allocMem(abi_size, abi_align, null); |
| 4418 | 4447 | ||
| ... | @@ -4448,21 +4477,21 @@ fn cmp( | ... | @@ -4448,21 +4477,21 @@ fn cmp( |
| 4448 | lhs_ty: Type, | 4477 | lhs_ty: Type, |
| 4449 | op: math.CompareOperator, | 4478 | op: math.CompareOperator, |
| 4450 | ) !MCValue { | 4479 | ) !MCValue { |
| 4451 | var int_buffer: Type.Payload.Bits = undefined; | 4480 | const mod = self.bin_file.options.module.?; |
| 4452 | const int_ty = switch (lhs_ty.zigTypeTag()) { | 4481 | const int_ty = switch (lhs_ty.zigTypeTag(mod)) { |
| 4453 | .Optional => blk: { | 4482 | .Optional => blk: { |
| 4454 | var opt_buffer: Type.Payload.ElemType = undefined; | 4483 | var opt_buffer: Type.Payload.ElemType = undefined; |
| 4455 | const payload_ty = lhs_ty.optionalChild(&opt_buffer); | 4484 | const payload_ty = lhs_ty.optionalChild(&opt_buffer); |
| 4456 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 4485 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4457 | break :blk Type.initTag(.u1); | 4486 | break :blk Type.initTag(.u1); |
| 4458 | } else if (lhs_ty.isPtrLikeOptional()) { | 4487 | } else if (lhs_ty.isPtrLikeOptional(mod)) { |
| 4459 | break :blk Type.usize; | 4488 | break :blk Type.usize; |
| 4460 | } else { | 4489 | } else { |
| 4461 | return self.fail("TODO ARM cmp non-pointer optionals", .{}); | 4490 | return self.fail("TODO ARM cmp non-pointer optionals", .{}); |
| 4462 | } | 4491 | } |
| 4463 | }, | 4492 | }, |
| 4464 | .Float => return self.fail("TODO ARM cmp floats", .{}), | 4493 | .Float => return self.fail("TODO ARM cmp floats", .{}), |
| 4465 | .Enum => lhs_ty.intTagType(&int_buffer), | 4494 | .Enum => lhs_ty.intTagType(), |
| 4466 | .Int => lhs_ty, | 4495 | .Int => lhs_ty, |
| 4467 | .Bool => Type.initTag(.u1), | 4496 | .Bool => Type.initTag(.u1), |
| 4468 | .Pointer => Type.usize, | 4497 | .Pointer => Type.usize, |
| ... | @@ -4470,7 +4499,7 @@ fn cmp( | ... | @@ -4470,7 +4499,7 @@ fn cmp( |
| 4470 | else => unreachable, | 4499 | else => unreachable, |
| 4471 | }; | 4500 | }; |
| 4472 | 4501 | ||
| 4473 | const int_info = int_ty.intInfo(self.target.*); | 4502 | const int_info = int_ty.intInfo(mod); |
| 4474 | if (int_info.bits <= 32) { | 4503 | if (int_info.bits <= 32) { |
| 4475 | try self.spillCompareFlagsIfOccupied(); | 4504 | try self.spillCompareFlagsIfOccupied(); |
| 4476 | 4505 | ||
| ... | @@ -4636,8 +4665,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4636,8 +4665,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 4636 | // whether it needs to be spilled in the branches | 4665 | // whether it needs to be spilled in the branches |
| 4637 | if (self.liveness.operandDies(inst, 0)) { | 4666 | if (self.liveness.operandDies(inst, 0)) { |
| 4638 | const op_int = @enumToInt(pl_op.operand); | 4667 | const op_int = @enumToInt(pl_op.operand); |
| 4639 | if (op_int >= Air.Inst.Ref.typed_value_map.len) { | 4668 | if (op_int >= Air.ref_start_index) { |
| 4640 | const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len); | 4669 | const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index); |
| 4641 | self.processDeath(op_index); | 4670 | self.processDeath(op_index); |
| 4642 | } | 4671 | } |
| 4643 | } | 4672 | } |
| ... | @@ -4772,8 +4801,9 @@ fn isNull( | ... | @@ -4772,8 +4801,9 @@ fn isNull( |
| 4772 | operand_bind: ReadArg.Bind, | 4801 | operand_bind: ReadArg.Bind, |
| 4773 | operand_ty: Type, | 4802 | operand_ty: Type, |
| 4774 | ) !MCValue { | 4803 | ) !MCValue { |
| 4775 | if (operand_ty.isPtrLikeOptional()) { | 4804 | const mod = self.bin_file.options.module.?; |
| 4776 | assert(operand_ty.abiSize(self.target.*) == 4); | 4805 | if (operand_ty.isPtrLikeOptional(mod)) { |
| 4806 | assert(operand_ty.abiSize(mod) == 4); | ||
| 4777 | 4807 | ||
| 4778 | const imm_bind: ReadArg.Bind = .{ .mcv = .{ .immediate = 0 } }; | 4808 | const imm_bind: ReadArg.Bind = .{ .mcv = .{ .immediate = 0 } }; |
| 4779 | return self.cmp(operand_bind, imm_bind, Type.usize, .eq); | 4809 | return self.cmp(operand_bind, imm_bind, Type.usize, .eq); |
| ... | @@ -5131,9 +5161,10 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5131,9 +5161,10 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 5131 | } | 5161 | } |
| 5132 | 5162 | ||
| 5133 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { | 5163 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 5164 | const mod = self.bin_file.options.module.?; | ||
| 5134 | const block_data = self.blocks.getPtr(block).?; | 5165 | const block_data = self.blocks.getPtr(block).?; |
| 5135 | 5166 | ||
| 5136 | if (self.air.typeOf(operand).hasRuntimeBits()) { | 5167 | if (self.air.typeOf(operand).hasRuntimeBits(mod)) { |
| 5137 | const operand_mcv = try self.resolveInst(operand); | 5168 | const operand_mcv = try self.resolveInst(operand); |
| 5138 | const block_mcv = block_data.mcv; | 5169 | const block_mcv = block_data.mcv; |
| 5139 | if (block_mcv == .none) { | 5170 | if (block_mcv == .none) { |
| ... | @@ -5301,7 +5332,8 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { | ... | @@ -5301,7 +5332,8 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { |
| 5301 | } | 5332 | } |
| 5302 | 5333 | ||
| 5303 | fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { | 5334 | fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { |
| 5304 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 5335 | const mod = self.bin_file.options.module.?; |
| 5336 | const abi_size = @intCast(u32, ty.abiSize(mod)); | ||
| 5305 | switch (mcv) { | 5337 | switch (mcv) { |
| 5306 | .dead => unreachable, | 5338 | .dead => unreachable, |
| 5307 | .unreach, .none => return, // Nothing to do. | 5339 | .unreach, .none => return, // Nothing to do. |
| ... | @@ -5382,7 +5414,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -5382,7 +5414,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5382 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg }); | 5414 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg }); |
| 5383 | 5415 | ||
| 5384 | const overflow_bit_ty = ty.structFieldType(1); | 5416 | const overflow_bit_ty = ty.structFieldType(1); |
| 5385 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*)); | 5417 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); |
| 5386 | const cond_reg = try self.register_manager.allocReg(null, gp); | 5418 | const cond_reg = try self.register_manager.allocReg(null, gp); |
| 5387 | 5419 | ||
| 5388 | // C flag: movcs reg, #1 | 5420 | // C flag: movcs reg, #1 |
| ... | @@ -5466,6 +5498,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -5466,6 +5498,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5466 | } | 5498 | } |
| 5467 | 5499 | ||
| 5468 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { | 5500 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { |
| 5501 | const mod = self.bin_file.options.module.?; | ||
| 5469 | switch (mcv) { | 5502 | switch (mcv) { |
| 5470 | .dead => unreachable, | 5503 | .dead => unreachable, |
| 5471 | .unreach, .none => return, // Nothing to do. | 5504 | .unreach, .none => return, // Nothing to do. |
| ... | @@ -5640,17 +5673,17 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -5640,17 +5673,17 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5640 | }, | 5673 | }, |
| 5641 | .stack_offset => |off| { | 5674 | .stack_offset => |off| { |
| 5642 | // TODO: maybe addressing from sp instead of fp | 5675 | // TODO: maybe addressing from sp instead of fp |
| 5643 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 5676 | const abi_size = @intCast(u32, ty.abiSize(mod)); |
| 5644 | 5677 | ||
| 5645 | const tag: Mir.Inst.Tag = switch (abi_size) { | 5678 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 5646 | 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb else .ldrb, | 5679 | 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb else .ldrb, |
| 5647 | 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh else .ldrh, | 5680 | 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh else .ldrh, |
| 5648 | 3, 4 => .ldr, | 5681 | 3, 4 => .ldr, |
| 5649 | else => unreachable, | 5682 | else => unreachable, |
| 5650 | }; | 5683 | }; |
| 5651 | 5684 | ||
| 5652 | const extra_offset = switch (abi_size) { | 5685 | const extra_offset = switch (abi_size) { |
| 5653 | 1 => ty.isSignedInt(), | 5686 | 1 => ty.isSignedInt(mod), |
| 5654 | 2 => true, | 5687 | 2 => true, |
| 5655 | 3, 4 => false, | 5688 | 3, 4 => false, |
| 5656 | else => unreachable, | 5689 | else => unreachable, |
| ... | @@ -5691,11 +5724,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -5691,11 +5724,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5691 | } | 5724 | } |
| 5692 | }, | 5725 | }, |
| 5693 | .stack_argument_offset => |off| { | 5726 | .stack_argument_offset => |off| { |
| 5694 | const abi_size = ty.abiSize(self.target.*); | 5727 | const abi_size = ty.abiSize(mod); |
| 5695 | 5728 | ||
| 5696 | const tag: Mir.Inst.Tag = switch (abi_size) { | 5729 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 5697 | 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument, | 5730 | 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument, |
| 5698 | 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument, | 5731 | 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument, |
| 5699 | 3, 4 => .ldr_stack_argument, | 5732 | 3, 4 => .ldr_stack_argument, |
| 5700 | else => unreachable, | 5733 | else => unreachable, |
| 5701 | }; | 5734 | }; |
| ... | @@ -5712,7 +5745,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -5712,7 +5745,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5712 | } | 5745 | } |
| 5713 | 5746 | ||
| 5714 | fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { | 5747 | fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { |
| 5715 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 5748 | const mod = self.bin_file.options.module.?; |
| 5749 | const abi_size = @intCast(u32, ty.abiSize(mod)); | ||
| 5716 | switch (mcv) { | 5750 | switch (mcv) { |
| 5717 | .dead => unreachable, | 5751 | .dead => unreachable, |
| 5718 | .none, .unreach => return, | 5752 | .none, .unreach => return, |
| ... | @@ -6039,8 +6073,9 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6039,8 +6073,9 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void { |
| 6039 | const result: MCValue = result: { | 6073 | const result: MCValue = result: { |
| 6040 | const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand }; | 6074 | const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand }; |
| 6041 | const error_union_ty = self.air.typeOf(pl_op.operand); | 6075 | const error_union_ty = self.air.typeOf(pl_op.operand); |
| 6042 | const error_union_size = @intCast(u32, error_union_ty.abiSize(self.target.*)); | 6076 | const mod = self.bin_file.options.module.?; |
| 6043 | const error_union_align = error_union_ty.abiAlignment(self.target.*); | 6077 | const error_union_size = @intCast(u32, error_union_ty.abiSize(mod)); |
| 6078 | const error_union_align = error_union_ty.abiAlignment(mod); | ||
| 6044 | 6079 | ||
| 6045 | // The error union will die in the body. However, we need the | 6080 | // The error union will die in the body. However, we need the |
| 6046 | // error union after the body in order to extract the payload | 6081 | // error union after the body in order to extract the payload |
| ... | @@ -6069,22 +6104,18 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6069,22 +6104,18 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6069 | } | 6104 | } |
| 6070 | 6105 | ||
| 6071 | fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { | 6106 | fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { |
| 6072 | // First section of indexes correspond to a set number of constant values. | 6107 | const mod = self.bin_file.options.module.?; |
| 6073 | const ref_int = @enumToInt(inst); | ||
| 6074 | if (ref_int < Air.Inst.Ref.typed_value_map.len) { | ||
| 6075 | const tv = Air.Inst.Ref.typed_value_map[ref_int]; | ||
| 6076 | if (!tv.ty.hasRuntimeBitsIgnoreComptime() and !tv.ty.isError()) { | ||
| 6077 | return MCValue{ .none = {} }; | ||
| 6078 | } | ||
| 6079 | return self.genTypedValue(tv); | ||
| 6080 | } | ||
| 6081 | 6108 | ||
| 6082 | // If the type has no codegen bits, no need to store it. | 6109 | // If the type has no codegen bits, no need to store it. |
| 6083 | const inst_ty = self.air.typeOf(inst); | 6110 | const inst_ty = self.air.typeOf(inst); |
| 6084 | if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError()) | 6111 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod)) |
| 6085 | return MCValue{ .none = {} }; | 6112 | return MCValue{ .none = {} }; |
| 6086 | 6113 | ||
| 6087 | const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len); | 6114 | const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{ |
| 6115 | .ty = inst_ty, | ||
| 6116 | .val = self.air.value(inst, mod).?, | ||
| 6117 | }); | ||
| 6118 | |||
| 6088 | switch (self.air.instructions.items(.tag)[inst_index]) { | 6119 | switch (self.air.instructions.items(.tag)[inst_index]) { |
| 6089 | .constant => { | 6120 | .constant => { |
| 6090 | // Constants have static lifetimes, so they are always memoized in the outer most table. | 6121 | // Constants have static lifetimes, so they are always memoized in the outer most table. |
| ... | @@ -6166,6 +6197,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6166,6 +6197,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6166 | errdefer self.gpa.free(result.args); | 6197 | errdefer self.gpa.free(result.args); |
| 6167 | 6198 | ||
| 6168 | const ret_ty = fn_ty.fnReturnType(); | 6199 | const ret_ty = fn_ty.fnReturnType(); |
| 6200 | const mod = self.bin_file.options.module.?; | ||
| 6169 | 6201 | ||
| 6170 | switch (cc) { | 6202 | switch (cc) { |
| 6171 | .Naked => { | 6203 | .Naked => { |
| ... | @@ -6180,12 +6212,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6180,12 +6212,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6180 | var ncrn: usize = 0; // Next Core Register Number | 6212 | var ncrn: usize = 0; // Next Core Register Number |
| 6181 | var nsaa: u32 = 0; // Next stacked argument address | 6213 | var nsaa: u32 = 0; // Next stacked argument address |
| 6182 | 6214 | ||
| 6183 | if (ret_ty.zigTypeTag() == .NoReturn) { | 6215 | if (ret_ty.zigTypeTag(mod) == .NoReturn) { |
| 6184 | result.return_value = .{ .unreach = {} }; | 6216 | result.return_value = .{ .unreach = {} }; |
| 6185 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime()) { | 6217 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6186 | result.return_value = .{ .none = {} }; | 6218 | result.return_value = .{ .none = {} }; |
| 6187 | } else { | 6219 | } else { |
| 6188 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 6220 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod)); |
| 6189 | // TODO handle cases where multiple registers are used | 6221 | // TODO handle cases where multiple registers are used |
| 6190 | if (ret_ty_size <= 4) { | 6222 | if (ret_ty_size <= 4) { |
| 6191 | result.return_value = .{ .register = c_abi_int_return_regs[0] }; | 6223 | result.return_value = .{ .register = c_abi_int_return_regs[0] }; |
| ... | @@ -6200,10 +6232,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6200,10 +6232,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6200 | } | 6232 | } |
| 6201 | 6233 | ||
| 6202 | for (param_types, 0..) |ty, i| { | 6234 | for (param_types, 0..) |ty, i| { |
| 6203 | if (ty.abiAlignment(self.target.*) == 8) | 6235 | if (ty.abiAlignment(mod) == 8) |
| 6204 | ncrn = std.mem.alignForwardGeneric(usize, ncrn, 2); | 6236 | ncrn = std.mem.alignForwardGeneric(usize, ncrn, 2); |
| 6205 | 6237 | ||
| 6206 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); | 6238 | const param_size = @intCast(u32, ty.abiSize(mod)); |
| 6207 | if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) { | 6239 | if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) { |
| 6208 | if (param_size <= 4) { | 6240 | if (param_size <= 4) { |
| 6209 | result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] }; | 6241 | result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] }; |
| ... | @@ -6215,7 +6247,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6215,7 +6247,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6215 | return self.fail("TODO MCValues split between registers and stack", .{}); | 6247 | return self.fail("TODO MCValues split between registers and stack", .{}); |
| 6216 | } else { | 6248 | } else { |
| 6217 | ncrn = 4; | 6249 | ncrn = 4; |
| 6218 | if (ty.abiAlignment(self.target.*) == 8) | 6250 | if (ty.abiAlignment(mod) == 8) |
| 6219 | nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8); | 6251 | nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8); |
| 6220 | 6252 | ||
| 6221 | result.args[i] = .{ .stack_argument_offset = nsaa }; | 6253 | result.args[i] = .{ .stack_argument_offset = nsaa }; |
| ... | @@ -6227,14 +6259,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6227,14 +6259,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6227 | result.stack_align = 8; | 6259 | result.stack_align = 8; |
| 6228 | }, | 6260 | }, |
| 6229 | .Unspecified => { | 6261 | .Unspecified => { |
| 6230 | if (ret_ty.zigTypeTag() == .NoReturn) { | 6262 | if (ret_ty.zigTypeTag(mod) == .NoReturn) { |
| 6231 | result.return_value = .{ .unreach = {} }; | 6263 | result.return_value = .{ .unreach = {} }; |
| 6232 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) { | 6264 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and !ret_ty.isError(mod)) { |
| 6233 | result.return_value = .{ .none = {} }; | 6265 | result.return_value = .{ .none = {} }; |
| 6234 | } else { | 6266 | } else { |
| 6235 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 6267 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod)); |
| 6236 | if (ret_ty_size == 0) { | 6268 | if (ret_ty_size == 0) { |
| 6237 | assert(ret_ty.isError()); | 6269 | assert(ret_ty.isError(mod)); |
| 6238 | result.return_value = .{ .immediate = 0 }; | 6270 | result.return_value = .{ .immediate = 0 }; |
| 6239 | } else if (ret_ty_size <= 4) { | 6271 | } else if (ret_ty_size <= 4) { |
| 6240 | result.return_value = .{ .register = .r0 }; | 6272 | result.return_value = .{ .register = .r0 }; |
| ... | @@ -6250,9 +6282,9 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -6250,9 +6282,9 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 6250 | var stack_offset: u32 = 0; | 6282 | var stack_offset: u32 = 0; |
| 6251 | 6283 | ||
| 6252 | for (param_types, 0..) |ty, i| { | 6284 | for (param_types, 0..) |ty, i| { |
| 6253 | if (ty.abiSize(self.target.*) > 0) { | 6285 | if (ty.abiSize(mod) > 0) { |
| 6254 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); | 6286 | const param_size = @intCast(u32, ty.abiSize(mod)); |
| 6255 | const param_alignment = ty.abiAlignment(self.target.*); | 6287 | const param_alignment = ty.abiAlignment(mod); |
| 6256 | 6288 | ||
| 6257 | stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment); | 6289 | stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment); |
| 6258 | result.args[i] = .{ .stack_argument_offset = stack_offset }; | 6290 | result.args[i] = .{ .stack_argument_offset = stack_offset }; |
src/arch/arm/abi.zig+22-19| ... | @@ -1,8 +1,10 @@ | ... | @@ -1,8 +1,10 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const assert = std.debug.assert; | ||
| 2 | const bits = @import("bits.zig"); | 3 | const bits = @import("bits.zig"); |
| 3 | const Register = bits.Register; | 4 | const Register = bits.Register; |
| 4 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; | 5 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; |
| 5 | const Type = @import("../../type.zig").Type; | 6 | const Type = @import("../../type.zig").Type; |
| 7 | const Module = @import("../../Module.zig"); | ||
| 6 | 8 | ||
| 7 | pub const Class = union(enum) { | 9 | pub const Class = union(enum) { |
| 8 | memory, | 10 | memory, |
| ... | @@ -22,28 +24,28 @@ pub const Class = union(enum) { | ... | @@ -22,28 +24,28 @@ pub const Class = union(enum) { |
| 22 | 24 | ||
| 23 | pub const Context = enum { ret, arg }; | 25 | pub const Context = enum { ret, arg }; |
| 24 | 26 | ||
| 25 | pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class { | 27 | pub fn classifyType(ty: Type, mod: *const Module, ctx: Context) Class { |
| 26 | std.debug.assert(ty.hasRuntimeBitsIgnoreComptime()); | 28 | assert(ty.hasRuntimeBitsIgnoreComptime(mod)); |
| 27 | 29 | ||
| 28 | var maybe_float_bits: ?u16 = null; | 30 | var maybe_float_bits: ?u16 = null; |
| 29 | const max_byval_size = 512; | 31 | const max_byval_size = 512; |
| 30 | switch (ty.zigTypeTag()) { | 32 | switch (ty.zigTypeTag(mod)) { |
| 31 | .Struct => { | 33 | .Struct => { |
| 32 | const bit_size = ty.bitSize(target); | 34 | const bit_size = ty.bitSize(mod); |
| 33 | if (ty.containerLayout() == .Packed) { | 35 | if (ty.containerLayout() == .Packed) { |
| 34 | if (bit_size > 64) return .memory; | 36 | if (bit_size > 64) return .memory; |
| 35 | return .byval; | 37 | return .byval; |
| 36 | } | 38 | } |
| 37 | if (bit_size > max_byval_size) return .memory; | 39 | if (bit_size > max_byval_size) return .memory; |
| 38 | const float_count = countFloats(ty, target, &maybe_float_bits); | 40 | const float_count = countFloats(ty, mod, &maybe_float_bits); |
| 39 | if (float_count <= byval_float_count) return .byval; | 41 | if (float_count <= byval_float_count) return .byval; |
| 40 | 42 | ||
| 41 | const fields = ty.structFieldCount(); | 43 | const fields = ty.structFieldCount(); |
| 42 | var i: u32 = 0; | 44 | var i: u32 = 0; |
| 43 | while (i < fields) : (i += 1) { | 45 | while (i < fields) : (i += 1) { |
| 44 | const field_ty = ty.structFieldType(i); | 46 | const field_ty = ty.structFieldType(i); |
| 45 | const field_alignment = ty.structFieldAlign(i, target); | 47 | const field_alignment = ty.structFieldAlign(i, mod); |
| 46 | const field_size = field_ty.bitSize(target); | 48 | const field_size = field_ty.bitSize(mod); |
| 47 | if (field_size > 32 or field_alignment > 32) { | 49 | if (field_size > 32 or field_alignment > 32) { |
| 48 | return Class.arrSize(bit_size, 64); | 50 | return Class.arrSize(bit_size, 64); |
| 49 | } | 51 | } |
| ... | @@ -51,17 +53,17 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class { | ... | @@ -51,17 +53,17 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class { |
| 51 | return Class.arrSize(bit_size, 32); | 53 | return Class.arrSize(bit_size, 32); |
| 52 | }, | 54 | }, |
| 53 | .Union => { | 55 | .Union => { |
| 54 | const bit_size = ty.bitSize(target); | 56 | const bit_size = ty.bitSize(mod); |
| 55 | if (ty.containerLayout() == .Packed) { | 57 | if (ty.containerLayout() == .Packed) { |
| 56 | if (bit_size > 64) return .memory; | 58 | if (bit_size > 64) return .memory; |
| 57 | return .byval; | 59 | return .byval; |
| 58 | } | 60 | } |
| 59 | if (bit_size > max_byval_size) return .memory; | 61 | if (bit_size > max_byval_size) return .memory; |
| 60 | const float_count = countFloats(ty, target, &maybe_float_bits); | 62 | const float_count = countFloats(ty, mod, &maybe_float_bits); |
| 61 | if (float_count <= byval_float_count) return .byval; | 63 | if (float_count <= byval_float_count) return .byval; |
| 62 | 64 | ||
| 63 | for (ty.unionFields().values()) |field| { | 65 | for (ty.unionFields().values()) |field| { |
| 64 | if (field.ty.bitSize(target) > 32 or field.normalAlignment(target) > 32) { | 66 | if (field.ty.bitSize(mod) > 32 or field.normalAlignment(mod) > 32) { |
| 65 | return Class.arrSize(bit_size, 64); | 67 | return Class.arrSize(bit_size, 64); |
| 66 | } | 68 | } |
| 67 | } | 69 | } |
| ... | @@ -71,28 +73,28 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class { | ... | @@ -71,28 +73,28 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class { |
| 71 | .Int => { | 73 | .Int => { |
| 72 | // TODO this is incorrect for _BitInt(128) but implementing | 74 | // TODO this is incorrect for _BitInt(128) but implementing |
| 73 | // this correctly makes implementing compiler-rt impossible. | 75 | // this correctly makes implementing compiler-rt impossible. |
| 74 | // const bit_size = ty.bitSize(target); | 76 | // const bit_size = ty.bitSize(mod); |
| 75 | // if (bit_size > 64) return .memory; | 77 | // if (bit_size > 64) return .memory; |
| 76 | return .byval; | 78 | return .byval; |
| 77 | }, | 79 | }, |
| 78 | .Enum, .ErrorSet => { | 80 | .Enum, .ErrorSet => { |
| 79 | const bit_size = ty.bitSize(target); | 81 | const bit_size = ty.bitSize(mod); |
| 80 | if (bit_size > 64) return .memory; | 82 | if (bit_size > 64) return .memory; |
| 81 | return .byval; | 83 | return .byval; |
| 82 | }, | 84 | }, |
| 83 | .Vector => { | 85 | .Vector => { |
| 84 | const bit_size = ty.bitSize(target); | 86 | const bit_size = ty.bitSize(mod); |
| 85 | // TODO is this controlled by a cpu feature? | 87 | // TODO is this controlled by a cpu feature? |
| 86 | if (ctx == .ret and bit_size > 128) return .memory; | 88 | if (ctx == .ret and bit_size > 128) return .memory; |
| 87 | if (bit_size > 512) return .memory; | 89 | if (bit_size > 512) return .memory; |
| 88 | return .byval; | 90 | return .byval; |
| 89 | }, | 91 | }, |
| 90 | .Optional => { | 92 | .Optional => { |
| 91 | std.debug.assert(ty.isPtrLikeOptional()); | 93 | assert(ty.isPtrLikeOptional(mod)); |
| 92 | return .byval; | 94 | return .byval; |
| 93 | }, | 95 | }, |
| 94 | .Pointer => { | 96 | .Pointer => { |
| 95 | std.debug.assert(!ty.isSlice()); | 97 | assert(!ty.isSlice()); |
| 96 | return .byval; | 98 | return .byval; |
| 97 | }, | 99 | }, |
| 98 | .ErrorUnion, | 100 | .ErrorUnion, |
| ... | @@ -114,14 +116,15 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class { | ... | @@ -114,14 +116,15 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class { |
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | const byval_float_count = 4; | 118 | const byval_float_count = 4; |
| 117 | fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 { | 119 | fn countFloats(ty: Type, mod: *const Module, maybe_float_bits: *?u16) u32 { |
| 120 | const target = mod.getTarget(); | ||
| 118 | const invalid = std.math.maxInt(u32); | 121 | const invalid = std.math.maxInt(u32); |
| 119 | switch (ty.zigTypeTag()) { | 122 | switch (ty.zigTypeTag(mod)) { |
| 120 | .Union => { | 123 | .Union => { |
| 121 | const fields = ty.unionFields(); | 124 | const fields = ty.unionFields(); |
| 122 | var max_count: u32 = 0; | 125 | var max_count: u32 = 0; |
| 123 | for (fields.values()) |field| { | 126 | for (fields.values()) |field| { |
| 124 | const field_count = countFloats(field.ty, target, maybe_float_bits); | 127 | const field_count = countFloats(field.ty, mod, maybe_float_bits); |
| 125 | if (field_count == invalid) return invalid; | 128 | if (field_count == invalid) return invalid; |
| 126 | if (field_count > max_count) max_count = field_count; | 129 | if (field_count > max_count) max_count = field_count; |
| 127 | if (max_count > byval_float_count) return invalid; | 130 | if (max_count > byval_float_count) return invalid; |
| ... | @@ -134,7 +137,7 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 { | ... | @@ -134,7 +137,7 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 { |
| 134 | var i: u32 = 0; | 137 | var i: u32 = 0; |
| 135 | while (i < fields_len) : (i += 1) { | 138 | while (i < fields_len) : (i += 1) { |
| 136 | const field_ty = ty.structFieldType(i); | 139 | const field_ty = ty.structFieldType(i); |
| 137 | const field_count = countFloats(field_ty, target, maybe_float_bits); | 140 | const field_count = countFloats(field_ty, mod, maybe_float_bits); |
| 138 | if (field_count == invalid) return invalid; | 141 | if (field_count == invalid) return invalid; |
| 139 | count += field_count; | 142 | count += field_count; |
| 140 | if (count > byval_float_count) return invalid; | 143 | if (count > byval_float_count) return invalid; |
src/arch/riscv64/CodeGen.zig+37-35| ... | @@ -755,8 +755,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live | ... | @@ -755,8 +755,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live |
| 755 | tomb_bits >>= 1; | 755 | tomb_bits >>= 1; |
| 756 | if (!dies) continue; | 756 | if (!dies) continue; |
| 757 | const op_int = @enumToInt(op); | 757 | const op_int = @enumToInt(op); |
| 758 | if (op_int < Air.Inst.Ref.typed_value_map.len) continue; | 758 | if (op_int < Air.ref_start_index) continue; |
| 759 | const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len); | 759 | const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index); |
| 760 | self.processDeath(op_index); | 760 | self.processDeath(op_index); |
| 761 | } | 761 | } |
| 762 | const is_used = @truncate(u1, tomb_bits) == 0; | 762 | const is_used = @truncate(u1, tomb_bits) == 0; |
| ... | @@ -805,22 +805,22 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u | ... | @@ -805,22 +805,22 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u |
| 805 | /// Use a pointer instruction as the basis for allocating stack memory. | 805 | /// Use a pointer instruction as the basis for allocating stack memory. |
| 806 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { | 806 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 807 | const elem_ty = self.air.typeOfIndex(inst).elemType(); | 807 | const elem_ty = self.air.typeOfIndex(inst).elemType(); |
| 808 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { | 808 | const mod = self.bin_file.options.module.?; |
| 809 | const mod = self.bin_file.options.module.?; | 809 | const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { |
| 810 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | 810 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 811 | }; | 811 | }; |
| 812 | // TODO swap this for inst.ty.ptrAlign | 812 | // TODO swap this for inst.ty.ptrAlign |
| 813 | const abi_align = elem_ty.abiAlignment(self.target.*); | 813 | const abi_align = elem_ty.abiAlignment(mod); |
| 814 | return self.allocMem(inst, abi_size, abi_align); | 814 | return self.allocMem(inst, abi_size, abi_align); |
| 815 | } | 815 | } |
| 816 | 816 | ||
| 817 | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { | 817 | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 818 | const elem_ty = self.air.typeOfIndex(inst); | 818 | const elem_ty = self.air.typeOfIndex(inst); |
| 819 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { | 819 | const mod = self.bin_file.options.module.?; |
| 820 | const mod = self.bin_file.options.module.?; | 820 | const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { |
| 821 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | 821 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 822 | }; | 822 | }; |
| 823 | const abi_align = elem_ty.abiAlignment(self.target.*); | 823 | const abi_align = elem_ty.abiAlignment(mod); |
| 824 | if (abi_align > self.stack_align) | 824 | if (abi_align > self.stack_align) |
| 825 | self.stack_align = abi_align; | 825 | self.stack_align = abi_align; |
| 826 | 826 | ||
| ... | @@ -893,10 +893,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -893,10 +893,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 893 | if (self.liveness.isUnused(inst)) | 893 | if (self.liveness.isUnused(inst)) |
| 894 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); | 894 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 895 | 895 | ||
| 896 | const mod = self.bin_file.options.module.?; | ||
| 896 | const operand_ty = self.air.typeOf(ty_op.operand); | 897 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 897 | const operand = try self.resolveInst(ty_op.operand); | 898 | const operand = try self.resolveInst(ty_op.operand); |
| 898 | const info_a = operand_ty.intInfo(self.target.*); | 899 | const info_a = operand_ty.intInfo(mod); |
| 899 | const info_b = self.air.typeOfIndex(inst).intInfo(self.target.*); | 900 | const info_b = self.air.typeOfIndex(inst).intInfo(mod); |
| 900 | if (info_a.signedness != info_b.signedness) | 901 | if (info_a.signedness != info_b.signedness) |
| 901 | return self.fail("TODO gen intcast sign safety in semantic analysis", .{}); | 902 | return self.fail("TODO gen intcast sign safety in semantic analysis", .{}); |
| 902 | 903 | ||
| ... | @@ -1068,18 +1069,18 @@ fn binOp( | ... | @@ -1068,18 +1069,18 @@ fn binOp( |
| 1068 | lhs_ty: Type, | 1069 | lhs_ty: Type, |
| 1069 | rhs_ty: Type, | 1070 | rhs_ty: Type, |
| 1070 | ) InnerError!MCValue { | 1071 | ) InnerError!MCValue { |
| 1072 | const mod = self.bin_file.options.module.?; | ||
| 1071 | switch (tag) { | 1073 | switch (tag) { |
| 1072 | // Arithmetic operations on integers and floats | 1074 | // Arithmetic operations on integers and floats |
| 1073 | .add, | 1075 | .add, |
| 1074 | .sub, | 1076 | .sub, |
| 1075 | => { | 1077 | => { |
| 1076 | switch (lhs_ty.zigTypeTag()) { | 1078 | switch (lhs_ty.zigTypeTag(mod)) { |
| 1077 | .Float => return self.fail("TODO binary operations on floats", .{}), | 1079 | .Float => return self.fail("TODO binary operations on floats", .{}), |
| 1078 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 1080 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1079 | .Int => { | 1081 | .Int => { |
| 1080 | const mod = self.bin_file.options.module.?; | ||
| 1081 | assert(lhs_ty.eql(rhs_ty, mod)); | 1082 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 1082 | const int_info = lhs_ty.intInfo(self.target.*); | 1083 | const int_info = lhs_ty.intInfo(mod); |
| 1083 | if (int_info.bits <= 64) { | 1084 | if (int_info.bits <= 64) { |
| 1084 | // TODO immediate operands | 1085 | // TODO immediate operands |
| 1085 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 1086 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| ... | @@ -1093,14 +1094,14 @@ fn binOp( | ... | @@ -1093,14 +1094,14 @@ fn binOp( |
| 1093 | .ptr_add, | 1094 | .ptr_add, |
| 1094 | .ptr_sub, | 1095 | .ptr_sub, |
| 1095 | => { | 1096 | => { |
| 1096 | switch (lhs_ty.zigTypeTag()) { | 1097 | switch (lhs_ty.zigTypeTag(mod)) { |
| 1097 | .Pointer => { | 1098 | .Pointer => { |
| 1098 | const ptr_ty = lhs_ty; | 1099 | const ptr_ty = lhs_ty; |
| 1099 | const elem_ty = switch (ptr_ty.ptrSize()) { | 1100 | const elem_ty = switch (ptr_ty.ptrSize()) { |
| 1100 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type | 1101 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type |
| 1101 | else => ptr_ty.childType(), | 1102 | else => ptr_ty.childType(), |
| 1102 | }; | 1103 | }; |
| 1103 | const elem_size = elem_ty.abiSize(self.target.*); | 1104 | const elem_size = elem_ty.abiSize(mod); |
| 1104 | 1105 | ||
| 1105 | if (elem_size == 1) { | 1106 | if (elem_size == 1) { |
| 1106 | const base_tag: Air.Inst.Tag = switch (tag) { | 1107 | const base_tag: Air.Inst.Tag = switch (tag) { |
| ... | @@ -1331,10 +1332,11 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1331,10 +1332,11 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { |
| 1331 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | 1332 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 1332 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1333 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1333 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1334 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1335 | const mod = self.bin_file.options.module.?; | ||
| 1334 | const optional_ty = self.air.typeOfIndex(inst); | 1336 | const optional_ty = self.air.typeOfIndex(inst); |
| 1335 | 1337 | ||
| 1336 | // Optional with a zero-bit payload type is just a boolean true | 1338 | // Optional with a zero-bit payload type is just a boolean true |
| 1337 | if (optional_ty.abiSize(self.target.*) == 1) | 1339 | if (optional_ty.abiSize(mod) == 1) |
| 1338 | break :result MCValue{ .immediate = 1 }; | 1340 | break :result MCValue{ .immediate = 1 }; |
| 1339 | 1341 | ||
| 1340 | return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch}); | 1342 | return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch}); |
| ... | @@ -1526,7 +1528,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1526,7 +1528,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1526 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1528 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1527 | const elem_ty = self.air.typeOfIndex(inst); | 1529 | const elem_ty = self.air.typeOfIndex(inst); |
| 1528 | const result: MCValue = result: { | 1530 | const result: MCValue = result: { |
| 1529 | if (!elem_ty.hasRuntimeBits()) | 1531 | const mod = self.bin_file.options.module.?; |
| 1532 | if (!elem_ty.hasRuntimeBits(mod)) | ||
| 1530 | break :result MCValue.none; | 1533 | break :result MCValue.none; |
| 1531 | 1534 | ||
| 1532 | const ptr = try self.resolveInst(ty_op.operand); | 1535 | const ptr = try self.resolveInst(ty_op.operand); |
| ... | @@ -1698,6 +1701,7 @@ fn airFence(self: *Self) !void { | ... | @@ -1698,6 +1701,7 @@ fn airFence(self: *Self) !void { |
| 1698 | } | 1701 | } |
| 1699 | 1702 | ||
| 1700 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { | 1703 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 1704 | const mod = self.bin_file.options.module.?; | ||
| 1701 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for riscv64", .{}); | 1705 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for riscv64", .{}); |
| 1702 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 1706 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 1703 | const fn_ty = self.air.typeOf(pl_op.operand); | 1707 | const fn_ty = self.air.typeOf(pl_op.operand); |
| ... | @@ -1736,7 +1740,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -1736,7 +1740,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1736 | } | 1740 | } |
| 1737 | } | 1741 | } |
| 1738 | 1742 | ||
| 1739 | if (self.air.value(callee)) |func_value| { | 1743 | if (self.air.value(callee, mod)) |func_value| { |
| 1740 | if (func_value.castTag(.function)) |func_payload| { | 1744 | if (func_value.castTag(.function)) |func_payload| { |
| 1741 | const func = func_payload.data; | 1745 | const func = func_payload.data; |
| 1742 | const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl); | 1746 | const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl); |
| ... | @@ -1828,7 +1832,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -1828,7 +1832,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 1828 | const ty = self.air.typeOf(bin_op.lhs); | 1832 | const ty = self.air.typeOf(bin_op.lhs); |
| 1829 | const mod = self.bin_file.options.module.?; | 1833 | const mod = self.bin_file.options.module.?; |
| 1830 | assert(ty.eql(self.air.typeOf(bin_op.rhs), mod)); | 1834 | assert(ty.eql(self.air.typeOf(bin_op.rhs), mod)); |
| 1831 | if (ty.zigTypeTag() == .ErrorSet) | 1835 | if (ty.zigTypeTag(mod) == .ErrorSet) |
| 1832 | return self.fail("TODO implement cmp for errors", .{}); | 1836 | return self.fail("TODO implement cmp for errors", .{}); |
| 1833 | 1837 | ||
| 1834 | const lhs = try self.resolveInst(bin_op.lhs); | 1838 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | @@ -2107,7 +2111,8 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2107,7 +2111,8 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { |
| 2107 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { | 2111 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 2108 | const block_data = self.blocks.getPtr(block).?; | 2112 | const block_data = self.blocks.getPtr(block).?; |
| 2109 | 2113 | ||
| 2110 | if (self.air.typeOf(operand).hasRuntimeBits()) { | 2114 | const mod = self.bin_file.options.module.?; |
| 2115 | if (self.air.typeOf(operand).hasRuntimeBits(mod)) { | ||
| 2111 | const operand_mcv = try self.resolveInst(operand); | 2116 | const operand_mcv = try self.resolveInst(operand); |
| 2112 | const block_mcv = block_data.mcv; | 2117 | const block_mcv = block_data.mcv; |
| 2113 | if (block_mcv == .none) { | 2118 | if (block_mcv == .none) { |
| ... | @@ -2533,22 +2538,18 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2533,22 +2538,18 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 2533 | } | 2538 | } |
| 2534 | 2539 | ||
| 2535 | fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { | 2540 | fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { |
| 2536 | // First section of indexes correspond to a set number of constant values. | 2541 | const mod = self.bin_file.options.module.?; |
| 2537 | const ref_int = @enumToInt(inst); | ||
| 2538 | if (ref_int < Air.Inst.Ref.typed_value_map.len) { | ||
| 2539 | const tv = Air.Inst.Ref.typed_value_map[ref_int]; | ||
| 2540 | if (!tv.ty.hasRuntimeBits()) { | ||
| 2541 | return MCValue{ .none = {} }; | ||
| 2542 | } | ||
| 2543 | return self.genTypedValue(tv); | ||
| 2544 | } | ||
| 2545 | 2542 | ||
| 2546 | // If the type has no codegen bits, no need to store it. | 2543 | // If the type has no codegen bits, no need to store it. |
| 2547 | const inst_ty = self.air.typeOf(inst); | 2544 | const inst_ty = self.air.typeOf(inst); |
| 2548 | if (!inst_ty.hasRuntimeBits()) | 2545 | if (!inst_ty.hasRuntimeBits(mod)) |
| 2549 | return MCValue{ .none = {} }; | 2546 | return MCValue{ .none = {} }; |
| 2550 | 2547 | ||
| 2551 | const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len); | 2548 | const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{ |
| 2549 | .ty = inst_ty, | ||
| 2550 | .val = self.air.value(inst, mod).?, | ||
| 2551 | }); | ||
| 2552 | |||
| 2552 | switch (self.air.instructions.items(.tag)[inst_index]) { | 2553 | switch (self.air.instructions.items(.tag)[inst_index]) { |
| 2553 | .constant => { | 2554 | .constant => { |
| 2554 | // Constants have static lifetimes, so they are always memoized in the outer most table. | 2555 | // Constants have static lifetimes, so they are always memoized in the outer most table. |
| ... | @@ -2630,6 +2631,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -2630,6 +2631,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 2630 | errdefer self.gpa.free(result.args); | 2631 | errdefer self.gpa.free(result.args); |
| 2631 | 2632 | ||
| 2632 | const ret_ty = fn_ty.fnReturnType(); | 2633 | const ret_ty = fn_ty.fnReturnType(); |
| 2634 | const mod = self.bin_file.options.module.?; | ||
| 2633 | 2635 | ||
| 2634 | switch (cc) { | 2636 | switch (cc) { |
| 2635 | .Naked => { | 2637 | .Naked => { |
| ... | @@ -2650,7 +2652,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -2650,7 +2652,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 2650 | const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 }; | 2652 | const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 }; |
| 2651 | 2653 | ||
| 2652 | for (param_types, 0..) |ty, i| { | 2654 | for (param_types, 0..) |ty, i| { |
| 2653 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); | 2655 | const param_size = @intCast(u32, ty.abiSize(mod)); |
| 2654 | if (param_size <= 8) { | 2656 | if (param_size <= 8) { |
| 2655 | if (next_register < argument_registers.len) { | 2657 | if (next_register < argument_registers.len) { |
| 2656 | result.args[i] = .{ .register = argument_registers[next_register] }; | 2658 | result.args[i] = .{ .register = argument_registers[next_register] }; |
| ... | @@ -2680,14 +2682,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -2680,14 +2682,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 2680 | else => return self.fail("TODO implement function parameters for {} on riscv64", .{cc}), | 2682 | else => return self.fail("TODO implement function parameters for {} on riscv64", .{cc}), |
| 2681 | } | 2683 | } |
| 2682 | 2684 | ||
| 2683 | if (ret_ty.zigTypeTag() == .NoReturn) { | 2685 | if (ret_ty.zigTypeTag(mod) == .NoReturn) { |
| 2684 | result.return_value = .{ .unreach = {} }; | 2686 | result.return_value = .{ .unreach = {} }; |
| 2685 | } else if (!ret_ty.hasRuntimeBits()) { | 2687 | } else if (!ret_ty.hasRuntimeBits(mod)) { |
| 2686 | result.return_value = .{ .none = {} }; | 2688 | result.return_value = .{ .none = {} }; |
| 2687 | } else switch (cc) { | 2689 | } else switch (cc) { |
| 2688 | .Naked => unreachable, | 2690 | .Naked => unreachable, |
| 2689 | .Unspecified, .C => { | 2691 | .Unspecified, .C => { |
| 2690 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 2692 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod)); |
| 2691 | if (ret_ty_size <= 8) { | 2693 | if (ret_ty_size <= 8) { |
| 2692 | result.return_value = .{ .register = .a0 }; | 2694 | result.return_value = .{ .register = .a0 }; |
| 2693 | } else if (ret_ty_size <= 16) { | 2695 | } else if (ret_ty_size <= 16) { |
src/arch/riscv64/abi.zig+10-8| ... | @@ -3,16 +3,18 @@ const bits = @import("bits.zig"); | ... | @@ -3,16 +3,18 @@ const bits = @import("bits.zig"); |
| 3 | const Register = bits.Register; | 3 | const Register = bits.Register; |
| 4 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; | 4 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; |
| 5 | const Type = @import("../../type.zig").Type; | 5 | const Type = @import("../../type.zig").Type; |
| 6 | const Module = @import("../../Module.zig"); | ||
| 6 | 7 | ||
| 7 | pub const Class = enum { memory, byval, integer, double_integer }; | 8 | pub const Class = enum { memory, byval, integer, double_integer }; |
| 8 | 9 | ||
| 9 | pub fn classifyType(ty: Type, target: std.Target) Class { | 10 | pub fn classifyType(ty: Type, mod: *const Module) Class { |
| 10 | std.debug.assert(ty.hasRuntimeBitsIgnoreComptime()); | 11 | const target = mod.getTarget(); |
| 12 | std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(mod)); | ||
| 11 | 13 | ||
| 12 | const max_byval_size = target.ptrBitWidth() * 2; | 14 | const max_byval_size = target.ptrBitWidth() * 2; |
| 13 | switch (ty.zigTypeTag()) { | 15 | switch (ty.zigTypeTag(mod)) { |
| 14 | .Struct => { | 16 | .Struct => { |
| 15 | const bit_size = ty.bitSize(target); | 17 | const bit_size = ty.bitSize(mod); |
| 16 | if (ty.containerLayout() == .Packed) { | 18 | if (ty.containerLayout() == .Packed) { |
| 17 | if (bit_size > max_byval_size) return .memory; | 19 | if (bit_size > max_byval_size) return .memory; |
| 18 | return .byval; | 20 | return .byval; |
| ... | @@ -23,7 +25,7 @@ pub fn classifyType(ty: Type, target: std.Target) Class { | ... | @@ -23,7 +25,7 @@ pub fn classifyType(ty: Type, target: std.Target) Class { |
| 23 | return .integer; | 25 | return .integer; |
| 24 | }, | 26 | }, |
| 25 | .Union => { | 27 | .Union => { |
| 26 | const bit_size = ty.bitSize(target); | 28 | const bit_size = ty.bitSize(mod); |
| 27 | if (ty.containerLayout() == .Packed) { | 29 | if (ty.containerLayout() == .Packed) { |
| 28 | if (bit_size > max_byval_size) return .memory; | 30 | if (bit_size > max_byval_size) return .memory; |
| 29 | return .byval; | 31 | return .byval; |
| ... | @@ -36,17 +38,17 @@ pub fn classifyType(ty: Type, target: std.Target) Class { | ... | @@ -36,17 +38,17 @@ pub fn classifyType(ty: Type, target: std.Target) Class { |
| 36 | .Bool => return .integer, | 38 | .Bool => return .integer, |
| 37 | .Float => return .byval, | 39 | .Float => return .byval, |
| 38 | .Int, .Enum, .ErrorSet => { | 40 | .Int, .Enum, .ErrorSet => { |
| 39 | const bit_size = ty.bitSize(target); | 41 | const bit_size = ty.bitSize(mod); |
| 40 | if (bit_size > max_byval_size) return .memory; | 42 | if (bit_size > max_byval_size) return .memory; |
| 41 | return .byval; | 43 | return .byval; |
| 42 | }, | 44 | }, |
| 43 | .Vector => { | 45 | .Vector => { |
| 44 | const bit_size = ty.bitSize(target); | 46 | const bit_size = ty.bitSize(mod); |
| 45 | if (bit_size > max_byval_size) return .memory; | 47 | if (bit_size > max_byval_size) return .memory; |
| 46 | return .integer; | 48 | return .integer; |
| 47 | }, | 49 | }, |
| 48 | .Optional => { | 50 | .Optional => { |
| 49 | std.debug.assert(ty.isPtrLikeOptional()); | 51 | std.debug.assert(ty.isPtrLikeOptional(mod)); |
| 50 | return .byval; | 52 | return .byval; |
| 51 | }, | 53 | }, |
| 52 | .Pointer => { | 54 | .Pointer => { |
src/arch/sparc64/CodeGen.zig+129-110| ... | @@ -758,18 +758,18 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -758,18 +758,18 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 758 | const tag = self.air.instructions.items(.tag)[inst]; | 758 | const tag = self.air.instructions.items(.tag)[inst]; |
| 759 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 759 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 760 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 760 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 761 | const mod = self.bin_file.options.module.?; | ||
| 761 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 762 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 762 | const lhs = try self.resolveInst(extra.lhs); | 763 | const lhs = try self.resolveInst(extra.lhs); |
| 763 | const rhs = try self.resolveInst(extra.rhs); | 764 | const rhs = try self.resolveInst(extra.rhs); |
| 764 | const lhs_ty = self.air.typeOf(extra.lhs); | 765 | const lhs_ty = self.air.typeOf(extra.lhs); |
| 765 | const rhs_ty = self.air.typeOf(extra.rhs); | 766 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 766 | 767 | ||
| 767 | switch (lhs_ty.zigTypeTag()) { | 768 | switch (lhs_ty.zigTypeTag(mod)) { |
| 768 | .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}), | 769 | .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}), |
| 769 | .Int => { | 770 | .Int => { |
| 770 | const mod = self.bin_file.options.module.?; | ||
| 771 | assert(lhs_ty.eql(rhs_ty, mod)); | 771 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 772 | const int_info = lhs_ty.intInfo(self.target.*); | 772 | const int_info = lhs_ty.intInfo(mod); |
| 773 | switch (int_info.bits) { | 773 | switch (int_info.bits) { |
| 774 | 32, 64 => { | 774 | 32, 64 => { |
| 775 | // Only say yes if the operation is | 775 | // Only say yes if the operation is |
| ... | @@ -1018,7 +1018,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1018,7 +1018,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 1018 | switch (arg) { | 1018 | switch (arg) { |
| 1019 | .stack_offset => |off| { | 1019 | .stack_offset => |off| { |
| 1020 | const mod = self.bin_file.options.module.?; | 1020 | const mod = self.bin_file.options.module.?; |
| 1021 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) orelse { | 1021 | const abi_size = math.cast(u32, ty.abiSize(mod)) orelse { |
| 1022 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)}); | 1022 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)}); |
| 1023 | }; | 1023 | }; |
| 1024 | const offset = off + abi_size; | 1024 | const offset = off + abi_size; |
| ... | @@ -1203,6 +1203,7 @@ fn airBreakpoint(self: *Self) !void { | ... | @@ -1203,6 +1203,7 @@ fn airBreakpoint(self: *Self) !void { |
| 1203 | } | 1203 | } |
| 1204 | 1204 | ||
| 1205 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { | 1205 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 1206 | const mod = self.bin_file.options.module.?; | ||
| 1206 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1207 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1207 | 1208 | ||
| 1208 | // We have hardware byteswapper in SPARCv9, don't let mainstream compilers mislead you. | 1209 | // We have hardware byteswapper in SPARCv9, don't let mainstream compilers mislead you. |
| ... | @@ -1218,14 +1219,14 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1218,14 +1219,14 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 1218 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1219 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1219 | const operand = try self.resolveInst(ty_op.operand); | 1220 | const operand = try self.resolveInst(ty_op.operand); |
| 1220 | const operand_ty = self.air.typeOf(ty_op.operand); | 1221 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 1221 | switch (operand_ty.zigTypeTag()) { | 1222 | switch (operand_ty.zigTypeTag(mod)) { |
| 1222 | .Vector => return self.fail("TODO byteswap for vectors", .{}), | 1223 | .Vector => return self.fail("TODO byteswap for vectors", .{}), |
| 1223 | .Int => { | 1224 | .Int => { |
| 1224 | const int_info = operand_ty.intInfo(self.target.*); | 1225 | const int_info = operand_ty.intInfo(mod); |
| 1225 | if (int_info.bits == 8) break :result operand; | 1226 | if (int_info.bits == 8) break :result operand; |
| 1226 | 1227 | ||
| 1227 | const abi_size = int_info.bits >> 3; | 1228 | const abi_size = int_info.bits >> 3; |
| 1228 | const abi_align = operand_ty.abiAlignment(self.target.*); | 1229 | const abi_align = operand_ty.abiAlignment(mod); |
| 1229 | const opposite_endian_asi = switch (self.target.cpu.arch.endian()) { | 1230 | const opposite_endian_asi = switch (self.target.cpu.arch.endian()) { |
| 1230 | Endian.Big => ASI.asi_primary_little, | 1231 | Endian.Big => ASI.asi_primary_little, |
| 1231 | Endian.Little => ASI.asi_primary, | 1232 | Endian.Little => ASI.asi_primary, |
| ... | @@ -1294,7 +1295,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -1294,7 +1295,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1294 | const extra = self.air.extraData(Air.Call, pl_op.payload); | 1295 | const extra = self.air.extraData(Air.Call, pl_op.payload); |
| 1295 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end .. extra.end + extra.data.args_len]); | 1296 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end .. extra.end + extra.data.args_len]); |
| 1296 | const ty = self.air.typeOf(callee); | 1297 | const ty = self.air.typeOf(callee); |
| 1297 | const fn_ty = switch (ty.zigTypeTag()) { | 1298 | const mod = self.bin_file.options.module.?; |
| 1299 | const fn_ty = switch (ty.zigTypeTag(mod)) { | ||
| 1298 | .Fn => ty, | 1300 | .Fn => ty, |
| 1299 | .Pointer => ty.childType(), | 1301 | .Pointer => ty.childType(), |
| 1300 | else => unreachable, | 1302 | else => unreachable, |
| ... | @@ -1337,7 +1339,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -1337,7 +1339,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1337 | 1339 | ||
| 1338 | // Due to incremental compilation, how function calls are generated depends | 1340 | // Due to incremental compilation, how function calls are generated depends |
| 1339 | // on linking. | 1341 | // on linking. |
| 1340 | if (self.air.value(callee)) |func_value| { | 1342 | if (self.air.value(callee, mod)) |func_value| { |
| 1341 | if (self.bin_file.tag == link.File.Elf.base_tag) { | 1343 | if (self.bin_file.tag == link.File.Elf.base_tag) { |
| 1342 | if (func_value.castTag(.function)) |func_payload| { | 1344 | if (func_value.castTag(.function)) |func_payload| { |
| 1343 | const func = func_payload.data; | 1345 | const func = func_payload.data; |
| ... | @@ -1374,7 +1376,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -1374,7 +1376,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1374 | } | 1376 | } |
| 1375 | } else @panic("TODO SPARCv9 currently does not support non-ELF binaries"); | 1377 | } else @panic("TODO SPARCv9 currently does not support non-ELF binaries"); |
| 1376 | } else { | 1378 | } else { |
| 1377 | assert(ty.zigTypeTag() == .Pointer); | 1379 | assert(ty.zigTypeTag(mod) == .Pointer); |
| 1378 | const mcv = try self.resolveInst(callee); | 1380 | const mcv = try self.resolveInst(callee); |
| 1379 | try self.genSetReg(ty, .o7, mcv); | 1381 | try self.genSetReg(ty, .o7, mcv); |
| 1380 | 1382 | ||
| ... | @@ -1422,15 +1424,15 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1422,15 +1424,15 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 1422 | 1424 | ||
| 1423 | fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | 1425 | fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 1424 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1426 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1427 | const mod = self.bin_file.options.module.?; | ||
| 1425 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1428 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1426 | const lhs = try self.resolveInst(bin_op.lhs); | 1429 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1427 | const rhs = try self.resolveInst(bin_op.rhs); | 1430 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1428 | const lhs_ty = self.air.typeOf(bin_op.lhs); | 1431 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| 1429 | 1432 | ||
| 1430 | var int_buffer: Type.Payload.Bits = undefined; | 1433 | const int_ty = switch (lhs_ty.zigTypeTag(mod)) { |
| 1431 | const int_ty = switch (lhs_ty.zigTypeTag()) { | ||
| 1432 | .Vector => unreachable, // Handled by cmp_vector. | 1434 | .Vector => unreachable, // Handled by cmp_vector. |
| 1433 | .Enum => lhs_ty.intTagType(&int_buffer), | 1435 | .Enum => lhs_ty.intTagType(), |
| 1434 | .Int => lhs_ty, | 1436 | .Int => lhs_ty, |
| 1435 | .Bool => Type.initTag(.u1), | 1437 | .Bool => Type.initTag(.u1), |
| 1436 | .Pointer => Type.usize, | 1438 | .Pointer => Type.usize, |
| ... | @@ -1438,9 +1440,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -1438,9 +1440,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 1438 | .Optional => blk: { | 1440 | .Optional => blk: { |
| 1439 | var opt_buffer: Type.Payload.ElemType = undefined; | 1441 | var opt_buffer: Type.Payload.ElemType = undefined; |
| 1440 | const payload_ty = lhs_ty.optionalChild(&opt_buffer); | 1442 | const payload_ty = lhs_ty.optionalChild(&opt_buffer); |
| 1441 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 1443 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1442 | break :blk Type.initTag(.u1); | 1444 | break :blk Type.initTag(.u1); |
| 1443 | } else if (lhs_ty.isPtrLikeOptional()) { | 1445 | } else if (lhs_ty.isPtrLikeOptional(mod)) { |
| 1444 | break :blk Type.usize; | 1446 | break :blk Type.usize; |
| 1445 | } else { | 1447 | } else { |
| 1446 | return self.fail("TODO SPARCv9 cmp non-pointer optionals", .{}); | 1448 | return self.fail("TODO SPARCv9 cmp non-pointer optionals", .{}); |
| ... | @@ -1450,7 +1452,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -1450,7 +1452,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 1450 | else => unreachable, | 1452 | else => unreachable, |
| 1451 | }; | 1453 | }; |
| 1452 | 1454 | ||
| 1453 | const int_info = int_ty.intInfo(self.target.*); | 1455 | const int_info = int_ty.intInfo(mod); |
| 1454 | if (int_info.bits <= 64) { | 1456 | if (int_info.bits <= 64) { |
| 1455 | _ = try self.binOp(.cmp_eq, lhs, rhs, int_ty, int_ty, BinOpMetadata{ | 1457 | _ = try self.binOp(.cmp_eq, lhs, rhs, int_ty, int_ty, BinOpMetadata{ |
| 1456 | .lhs = bin_op.lhs, | 1458 | .lhs = bin_op.lhs, |
| ... | @@ -1512,8 +1514,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1512,8 +1514,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 1512 | // whether it needs to be spilled in the branches | 1514 | // whether it needs to be spilled in the branches |
| 1513 | if (self.liveness.operandDies(inst, 0)) { | 1515 | if (self.liveness.operandDies(inst, 0)) { |
| 1514 | const op_int = @enumToInt(pl_op.operand); | 1516 | const op_int = @enumToInt(pl_op.operand); |
| 1515 | if (op_int >= Air.Inst.Ref.typed_value_map.len) { | 1517 | if (op_int >= Air.ref_start_index) { |
| 1516 | const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len); | 1518 | const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index); |
| 1517 | self.processDeath(op_index); | 1519 | self.processDeath(op_index); |
| 1518 | } | 1520 | } |
| 1519 | } | 1521 | } |
| ... | @@ -1752,10 +1754,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1752,10 +1754,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1752 | if (self.liveness.isUnused(inst)) | 1754 | if (self.liveness.isUnused(inst)) |
| 1753 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); | 1755 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1754 | 1756 | ||
| 1757 | const mod = self.bin_file.options.module.?; | ||
| 1755 | const operand_ty = self.air.typeOf(ty_op.operand); | 1758 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 1756 | const operand = try self.resolveInst(ty_op.operand); | 1759 | const operand = try self.resolveInst(ty_op.operand); |
| 1757 | const info_a = operand_ty.intInfo(self.target.*); | 1760 | const info_a = operand_ty.intInfo(mod); |
| 1758 | const info_b = self.air.typeOfIndex(inst).intInfo(self.target.*); | 1761 | const info_b = self.air.typeOfIndex(inst).intInfo(mod); |
| 1759 | if (info_a.signedness != info_b.signedness) | 1762 | if (info_a.signedness != info_b.signedness) |
| 1760 | return self.fail("TODO gen intcast sign safety in semantic analysis", .{}); | 1763 | return self.fail("TODO gen intcast sign safety in semantic analysis", .{}); |
| 1761 | 1764 | ||
| ... | @@ -1814,9 +1817,10 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1814,9 +1817,10 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void { |
| 1814 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | 1817 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1815 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1818 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1816 | const elem_ty = self.air.typeOfIndex(inst); | 1819 | const elem_ty = self.air.typeOfIndex(inst); |
| 1817 | const elem_size = elem_ty.abiSize(self.target.*); | 1820 | const mod = self.bin_file.options.module.?; |
| 1821 | const elem_size = elem_ty.abiSize(mod); | ||
| 1818 | const result: MCValue = result: { | 1822 | const result: MCValue = result: { |
| 1819 | if (!elem_ty.hasRuntimeBits()) | 1823 | if (!elem_ty.hasRuntimeBits(mod)) |
| 1820 | break :result MCValue.none; | 1824 | break :result MCValue.none; |
| 1821 | 1825 | ||
| 1822 | const ptr = try self.resolveInst(ty_op.operand); | 1826 | const ptr = try self.resolveInst(ty_op.operand); |
| ... | @@ -2037,18 +2041,18 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2037,18 +2041,18 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2037 | //const tag = self.air.instructions.items(.tag)[inst]; | 2041 | //const tag = self.air.instructions.items(.tag)[inst]; |
| 2038 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2042 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2039 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 2043 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2044 | const mod = self.bin_file.options.module.?; | ||
| 2040 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2045 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2041 | const lhs = try self.resolveInst(extra.lhs); | 2046 | const lhs = try self.resolveInst(extra.lhs); |
| 2042 | const rhs = try self.resolveInst(extra.rhs); | 2047 | const rhs = try self.resolveInst(extra.rhs); |
| 2043 | const lhs_ty = self.air.typeOf(extra.lhs); | 2048 | const lhs_ty = self.air.typeOf(extra.lhs); |
| 2044 | const rhs_ty = self.air.typeOf(extra.rhs); | 2049 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 2045 | 2050 | ||
| 2046 | switch (lhs_ty.zigTypeTag()) { | 2051 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2047 | .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), | 2052 | .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), |
| 2048 | .Int => { | 2053 | .Int => { |
| 2049 | const mod = self.bin_file.options.module.?; | ||
| 2050 | assert(lhs_ty.eql(rhs_ty, mod)); | 2054 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2051 | const int_info = lhs_ty.intInfo(self.target.*); | 2055 | const int_info = lhs_ty.intInfo(mod); |
| 2052 | switch (int_info.bits) { | 2056 | switch (int_info.bits) { |
| 2053 | 1...32 => { | 2057 | 1...32 => { |
| 2054 | try self.spillConditionFlagsIfOccupied(); | 2058 | try self.spillConditionFlagsIfOccupied(); |
| ... | @@ -2101,6 +2105,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2101,6 +2105,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2101 | 2105 | ||
| 2102 | fn airNot(self: *Self, inst: Air.Inst.Index) !void { | 2106 | fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 2103 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2107 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2108 | const mod = self.bin_file.options.module.?; | ||
| 2104 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2109 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2105 | const operand = try self.resolveInst(ty_op.operand); | 2110 | const operand = try self.resolveInst(ty_op.operand); |
| 2106 | const operand_ty = self.air.typeOf(ty_op.operand); | 2111 | const operand_ty = self.air.typeOf(ty_op.operand); |
| ... | @@ -2116,7 +2121,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2116,7 +2121,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 2116 | }; | 2121 | }; |
| 2117 | }, | 2122 | }, |
| 2118 | else => { | 2123 | else => { |
| 2119 | switch (operand_ty.zigTypeTag()) { | 2124 | switch (operand_ty.zigTypeTag(mod)) { |
| 2120 | .Bool => { | 2125 | .Bool => { |
| 2121 | const op_reg = switch (operand) { | 2126 | const op_reg = switch (operand) { |
| 2122 | .register => |r| r, | 2127 | .register => |r| r, |
| ... | @@ -2150,7 +2155,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2150,7 +2155,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 2150 | }, | 2155 | }, |
| 2151 | .Vector => return self.fail("TODO bitwise not for vectors", .{}), | 2156 | .Vector => return self.fail("TODO bitwise not for vectors", .{}), |
| 2152 | .Int => { | 2157 | .Int => { |
| 2153 | const int_info = operand_ty.intInfo(self.target.*); | 2158 | const int_info = operand_ty.intInfo(mod); |
| 2154 | if (int_info.bits <= 64) { | 2159 | if (int_info.bits <= 64) { |
| 2155 | const op_reg = switch (operand) { | 2160 | const op_reg = switch (operand) { |
| 2156 | .register => |r| r, | 2161 | .register => |r| r, |
| ... | @@ -2332,16 +2337,17 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2332,16 +2337,17 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2332 | fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | 2337 | fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2333 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2338 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2334 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 2339 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2340 | const mod = self.bin_file.options.module.?; | ||
| 2335 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2341 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2336 | const lhs = try self.resolveInst(extra.lhs); | 2342 | const lhs = try self.resolveInst(extra.lhs); |
| 2337 | const rhs = try self.resolveInst(extra.rhs); | 2343 | const rhs = try self.resolveInst(extra.rhs); |
| 2338 | const lhs_ty = self.air.typeOf(extra.lhs); | 2344 | const lhs_ty = self.air.typeOf(extra.lhs); |
| 2339 | const rhs_ty = self.air.typeOf(extra.rhs); | 2345 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 2340 | 2346 | ||
| 2341 | switch (lhs_ty.zigTypeTag()) { | 2347 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2342 | .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), | 2348 | .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), |
| 2343 | .Int => { | 2349 | .Int => { |
| 2344 | const int_info = lhs_ty.intInfo(self.target.*); | 2350 | const int_info = lhs_ty.intInfo(mod); |
| 2345 | if (int_info.bits <= 64) { | 2351 | if (int_info.bits <= 64) { |
| 2346 | try self.spillConditionFlagsIfOccupied(); | 2352 | try self.spillConditionFlagsIfOccupied(); |
| 2347 | 2353 | ||
| ... | @@ -2449,7 +2455,8 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2449,7 +2455,8 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2449 | 2455 | ||
| 2450 | const slice_ty = self.air.typeOf(bin_op.lhs); | 2456 | const slice_ty = self.air.typeOf(bin_op.lhs); |
| 2451 | const elem_ty = slice_ty.childType(); | 2457 | const elem_ty = slice_ty.childType(); |
| 2452 | const elem_size = elem_ty.abiSize(self.target.*); | 2458 | const mod = self.bin_file.options.module.?; |
| 2459 | const elem_size = elem_ty.abiSize(mod); | ||
| 2453 | 2460 | ||
| 2454 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 2461 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 2455 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); | 2462 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); |
| ... | @@ -2564,9 +2571,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2564,9 +2571,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2564 | const operand = extra.struct_operand; | 2571 | const operand = extra.struct_operand; |
| 2565 | const index = extra.field_index; | 2572 | const index = extra.field_index; |
| 2566 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2573 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2574 | const mod = self.bin_file.options.module.?; | ||
| 2567 | const mcv = try self.resolveInst(operand); | 2575 | const mcv = try self.resolveInst(operand); |
| 2568 | const struct_ty = self.air.typeOf(operand); | 2576 | const struct_ty = self.air.typeOf(operand); |
| 2569 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); | 2577 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod)); |
| 2570 | 2578 | ||
| 2571 | switch (mcv) { | 2579 | switch (mcv) { |
| 2572 | .dead, .unreach => unreachable, | 2580 | .dead, .unreach => unreachable, |
| ... | @@ -2701,7 +2709,8 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2701,7 +2709,8 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 2701 | const error_union_ty = self.air.typeOf(ty_op.operand); | 2709 | const error_union_ty = self.air.typeOf(ty_op.operand); |
| 2702 | const payload_ty = error_union_ty.errorUnionPayload(); | 2710 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 2703 | const mcv = try self.resolveInst(ty_op.operand); | 2711 | const mcv = try self.resolveInst(ty_op.operand); |
| 2704 | if (!payload_ty.hasRuntimeBits()) break :result mcv; | 2712 | const mod = self.bin_file.options.module.?; |
| 2713 | if (!payload_ty.hasRuntimeBits(mod)) break :result mcv; | ||
| 2705 | 2714 | ||
| 2706 | return self.fail("TODO implement unwrap error union error for non-empty payloads", .{}); | 2715 | return self.fail("TODO implement unwrap error union error for non-empty payloads", .{}); |
| 2707 | }; | 2716 | }; |
| ... | @@ -2713,7 +2722,8 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2713,7 +2722,8 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 2713 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2722 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2714 | const error_union_ty = self.air.typeOf(ty_op.operand); | 2723 | const error_union_ty = self.air.typeOf(ty_op.operand); |
| 2715 | const payload_ty = error_union_ty.errorUnionPayload(); | 2724 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 2716 | if (!payload_ty.hasRuntimeBits()) break :result MCValue.none; | 2725 | const mod = self.bin_file.options.module.?; |
| 2726 | if (!payload_ty.hasRuntimeBits(mod)) break :result MCValue.none; | ||
| 2717 | 2727 | ||
| 2718 | return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{}); | 2728 | return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{}); |
| 2719 | }; | 2729 | }; |
| ... | @@ -2727,7 +2737,8 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2727,7 +2737,8 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 2727 | const error_union_ty = self.air.getRefType(ty_op.ty); | 2737 | const error_union_ty = self.air.getRefType(ty_op.ty); |
| 2728 | const payload_ty = error_union_ty.errorUnionPayload(); | 2738 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 2729 | const mcv = try self.resolveInst(ty_op.operand); | 2739 | const mcv = try self.resolveInst(ty_op.operand); |
| 2730 | if (!payload_ty.hasRuntimeBits()) break :result mcv; | 2740 | const mod = self.bin_file.options.module.?; |
| 2741 | if (!payload_ty.hasRuntimeBits(mod)) break :result mcv; | ||
| 2731 | 2742 | ||
| 2732 | return self.fail("TODO implement wrap errunion error for non-empty payloads", .{}); | 2743 | return self.fail("TODO implement wrap errunion error for non-empty payloads", .{}); |
| 2733 | }; | 2744 | }; |
| ... | @@ -2747,7 +2758,8 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2747,7 +2758,8 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 2747 | const optional_ty = self.air.typeOfIndex(inst); | 2758 | const optional_ty = self.air.typeOfIndex(inst); |
| 2748 | 2759 | ||
| 2749 | // Optional with a zero-bit payload type is just a boolean true | 2760 | // Optional with a zero-bit payload type is just a boolean true |
| 2750 | if (optional_ty.abiSize(self.target.*) == 1) | 2761 | const mod = self.bin_file.options.module.?; |
| 2762 | if (optional_ty.abiSize(mod) == 1) | ||
| 2751 | break :result MCValue{ .immediate = 1 }; | 2763 | break :result MCValue{ .immediate = 1 }; |
| 2752 | 2764 | ||
| 2753 | return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch}); | 2765 | return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch}); |
| ... | @@ -2784,7 +2796,8 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u | ... | @@ -2784,7 +2796,8 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u |
| 2784 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { | 2796 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 2785 | const elem_ty = self.air.typeOfIndex(inst).elemType(); | 2797 | const elem_ty = self.air.typeOfIndex(inst).elemType(); |
| 2786 | 2798 | ||
| 2787 | if (!elem_ty.hasRuntimeBits()) { | 2799 | const mod = self.bin_file.options.module.?; |
| 2800 | if (!elem_ty.hasRuntimeBits(mod)) { | ||
| 2788 | // As this stack item will never be dereferenced at runtime, | 2801 | // As this stack item will never be dereferenced at runtime, |
| 2789 | // return the stack offset 0. Stack offset 0 will be where all | 2802 | // return the stack offset 0. Stack offset 0 will be where all |
| 2790 | // zero-sized stack allocations live as non-zero-sized | 2803 | // zero-sized stack allocations live as non-zero-sized |
| ... | @@ -2792,22 +2805,21 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { | ... | @@ -2792,22 +2805,21 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 2792 | return @as(u32, 0); | 2805 | return @as(u32, 0); |
| 2793 | } | 2806 | } |
| 2794 | 2807 | ||
| 2795 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { | 2808 | const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { |
| 2796 | const mod = self.bin_file.options.module.?; | ||
| 2797 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | 2809 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 2798 | }; | 2810 | }; |
| 2799 | // TODO swap this for inst.ty.ptrAlign | 2811 | // TODO swap this for inst.ty.ptrAlign |
| 2800 | const abi_align = elem_ty.abiAlignment(self.target.*); | 2812 | const abi_align = elem_ty.abiAlignment(mod); |
| 2801 | return self.allocMem(inst, abi_size, abi_align); | 2813 | return self.allocMem(inst, abi_size, abi_align); |
| 2802 | } | 2814 | } |
| 2803 | 2815 | ||
| 2804 | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { | 2816 | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 2805 | const elem_ty = self.air.typeOfIndex(inst); | 2817 | const elem_ty = self.air.typeOfIndex(inst); |
| 2806 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { | 2818 | const mod = self.bin_file.options.module.?; |
| 2807 | const mod = self.bin_file.options.module.?; | 2819 | const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { |
| 2808 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | 2820 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 2809 | }; | 2821 | }; |
| 2810 | const abi_align = elem_ty.abiAlignment(self.target.*); | 2822 | const abi_align = elem_ty.abiAlignment(mod); |
| 2811 | if (abi_align > self.stack_align) | 2823 | if (abi_align > self.stack_align) |
| 2812 | self.stack_align = abi_align; | 2824 | self.stack_align = abi_align; |
| 2813 | 2825 | ||
| ... | @@ -2860,12 +2872,12 @@ fn binOp( | ... | @@ -2860,12 +2872,12 @@ fn binOp( |
| 2860 | .xor, | 2872 | .xor, |
| 2861 | .cmp_eq, | 2873 | .cmp_eq, |
| 2862 | => { | 2874 | => { |
| 2863 | switch (lhs_ty.zigTypeTag()) { | 2875 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2864 | .Float => return self.fail("TODO binary operations on floats", .{}), | 2876 | .Float => return self.fail("TODO binary operations on floats", .{}), |
| 2865 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2877 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 2866 | .Int => { | 2878 | .Int => { |
| 2867 | assert(lhs_ty.eql(rhs_ty, mod)); | 2879 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2868 | const int_info = lhs_ty.intInfo(self.target.*); | 2880 | const int_info = lhs_ty.intInfo(mod); |
| 2869 | if (int_info.bits <= 64) { | 2881 | if (int_info.bits <= 64) { |
| 2870 | // Only say yes if the operation is | 2882 | // Only say yes if the operation is |
| 2871 | // commutative, i.e. we can swap both of the | 2883 | // commutative, i.e. we can swap both of the |
| ... | @@ -2934,10 +2946,10 @@ fn binOp( | ... | @@ -2934,10 +2946,10 @@ fn binOp( |
| 2934 | const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); | 2946 | const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); |
| 2935 | 2947 | ||
| 2936 | // Truncate if necessary | 2948 | // Truncate if necessary |
| 2937 | switch (lhs_ty.zigTypeTag()) { | 2949 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2938 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2950 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 2939 | .Int => { | 2951 | .Int => { |
| 2940 | const int_info = lhs_ty.intInfo(self.target.*); | 2952 | const int_info = lhs_ty.intInfo(mod); |
| 2941 | if (int_info.bits <= 64) { | 2953 | if (int_info.bits <= 64) { |
| 2942 | const result_reg = result.register; | 2954 | const result_reg = result.register; |
| 2943 | try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits); | 2955 | try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits); |
| ... | @@ -2951,11 +2963,11 @@ fn binOp( | ... | @@ -2951,11 +2963,11 @@ fn binOp( |
| 2951 | }, | 2963 | }, |
| 2952 | 2964 | ||
| 2953 | .div_trunc => { | 2965 | .div_trunc => { |
| 2954 | switch (lhs_ty.zigTypeTag()) { | 2966 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2955 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 2967 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 2956 | .Int => { | 2968 | .Int => { |
| 2957 | assert(lhs_ty.eql(rhs_ty, mod)); | 2969 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2958 | const int_info = lhs_ty.intInfo(self.target.*); | 2970 | const int_info = lhs_ty.intInfo(mod); |
| 2959 | if (int_info.bits <= 64) { | 2971 | if (int_info.bits <= 64) { |
| 2960 | const rhs_immediate_ok = switch (tag) { | 2972 | const rhs_immediate_ok = switch (tag) { |
| 2961 | .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12), | 2973 | .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12), |
| ... | @@ -2984,14 +2996,14 @@ fn binOp( | ... | @@ -2984,14 +2996,14 @@ fn binOp( |
| 2984 | }, | 2996 | }, |
| 2985 | 2997 | ||
| 2986 | .ptr_add => { | 2998 | .ptr_add => { |
| 2987 | switch (lhs_ty.zigTypeTag()) { | 2999 | switch (lhs_ty.zigTypeTag(mod)) { |
| 2988 | .Pointer => { | 3000 | .Pointer => { |
| 2989 | const ptr_ty = lhs_ty; | 3001 | const ptr_ty = lhs_ty; |
| 2990 | const elem_ty = switch (ptr_ty.ptrSize()) { | 3002 | const elem_ty = switch (ptr_ty.ptrSize()) { |
| 2991 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type | 3003 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type |
| 2992 | else => ptr_ty.childType(), | 3004 | else => ptr_ty.childType(), |
| 2993 | }; | 3005 | }; |
| 2994 | const elem_size = elem_ty.abiSize(self.target.*); | 3006 | const elem_size = elem_ty.abiSize(mod); |
| 2995 | 3007 | ||
| 2996 | if (elem_size == 1) { | 3008 | if (elem_size == 1) { |
| 2997 | const base_tag: Mir.Inst.Tag = switch (tag) { | 3009 | const base_tag: Mir.Inst.Tag = switch (tag) { |
| ... | @@ -3016,7 +3028,7 @@ fn binOp( | ... | @@ -3016,7 +3028,7 @@ fn binOp( |
| 3016 | .bool_and, | 3028 | .bool_and, |
| 3017 | .bool_or, | 3029 | .bool_or, |
| 3018 | => { | 3030 | => { |
| 3019 | switch (lhs_ty.zigTypeTag()) { | 3031 | switch (lhs_ty.zigTypeTag(mod)) { |
| 3020 | .Bool => { | 3032 | .Bool => { |
| 3021 | assert(lhs != .immediate); // should have been handled by Sema | 3033 | assert(lhs != .immediate); // should have been handled by Sema |
| 3022 | assert(rhs != .immediate); // should have been handled by Sema | 3034 | assert(rhs != .immediate); // should have been handled by Sema |
| ... | @@ -3046,10 +3058,10 @@ fn binOp( | ... | @@ -3046,10 +3058,10 @@ fn binOp( |
| 3046 | const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); | 3058 | const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); |
| 3047 | 3059 | ||
| 3048 | // Truncate if necessary | 3060 | // Truncate if necessary |
| 3049 | switch (lhs_ty.zigTypeTag()) { | 3061 | switch (lhs_ty.zigTypeTag(mod)) { |
| 3050 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 3062 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 3051 | .Int => { | 3063 | .Int => { |
| 3052 | const int_info = lhs_ty.intInfo(self.target.*); | 3064 | const int_info = lhs_ty.intInfo(mod); |
| 3053 | if (int_info.bits <= 64) { | 3065 | if (int_info.bits <= 64) { |
| 3054 | // 32 and 64 bit operands doesn't need truncating | 3066 | // 32 and 64 bit operands doesn't need truncating |
| 3055 | if (int_info.bits == 32 or int_info.bits == 64) return result; | 3067 | if (int_info.bits == 32 or int_info.bits == 64) return result; |
| ... | @@ -3068,10 +3080,10 @@ fn binOp( | ... | @@ -3068,10 +3080,10 @@ fn binOp( |
| 3068 | .shl_exact, | 3080 | .shl_exact, |
| 3069 | .shr_exact, | 3081 | .shr_exact, |
| 3070 | => { | 3082 | => { |
| 3071 | switch (lhs_ty.zigTypeTag()) { | 3083 | switch (lhs_ty.zigTypeTag(mod)) { |
| 3072 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 3084 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 3073 | .Int => { | 3085 | .Int => { |
| 3074 | const int_info = lhs_ty.intInfo(self.target.*); | 3086 | const int_info = lhs_ty.intInfo(mod); |
| 3075 | if (int_info.bits <= 64) { | 3087 | if (int_info.bits <= 64) { |
| 3076 | const rhs_immediate_ok = rhs == .immediate; | 3088 | const rhs_immediate_ok = rhs == .immediate; |
| 3077 | 3089 | ||
| ... | @@ -3393,7 +3405,8 @@ fn binOpRegister( | ... | @@ -3393,7 +3405,8 @@ fn binOpRegister( |
| 3393 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { | 3405 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 3394 | const block_data = self.blocks.getPtr(block).?; | 3406 | const block_data = self.blocks.getPtr(block).?; |
| 3395 | 3407 | ||
| 3396 | if (self.air.typeOf(operand).hasRuntimeBits()) { | 3408 | const mod = self.bin_file.options.module.?; |
| 3409 | if (self.air.typeOf(operand).hasRuntimeBits(mod)) { | ||
| 3397 | const operand_mcv = try self.resolveInst(operand); | 3410 | const operand_mcv = try self.resolveInst(operand); |
| 3398 | const block_mcv = block_data.mcv; | 3411 | const block_mcv = block_data.mcv; |
| 3399 | if (block_mcv == .none) { | 3412 | if (block_mcv == .none) { |
| ... | @@ -3512,16 +3525,17 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { | ... | @@ -3512,16 +3525,17 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { |
| 3512 | 3525 | ||
| 3513 | /// Given an error union, returns the payload | 3526 | /// Given an error union, returns the payload |
| 3514 | fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { | 3527 | fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { |
| 3528 | const mod = self.bin_file.options.module.?; | ||
| 3515 | const err_ty = error_union_ty.errorUnionSet(); | 3529 | const err_ty = error_union_ty.errorUnionSet(); |
| 3516 | const payload_ty = error_union_ty.errorUnionPayload(); | 3530 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 3517 | if (err_ty.errorSetIsEmpty()) { | 3531 | if (err_ty.errorSetIsEmpty()) { |
| 3518 | return error_union_mcv; | 3532 | return error_union_mcv; |
| 3519 | } | 3533 | } |
| 3520 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 3534 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3521 | return MCValue.none; | 3535 | return MCValue.none; |
| 3522 | } | 3536 | } |
| 3523 | 3537 | ||
| 3524 | const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*)); | 3538 | const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod)); |
| 3525 | switch (error_union_mcv) { | 3539 | switch (error_union_mcv) { |
| 3526 | .register => return self.fail("TODO errUnionPayload for registers", .{}), | 3540 | .register => return self.fail("TODO errUnionPayload for registers", .{}), |
| 3527 | .stack_offset => |off| { | 3541 | .stack_offset => |off| { |
| ... | @@ -3555,8 +3569,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live | ... | @@ -3555,8 +3569,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live |
| 3555 | tomb_bits >>= 1; | 3569 | tomb_bits >>= 1; |
| 3556 | if (!dies) continue; | 3570 | if (!dies) continue; |
| 3557 | const op_int = @enumToInt(op); | 3571 | const op_int = @enumToInt(op); |
| 3558 | if (op_int < Air.Inst.Ref.typed_value_map.len) continue; | 3572 | if (op_int < Air.ref_start_index) continue; |
| 3559 | const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len); | 3573 | const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index); |
| 3560 | self.processDeath(op_index); | 3574 | self.processDeath(op_index); |
| 3561 | } | 3575 | } |
| 3562 | const is_used = @truncate(u1, tomb_bits) == 0; | 3576 | const is_used = @truncate(u1, tomb_bits) == 0; |
| ... | @@ -3730,6 +3744,7 @@ fn genLoadASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Reg | ... | @@ -3730,6 +3744,7 @@ fn genLoadASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Reg |
| 3730 | } | 3744 | } |
| 3731 | 3745 | ||
| 3732 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { | 3746 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { |
| 3747 | const mod = self.bin_file.options.module.?; | ||
| 3733 | switch (mcv) { | 3748 | switch (mcv) { |
| 3734 | .dead => unreachable, | 3749 | .dead => unreachable, |
| 3735 | .unreach, .none => return, // Nothing to do. | 3750 | .unreach, .none => return, // Nothing to do. |
| ... | @@ -3928,19 +3943,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -3928,19 +3943,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3928 | // The value is in memory at a hard-coded address. | 3943 | // The value is in memory at a hard-coded address. |
| 3929 | // If the type is a pointer, it means the pointer address is at this memory location. | 3944 | // If the type is a pointer, it means the pointer address is at this memory location. |
| 3930 | try self.genSetReg(ty, reg, .{ .immediate = addr }); | 3945 | try self.genSetReg(ty, reg, .{ .immediate = addr }); |
| 3931 | try self.genLoad(reg, reg, i13, 0, ty.abiSize(self.target.*)); | 3946 | try self.genLoad(reg, reg, i13, 0, ty.abiSize(mod)); |
| 3932 | }, | 3947 | }, |
| 3933 | .stack_offset => |off| { | 3948 | .stack_offset => |off| { |
| 3934 | const real_offset = realStackOffset(off); | 3949 | const real_offset = realStackOffset(off); |
| 3935 | const simm13 = math.cast(i13, real_offset) orelse | 3950 | const simm13 = math.cast(i13, real_offset) orelse |
| 3936 | return self.fail("TODO larger stack offsets: {}", .{real_offset}); | 3951 | return self.fail("TODO larger stack offsets: {}", .{real_offset}); |
| 3937 | try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(self.target.*)); | 3952 | try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(mod)); |
| 3938 | }, | 3953 | }, |
| 3939 | } | 3954 | } |
| 3940 | } | 3955 | } |
| 3941 | 3956 | ||
| 3942 | fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { | 3957 | fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { |
| 3943 | const abi_size = ty.abiSize(self.target.*); | 3958 | const mod = self.bin_file.options.module.?; |
| 3959 | const abi_size = ty.abiSize(mod); | ||
| 3944 | switch (mcv) { | 3960 | switch (mcv) { |
| 3945 | .dead => unreachable, | 3961 | .dead => unreachable, |
| 3946 | .unreach, .none => return, // Nothing to do. | 3962 | .unreach, .none => return, // Nothing to do. |
| ... | @@ -3948,7 +3964,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3948,7 +3964,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3948 | if (!self.wantSafety()) | 3964 | if (!self.wantSafety()) |
| 3949 | return; // The already existing value will do just fine. | 3965 | return; // The already existing value will do just fine. |
| 3950 | // TODO Upgrade this to a memset call when we have that available. | 3966 | // TODO Upgrade this to a memset call when we have that available. |
| 3951 | switch (ty.abiSize(self.target.*)) { | 3967 | switch (ty.abiSize(mod)) { |
| 3952 | 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }), | 3968 | 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }), |
| 3953 | 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }), | 3969 | 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }), |
| 3954 | 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }), | 3970 | 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }), |
| ... | @@ -3978,7 +3994,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3978,7 +3994,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3978 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg }); | 3994 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg }); |
| 3979 | 3995 | ||
| 3980 | const overflow_bit_ty = ty.structFieldType(1); | 3996 | const overflow_bit_ty = ty.structFieldType(1); |
| 3981 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*)); | 3997 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod)); |
| 3982 | const cond_reg = try self.register_manager.allocReg(null, gp); | 3998 | const cond_reg = try self.register_manager.allocReg(null, gp); |
| 3983 | 3999 | ||
| 3984 | // TODO handle floating point CCRs | 4000 | // TODO handle floating point CCRs |
| ... | @@ -4152,13 +4168,14 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { | ... | @@ -4152,13 +4168,14 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 4152 | } | 4168 | } |
| 4153 | 4169 | ||
| 4154 | fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { | 4170 | fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 4171 | const mod = self.bin_file.options.module.?; | ||
| 4155 | const error_type = ty.errorUnionSet(); | 4172 | const error_type = ty.errorUnionSet(); |
| 4156 | const payload_type = ty.errorUnionPayload(); | 4173 | const payload_type = ty.errorUnionPayload(); |
| 4157 | 4174 | ||
| 4158 | if (!error_type.hasRuntimeBits()) { | 4175 | if (!error_type.hasRuntimeBits(mod)) { |
| 4159 | return MCValue{ .immediate = 0 }; // always false | 4176 | return MCValue{ .immediate = 0 }; // always false |
| 4160 | } else if (!payload_type.hasRuntimeBits()) { | 4177 | } else if (!payload_type.hasRuntimeBits(mod)) { |
| 4161 | if (error_type.abiSize(self.target.*) <= 8) { | 4178 | if (error_type.abiSize(mod) <= 8) { |
| 4162 | const reg_mcv: MCValue = switch (operand) { | 4179 | const reg_mcv: MCValue = switch (operand) { |
| 4163 | .register => operand, | 4180 | .register => operand, |
| 4164 | else => .{ .register = try self.copyToTmpRegister(error_type, operand) }, | 4181 | else => .{ .register = try self.copyToTmpRegister(error_type, operand) }, |
| ... | @@ -4249,8 +4266,9 @@ fn jump(self: *Self, inst: Mir.Inst.Index) !void { | ... | @@ -4249,8 +4266,9 @@ fn jump(self: *Self, inst: Mir.Inst.Index) !void { |
| 4249 | } | 4266 | } |
| 4250 | 4267 | ||
| 4251 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { | 4268 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 4269 | const mod = self.bin_file.options.module.?; | ||
| 4252 | const elem_ty = ptr_ty.elemType(); | 4270 | const elem_ty = ptr_ty.elemType(); |
| 4253 | const elem_size = elem_ty.abiSize(self.target.*); | 4271 | const elem_size = elem_ty.abiSize(mod); |
| 4254 | 4272 | ||
| 4255 | switch (ptr) { | 4273 | switch (ptr) { |
| 4256 | .none => unreachable, | 4274 | .none => unreachable, |
| ... | @@ -4321,11 +4339,11 @@ fn minMax( | ... | @@ -4321,11 +4339,11 @@ fn minMax( |
| 4321 | ) InnerError!MCValue { | 4339 | ) InnerError!MCValue { |
| 4322 | const mod = self.bin_file.options.module.?; | 4340 | const mod = self.bin_file.options.module.?; |
| 4323 | assert(lhs_ty.eql(rhs_ty, mod)); | 4341 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 4324 | switch (lhs_ty.zigTypeTag()) { | 4342 | switch (lhs_ty.zigTypeTag(mod)) { |
| 4325 | .Float => return self.fail("TODO min/max on floats", .{}), | 4343 | .Float => return self.fail("TODO min/max on floats", .{}), |
| 4326 | .Vector => return self.fail("TODO min/max on vectors", .{}), | 4344 | .Vector => return self.fail("TODO min/max on vectors", .{}), |
| 4327 | .Int => { | 4345 | .Int => { |
| 4328 | const int_info = lhs_ty.intInfo(self.target.*); | 4346 | const int_info = lhs_ty.intInfo(mod); |
| 4329 | if (int_info.bits <= 64) { | 4347 | if (int_info.bits <= 64) { |
| 4330 | // TODO skip register setting when one of the operands | 4348 | // TODO skip register setting when one of the operands |
| 4331 | // is a small (fits in i13) immediate. | 4349 | // is a small (fits in i13) immediate. |
| ... | @@ -4455,6 +4473,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) | ... | @@ -4455,6 +4473,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) |
| 4455 | errdefer self.gpa.free(result.args); | 4473 | errdefer self.gpa.free(result.args); |
| 4456 | 4474 | ||
| 4457 | const ret_ty = fn_ty.fnReturnType(); | 4475 | const ret_ty = fn_ty.fnReturnType(); |
| 4476 | const mod = self.bin_file.options.module.?; | ||
| 4458 | 4477 | ||
| 4459 | switch (cc) { | 4478 | switch (cc) { |
| 4460 | .Naked => { | 4479 | .Naked => { |
| ... | @@ -4478,7 +4497,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) | ... | @@ -4478,7 +4497,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) |
| 4478 | }; | 4497 | }; |
| 4479 | 4498 | ||
| 4480 | for (param_types, 0..) |ty, i| { | 4499 | for (param_types, 0..) |ty, i| { |
| 4481 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); | 4500 | const param_size = @intCast(u32, ty.abiSize(mod)); |
| 4482 | if (param_size <= 8) { | 4501 | if (param_size <= 8) { |
| 4483 | if (next_register < argument_registers.len) { | 4502 | if (next_register < argument_registers.len) { |
| 4484 | result.args[i] = .{ .register = argument_registers[next_register] }; | 4503 | result.args[i] = .{ .register = argument_registers[next_register] }; |
| ... | @@ -4505,12 +4524,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) | ... | @@ -4505,12 +4524,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) |
| 4505 | result.stack_byte_count = next_stack_offset; | 4524 | result.stack_byte_count = next_stack_offset; |
| 4506 | result.stack_align = 16; | 4525 | result.stack_align = 16; |
| 4507 | 4526 | ||
| 4508 | if (ret_ty.zigTypeTag() == .NoReturn) { | 4527 | if (ret_ty.zigTypeTag(mod) == .NoReturn) { |
| 4509 | result.return_value = .{ .unreach = {} }; | 4528 | result.return_value = .{ .unreach = {} }; |
| 4510 | } else if (!ret_ty.hasRuntimeBits()) { | 4529 | } else if (!ret_ty.hasRuntimeBits(mod)) { |
| 4511 | result.return_value = .{ .none = {} }; | 4530 | result.return_value = .{ .none = {} }; |
| 4512 | } else { | 4531 | } else { |
| 4513 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 4532 | const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod)); |
| 4514 | // The callee puts the return values in %i0-%i3, which becomes %o0-%o3 inside the caller. | 4533 | // The callee puts the return values in %i0-%i3, which becomes %o0-%o3 inside the caller. |
| 4515 | if (ret_ty_size <= 8) { | 4534 | if (ret_ty_size <= 8) { |
| 4516 | result.return_value = switch (role) { | 4535 | result.return_value = switch (role) { |
| ... | @@ -4528,40 +4547,37 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) | ... | @@ -4528,40 +4547,37 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) |
| 4528 | return result; | 4547 | return result; |
| 4529 | } | 4548 | } |
| 4530 | 4549 | ||
| 4531 | fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { | 4550 | fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 4532 | // First section of indexes correspond to a set number of constant values. | 4551 | const mod = self.bin_file.options.module.?; |
| 4533 | const ref_int = @enumToInt(inst); | 4552 | const ty = self.air.typeOf(ref); |
| 4534 | if (ref_int < Air.Inst.Ref.typed_value_map.len) { | ||
| 4535 | const tv = Air.Inst.Ref.typed_value_map[ref_int]; | ||
| 4536 | if (!tv.ty.hasRuntimeBitsIgnoreComptime() and !tv.ty.isError()) { | ||
| 4537 | return MCValue{ .none = {} }; | ||
| 4538 | } | ||
| 4539 | return self.genTypedValue(tv); | ||
| 4540 | } | ||
| 4541 | 4553 | ||
| 4542 | // If the type has no codegen bits, no need to store it. | 4554 | // If the type has no codegen bits, no need to store it. |
| 4543 | const inst_ty = self.air.typeOf(inst); | 4555 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return .none; |
| 4544 | if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError()) | 4556 | |
| 4545 | return MCValue{ .none = {} }; | 4557 | if (Air.refToIndex(ref)) |inst| { |
| 4546 | 4558 | switch (self.air.instructions.items(.tag)[inst]) { | |
| 4547 | const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len); | 4559 | .constant => { |
| 4548 | switch (self.air.instructions.items(.tag)[inst_index]) { | 4560 | // Constants have static lifetimes, so they are always memoized in the outer most table. |
| 4549 | .constant => { | 4561 | const branch = &self.branch_stack.items[0]; |
| 4550 | // Constants have static lifetimes, so they are always memoized in the outer most table. | 4562 | const gop = try branch.inst_table.getOrPut(self.gpa, inst); |
| 4551 | const branch = &self.branch_stack.items[0]; | 4563 | if (!gop.found_existing) { |
| 4552 | const gop = try branch.inst_table.getOrPut(self.gpa, inst_index); | 4564 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 4553 | if (!gop.found_existing) { | 4565 | gop.value_ptr.* = try self.genTypedValue(.{ |
| 4554 | const ty_pl = self.air.instructions.items(.data)[inst_index].ty_pl; | 4566 | .ty = ty, |
| 4555 | gop.value_ptr.* = try self.genTypedValue(.{ | 4567 | .val = self.air.values[ty_pl.payload], |
| 4556 | .ty = inst_ty, | 4568 | }); |
| 4557 | .val = self.air.values[ty_pl.payload], | 4569 | } |
| 4558 | }); | 4570 | return gop.value_ptr.*; |
| 4559 | } | 4571 | }, |
| 4560 | return gop.value_ptr.*; | 4572 | .const_ty => unreachable, |
| 4561 | }, | 4573 | else => return self.getResolvedInstValue(inst), |
| 4562 | .const_ty => unreachable, | 4574 | } |
| 4563 | else => return self.getResolvedInstValue(inst_index), | ||
| 4564 | } | 4575 | } |
| 4576 | |||
| 4577 | return self.genTypedValue(.{ | ||
| 4578 | .ty = ty, | ||
| 4579 | .val = self.air.value(ref, mod).?, | ||
| 4580 | }); | ||
| 4565 | } | 4581 | } |
| 4566 | 4582 | ||
| 4567 | fn ret(self: *Self, mcv: MCValue) !void { | 4583 | fn ret(self: *Self, mcv: MCValue) !void { |
| ... | @@ -4666,7 +4682,8 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void | ... | @@ -4666,7 +4682,8 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 4666 | } | 4682 | } |
| 4667 | 4683 | ||
| 4668 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { | 4684 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { |
| 4669 | const abi_size = value_ty.abiSize(self.target.*); | 4685 | const mod = self.bin_file.options.module.?; |
| 4686 | const abi_size = value_ty.abiSize(mod); | ||
| 4670 | 4687 | ||
| 4671 | switch (ptr) { | 4688 | switch (ptr) { |
| 4672 | .none => unreachable, | 4689 | .none => unreachable, |
| ... | @@ -4707,10 +4724,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -4707,10 +4724,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 4707 | 4724 | ||
| 4708 | fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { | 4725 | fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { |
| 4709 | return if (self.liveness.isUnused(inst)) .dead else result: { | 4726 | return if (self.liveness.isUnused(inst)) .dead else result: { |
| 4727 | const mod = self.bin_file.options.module.?; | ||
| 4710 | const mcv = try self.resolveInst(operand); | 4728 | const mcv = try self.resolveInst(operand); |
| 4711 | const ptr_ty = self.air.typeOf(operand); | 4729 | const ptr_ty = self.air.typeOf(operand); |
| 4712 | const struct_ty = ptr_ty.childType(); | 4730 | const struct_ty = ptr_ty.childType(); |
| 4713 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); | 4731 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod)); |
| 4714 | switch (mcv) { | 4732 | switch (mcv) { |
| 4715 | .ptr_stack_offset => |off| { | 4733 | .ptr_stack_offset => |off| { |
| 4716 | break :result MCValue{ .ptr_stack_offset = off - struct_field_offset }; | 4734 | break :result MCValue{ .ptr_stack_offset = off - struct_field_offset }; |
| ... | @@ -4748,8 +4766,9 @@ fn trunc( | ... | @@ -4748,8 +4766,9 @@ fn trunc( |
| 4748 | operand_ty: Type, | 4766 | operand_ty: Type, |
| 4749 | dest_ty: Type, | 4767 | dest_ty: Type, |
| 4750 | ) !MCValue { | 4768 | ) !MCValue { |
| 4751 | const info_a = operand_ty.intInfo(self.target.*); | 4769 | const mod = self.bin_file.options.module.?; |
| 4752 | const info_b = dest_ty.intInfo(self.target.*); | 4770 | const info_a = operand_ty.intInfo(mod); |
| 4771 | const info_b = dest_ty.intInfo(mod); | ||
| 4753 | 4772 | ||
| 4754 | if (info_b.bits <= 64) { | 4773 | if (info_b.bits <= 64) { |
| 4755 | const operand_reg = switch (operand) { | 4774 | const operand_reg = switch (operand) { |
src/arch/wasm/CodeGen.zig+504-462| ... | @@ -788,9 +788,10 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { | ... | @@ -788,9 +788,10 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { |
| 788 | const gop = try func.branches.items[0].values.getOrPut(func.gpa, ref); | 788 | const gop = try func.branches.items[0].values.getOrPut(func.gpa, ref); |
| 789 | assert(!gop.found_existing); | 789 | assert(!gop.found_existing); |
| 790 | 790 | ||
| 791 | const val = func.air.value(ref).?; | 791 | const mod = func.bin_file.base.options.module.?; |
| 792 | const val = func.air.value(ref, mod).?; | ||
| 792 | const ty = func.air.typeOf(ref); | 793 | const ty = func.air.typeOf(ref); |
| 793 | if (!ty.hasRuntimeBitsIgnoreComptime() and !ty.isInt() and !ty.isError()) { | 794 | if (!ty.hasRuntimeBitsIgnoreComptime(mod) and !ty.isInt(mod) and !ty.isError(mod)) { |
| 794 | gop.value_ptr.* = WValue{ .none = {} }; | 795 | gop.value_ptr.* = WValue{ .none = {} }; |
| 795 | return gop.value_ptr.*; | 796 | return gop.value_ptr.*; |
| 796 | } | 797 | } |
| ... | @@ -801,7 +802,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { | ... | @@ -801,7 +802,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { |
| 801 | // | 802 | // |
| 802 | // In the other cases, we will simply lower the constant to a value that fits | 803 | // In the other cases, we will simply lower the constant to a value that fits |
| 803 | // into a single local (such as a pointer, integer, bool, etc). | 804 | // into a single local (such as a pointer, integer, bool, etc). |
| 804 | const result = if (isByRef(ty, func.target)) blk: { | 805 | const result = if (isByRef(ty, mod)) blk: { |
| 805 | const sym_index = try func.bin_file.lowerUnnamedConst(.{ .ty = ty, .val = val }, func.decl_index); | 806 | const sym_index = try func.bin_file.lowerUnnamedConst(.{ .ty = ty, .val = val }, func.decl_index); |
| 806 | break :blk WValue{ .memory = sym_index }; | 807 | break :blk WValue{ .memory = sym_index }; |
| 807 | } else try func.lowerConstant(val, ty); | 808 | } else try func.lowerConstant(val, ty); |
| ... | @@ -987,8 +988,9 @@ fn addExtraAssumeCapacity(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32 | ... | @@ -987,8 +988,9 @@ fn addExtraAssumeCapacity(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32 |
| 987 | } | 988 | } |
| 988 | 989 | ||
| 989 | /// Using a given `Type`, returns the corresponding type | 990 | /// Using a given `Type`, returns the corresponding type |
| 990 | fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { | 991 | fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype { |
| 991 | return switch (ty.zigTypeTag()) { | 992 | const target = mod.getTarget(); |
| 993 | return switch (ty.zigTypeTag(mod)) { | ||
| 992 | .Float => blk: { | 994 | .Float => blk: { |
| 993 | const bits = ty.floatBits(target); | 995 | const bits = ty.floatBits(target); |
| 994 | if (bits == 16) return wasm.Valtype.i32; // stored/loaded as u16 | 996 | if (bits == 16) return wasm.Valtype.i32; // stored/loaded as u16 |
| ... | @@ -998,7 +1000,7 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { | ... | @@ -998,7 +1000,7 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { |
| 998 | return wasm.Valtype.i32; // represented as pointer to stack | 1000 | return wasm.Valtype.i32; // represented as pointer to stack |
| 999 | }, | 1001 | }, |
| 1000 | .Int, .Enum => blk: { | 1002 | .Int, .Enum => blk: { |
| 1001 | const info = ty.intInfo(target); | 1003 | const info = ty.intInfo(mod); |
| 1002 | if (info.bits <= 32) break :blk wasm.Valtype.i32; | 1004 | if (info.bits <= 32) break :blk wasm.Valtype.i32; |
| 1003 | if (info.bits > 32 and info.bits <= 128) break :blk wasm.Valtype.i64; | 1005 | if (info.bits > 32 and info.bits <= 128) break :blk wasm.Valtype.i64; |
| 1004 | break :blk wasm.Valtype.i32; // represented as pointer to stack | 1006 | break :blk wasm.Valtype.i32; // represented as pointer to stack |
| ... | @@ -1006,22 +1008,18 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { | ... | @@ -1006,22 +1008,18 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { |
| 1006 | .Struct => switch (ty.containerLayout()) { | 1008 | .Struct => switch (ty.containerLayout()) { |
| 1007 | .Packed => { | 1009 | .Packed => { |
| 1008 | const struct_obj = ty.castTag(.@"struct").?.data; | 1010 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 1009 | return typeToValtype(struct_obj.backing_int_ty, target); | 1011 | return typeToValtype(struct_obj.backing_int_ty, mod); |
| 1010 | }, | 1012 | }, |
| 1011 | else => wasm.Valtype.i32, | 1013 | else => wasm.Valtype.i32, |
| 1012 | }, | 1014 | }, |
| 1013 | .Vector => switch (determineSimdStoreStrategy(ty, target)) { | 1015 | .Vector => switch (determineSimdStoreStrategy(ty, mod)) { |
| 1014 | .direct => wasm.Valtype.v128, | 1016 | .direct => wasm.Valtype.v128, |
| 1015 | .unrolled => wasm.Valtype.i32, | 1017 | .unrolled => wasm.Valtype.i32, |
| 1016 | }, | 1018 | }, |
| 1017 | .Union => switch (ty.containerLayout()) { | 1019 | .Union => switch (ty.containerLayout()) { |
| 1018 | .Packed => { | 1020 | .Packed => { |
| 1019 | var int_ty_payload: Type.Payload.Bits = .{ | 1021 | const int_ty = mod.intType(.unsigned, @intCast(u16, ty.bitSize(mod))) catch @panic("out of memory"); |
| 1020 | .base = .{ .tag = .int_unsigned }, | 1022 | return typeToValtype(int_ty, mod); |
| 1021 | .data = @intCast(u16, ty.bitSize(target)), | ||
| 1022 | }; | ||
| 1023 | const int_ty = Type.initPayload(&int_ty_payload.base); | ||
| 1024 | return typeToValtype(int_ty, target); | ||
| 1025 | }, | 1023 | }, |
| 1026 | else => wasm.Valtype.i32, | 1024 | else => wasm.Valtype.i32, |
| 1027 | }, | 1025 | }, |
| ... | @@ -1030,17 +1028,17 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { | ... | @@ -1030,17 +1028,17 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { |
| 1030 | } | 1028 | } |
| 1031 | 1029 | ||
| 1032 | /// Using a given `Type`, returns the byte representation of its wasm value type | 1030 | /// Using a given `Type`, returns the byte representation of its wasm value type |
| 1033 | fn genValtype(ty: Type, target: std.Target) u8 { | 1031 | fn genValtype(ty: Type, mod: *Module) u8 { |
| 1034 | return wasm.valtype(typeToValtype(ty, target)); | 1032 | return wasm.valtype(typeToValtype(ty, mod)); |
| 1035 | } | 1033 | } |
| 1036 | 1034 | ||
| 1037 | /// Using a given `Type`, returns the corresponding wasm value type | 1035 | /// Using a given `Type`, returns the corresponding wasm value type |
| 1038 | /// Differently from `genValtype` this also allows `void` to create a block | 1036 | /// Differently from `genValtype` this also allows `void` to create a block |
| 1039 | /// with no return type | 1037 | /// with no return type |
| 1040 | fn genBlockType(ty: Type, target: std.Target) u8 { | 1038 | fn genBlockType(ty: Type, mod: *Module) u8 { |
| 1041 | return switch (ty.tag()) { | 1039 | return switch (ty.tag()) { |
| 1042 | .void, .noreturn => wasm.block_empty, | 1040 | .void, .noreturn => wasm.block_empty, |
| 1043 | else => genValtype(ty, target), | 1041 | else => genValtype(ty, mod), |
| 1044 | }; | 1042 | }; |
| 1045 | } | 1043 | } |
| 1046 | 1044 | ||
| ... | @@ -1101,7 +1099,8 @@ fn getResolvedInst(func: *CodeGen, ref: Air.Inst.Ref) *WValue { | ... | @@ -1101,7 +1099,8 @@ fn getResolvedInst(func: *CodeGen, ref: Air.Inst.Ref) *WValue { |
| 1101 | /// Creates one locals for a given `Type`. | 1099 | /// Creates one locals for a given `Type`. |
| 1102 | /// Returns a corresponding `Wvalue` with `local` as active tag | 1100 | /// Returns a corresponding `Wvalue` with `local` as active tag |
| 1103 | fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue { | 1101 | fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue { |
| 1104 | const valtype = typeToValtype(ty, func.target); | 1102 | const mod = func.bin_file.base.options.module.?; |
| 1103 | const valtype = typeToValtype(ty, mod); | ||
| 1105 | switch (valtype) { | 1104 | switch (valtype) { |
| 1106 | .i32 => if (func.free_locals_i32.popOrNull()) |index| { | 1105 | .i32 => if (func.free_locals_i32.popOrNull()) |index| { |
| 1107 | log.debug("reusing local ({d}) of type {}", .{ index, valtype }); | 1106 | log.debug("reusing local ({d}) of type {}", .{ index, valtype }); |
| ... | @@ -1132,7 +1131,8 @@ fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue { | ... | @@ -1132,7 +1131,8 @@ fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue { |
| 1132 | /// Ensures a new local will be created. This is useful when it's useful | 1131 | /// Ensures a new local will be created. This is useful when it's useful |
| 1133 | /// to use a zero-initialized local. | 1132 | /// to use a zero-initialized local. |
| 1134 | fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue { | 1133 | fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue { |
| 1135 | try func.locals.append(func.gpa, genValtype(ty, func.target)); | 1134 | const mod = func.bin_file.base.options.module.?; |
| 1135 | try func.locals.append(func.gpa, genValtype(ty, mod)); | ||
| 1136 | const initial_index = func.local_index; | 1136 | const initial_index = func.local_index; |
| 1137 | func.local_index += 1; | 1137 | func.local_index += 1; |
| 1138 | return WValue{ .local = .{ .value = initial_index, .references = 1 } }; | 1138 | return WValue{ .local = .{ .value = initial_index, .references = 1 } }; |
| ... | @@ -1140,48 +1140,54 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue { | ... | @@ -1140,48 +1140,54 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue { |
| 1140 | 1140 | ||
| 1141 | /// Generates a `wasm.Type` from a given function type. | 1141 | /// Generates a `wasm.Type` from a given function type. |
| 1142 | /// Memory is owned by the caller. | 1142 | /// Memory is owned by the caller. |
| 1143 | fn genFunctype(gpa: Allocator, cc: std.builtin.CallingConvention, params: []const Type, return_type: Type, target: std.Target) !wasm.Type { | 1143 | fn genFunctype( |
| 1144 | gpa: Allocator, | ||
| 1145 | cc: std.builtin.CallingConvention, | ||
| 1146 | params: []const Type, | ||
| 1147 | return_type: Type, | ||
| 1148 | mod: *Module, | ||
| 1149 | ) !wasm.Type { | ||
| 1144 | var temp_params = std.ArrayList(wasm.Valtype).init(gpa); | 1150 | var temp_params = std.ArrayList(wasm.Valtype).init(gpa); |
| 1145 | defer temp_params.deinit(); | 1151 | defer temp_params.deinit(); |
| 1146 | var returns = std.ArrayList(wasm.Valtype).init(gpa); | 1152 | var returns = std.ArrayList(wasm.Valtype).init(gpa); |
| 1147 | defer returns.deinit(); | 1153 | defer returns.deinit(); |
| 1148 | 1154 | ||
| 1149 | if (firstParamSRet(cc, return_type, target)) { | 1155 | if (firstParamSRet(cc, return_type, mod)) { |
| 1150 | try temp_params.append(.i32); // memory address is always a 32-bit handle | 1156 | try temp_params.append(.i32); // memory address is always a 32-bit handle |
| 1151 | } else if (return_type.hasRuntimeBitsIgnoreComptime()) { | 1157 | } else if (return_type.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1152 | if (cc == .C) { | 1158 | if (cc == .C) { |
| 1153 | const res_classes = abi.classifyType(return_type, target); | 1159 | const res_classes = abi.classifyType(return_type, mod); |
| 1154 | assert(res_classes[0] == .direct and res_classes[1] == .none); | 1160 | assert(res_classes[0] == .direct and res_classes[1] == .none); |
| 1155 | const scalar_type = abi.scalarType(return_type, target); | 1161 | const scalar_type = abi.scalarType(return_type, mod); |
| 1156 | try returns.append(typeToValtype(scalar_type, target)); | 1162 | try returns.append(typeToValtype(scalar_type, mod)); |
| 1157 | } else { | 1163 | } else { |
| 1158 | try returns.append(typeToValtype(return_type, target)); | 1164 | try returns.append(typeToValtype(return_type, mod)); |
| 1159 | } | 1165 | } |
| 1160 | } else if (return_type.isError()) { | 1166 | } else if (return_type.isError(mod)) { |
| 1161 | try returns.append(.i32); | 1167 | try returns.append(.i32); |
| 1162 | } | 1168 | } |
| 1163 | 1169 | ||
| 1164 | // param types | 1170 | // param types |
| 1165 | for (params) |param_type| { | 1171 | for (params) |param_type| { |
| 1166 | if (!param_type.hasRuntimeBitsIgnoreComptime()) continue; | 1172 | if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1167 | 1173 | ||
| 1168 | switch (cc) { | 1174 | switch (cc) { |
| 1169 | .C => { | 1175 | .C => { |
| 1170 | const param_classes = abi.classifyType(param_type, target); | 1176 | const param_classes = abi.classifyType(param_type, mod); |
| 1171 | for (param_classes) |class| { | 1177 | for (param_classes) |class| { |
| 1172 | if (class == .none) continue; | 1178 | if (class == .none) continue; |
| 1173 | if (class == .direct) { | 1179 | if (class == .direct) { |
| 1174 | const scalar_type = abi.scalarType(param_type, target); | 1180 | const scalar_type = abi.scalarType(param_type, mod); |
| 1175 | try temp_params.append(typeToValtype(scalar_type, target)); | 1181 | try temp_params.append(typeToValtype(scalar_type, mod)); |
| 1176 | } else { | 1182 | } else { |
| 1177 | try temp_params.append(typeToValtype(param_type, target)); | 1183 | try temp_params.append(typeToValtype(param_type, mod)); |
| 1178 | } | 1184 | } |
| 1179 | } | 1185 | } |
| 1180 | }, | 1186 | }, |
| 1181 | else => if (isByRef(param_type, target)) | 1187 | else => if (isByRef(param_type, mod)) |
| 1182 | try temp_params.append(.i32) | 1188 | try temp_params.append(.i32) |
| 1183 | else | 1189 | else |
| 1184 | try temp_params.append(typeToValtype(param_type, target)), | 1190 | try temp_params.append(typeToValtype(param_type, mod)), |
| 1185 | } | 1191 | } |
| 1186 | } | 1192 | } |
| 1187 | 1193 | ||
| ... | @@ -1227,7 +1233,8 @@ pub fn generate( | ... | @@ -1227,7 +1233,8 @@ pub fn generate( |
| 1227 | 1233 | ||
| 1228 | fn genFunc(func: *CodeGen) InnerError!void { | 1234 | fn genFunc(func: *CodeGen) InnerError!void { |
| 1229 | const fn_info = func.decl.ty.fnInfo(); | 1235 | const fn_info = func.decl.ty.fnInfo(); |
| 1230 | var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type, func.target); | 1236 | const mod = func.bin_file.base.options.module.?; |
| 1237 | var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type, mod); | ||
| 1231 | defer func_type.deinit(func.gpa); | 1238 | defer func_type.deinit(func.gpa); |
| 1232 | _ = try func.bin_file.storeDeclType(func.decl_index, func_type); | 1239 | _ = try func.bin_file.storeDeclType(func.decl_index, func_type); |
| 1233 | 1240 | ||
| ... | @@ -1254,7 +1261,7 @@ fn genFunc(func: *CodeGen) InnerError!void { | ... | @@ -1254,7 +1261,7 @@ fn genFunc(func: *CodeGen) InnerError!void { |
| 1254 | if (func_type.returns.len != 0 and func.air.instructions.len > 0) { | 1261 | if (func_type.returns.len != 0 and func.air.instructions.len > 0) { |
| 1255 | const inst = @intCast(u32, func.air.instructions.len - 1); | 1262 | const inst = @intCast(u32, func.air.instructions.len - 1); |
| 1256 | const last_inst_ty = func.air.typeOfIndex(inst); | 1263 | const last_inst_ty = func.air.typeOfIndex(inst); |
| 1257 | if (!last_inst_ty.hasRuntimeBitsIgnoreComptime() or last_inst_ty.isNoReturn()) { | 1264 | if (!last_inst_ty.hasRuntimeBitsIgnoreComptime(mod) or last_inst_ty.isNoReturn()) { |
| 1258 | try func.addTag(.@"unreachable"); | 1265 | try func.addTag(.@"unreachable"); |
| 1259 | } | 1266 | } |
| 1260 | } | 1267 | } |
| ... | @@ -1335,6 +1342,7 @@ const CallWValues = struct { | ... | @@ -1335,6 +1342,7 @@ const CallWValues = struct { |
| 1335 | }; | 1342 | }; |
| 1336 | 1343 | ||
| 1337 | fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues { | 1344 | fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues { |
| 1345 | const mod = func.bin_file.base.options.module.?; | ||
| 1338 | const cc = fn_ty.fnCallingConvention(); | 1346 | const cc = fn_ty.fnCallingConvention(); |
| 1339 | const param_types = try func.gpa.alloc(Type, fn_ty.fnParamLen()); | 1347 | const param_types = try func.gpa.alloc(Type, fn_ty.fnParamLen()); |
| 1340 | defer func.gpa.free(param_types); | 1348 | defer func.gpa.free(param_types); |
| ... | @@ -1351,7 +1359,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV | ... | @@ -1351,7 +1359,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV |
| 1351 | // Check if we store the result as a pointer to the stack rather than | 1359 | // Check if we store the result as a pointer to the stack rather than |
| 1352 | // by value | 1360 | // by value |
| 1353 | const fn_info = fn_ty.fnInfo(); | 1361 | const fn_info = fn_ty.fnInfo(); |
| 1354 | if (firstParamSRet(fn_info.cc, fn_info.return_type, func.target)) { | 1362 | if (firstParamSRet(fn_info.cc, fn_info.return_type, mod)) { |
| 1355 | // the sret arg will be passed as first argument, therefore we | 1363 | // the sret arg will be passed as first argument, therefore we |
| 1356 | // set the `return_value` before allocating locals for regular args. | 1364 | // set the `return_value` before allocating locals for regular args. |
| 1357 | result.return_value = .{ .local = .{ .value = func.local_index, .references = 1 } }; | 1365 | result.return_value = .{ .local = .{ .value = func.local_index, .references = 1 } }; |
| ... | @@ -1361,7 +1369,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV | ... | @@ -1361,7 +1369,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV |
| 1361 | switch (cc) { | 1369 | switch (cc) { |
| 1362 | .Unspecified => { | 1370 | .Unspecified => { |
| 1363 | for (param_types) |ty| { | 1371 | for (param_types) |ty| { |
| 1364 | if (!ty.hasRuntimeBitsIgnoreComptime()) { | 1372 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1365 | continue; | 1373 | continue; |
| 1366 | } | 1374 | } |
| 1367 | 1375 | ||
| ... | @@ -1371,7 +1379,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV | ... | @@ -1371,7 +1379,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV |
| 1371 | }, | 1379 | }, |
| 1372 | .C => { | 1380 | .C => { |
| 1373 | for (param_types) |ty| { | 1381 | for (param_types) |ty| { |
| 1374 | const ty_classes = abi.classifyType(ty, func.target); | 1382 | const ty_classes = abi.classifyType(ty, mod); |
| 1375 | for (ty_classes) |class| { | 1383 | for (ty_classes) |class| { |
| 1376 | if (class == .none) continue; | 1384 | if (class == .none) continue; |
| 1377 | try args.append(.{ .local = .{ .value = func.local_index, .references = 1 } }); | 1385 | try args.append(.{ .local = .{ .value = func.local_index, .references = 1 } }); |
| ... | @@ -1385,11 +1393,11 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV | ... | @@ -1385,11 +1393,11 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV |
| 1385 | return result; | 1393 | return result; |
| 1386 | } | 1394 | } |
| 1387 | 1395 | ||
| 1388 | fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, target: std.Target) bool { | 1396 | fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, mod: *const Module) bool { |
| 1389 | switch (cc) { | 1397 | switch (cc) { |
| 1390 | .Unspecified, .Inline => return isByRef(return_type, target), | 1398 | .Unspecified, .Inline => return isByRef(return_type, mod), |
| 1391 | .C => { | 1399 | .C => { |
| 1392 | const ty_classes = abi.classifyType(return_type, target); | 1400 | const ty_classes = abi.classifyType(return_type, mod); |
| 1393 | if (ty_classes[0] == .indirect) return true; | 1401 | if (ty_classes[0] == .indirect) return true; |
| 1394 | if (ty_classes[0] == .direct and ty_classes[1] == .direct) return true; | 1402 | if (ty_classes[0] == .direct and ty_classes[1] == .direct) return true; |
| 1395 | return false; | 1403 | return false; |
| ... | @@ -1405,16 +1413,17 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: | ... | @@ -1405,16 +1413,17 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: |
| 1405 | return func.lowerToStack(value); | 1413 | return func.lowerToStack(value); |
| 1406 | } | 1414 | } |
| 1407 | 1415 | ||
| 1408 | const ty_classes = abi.classifyType(ty, func.target); | 1416 | const mod = func.bin_file.base.options.module.?; |
| 1417 | const ty_classes = abi.classifyType(ty, mod); | ||
| 1409 | assert(ty_classes[0] != .none); | 1418 | assert(ty_classes[0] != .none); |
| 1410 | switch (ty.zigTypeTag()) { | 1419 | switch (ty.zigTypeTag(mod)) { |
| 1411 | .Struct, .Union => { | 1420 | .Struct, .Union => { |
| 1412 | if (ty_classes[0] == .indirect) { | 1421 | if (ty_classes[0] == .indirect) { |
| 1413 | return func.lowerToStack(value); | 1422 | return func.lowerToStack(value); |
| 1414 | } | 1423 | } |
| 1415 | assert(ty_classes[0] == .direct); | 1424 | assert(ty_classes[0] == .direct); |
| 1416 | const scalar_type = abi.scalarType(ty, func.target); | 1425 | const scalar_type = abi.scalarType(ty, mod); |
| 1417 | const abi_size = scalar_type.abiSize(func.target); | 1426 | const abi_size = scalar_type.abiSize(mod); |
| 1418 | try func.emitWValue(value); | 1427 | try func.emitWValue(value); |
| 1419 | 1428 | ||
| 1420 | // When the value lives in the virtual stack, we must load it onto the actual stack | 1429 | // When the value lives in the virtual stack, we must load it onto the actual stack |
| ... | @@ -1422,12 +1431,12 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: | ... | @@ -1422,12 +1431,12 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: |
| 1422 | const opcode = buildOpcode(.{ | 1431 | const opcode = buildOpcode(.{ |
| 1423 | .op = .load, | 1432 | .op = .load, |
| 1424 | .width = @intCast(u8, abi_size), | 1433 | .width = @intCast(u8, abi_size), |
| 1425 | .signedness = if (scalar_type.isSignedInt()) .signed else .unsigned, | 1434 | .signedness = if (scalar_type.isSignedInt(mod)) .signed else .unsigned, |
| 1426 | .valtype1 = typeToValtype(scalar_type, func.target), | 1435 | .valtype1 = typeToValtype(scalar_type, mod), |
| 1427 | }); | 1436 | }); |
| 1428 | try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ | 1437 | try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ |
| 1429 | .offset = value.offset(), | 1438 | .offset = value.offset(), |
| 1430 | .alignment = scalar_type.abiAlignment(func.target), | 1439 | .alignment = scalar_type.abiAlignment(mod), |
| 1431 | }); | 1440 | }); |
| 1432 | } | 1441 | } |
| 1433 | }, | 1442 | }, |
| ... | @@ -1436,7 +1445,7 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: | ... | @@ -1436,7 +1445,7 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: |
| 1436 | return func.lowerToStack(value); | 1445 | return func.lowerToStack(value); |
| 1437 | } | 1446 | } |
| 1438 | assert(ty_classes[0] == .direct and ty_classes[1] == .direct); | 1447 | assert(ty_classes[0] == .direct and ty_classes[1] == .direct); |
| 1439 | assert(ty.abiSize(func.target) == 16); | 1448 | assert(ty.abiSize(mod) == 16); |
| 1440 | // in this case we have an integer or float that must be lowered as 2 i64's. | 1449 | // in this case we have an integer or float that must be lowered as 2 i64's. |
| 1441 | try func.emitWValue(value); | 1450 | try func.emitWValue(value); |
| 1442 | try func.addMemArg(.i64_load, .{ .offset = value.offset(), .alignment = 8 }); | 1451 | try func.addMemArg(.i64_load, .{ .offset = value.offset(), .alignment = 8 }); |
| ... | @@ -1503,18 +1512,18 @@ fn restoreStackPointer(func: *CodeGen) !void { | ... | @@ -1503,18 +1512,18 @@ fn restoreStackPointer(func: *CodeGen) !void { |
| 1503 | /// | 1512 | /// |
| 1504 | /// Asserts Type has codegenbits | 1513 | /// Asserts Type has codegenbits |
| 1505 | fn allocStack(func: *CodeGen, ty: Type) !WValue { | 1514 | fn allocStack(func: *CodeGen, ty: Type) !WValue { |
| 1506 | assert(ty.hasRuntimeBitsIgnoreComptime()); | 1515 | const mod = func.bin_file.base.options.module.?; |
| 1516 | assert(ty.hasRuntimeBitsIgnoreComptime(mod)); | ||
| 1507 | if (func.initial_stack_value == .none) { | 1517 | if (func.initial_stack_value == .none) { |
| 1508 | try func.initializeStack(); | 1518 | try func.initializeStack(); |
| 1509 | } | 1519 | } |
| 1510 | 1520 | ||
| 1511 | const abi_size = std.math.cast(u32, ty.abiSize(func.target)) orelse { | 1521 | const abi_size = std.math.cast(u32, ty.abiSize(mod)) orelse { |
| 1512 | const module = func.bin_file.base.options.module.?; | ||
| 1513 | return func.fail("Type {} with ABI size of {d} exceeds stack frame size", .{ | 1522 | return func.fail("Type {} with ABI size of {d} exceeds stack frame size", .{ |
| 1514 | ty.fmt(module), ty.abiSize(func.target), | 1523 | ty.fmt(mod), ty.abiSize(mod), |
| 1515 | }); | 1524 | }); |
| 1516 | }; | 1525 | }; |
| 1517 | const abi_align = ty.abiAlignment(func.target); | 1526 | const abi_align = ty.abiAlignment(mod); |
| 1518 | 1527 | ||
| 1519 | if (abi_align > func.stack_alignment) { | 1528 | if (abi_align > func.stack_alignment) { |
| 1520 | func.stack_alignment = abi_align; | 1529 | func.stack_alignment = abi_align; |
| ... | @@ -1531,6 +1540,7 @@ fn allocStack(func: *CodeGen, ty: Type) !WValue { | ... | @@ -1531,6 +1540,7 @@ fn allocStack(func: *CodeGen, ty: Type) !WValue { |
| 1531 | /// This is different from allocStack where this will use the pointer's alignment | 1540 | /// This is different from allocStack where this will use the pointer's alignment |
| 1532 | /// if it is set, to ensure the stack alignment will be set correctly. | 1541 | /// if it is set, to ensure the stack alignment will be set correctly. |
| 1533 | fn allocStackPtr(func: *CodeGen, inst: Air.Inst.Index) !WValue { | 1542 | fn allocStackPtr(func: *CodeGen, inst: Air.Inst.Index) !WValue { |
| 1543 | const mod = func.bin_file.base.options.module.?; | ||
| 1534 | const ptr_ty = func.air.typeOfIndex(inst); | 1544 | const ptr_ty = func.air.typeOfIndex(inst); |
| 1535 | const pointee_ty = ptr_ty.childType(); | 1545 | const pointee_ty = ptr_ty.childType(); |
| 1536 | 1546 | ||
| ... | @@ -1538,15 +1548,14 @@ fn allocStackPtr(func: *CodeGen, inst: Air.Inst.Index) !WValue { | ... | @@ -1538,15 +1548,14 @@ fn allocStackPtr(func: *CodeGen, inst: Air.Inst.Index) !WValue { |
| 1538 | try func.initializeStack(); | 1548 | try func.initializeStack(); |
| 1539 | } | 1549 | } |
| 1540 | 1550 | ||
| 1541 | if (!pointee_ty.hasRuntimeBitsIgnoreComptime()) { | 1551 | if (!pointee_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1542 | return func.allocStack(Type.usize); // create a value containing just the stack pointer. | 1552 | return func.allocStack(Type.usize); // create a value containing just the stack pointer. |
| 1543 | } | 1553 | } |
| 1544 | 1554 | ||
| 1545 | const abi_alignment = ptr_ty.ptrAlignment(func.target); | 1555 | const abi_alignment = ptr_ty.ptrAlignment(mod); |
| 1546 | const abi_size = std.math.cast(u32, pointee_ty.abiSize(func.target)) orelse { | 1556 | const abi_size = std.math.cast(u32, pointee_ty.abiSize(mod)) orelse { |
| 1547 | const module = func.bin_file.base.options.module.?; | ||
| 1548 | return func.fail("Type {} with ABI size of {d} exceeds stack frame size", .{ | 1557 | return func.fail("Type {} with ABI size of {d} exceeds stack frame size", .{ |
| 1549 | pointee_ty.fmt(module), pointee_ty.abiSize(func.target), | 1558 | pointee_ty.fmt(mod), pointee_ty.abiSize(mod), |
| 1550 | }); | 1559 | }); |
| 1551 | }; | 1560 | }; |
| 1552 | if (abi_alignment > func.stack_alignment) { | 1561 | if (abi_alignment > func.stack_alignment) { |
| ... | @@ -1704,8 +1713,9 @@ fn arch(func: *const CodeGen) std.Target.Cpu.Arch { | ... | @@ -1704,8 +1713,9 @@ fn arch(func: *const CodeGen) std.Target.Cpu.Arch { |
| 1704 | 1713 | ||
| 1705 | /// For a given `Type`, will return true when the type will be passed | 1714 | /// For a given `Type`, will return true when the type will be passed |
| 1706 | /// by reference, rather than by value | 1715 | /// by reference, rather than by value |
| 1707 | fn isByRef(ty: Type, target: std.Target) bool { | 1716 | fn isByRef(ty: Type, mod: *const Module) bool { |
| 1708 | switch (ty.zigTypeTag()) { | 1717 | const target = mod.getTarget(); |
| 1718 | switch (ty.zigTypeTag(mod)) { | ||
| 1709 | .Type, | 1719 | .Type, |
| 1710 | .ComptimeInt, | 1720 | .ComptimeInt, |
| 1711 | .ComptimeFloat, | 1721 | .ComptimeFloat, |
| ... | @@ -1726,40 +1736,40 @@ fn isByRef(ty: Type, target: std.Target) bool { | ... | @@ -1726,40 +1736,40 @@ fn isByRef(ty: Type, target: std.Target) bool { |
| 1726 | 1736 | ||
| 1727 | .Array, | 1737 | .Array, |
| 1728 | .Frame, | 1738 | .Frame, |
| 1729 | => return ty.hasRuntimeBitsIgnoreComptime(), | 1739 | => return ty.hasRuntimeBitsIgnoreComptime(mod), |
| 1730 | .Union => { | 1740 | .Union => { |
| 1731 | if (ty.castTag(.@"union")) |union_ty| { | 1741 | if (ty.castTag(.@"union")) |union_ty| { |
| 1732 | if (union_ty.data.layout == .Packed) { | 1742 | if (union_ty.data.layout == .Packed) { |
| 1733 | return ty.abiSize(target) > 8; | 1743 | return ty.abiSize(mod) > 8; |
| 1734 | } | 1744 | } |
| 1735 | } | 1745 | } |
| 1736 | return ty.hasRuntimeBitsIgnoreComptime(); | 1746 | return ty.hasRuntimeBitsIgnoreComptime(mod); |
| 1737 | }, | 1747 | }, |
| 1738 | .Struct => { | 1748 | .Struct => { |
| 1739 | if (ty.castTag(.@"struct")) |struct_ty| { | 1749 | if (ty.castTag(.@"struct")) |struct_ty| { |
| 1740 | const struct_obj = struct_ty.data; | 1750 | const struct_obj = struct_ty.data; |
| 1741 | if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { | 1751 | if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { |
| 1742 | return isByRef(struct_obj.backing_int_ty, target); | 1752 | return isByRef(struct_obj.backing_int_ty, mod); |
| 1743 | } | 1753 | } |
| 1744 | } | 1754 | } |
| 1745 | return ty.hasRuntimeBitsIgnoreComptime(); | 1755 | return ty.hasRuntimeBitsIgnoreComptime(mod); |
| 1746 | }, | 1756 | }, |
| 1747 | .Vector => return determineSimdStoreStrategy(ty, target) == .unrolled, | 1757 | .Vector => return determineSimdStoreStrategy(ty, mod) == .unrolled, |
| 1748 | .Int => return ty.intInfo(target).bits > 64, | 1758 | .Int => return ty.intInfo(mod).bits > 64, |
| 1749 | .Float => return ty.floatBits(target) > 64, | 1759 | .Float => return ty.floatBits(target) > 64, |
| 1750 | .ErrorUnion => { | 1760 | .ErrorUnion => { |
| 1751 | const pl_ty = ty.errorUnionPayload(); | 1761 | const pl_ty = ty.errorUnionPayload(); |
| 1752 | if (!pl_ty.hasRuntimeBitsIgnoreComptime()) { | 1762 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1753 | return false; | 1763 | return false; |
| 1754 | } | 1764 | } |
| 1755 | return true; | 1765 | return true; |
| 1756 | }, | 1766 | }, |
| 1757 | .Optional => { | 1767 | .Optional => { |
| 1758 | if (ty.isPtrLikeOptional()) return false; | 1768 | if (ty.isPtrLikeOptional(mod)) return false; |
| 1759 | var buf: Type.Payload.ElemType = undefined; | 1769 | var buf: Type.Payload.ElemType = undefined; |
| 1760 | const pl_type = ty.optionalChild(&buf); | 1770 | const pl_type = ty.optionalChild(&buf); |
| 1761 | if (pl_type.zigTypeTag() == .ErrorSet) return false; | 1771 | if (pl_type.zigTypeTag(mod) == .ErrorSet) return false; |
| 1762 | return pl_type.hasRuntimeBitsIgnoreComptime(); | 1772 | return pl_type.hasRuntimeBitsIgnoreComptime(mod); |
| 1763 | }, | 1773 | }, |
| 1764 | .Pointer => { | 1774 | .Pointer => { |
| 1765 | // Slices act like struct and will be passed by reference | 1775 | // Slices act like struct and will be passed by reference |
| ... | @@ -1778,10 +1788,11 @@ const SimdStoreStrategy = enum { | ... | @@ -1778,10 +1788,11 @@ const SimdStoreStrategy = enum { |
| 1778 | /// This means when a given type is 128 bits and either the simd128 or relaxed-simd | 1788 | /// This means when a given type is 128 bits and either the simd128 or relaxed-simd |
| 1779 | /// features are enabled, the function will return `.direct`. This would allow to store | 1789 | /// features are enabled, the function will return `.direct`. This would allow to store |
| 1780 | /// it using a instruction, rather than an unrolled version. | 1790 | /// it using a instruction, rather than an unrolled version. |
| 1781 | fn determineSimdStoreStrategy(ty: Type, target: std.Target) SimdStoreStrategy { | 1791 | fn determineSimdStoreStrategy(ty: Type, mod: *const Module) SimdStoreStrategy { |
| 1782 | std.debug.assert(ty.zigTypeTag() == .Vector); | 1792 | std.debug.assert(ty.zigTypeTag(mod) == .Vector); |
| 1783 | if (ty.bitSize(target) != 128) return .unrolled; | 1793 | if (ty.bitSize(mod) != 128) return .unrolled; |
| 1784 | const hasFeature = std.Target.wasm.featureSetHas; | 1794 | const hasFeature = std.Target.wasm.featureSetHas; |
| 1795 | const target = mod.getTarget(); | ||
| 1785 | const features = target.cpu.features; | 1796 | const features = target.cpu.features; |
| 1786 | if (hasFeature(features, .relaxed_simd) or hasFeature(features, .simd128)) { | 1797 | if (hasFeature(features, .relaxed_simd) or hasFeature(features, .simd128)) { |
| 1787 | return .direct; | 1798 | return .direct; |
| ... | @@ -2084,32 +2095,33 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2084,32 +2095,33 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2084 | const operand = try func.resolveInst(un_op); | 2095 | const operand = try func.resolveInst(un_op); |
| 2085 | const fn_info = func.decl.ty.fnInfo(); | 2096 | const fn_info = func.decl.ty.fnInfo(); |
| 2086 | const ret_ty = fn_info.return_type; | 2097 | const ret_ty = fn_info.return_type; |
| 2098 | const mod = func.bin_file.base.options.module.?; | ||
| 2087 | 2099 | ||
| 2088 | // result must be stored in the stack and we return a pointer | 2100 | // result must be stored in the stack and we return a pointer |
| 2089 | // to the stack instead | 2101 | // to the stack instead |
| 2090 | if (func.return_value != .none) { | 2102 | if (func.return_value != .none) { |
| 2091 | try func.store(func.return_value, operand, ret_ty, 0); | 2103 | try func.store(func.return_value, operand, ret_ty, 0); |
| 2092 | } else if (fn_info.cc == .C and ret_ty.hasRuntimeBitsIgnoreComptime()) { | 2104 | } else if (fn_info.cc == .C and ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2093 | switch (ret_ty.zigTypeTag()) { | 2105 | switch (ret_ty.zigTypeTag(mod)) { |
| 2094 | // Aggregate types can be lowered as a singular value | 2106 | // Aggregate types can be lowered as a singular value |
| 2095 | .Struct, .Union => { | 2107 | .Struct, .Union => { |
| 2096 | const scalar_type = abi.scalarType(ret_ty, func.target); | 2108 | const scalar_type = abi.scalarType(ret_ty, mod); |
| 2097 | try func.emitWValue(operand); | 2109 | try func.emitWValue(operand); |
| 2098 | const opcode = buildOpcode(.{ | 2110 | const opcode = buildOpcode(.{ |
| 2099 | .op = .load, | 2111 | .op = .load, |
| 2100 | .width = @intCast(u8, scalar_type.abiSize(func.target) * 8), | 2112 | .width = @intCast(u8, scalar_type.abiSize(mod) * 8), |
| 2101 | .signedness = if (scalar_type.isSignedInt()) .signed else .unsigned, | 2113 | .signedness = if (scalar_type.isSignedInt(mod)) .signed else .unsigned, |
| 2102 | .valtype1 = typeToValtype(scalar_type, func.target), | 2114 | .valtype1 = typeToValtype(scalar_type, mod), |
| 2103 | }); | 2115 | }); |
| 2104 | try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ | 2116 | try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ |
| 2105 | .offset = operand.offset(), | 2117 | .offset = operand.offset(), |
| 2106 | .alignment = scalar_type.abiAlignment(func.target), | 2118 | .alignment = scalar_type.abiAlignment(mod), |
| 2107 | }); | 2119 | }); |
| 2108 | }, | 2120 | }, |
| 2109 | else => try func.emitWValue(operand), | 2121 | else => try func.emitWValue(operand), |
| 2110 | } | 2122 | } |
| 2111 | } else { | 2123 | } else { |
| 2112 | if (!ret_ty.hasRuntimeBitsIgnoreComptime() and ret_ty.isError()) { | 2124 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and ret_ty.isError(mod)) { |
| 2113 | try func.addImm32(0); | 2125 | try func.addImm32(0); |
| 2114 | } else { | 2126 | } else { |
| 2115 | try func.emitWValue(operand); | 2127 | try func.emitWValue(operand); |
| ... | @@ -2123,14 +2135,15 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2123,14 +2135,15 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2123 | 2135 | ||
| 2124 | fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 2136 | fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2125 | const child_type = func.air.typeOfIndex(inst).childType(); | 2137 | const child_type = func.air.typeOfIndex(inst).childType(); |
| 2138 | const mod = func.bin_file.base.options.module.?; | ||
| 2126 | 2139 | ||
| 2127 | var result = result: { | 2140 | var result = result: { |
| 2128 | if (!child_type.isFnOrHasRuntimeBitsIgnoreComptime()) { | 2141 | if (!child_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) { |
| 2129 | break :result try func.allocStack(Type.usize); // create pointer to void | 2142 | break :result try func.allocStack(Type.usize); // create pointer to void |
| 2130 | } | 2143 | } |
| 2131 | 2144 | ||
| 2132 | const fn_info = func.decl.ty.fnInfo(); | 2145 | const fn_info = func.decl.ty.fnInfo(); |
| 2133 | if (firstParamSRet(fn_info.cc, fn_info.return_type, func.target)) { | 2146 | if (firstParamSRet(fn_info.cc, fn_info.return_type, mod)) { |
| 2134 | break :result func.return_value; | 2147 | break :result func.return_value; |
| 2135 | } | 2148 | } |
| 2136 | 2149 | ||
| ... | @@ -2141,16 +2154,17 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2141,16 +2154,17 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2141 | } | 2154 | } |
| 2142 | 2155 | ||
| 2143 | fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 2156 | fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2157 | const mod = func.bin_file.base.options.module.?; | ||
| 2144 | const un_op = func.air.instructions.items(.data)[inst].un_op; | 2158 | const un_op = func.air.instructions.items(.data)[inst].un_op; |
| 2145 | const operand = try func.resolveInst(un_op); | 2159 | const operand = try func.resolveInst(un_op); |
| 2146 | const ret_ty = func.air.typeOf(un_op).childType(); | 2160 | const ret_ty = func.air.typeOf(un_op).childType(); |
| 2147 | 2161 | ||
| 2148 | const fn_info = func.decl.ty.fnInfo(); | 2162 | const fn_info = func.decl.ty.fnInfo(); |
| 2149 | if (!ret_ty.hasRuntimeBitsIgnoreComptime()) { | 2163 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2150 | if (ret_ty.isError()) { | 2164 | if (ret_ty.isError(mod)) { |
| 2151 | try func.addImm32(0); | 2165 | try func.addImm32(0); |
| 2152 | } | 2166 | } |
| 2153 | } else if (!firstParamSRet(fn_info.cc, fn_info.return_type, func.target)) { | 2167 | } else if (!firstParamSRet(fn_info.cc, fn_info.return_type, mod)) { |
| 2154 | // leave on the stack | 2168 | // leave on the stack |
| 2155 | _ = try func.load(operand, ret_ty, 0); | 2169 | _ = try func.load(operand, ret_ty, 0); |
| 2156 | } | 2170 | } |
| ... | @@ -2167,26 +2181,26 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif | ... | @@ -2167,26 +2181,26 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2167 | const args = @ptrCast([]const Air.Inst.Ref, func.air.extra[extra.end..][0..extra.data.args_len]); | 2181 | const args = @ptrCast([]const Air.Inst.Ref, func.air.extra[extra.end..][0..extra.data.args_len]); |
| 2168 | const ty = func.air.typeOf(pl_op.operand); | 2182 | const ty = func.air.typeOf(pl_op.operand); |
| 2169 | 2183 | ||
| 2170 | const fn_ty = switch (ty.zigTypeTag()) { | 2184 | const mod = func.bin_file.base.options.module.?; |
| 2185 | const fn_ty = switch (ty.zigTypeTag(mod)) { | ||
| 2171 | .Fn => ty, | 2186 | .Fn => ty, |
| 2172 | .Pointer => ty.childType(), | 2187 | .Pointer => ty.childType(), |
| 2173 | else => unreachable, | 2188 | else => unreachable, |
| 2174 | }; | 2189 | }; |
| 2175 | const ret_ty = fn_ty.fnReturnType(); | 2190 | const ret_ty = fn_ty.fnReturnType(); |
| 2176 | const fn_info = fn_ty.fnInfo(); | 2191 | const fn_info = fn_ty.fnInfo(); |
| 2177 | const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type, func.target); | 2192 | const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type, mod); |
| 2178 | 2193 | ||
| 2179 | const callee: ?Decl.Index = blk: { | 2194 | const callee: ?Decl.Index = blk: { |
| 2180 | const func_val = func.air.value(pl_op.operand) orelse break :blk null; | 2195 | const func_val = func.air.value(pl_op.operand, mod) orelse break :blk null; |
| 2181 | const module = func.bin_file.base.options.module.?; | ||
| 2182 | 2196 | ||
| 2183 | if (func_val.castTag(.function)) |function| { | 2197 | if (func_val.castTag(.function)) |function| { |
| 2184 | _ = try func.bin_file.getOrCreateAtomForDecl(function.data.owner_decl); | 2198 | _ = try func.bin_file.getOrCreateAtomForDecl(function.data.owner_decl); |
| 2185 | break :blk function.data.owner_decl; | 2199 | break :blk function.data.owner_decl; |
| 2186 | } else if (func_val.castTag(.extern_fn)) |extern_fn| { | 2200 | } else if (func_val.castTag(.extern_fn)) |extern_fn| { |
| 2187 | const ext_decl = module.declPtr(extern_fn.data.owner_decl); | 2201 | const ext_decl = mod.declPtr(extern_fn.data.owner_decl); |
| 2188 | const ext_info = ext_decl.ty.fnInfo(); | 2202 | const ext_info = ext_decl.ty.fnInfo(); |
| 2189 | var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type, func.target); | 2203 | var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type, mod); |
| 2190 | defer func_type.deinit(func.gpa); | 2204 | defer func_type.deinit(func.gpa); |
| 2191 | const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_fn.data.owner_decl); | 2205 | const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_fn.data.owner_decl); |
| 2192 | const atom = func.bin_file.getAtomPtr(atom_index); | 2206 | const atom = func.bin_file.getAtomPtr(atom_index); |
| ... | @@ -2215,7 +2229,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif | ... | @@ -2215,7 +2229,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2215 | const arg_val = try func.resolveInst(arg); | 2229 | const arg_val = try func.resolveInst(arg); |
| 2216 | 2230 | ||
| 2217 | const arg_ty = func.air.typeOf(arg); | 2231 | const arg_ty = func.air.typeOf(arg); |
| 2218 | if (!arg_ty.hasRuntimeBitsIgnoreComptime()) continue; | 2232 | if (!arg_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2219 | 2233 | ||
| 2220 | try func.lowerArg(fn_ty.fnInfo().cc, arg_ty, arg_val); | 2234 | try func.lowerArg(fn_ty.fnInfo().cc, arg_ty, arg_val); |
| 2221 | } | 2235 | } |
| ... | @@ -2226,11 +2240,11 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif | ... | @@ -2226,11 +2240,11 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2226 | } else { | 2240 | } else { |
| 2227 | // in this case we call a function pointer | 2241 | // in this case we call a function pointer |
| 2228 | // so load its value onto the stack | 2242 | // so load its value onto the stack |
| 2229 | std.debug.assert(ty.zigTypeTag() == .Pointer); | 2243 | std.debug.assert(ty.zigTypeTag(mod) == .Pointer); |
| 2230 | const operand = try func.resolveInst(pl_op.operand); | 2244 | const operand = try func.resolveInst(pl_op.operand); |
| 2231 | try func.emitWValue(operand); | 2245 | try func.emitWValue(operand); |
| 2232 | 2246 | ||
| 2233 | var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type, func.target); | 2247 | var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type, mod); |
| 2234 | defer fn_type.deinit(func.gpa); | 2248 | defer fn_type.deinit(func.gpa); |
| 2235 | 2249 | ||
| 2236 | const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type); | 2250 | const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type); |
| ... | @@ -2238,7 +2252,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif | ... | @@ -2238,7 +2252,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2238 | } | 2252 | } |
| 2239 | 2253 | ||
| 2240 | const result_value = result_value: { | 2254 | const result_value = result_value: { |
| 2241 | if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) { | 2255 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and !ret_ty.isError(mod)) { |
| 2242 | break :result_value WValue{ .none = {} }; | 2256 | break :result_value WValue{ .none = {} }; |
| 2243 | } else if (ret_ty.isNoReturn()) { | 2257 | } else if (ret_ty.isNoReturn()) { |
| 2244 | try func.addTag(.@"unreachable"); | 2258 | try func.addTag(.@"unreachable"); |
| ... | @@ -2246,10 +2260,10 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif | ... | @@ -2246,10 +2260,10 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif |
| 2246 | } else if (first_param_sret) { | 2260 | } else if (first_param_sret) { |
| 2247 | break :result_value sret; | 2261 | break :result_value sret; |
| 2248 | // TODO: Make this less fragile and optimize | 2262 | // TODO: Make this less fragile and optimize |
| 2249 | } else if (fn_ty.fnInfo().cc == .C and ret_ty.zigTypeTag() == .Struct or ret_ty.zigTypeTag() == .Union) { | 2263 | } else if (fn_ty.fnInfo().cc == .C and ret_ty.zigTypeTag(mod) == .Struct or ret_ty.zigTypeTag(mod) == .Union) { |
| 2250 | const result_local = try func.allocLocal(ret_ty); | 2264 | const result_local = try func.allocLocal(ret_ty); |
| 2251 | try func.addLabel(.local_set, result_local.local.value); | 2265 | try func.addLabel(.local_set, result_local.local.value); |
| 2252 | const scalar_type = abi.scalarType(ret_ty, func.target); | 2266 | const scalar_type = abi.scalarType(ret_ty, mod); |
| 2253 | const result = try func.allocStack(scalar_type); | 2267 | const result = try func.allocStack(scalar_type); |
| 2254 | try func.store(result, result_local, scalar_type, 0); | 2268 | try func.store(result, result_local, scalar_type, 0); |
| 2255 | break :result_value result; | 2269 | break :result_value result; |
| ... | @@ -2272,6 +2286,7 @@ fn airAlloc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2272,6 +2286,7 @@ fn airAlloc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2272 | } | 2286 | } |
| 2273 | 2287 | ||
| 2274 | fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void { | 2288 | fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void { |
| 2289 | const mod = func.bin_file.base.options.module.?; | ||
| 2275 | if (safety) { | 2290 | if (safety) { |
| 2276 | // TODO if the value is undef, write 0xaa bytes to dest | 2291 | // TODO if the value is undef, write 0xaa bytes to dest |
| 2277 | } else { | 2292 | } else { |
| ... | @@ -2290,17 +2305,13 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void | ... | @@ -2290,17 +2305,13 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void |
| 2290 | } else { | 2305 | } else { |
| 2291 | // at this point we have a non-natural alignment, we must | 2306 | // at this point we have a non-natural alignment, we must |
| 2292 | // load the value, and then shift+or the rhs into the result location. | 2307 | // load the value, and then shift+or the rhs into the result location. |
| 2293 | var int_ty_payload: Type.Payload.Bits = .{ | 2308 | const int_elem_ty = try mod.intType(.unsigned, ptr_info.host_size * 8); |
| 2294 | .base = .{ .tag = .int_unsigned }, | ||
| 2295 | .data = ptr_info.host_size * 8, | ||
| 2296 | }; | ||
| 2297 | const int_elem_ty = Type.initPayload(&int_ty_payload.base); | ||
| 2298 | 2309 | ||
| 2299 | if (isByRef(int_elem_ty, func.target)) { | 2310 | if (isByRef(int_elem_ty, mod)) { |
| 2300 | return func.fail("TODO: airStore for pointers to bitfields with backing type larger than 64bits", .{}); | 2311 | return func.fail("TODO: airStore for pointers to bitfields with backing type larger than 64bits", .{}); |
| 2301 | } | 2312 | } |
| 2302 | 2313 | ||
| 2303 | var mask = @intCast(u64, (@as(u65, 1) << @intCast(u7, ty.bitSize(func.target))) - 1); | 2314 | var mask = @intCast(u64, (@as(u65, 1) << @intCast(u7, ty.bitSize(mod))) - 1); |
| 2304 | mask <<= @intCast(u6, ptr_info.bit_offset); | 2315 | mask <<= @intCast(u6, ptr_info.bit_offset); |
| 2305 | mask ^= ~@as(u64, 0); | 2316 | mask ^= ~@as(u64, 0); |
| 2306 | const shift_val = if (ptr_info.host_size <= 4) | 2317 | const shift_val = if (ptr_info.host_size <= 4) |
| ... | @@ -2329,11 +2340,12 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void | ... | @@ -2329,11 +2340,12 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void |
| 2329 | 2340 | ||
| 2330 | fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void { | 2341 | fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void { |
| 2331 | assert(!(lhs != .stack and rhs == .stack)); | 2342 | assert(!(lhs != .stack and rhs == .stack)); |
| 2332 | const abi_size = ty.abiSize(func.target); | 2343 | const mod = func.bin_file.base.options.module.?; |
| 2333 | switch (ty.zigTypeTag()) { | 2344 | const abi_size = ty.abiSize(mod); |
| 2345 | switch (ty.zigTypeTag(mod)) { | ||
| 2334 | .ErrorUnion => { | 2346 | .ErrorUnion => { |
| 2335 | const pl_ty = ty.errorUnionPayload(); | 2347 | const pl_ty = ty.errorUnionPayload(); |
| 2336 | if (!pl_ty.hasRuntimeBitsIgnoreComptime()) { | 2348 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2337 | return func.store(lhs, rhs, Type.anyerror, 0); | 2349 | return func.store(lhs, rhs, Type.anyerror, 0); |
| 2338 | } | 2350 | } |
| 2339 | 2351 | ||
| ... | @@ -2341,26 +2353,26 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE | ... | @@ -2341,26 +2353,26 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2341 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); | 2353 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2342 | }, | 2354 | }, |
| 2343 | .Optional => { | 2355 | .Optional => { |
| 2344 | if (ty.isPtrLikeOptional()) { | 2356 | if (ty.isPtrLikeOptional(mod)) { |
| 2345 | return func.store(lhs, rhs, Type.usize, 0); | 2357 | return func.store(lhs, rhs, Type.usize, 0); |
| 2346 | } | 2358 | } |
| 2347 | var buf: Type.Payload.ElemType = undefined; | 2359 | var buf: Type.Payload.ElemType = undefined; |
| 2348 | const pl_ty = ty.optionalChild(&buf); | 2360 | const pl_ty = ty.optionalChild(&buf); |
| 2349 | if (!pl_ty.hasRuntimeBitsIgnoreComptime()) { | 2361 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2350 | return func.store(lhs, rhs, Type.u8, 0); | 2362 | return func.store(lhs, rhs, Type.u8, 0); |
| 2351 | } | 2363 | } |
| 2352 | if (pl_ty.zigTypeTag() == .ErrorSet) { | 2364 | if (pl_ty.zigTypeTag(mod) == .ErrorSet) { |
| 2353 | return func.store(lhs, rhs, Type.anyerror, 0); | 2365 | return func.store(lhs, rhs, Type.anyerror, 0); |
| 2354 | } | 2366 | } |
| 2355 | 2367 | ||
| 2356 | const len = @intCast(u32, abi_size); | 2368 | const len = @intCast(u32, abi_size); |
| 2357 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); | 2369 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2358 | }, | 2370 | }, |
| 2359 | .Struct, .Array, .Union => if (isByRef(ty, func.target)) { | 2371 | .Struct, .Array, .Union => if (isByRef(ty, mod)) { |
| 2360 | const len = @intCast(u32, abi_size); | 2372 | const len = @intCast(u32, abi_size); |
| 2361 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); | 2373 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2362 | }, | 2374 | }, |
| 2363 | .Vector => switch (determineSimdStoreStrategy(ty, func.target)) { | 2375 | .Vector => switch (determineSimdStoreStrategy(ty, mod)) { |
| 2364 | .unrolled => { | 2376 | .unrolled => { |
| 2365 | const len = @intCast(u32, abi_size); | 2377 | const len = @intCast(u32, abi_size); |
| 2366 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); | 2378 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); |
| ... | @@ -2374,7 +2386,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE | ... | @@ -2374,7 +2386,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2374 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ | 2386 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 2375 | std.wasm.simdOpcode(.v128_store), | 2387 | std.wasm.simdOpcode(.v128_store), |
| 2376 | offset + lhs.offset(), | 2388 | offset + lhs.offset(), |
| 2377 | ty.abiAlignment(func.target), | 2389 | ty.abiAlignment(mod), |
| 2378 | }); | 2390 | }); |
| 2379 | return func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); | 2391 | return func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 2380 | }, | 2392 | }, |
| ... | @@ -2404,7 +2416,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE | ... | @@ -2404,7 +2416,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2404 | try func.store(.{ .stack = {} }, msb, Type.u64, 8 + lhs.offset()); | 2416 | try func.store(.{ .stack = {} }, msb, Type.u64, 8 + lhs.offset()); |
| 2405 | return; | 2417 | return; |
| 2406 | } else if (abi_size > 16) { | 2418 | } else if (abi_size > 16) { |
| 2407 | try func.memcpy(lhs, rhs, .{ .imm32 = @intCast(u32, ty.abiSize(func.target)) }); | 2419 | try func.memcpy(lhs, rhs, .{ .imm32 = @intCast(u32, ty.abiSize(mod)) }); |
| 2408 | }, | 2420 | }, |
| 2409 | else => if (abi_size > 8) { | 2421 | else => if (abi_size > 8) { |
| 2410 | return func.fail("TODO: `store` for type `{}` with abisize `{d}`", .{ | 2422 | return func.fail("TODO: `store` for type `{}` with abisize `{d}`", .{ |
| ... | @@ -2418,7 +2430,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE | ... | @@ -2418,7 +2430,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2418 | // into lhs, so we calculate that and emit that instead | 2430 | // into lhs, so we calculate that and emit that instead |
| 2419 | try func.lowerToStack(rhs); | 2431 | try func.lowerToStack(rhs); |
| 2420 | 2432 | ||
| 2421 | const valtype = typeToValtype(ty, func.target); | 2433 | const valtype = typeToValtype(ty, mod); |
| 2422 | const opcode = buildOpcode(.{ | 2434 | const opcode = buildOpcode(.{ |
| 2423 | .valtype1 = valtype, | 2435 | .valtype1 = valtype, |
| 2424 | .width = @intCast(u8, abi_size * 8), | 2436 | .width = @intCast(u8, abi_size * 8), |
| ... | @@ -2428,21 +2440,22 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE | ... | @@ -2428,21 +2440,22 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2428 | // store rhs value at stack pointer's location in memory | 2440 | // store rhs value at stack pointer's location in memory |
| 2429 | try func.addMemArg( | 2441 | try func.addMemArg( |
| 2430 | Mir.Inst.Tag.fromOpcode(opcode), | 2442 | Mir.Inst.Tag.fromOpcode(opcode), |
| 2431 | .{ .offset = offset + lhs.offset(), .alignment = ty.abiAlignment(func.target) }, | 2443 | .{ .offset = offset + lhs.offset(), .alignment = ty.abiAlignment(mod) }, |
| 2432 | ); | 2444 | ); |
| 2433 | } | 2445 | } |
| 2434 | 2446 | ||
| 2435 | fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 2447 | fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2448 | const mod = func.bin_file.base.options.module.?; | ||
| 2436 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 2449 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 2437 | const operand = try func.resolveInst(ty_op.operand); | 2450 | const operand = try func.resolveInst(ty_op.operand); |
| 2438 | const ty = func.air.getRefType(ty_op.ty); | 2451 | const ty = func.air.getRefType(ty_op.ty); |
| 2439 | const ptr_ty = func.air.typeOf(ty_op.operand); | 2452 | const ptr_ty = func.air.typeOf(ty_op.operand); |
| 2440 | const ptr_info = ptr_ty.ptrInfo().data; | 2453 | const ptr_info = ptr_ty.ptrInfo().data; |
| 2441 | 2454 | ||
| 2442 | if (!ty.hasRuntimeBitsIgnoreComptime()) return func.finishAir(inst, .none, &.{ty_op.operand}); | 2455 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return func.finishAir(inst, .none, &.{ty_op.operand}); |
| 2443 | 2456 | ||
| 2444 | const result = result: { | 2457 | const result = result: { |
| 2445 | if (isByRef(ty, func.target)) { | 2458 | if (isByRef(ty, mod)) { |
| 2446 | const new_local = try func.allocStack(ty); | 2459 | const new_local = try func.allocStack(ty); |
| 2447 | try func.store(new_local, operand, ty, 0); | 2460 | try func.store(new_local, operand, ty, 0); |
| 2448 | break :result new_local; | 2461 | break :result new_local; |
| ... | @@ -2455,11 +2468,7 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2455,11 +2468,7 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2455 | 2468 | ||
| 2456 | // at this point we have a non-natural alignment, we must | 2469 | // at this point we have a non-natural alignment, we must |
| 2457 | // shift the value to obtain the correct bit. | 2470 | // shift the value to obtain the correct bit. |
| 2458 | var int_ty_payload: Type.Payload.Bits = .{ | 2471 | const int_elem_ty = try mod.intType(.unsigned, ptr_info.host_size * 8); |
| 2459 | .base = .{ .tag = .int_unsigned }, | ||
| 2460 | .data = ptr_info.host_size * 8, | ||
| 2461 | }; | ||
| 2462 | const int_elem_ty = Type.initPayload(&int_ty_payload.base); | ||
| 2463 | const shift_val = if (ptr_info.host_size <= 4) | 2472 | const shift_val = if (ptr_info.host_size <= 4) |
| 2464 | WValue{ .imm32 = ptr_info.bit_offset } | 2473 | WValue{ .imm32 = ptr_info.bit_offset } |
| 2465 | else if (ptr_info.host_size <= 8) | 2474 | else if (ptr_info.host_size <= 8) |
| ... | @@ -2479,25 +2488,26 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2479,25 +2488,26 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2479 | /// Loads an operand from the linear memory section. | 2488 | /// Loads an operand from the linear memory section. |
| 2480 | /// NOTE: Leaves the value on the stack. | 2489 | /// NOTE: Leaves the value on the stack. |
| 2481 | fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue { | 2490 | fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue { |
| 2491 | const mod = func.bin_file.base.options.module.?; | ||
| 2482 | // load local's value from memory by its stack position | 2492 | // load local's value from memory by its stack position |
| 2483 | try func.emitWValue(operand); | 2493 | try func.emitWValue(operand); |
| 2484 | 2494 | ||
| 2485 | if (ty.zigTypeTag() == .Vector) { | 2495 | if (ty.zigTypeTag(mod) == .Vector) { |
| 2486 | // TODO: Add helper functions for simd opcodes | 2496 | // TODO: Add helper functions for simd opcodes |
| 2487 | const extra_index = @intCast(u32, func.mir_extra.items.len); | 2497 | const extra_index = @intCast(u32, func.mir_extra.items.len); |
| 2488 | // stores as := opcode, offset, alignment (opcode::memarg) | 2498 | // stores as := opcode, offset, alignment (opcode::memarg) |
| 2489 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ | 2499 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 2490 | std.wasm.simdOpcode(.v128_load), | 2500 | std.wasm.simdOpcode(.v128_load), |
| 2491 | offset + operand.offset(), | 2501 | offset + operand.offset(), |
| 2492 | ty.abiAlignment(func.target), | 2502 | ty.abiAlignment(mod), |
| 2493 | }); | 2503 | }); |
| 2494 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); | 2504 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 2495 | return WValue{ .stack = {} }; | 2505 | return WValue{ .stack = {} }; |
| 2496 | } | 2506 | } |
| 2497 | 2507 | ||
| 2498 | const abi_size = @intCast(u8, ty.abiSize(func.target)); | 2508 | const abi_size = @intCast(u8, ty.abiSize(mod)); |
| 2499 | const opcode = buildOpcode(.{ | 2509 | const opcode = buildOpcode(.{ |
| 2500 | .valtype1 = typeToValtype(ty, func.target), | 2510 | .valtype1 = typeToValtype(ty, mod), |
| 2501 | .width = abi_size * 8, | 2511 | .width = abi_size * 8, |
| 2502 | .op = .load, | 2512 | .op = .load, |
| 2503 | .signedness = .unsigned, | 2513 | .signedness = .unsigned, |
| ... | @@ -2505,7 +2515,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu | ... | @@ -2505,7 +2515,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu |
| 2505 | 2515 | ||
| 2506 | try func.addMemArg( | 2516 | try func.addMemArg( |
| 2507 | Mir.Inst.Tag.fromOpcode(opcode), | 2517 | Mir.Inst.Tag.fromOpcode(opcode), |
| 2508 | .{ .offset = offset + operand.offset(), .alignment = ty.abiAlignment(func.target) }, | 2518 | .{ .offset = offset + operand.offset(), .alignment = ty.abiAlignment(mod) }, |
| 2509 | ); | 2519 | ); |
| 2510 | 2520 | ||
| 2511 | return WValue{ .stack = {} }; | 2521 | return WValue{ .stack = {} }; |
| ... | @@ -2516,8 +2526,9 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2516,8 +2526,9 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2516 | const arg = func.args[arg_index]; | 2526 | const arg = func.args[arg_index]; |
| 2517 | const cc = func.decl.ty.fnInfo().cc; | 2527 | const cc = func.decl.ty.fnInfo().cc; |
| 2518 | const arg_ty = func.air.typeOfIndex(inst); | 2528 | const arg_ty = func.air.typeOfIndex(inst); |
| 2529 | const mod = func.bin_file.base.options.module.?; | ||
| 2519 | if (cc == .C) { | 2530 | if (cc == .C) { |
| 2520 | const arg_classes = abi.classifyType(arg_ty, func.target); | 2531 | const arg_classes = abi.classifyType(arg_ty, mod); |
| 2521 | for (arg_classes) |class| { | 2532 | for (arg_classes) |class| { |
| 2522 | if (class != .none) { | 2533 | if (class != .none) { |
| 2523 | func.arg_index += 1; | 2534 | func.arg_index += 1; |
| ... | @@ -2527,7 +2538,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2527,7 +2538,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2527 | // When we have an argument that's passed using more than a single parameter, | 2538 | // When we have an argument that's passed using more than a single parameter, |
| 2528 | // we combine them into a single stack value | 2539 | // we combine them into a single stack value |
| 2529 | if (arg_classes[0] == .direct and arg_classes[1] == .direct) { | 2540 | if (arg_classes[0] == .direct and arg_classes[1] == .direct) { |
| 2530 | if (arg_ty.zigTypeTag() != .Int and arg_ty.zigTypeTag() != .Float) { | 2541 | if (arg_ty.zigTypeTag(mod) != .Int and arg_ty.zigTypeTag(mod) != .Float) { |
| 2531 | return func.fail( | 2542 | return func.fail( |
| 2532 | "TODO: Implement C-ABI argument for type '{}'", | 2543 | "TODO: Implement C-ABI argument for type '{}'", |
| 2533 | .{arg_ty.fmt(func.bin_file.base.options.module.?)}, | 2544 | .{arg_ty.fmt(func.bin_file.base.options.module.?)}, |
| ... | @@ -2557,6 +2568,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2557,6 +2568,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2557 | } | 2568 | } |
| 2558 | 2569 | ||
| 2559 | fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | 2570 | fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 2571 | const mod = func.bin_file.base.options.module.?; | ||
| 2560 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 2572 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 2561 | const lhs = try func.resolveInst(bin_op.lhs); | 2573 | const lhs = try func.resolveInst(bin_op.lhs); |
| 2562 | const rhs = try func.resolveInst(bin_op.rhs); | 2574 | const rhs = try func.resolveInst(bin_op.rhs); |
| ... | @@ -2570,10 +2582,10 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | ... | @@ -2570,10 +2582,10 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 2570 | // For big integers we can ignore this as we will call into compiler-rt which handles this. | 2582 | // For big integers we can ignore this as we will call into compiler-rt which handles this. |
| 2571 | const result = switch (op) { | 2583 | const result = switch (op) { |
| 2572 | .shr, .shl => res: { | 2584 | .shr, .shl => res: { |
| 2573 | const lhs_wasm_bits = toWasmBits(@intCast(u16, lhs_ty.bitSize(func.target))) orelse { | 2585 | const lhs_wasm_bits = toWasmBits(@intCast(u16, lhs_ty.bitSize(mod))) orelse { |
| 2574 | return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)}); | 2586 | return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)}); |
| 2575 | }; | 2587 | }; |
| 2576 | const rhs_wasm_bits = toWasmBits(@intCast(u16, rhs_ty.bitSize(func.target))).?; | 2588 | const rhs_wasm_bits = toWasmBits(@intCast(u16, rhs_ty.bitSize(mod))).?; |
| 2577 | const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: { | 2589 | const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: { |
| 2578 | const tmp = try func.intcast(rhs, rhs_ty, lhs_ty); | 2590 | const tmp = try func.intcast(rhs, rhs_ty, lhs_ty); |
| 2579 | break :blk try tmp.toLocal(func, lhs_ty); | 2591 | break :blk try tmp.toLocal(func, lhs_ty); |
| ... | @@ -2593,6 +2605,7 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | ... | @@ -2593,6 +2605,7 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 2593 | /// Performs a binary operation on the given `WValue`'s | 2605 | /// Performs a binary operation on the given `WValue`'s |
| 2594 | /// NOTE: THis leaves the value on top of the stack. | 2606 | /// NOTE: THis leaves the value on top of the stack. |
| 2595 | fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue { | 2607 | fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue { |
| 2608 | const mod = func.bin_file.base.options.module.?; | ||
| 2596 | assert(!(lhs != .stack and rhs == .stack)); | 2609 | assert(!(lhs != .stack and rhs == .stack)); |
| 2597 | 2610 | ||
| 2598 | if (ty.isAnyFloat()) { | 2611 | if (ty.isAnyFloat()) { |
| ... | @@ -2600,8 +2613,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! | ... | @@ -2600,8 +2613,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! |
| 2600 | return func.floatOp(float_op, ty, &.{ lhs, rhs }); | 2613 | return func.floatOp(float_op, ty, &.{ lhs, rhs }); |
| 2601 | } | 2614 | } |
| 2602 | 2615 | ||
| 2603 | if (isByRef(ty, func.target)) { | 2616 | if (isByRef(ty, mod)) { |
| 2604 | if (ty.zigTypeTag() == .Int) { | 2617 | if (ty.zigTypeTag(mod) == .Int) { |
| 2605 | return func.binOpBigInt(lhs, rhs, ty, op); | 2618 | return func.binOpBigInt(lhs, rhs, ty, op); |
| 2606 | } else { | 2619 | } else { |
| 2607 | return func.fail( | 2620 | return func.fail( |
| ... | @@ -2613,8 +2626,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! | ... | @@ -2613,8 +2626,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! |
| 2613 | 2626 | ||
| 2614 | const opcode: wasm.Opcode = buildOpcode(.{ | 2627 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 2615 | .op = op, | 2628 | .op = op, |
| 2616 | .valtype1 = typeToValtype(ty, func.target), | 2629 | .valtype1 = typeToValtype(ty, mod), |
| 2617 | .signedness = if (ty.isSignedInt()) .signed else .unsigned, | 2630 | .signedness = if (ty.isSignedInt(mod)) .signed else .unsigned, |
| 2618 | }); | 2631 | }); |
| 2619 | try func.emitWValue(lhs); | 2632 | try func.emitWValue(lhs); |
| 2620 | try func.emitWValue(rhs); | 2633 | try func.emitWValue(rhs); |
| ... | @@ -2625,7 +2638,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! | ... | @@ -2625,7 +2638,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! |
| 2625 | } | 2638 | } |
| 2626 | 2639 | ||
| 2627 | fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue { | 2640 | fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue { |
| 2628 | if (ty.intInfo(func.target).bits > 128) { | 2641 | const mod = func.bin_file.base.options.module.?; |
| 2642 | if (ty.intInfo(mod).bits > 128) { | ||
| 2629 | return func.fail("TODO: Implement binary operation for big integers larger than 128 bits", .{}); | 2643 | return func.fail("TODO: Implement binary operation for big integers larger than 128 bits", .{}); |
| 2630 | } | 2644 | } |
| 2631 | 2645 | ||
| ... | @@ -2763,7 +2777,8 @@ fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError | ... | @@ -2763,7 +2777,8 @@ fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError |
| 2763 | } | 2777 | } |
| 2764 | 2778 | ||
| 2765 | fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) InnerError!WValue { | 2779 | fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) InnerError!WValue { |
| 2766 | if (ty.zigTypeTag() == .Vector) { | 2780 | const mod = func.bin_file.base.options.module.?; |
| 2781 | if (ty.zigTypeTag(mod) == .Vector) { | ||
| 2767 | return func.fail("TODO: Implement floatOps for vectors", .{}); | 2782 | return func.fail("TODO: Implement floatOps for vectors", .{}); |
| 2768 | } | 2783 | } |
| 2769 | 2784 | ||
| ... | @@ -2773,7 +2788,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In | ... | @@ -2773,7 +2788,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In |
| 2773 | for (args) |operand| { | 2788 | for (args) |operand| { |
| 2774 | try func.emitWValue(operand); | 2789 | try func.emitWValue(operand); |
| 2775 | } | 2790 | } |
| 2776 | const opcode = buildOpcode(.{ .op = op, .valtype1 = typeToValtype(ty, func.target) }); | 2791 | const opcode = buildOpcode(.{ .op = op, .valtype1 = typeToValtype(ty, mod) }); |
| 2777 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); | 2792 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| 2778 | return .stack; | 2793 | return .stack; |
| 2779 | } | 2794 | } |
| ... | @@ -2827,6 +2842,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In | ... | @@ -2827,6 +2842,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In |
| 2827 | } | 2842 | } |
| 2828 | 2843 | ||
| 2829 | fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | 2844 | fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 2845 | const mod = func.bin_file.base.options.module.?; | ||
| 2830 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 2846 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 2831 | 2847 | ||
| 2832 | const lhs = try func.resolveInst(bin_op.lhs); | 2848 | const lhs = try func.resolveInst(bin_op.lhs); |
| ... | @@ -2834,7 +2850,7 @@ fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | ... | @@ -2834,7 +2850,7 @@ fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 2834 | const lhs_ty = func.air.typeOf(bin_op.lhs); | 2850 | const lhs_ty = func.air.typeOf(bin_op.lhs); |
| 2835 | const rhs_ty = func.air.typeOf(bin_op.rhs); | 2851 | const rhs_ty = func.air.typeOf(bin_op.rhs); |
| 2836 | 2852 | ||
| 2837 | if (lhs_ty.zigTypeTag() == .Vector or rhs_ty.zigTypeTag() == .Vector) { | 2853 | if (lhs_ty.zigTypeTag(mod) == .Vector or rhs_ty.zigTypeTag(mod) == .Vector) { |
| 2838 | return func.fail("TODO: Implement wrapping arithmetic for vectors", .{}); | 2854 | return func.fail("TODO: Implement wrapping arithmetic for vectors", .{}); |
| 2839 | } | 2855 | } |
| 2840 | 2856 | ||
| ... | @@ -2845,10 +2861,10 @@ fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | ... | @@ -2845,10 +2861,10 @@ fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 2845 | // For big integers we can ignore this as we will call into compiler-rt which handles this. | 2861 | // For big integers we can ignore this as we will call into compiler-rt which handles this. |
| 2846 | const result = switch (op) { | 2862 | const result = switch (op) { |
| 2847 | .shr, .shl => res: { | 2863 | .shr, .shl => res: { |
| 2848 | const lhs_wasm_bits = toWasmBits(@intCast(u16, lhs_ty.bitSize(func.target))) orelse { | 2864 | const lhs_wasm_bits = toWasmBits(@intCast(u16, lhs_ty.bitSize(mod))) orelse { |
| 2849 | return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)}); | 2865 | return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)}); |
| 2850 | }; | 2866 | }; |
| 2851 | const rhs_wasm_bits = toWasmBits(@intCast(u16, rhs_ty.bitSize(func.target))).?; | 2867 | const rhs_wasm_bits = toWasmBits(@intCast(u16, rhs_ty.bitSize(mod))).?; |
| 2852 | const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: { | 2868 | const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: { |
| 2853 | const tmp = try func.intcast(rhs, rhs_ty, lhs_ty); | 2869 | const tmp = try func.intcast(rhs, rhs_ty, lhs_ty); |
| 2854 | break :blk try tmp.toLocal(func, lhs_ty); | 2870 | break :blk try tmp.toLocal(func, lhs_ty); |
| ... | @@ -2877,8 +2893,9 @@ fn wrapBinOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr | ... | @@ -2877,8 +2893,9 @@ fn wrapBinOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr |
| 2877 | /// Asserts `Type` is <= 128 bits. | 2893 | /// Asserts `Type` is <= 128 bits. |
| 2878 | /// NOTE: When the Type is <= 64 bits, leaves the value on top of the stack. | 2894 | /// NOTE: When the Type is <= 64 bits, leaves the value on top of the stack. |
| 2879 | fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue { | 2895 | fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue { |
| 2880 | assert(ty.abiSize(func.target) <= 16); | 2896 | const mod = func.bin_file.base.options.module.?; |
| 2881 | const bitsize = @intCast(u16, ty.bitSize(func.target)); | 2897 | assert(ty.abiSize(mod) <= 16); |
| 2898 | const bitsize = @intCast(u16, ty.bitSize(mod)); | ||
| 2882 | const wasm_bits = toWasmBits(bitsize) orelse { | 2899 | const wasm_bits = toWasmBits(bitsize) orelse { |
| 2883 | return func.fail("TODO: Implement wrapOperand for bitsize '{d}'", .{bitsize}); | 2900 | return func.fail("TODO: Implement wrapOperand for bitsize '{d}'", .{bitsize}); |
| 2884 | }; | 2901 | }; |
| ... | @@ -2915,6 +2932,7 @@ fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue { | ... | @@ -2915,6 +2932,7 @@ fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue { |
| 2915 | } | 2932 | } |
| 2916 | 2933 | ||
| 2917 | fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue { | 2934 | fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue { |
| 2935 | const mod = func.bin_file.base.options.module.?; | ||
| 2918 | switch (ptr_val.tag()) { | 2936 | switch (ptr_val.tag()) { |
| 2919 | .decl_ref_mut => { | 2937 | .decl_ref_mut => { |
| 2920 | const decl_index = ptr_val.castTag(.decl_ref_mut).?.data.decl_index; | 2938 | const decl_index = ptr_val.castTag(.decl_ref_mut).?.data.decl_index; |
| ... | @@ -2932,15 +2950,15 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue | ... | @@ -2932,15 +2950,15 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue |
| 2932 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; | 2950 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| 2933 | const parent_ty = field_ptr.container_ty; | 2951 | const parent_ty = field_ptr.container_ty; |
| 2934 | 2952 | ||
| 2935 | const field_offset = switch (parent_ty.zigTypeTag()) { | 2953 | const field_offset = switch (parent_ty.zigTypeTag(mod)) { |
| 2936 | .Struct => switch (parent_ty.containerLayout()) { | 2954 | .Struct => switch (parent_ty.containerLayout()) { |
| 2937 | .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, func.target), | 2955 | .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, mod), |
| 2938 | else => parent_ty.structFieldOffset(field_ptr.field_index, func.target), | 2956 | else => parent_ty.structFieldOffset(field_ptr.field_index, mod), |
| 2939 | }, | 2957 | }, |
| 2940 | .Union => switch (parent_ty.containerLayout()) { | 2958 | .Union => switch (parent_ty.containerLayout()) { |
| 2941 | .Packed => 0, | 2959 | .Packed => 0, |
| 2942 | else => blk: { | 2960 | else => blk: { |
| 2943 | const layout: Module.Union.Layout = parent_ty.unionGetLayout(func.target); | 2961 | const layout: Module.Union.Layout = parent_ty.unionGetLayout(mod); |
| 2944 | if (layout.payload_size == 0) break :blk 0; | 2962 | if (layout.payload_size == 0) break :blk 0; |
| 2945 | if (layout.payload_align > layout.tag_align) break :blk 0; | 2963 | if (layout.payload_align > layout.tag_align) break :blk 0; |
| 2946 | 2964 | ||
| ... | @@ -2964,7 +2982,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue | ... | @@ -2964,7 +2982,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue |
| 2964 | .elem_ptr => { | 2982 | .elem_ptr => { |
| 2965 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; | 2983 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; |
| 2966 | const index = elem_ptr.index; | 2984 | const index = elem_ptr.index; |
| 2967 | const elem_offset = index * elem_ptr.elem_ty.abiSize(func.target); | 2985 | const elem_offset = index * elem_ptr.elem_ty.abiSize(mod); |
| 2968 | return func.lowerParentPtr(elem_ptr.array_ptr, offset + @intCast(u32, elem_offset)); | 2986 | return func.lowerParentPtr(elem_ptr.array_ptr, offset + @intCast(u32, elem_offset)); |
| 2969 | }, | 2987 | }, |
| 2970 | .opt_payload_ptr => { | 2988 | .opt_payload_ptr => { |
| ... | @@ -2976,9 +2994,9 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue | ... | @@ -2976,9 +2994,9 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue |
| 2976 | } | 2994 | } |
| 2977 | 2995 | ||
| 2978 | fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.Index, offset: u32) InnerError!WValue { | 2996 | fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.Index, offset: u32) InnerError!WValue { |
| 2979 | const module = func.bin_file.base.options.module.?; | 2997 | const mod = func.bin_file.base.options.module.?; |
| 2980 | const decl = module.declPtr(decl_index); | 2998 | const decl = mod.declPtr(decl_index); |
| 2981 | module.markDeclAlive(decl); | 2999 | mod.markDeclAlive(decl); |
| 2982 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 3000 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 2983 | .base = .{ .tag = .single_mut_pointer }, | 3001 | .base = .{ .tag = .single_mut_pointer }, |
| 2984 | .data = decl.ty, | 3002 | .data = decl.ty, |
| ... | @@ -2992,18 +3010,18 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: Module.Decl.Ind | ... | @@ -2992,18 +3010,18 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: Module.Decl.Ind |
| 2992 | return WValue{ .memory = try func.bin_file.lowerUnnamedConst(tv, decl_index) }; | 3010 | return WValue{ .memory = try func.bin_file.lowerUnnamedConst(tv, decl_index) }; |
| 2993 | } | 3011 | } |
| 2994 | 3012 | ||
| 2995 | const module = func.bin_file.base.options.module.?; | 3013 | const mod = func.bin_file.base.options.module.?; |
| 2996 | const decl = module.declPtr(decl_index); | 3014 | const decl = mod.declPtr(decl_index); |
| 2997 | if (decl.ty.zigTypeTag() != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime()) { | 3015 | if (decl.ty.zigTypeTag(mod) != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2998 | return WValue{ .imm32 = 0xaaaaaaaa }; | 3016 | return WValue{ .imm32 = 0xaaaaaaaa }; |
| 2999 | } | 3017 | } |
| 3000 | 3018 | ||
| 3001 | module.markDeclAlive(decl); | 3019 | mod.markDeclAlive(decl); |
| 3002 | const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index); | 3020 | const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index); |
| 3003 | const atom = func.bin_file.getAtom(atom_index); | 3021 | const atom = func.bin_file.getAtom(atom_index); |
| 3004 | 3022 | ||
| 3005 | const target_sym_index = atom.sym_index; | 3023 | const target_sym_index = atom.sym_index; |
| 3006 | if (decl.ty.zigTypeTag() == .Fn) { | 3024 | if (decl.ty.zigTypeTag(mod) == .Fn) { |
| 3007 | try func.bin_file.addTableFunction(target_sym_index); | 3025 | try func.bin_file.addTableFunction(target_sym_index); |
| 3008 | return WValue{ .function_index = target_sym_index }; | 3026 | return WValue{ .function_index = target_sym_index }; |
| 3009 | } else if (offset == 0) { | 3027 | } else if (offset == 0) { |
| ... | @@ -3041,31 +3059,31 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { | ... | @@ -3041,31 +3059,31 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 3041 | const decl_index = decl_ref_mut.data.decl_index; | 3059 | const decl_index = decl_ref_mut.data.decl_index; |
| 3042 | return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index, 0); | 3060 | return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index, 0); |
| 3043 | } | 3061 | } |
| 3044 | const target = func.target; | 3062 | const mod = func.bin_file.base.options.module.?; |
| 3045 | switch (ty.zigTypeTag()) { | 3063 | switch (ty.zigTypeTag(mod)) { |
| 3046 | .Void => return WValue{ .none = {} }, | 3064 | .Void => return WValue{ .none = {} }, |
| 3047 | .Int => { | 3065 | .Int => { |
| 3048 | const int_info = ty.intInfo(func.target); | 3066 | const int_info = ty.intInfo(mod); |
| 3049 | switch (int_info.signedness) { | 3067 | switch (int_info.signedness) { |
| 3050 | .signed => switch (int_info.bits) { | 3068 | .signed => switch (int_info.bits) { |
| 3051 | 0...32 => return WValue{ .imm32 = @intCast(u32, toTwosComplement( | 3069 | 0...32 => return WValue{ .imm32 = @intCast(u32, toTwosComplement( |
| 3052 | val.toSignedInt(target), | 3070 | val.toSignedInt(mod), |
| 3053 | @intCast(u6, int_info.bits), | 3071 | @intCast(u6, int_info.bits), |
| 3054 | )) }, | 3072 | )) }, |
| 3055 | 33...64 => return WValue{ .imm64 = toTwosComplement( | 3073 | 33...64 => return WValue{ .imm64 = toTwosComplement( |
| 3056 | val.toSignedInt(target), | 3074 | val.toSignedInt(mod), |
| 3057 | @intCast(u7, int_info.bits), | 3075 | @intCast(u7, int_info.bits), |
| 3058 | ) }, | 3076 | ) }, |
| 3059 | else => unreachable, | 3077 | else => unreachable, |
| 3060 | }, | 3078 | }, |
| 3061 | .unsigned => switch (int_info.bits) { | 3079 | .unsigned => switch (int_info.bits) { |
| 3062 | 0...32 => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(target)) }, | 3080 | 0...32 => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(mod)) }, |
| 3063 | 33...64 => return WValue{ .imm64 = val.toUnsignedInt(target) }, | 3081 | 33...64 => return WValue{ .imm64 = val.toUnsignedInt(mod) }, |
| 3064 | else => unreachable, | 3082 | else => unreachable, |
| 3065 | }, | 3083 | }, |
| 3066 | } | 3084 | } |
| 3067 | }, | 3085 | }, |
| 3068 | .Bool => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(target)) }, | 3086 | .Bool => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(mod)) }, |
| 3069 | .Float => switch (ty.floatBits(func.target)) { | 3087 | .Float => switch (ty.floatBits(func.target)) { |
| 3070 | 16 => return WValue{ .imm32 = @bitCast(u16, val.toFloat(f16)) }, | 3088 | 16 => return WValue{ .imm32 = @bitCast(u16, val.toFloat(f16)) }, |
| 3071 | 32 => return WValue{ .float32 = val.toFloat(f32) }, | 3089 | 32 => return WValue{ .float32 = val.toFloat(f32) }, |
| ... | @@ -3074,7 +3092,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { | ... | @@ -3074,7 +3092,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 3074 | }, | 3092 | }, |
| 3075 | .Pointer => switch (val.tag()) { | 3093 | .Pointer => switch (val.tag()) { |
| 3076 | .field_ptr, .elem_ptr, .opt_payload_ptr => return func.lowerParentPtr(val, 0), | 3094 | .field_ptr, .elem_ptr, .opt_payload_ptr => return func.lowerParentPtr(val, 0), |
| 3077 | .int_u64, .one => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(target)) }, | 3095 | .int_u64, .one => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(mod)) }, |
| 3078 | .zero, .null_value => return WValue{ .imm32 = 0 }, | 3096 | .zero, .null_value => return WValue{ .imm32 = 0 }, |
| 3079 | else => return func.fail("Wasm TODO: lowerConstant for other const pointer tag {}", .{val.tag()}), | 3097 | else => return func.fail("Wasm TODO: lowerConstant for other const pointer tag {}", .{val.tag()}), |
| 3080 | }, | 3098 | }, |
| ... | @@ -3100,8 +3118,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { | ... | @@ -3100,8 +3118,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 3100 | else => return func.fail("TODO: lowerConstant for enum tag: {}", .{ty.tag()}), | 3118 | else => return func.fail("TODO: lowerConstant for enum tag: {}", .{ty.tag()}), |
| 3101 | } | 3119 | } |
| 3102 | } else { | 3120 | } else { |
| 3103 | var int_tag_buffer: Type.Payload.Bits = undefined; | 3121 | const int_tag_ty = ty.intTagType(); |
| 3104 | const int_tag_ty = ty.intTagType(&int_tag_buffer); | ||
| 3105 | return func.lowerConstant(val, int_tag_ty); | 3122 | return func.lowerConstant(val, int_tag_ty); |
| 3106 | } | 3123 | } |
| 3107 | }, | 3124 | }, |
| ... | @@ -3115,7 +3132,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { | ... | @@ -3115,7 +3132,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 3115 | .ErrorUnion => { | 3132 | .ErrorUnion => { |
| 3116 | const error_type = ty.errorUnionSet(); | 3133 | const error_type = ty.errorUnionSet(); |
| 3117 | const payload_type = ty.errorUnionPayload(); | 3134 | const payload_type = ty.errorUnionPayload(); |
| 3118 | if (!payload_type.hasRuntimeBitsIgnoreComptime()) { | 3135 | if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3119 | // We use the error type directly as the type. | 3136 | // We use the error type directly as the type. |
| 3120 | const is_pl = val.errorUnionIsPayload(); | 3137 | const is_pl = val.errorUnionIsPayload(); |
| 3121 | const err_val = if (!is_pl) val else Value.initTag(.zero); | 3138 | const err_val = if (!is_pl) val else Value.initTag(.zero); |
| ... | @@ -3123,12 +3140,12 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { | ... | @@ -3123,12 +3140,12 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 3123 | } | 3140 | } |
| 3124 | return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{}); | 3141 | return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{}); |
| 3125 | }, | 3142 | }, |
| 3126 | .Optional => if (ty.optionalReprIsPayload()) { | 3143 | .Optional => if (ty.optionalReprIsPayload(mod)) { |
| 3127 | var buf: Type.Payload.ElemType = undefined; | 3144 | var buf: Type.Payload.ElemType = undefined; |
| 3128 | const pl_ty = ty.optionalChild(&buf); | 3145 | const pl_ty = ty.optionalChild(&buf); |
| 3129 | if (val.castTag(.opt_payload)) |payload| { | 3146 | if (val.castTag(.opt_payload)) |payload| { |
| 3130 | return func.lowerConstant(payload.data, pl_ty); | 3147 | return func.lowerConstant(payload.data, pl_ty); |
| 3131 | } else if (val.isNull()) { | 3148 | } else if (val.isNull(mod)) { |
| 3132 | return WValue{ .imm32 = 0 }; | 3149 | return WValue{ .imm32 = 0 }; |
| 3133 | } else { | 3150 | } else { |
| 3134 | return func.lowerConstant(val, pl_ty); | 3151 | return func.lowerConstant(val, pl_ty); |
| ... | @@ -3150,7 +3167,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { | ... | @@ -3150,7 +3167,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 3150 | return func.lowerConstant(int_val, struct_obj.backing_int_ty); | 3167 | return func.lowerConstant(int_val, struct_obj.backing_int_ty); |
| 3151 | }, | 3168 | }, |
| 3152 | .Vector => { | 3169 | .Vector => { |
| 3153 | assert(determineSimdStoreStrategy(ty, target) == .direct); | 3170 | assert(determineSimdStoreStrategy(ty, mod) == .direct); |
| 3154 | var buf: [16]u8 = undefined; | 3171 | var buf: [16]u8 = undefined; |
| 3155 | val.writeToMemory(ty, func.bin_file.base.options.module.?, &buf) catch unreachable; | 3172 | val.writeToMemory(ty, func.bin_file.base.options.module.?, &buf) catch unreachable; |
| 3156 | return func.storeSimdImmd(buf); | 3173 | return func.storeSimdImmd(buf); |
| ... | @@ -3176,9 +3193,10 @@ fn storeSimdImmd(func: *CodeGen, value: [16]u8) !WValue { | ... | @@ -3176,9 +3193,10 @@ fn storeSimdImmd(func: *CodeGen, value: [16]u8) !WValue { |
| 3176 | } | 3193 | } |
| 3177 | 3194 | ||
| 3178 | fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { | 3195 | fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { |
| 3179 | switch (ty.zigTypeTag()) { | 3196 | const mod = func.bin_file.base.options.module.?; |
| 3197 | switch (ty.zigTypeTag(mod)) { | ||
| 3180 | .Bool, .ErrorSet => return WValue{ .imm32 = 0xaaaaaaaa }, | 3198 | .Bool, .ErrorSet => return WValue{ .imm32 = 0xaaaaaaaa }, |
| 3181 | .Int, .Enum => switch (ty.intInfo(func.target).bits) { | 3199 | .Int, .Enum => switch (ty.intInfo(mod).bits) { |
| 3182 | 0...32 => return WValue{ .imm32 = 0xaaaaaaaa }, | 3200 | 0...32 => return WValue{ .imm32 = 0xaaaaaaaa }, |
| 3183 | 33...64 => return WValue{ .imm64 = 0xaaaaaaaaaaaaaaaa }, | 3201 | 33...64 => return WValue{ .imm64 = 0xaaaaaaaaaaaaaaaa }, |
| 3184 | else => unreachable, | 3202 | else => unreachable, |
| ... | @@ -3197,7 +3215,7 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { | ... | @@ -3197,7 +3215,7 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { |
| 3197 | .Optional => { | 3215 | .Optional => { |
| 3198 | var buf: Type.Payload.ElemType = undefined; | 3216 | var buf: Type.Payload.ElemType = undefined; |
| 3199 | const pl_ty = ty.optionalChild(&buf); | 3217 | const pl_ty = ty.optionalChild(&buf); |
| 3200 | if (ty.optionalReprIsPayload()) { | 3218 | if (ty.optionalReprIsPayload(mod)) { |
| 3201 | return func.emitUndefined(pl_ty); | 3219 | return func.emitUndefined(pl_ty); |
| 3202 | } | 3220 | } |
| 3203 | return WValue{ .imm32 = 0xaaaaaaaa }; | 3221 | return WValue{ .imm32 = 0xaaaaaaaa }; |
| ... | @@ -3210,7 +3228,7 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { | ... | @@ -3210,7 +3228,7 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { |
| 3210 | assert(struct_obj.layout == .Packed); | 3228 | assert(struct_obj.layout == .Packed); |
| 3211 | return func.emitUndefined(struct_obj.backing_int_ty); | 3229 | return func.emitUndefined(struct_obj.backing_int_ty); |
| 3212 | }, | 3230 | }, |
| 3213 | else => return func.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty.zigTypeTag()}), | 3231 | else => return func.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty.zigTypeTag(mod)}), |
| 3214 | } | 3232 | } |
| 3215 | } | 3233 | } |
| 3216 | 3234 | ||
| ... | @@ -3218,8 +3236,8 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { | ... | @@ -3218,8 +3236,8 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { |
| 3218 | /// It's illegal to provide a value with a type that cannot be represented | 3236 | /// It's illegal to provide a value with a type that cannot be represented |
| 3219 | /// as an integer value. | 3237 | /// as an integer value. |
| 3220 | fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 { | 3238 | fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 { |
| 3221 | const target = func.target; | 3239 | const mod = func.bin_file.base.options.module.?; |
| 3222 | switch (ty.zigTypeTag()) { | 3240 | switch (ty.zigTypeTag(mod)) { |
| 3223 | .Enum => { | 3241 | .Enum => { |
| 3224 | if (val.castTag(.enum_field_index)) |field_index| { | 3242 | if (val.castTag(.enum_field_index)) |field_index| { |
| 3225 | switch (ty.tag()) { | 3243 | switch (ty.tag()) { |
| ... | @@ -3239,35 +3257,35 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 { | ... | @@ -3239,35 +3257,35 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 { |
| 3239 | else => unreachable, | 3257 | else => unreachable, |
| 3240 | } | 3258 | } |
| 3241 | } else { | 3259 | } else { |
| 3242 | var int_tag_buffer: Type.Payload.Bits = undefined; | 3260 | const int_tag_ty = ty.intTagType(); |
| 3243 | const int_tag_ty = ty.intTagType(&int_tag_buffer); | ||
| 3244 | return func.valueAsI32(val, int_tag_ty); | 3261 | return func.valueAsI32(val, int_tag_ty); |
| 3245 | } | 3262 | } |
| 3246 | }, | 3263 | }, |
| 3247 | .Int => switch (ty.intInfo(func.target).signedness) { | 3264 | .Int => switch (ty.intInfo(mod).signedness) { |
| 3248 | .signed => return @truncate(i32, val.toSignedInt(target)), | 3265 | .signed => return @truncate(i32, val.toSignedInt(mod)), |
| 3249 | .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt(target))), | 3266 | .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt(mod))), |
| 3250 | }, | 3267 | }, |
| 3251 | .ErrorSet => { | 3268 | .ErrorSet => { |
| 3252 | const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function | 3269 | const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function |
| 3253 | return @bitCast(i32, kv.value); | 3270 | return @bitCast(i32, kv.value); |
| 3254 | }, | 3271 | }, |
| 3255 | .Bool => return @intCast(i32, val.toSignedInt(target)), | 3272 | .Bool => return @intCast(i32, val.toSignedInt(mod)), |
| 3256 | .Pointer => return @intCast(i32, val.toSignedInt(target)), | 3273 | .Pointer => return @intCast(i32, val.toSignedInt(mod)), |
| 3257 | else => unreachable, // Programmer called this function for an illegal type | 3274 | else => unreachable, // Programmer called this function for an illegal type |
| 3258 | } | 3275 | } |
| 3259 | } | 3276 | } |
| 3260 | 3277 | ||
| 3261 | fn airBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 3278 | fn airBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3279 | const mod = func.bin_file.base.options.module.?; | ||
| 3262 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; | 3280 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; |
| 3263 | const block_ty = func.air.getRefType(ty_pl.ty); | 3281 | const block_ty = func.air.getRefType(ty_pl.ty); |
| 3264 | const wasm_block_ty = genBlockType(block_ty, func.target); | 3282 | const wasm_block_ty = genBlockType(block_ty, mod); |
| 3265 | const extra = func.air.extraData(Air.Block, ty_pl.payload); | 3283 | const extra = func.air.extraData(Air.Block, ty_pl.payload); |
| 3266 | const body = func.air.extra[extra.end..][0..extra.data.body_len]; | 3284 | const body = func.air.extra[extra.end..][0..extra.data.body_len]; |
| 3267 | 3285 | ||
| 3268 | // if wasm_block_ty is non-empty, we create a register to store the temporary value | 3286 | // if wasm_block_ty is non-empty, we create a register to store the temporary value |
| 3269 | const block_result: WValue = if (wasm_block_ty != wasm.block_empty) blk: { | 3287 | const block_result: WValue = if (wasm_block_ty != wasm.block_empty) blk: { |
| 3270 | const ty: Type = if (isByRef(block_ty, func.target)) Type.u32 else block_ty; | 3288 | const ty: Type = if (isByRef(block_ty, mod)) Type.u32 else block_ty; |
| 3271 | break :blk try func.ensureAllocLocal(ty); // make sure it's a clean local as it may never get overwritten | 3289 | break :blk try func.ensureAllocLocal(ty); // make sure it's a clean local as it may never get overwritten |
| 3272 | } else WValue.none; | 3290 | } else WValue.none; |
| 3273 | 3291 | ||
| ... | @@ -3379,16 +3397,17 @@ fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) In | ... | @@ -3379,16 +3397,17 @@ fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) In |
| 3379 | /// NOTE: This leaves the result on top of the stack, rather than a new local. | 3397 | /// NOTE: This leaves the result on top of the stack, rather than a new local. |
| 3380 | fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOperator) InnerError!WValue { | 3398 | fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOperator) InnerError!WValue { |
| 3381 | assert(!(lhs != .stack and rhs == .stack)); | 3399 | assert(!(lhs != .stack and rhs == .stack)); |
| 3382 | if (ty.zigTypeTag() == .Optional and !ty.optionalReprIsPayload()) { | 3400 | const mod = func.bin_file.base.options.module.?; |
| 3401 | if (ty.zigTypeTag(mod) == .Optional and !ty.optionalReprIsPayload(mod)) { | ||
| 3383 | var buf: Type.Payload.ElemType = undefined; | 3402 | var buf: Type.Payload.ElemType = undefined; |
| 3384 | const payload_ty = ty.optionalChild(&buf); | 3403 | const payload_ty = ty.optionalChild(&buf); |
| 3385 | if (payload_ty.hasRuntimeBitsIgnoreComptime()) { | 3404 | if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3386 | // When we hit this case, we must check the value of optionals | 3405 | // When we hit this case, we must check the value of optionals |
| 3387 | // that are not pointers. This means first checking against non-null for | 3406 | // that are not pointers. This means first checking against non-null for |
| 3388 | // both lhs and rhs, as well as checking the payload are matching of lhs and rhs | 3407 | // both lhs and rhs, as well as checking the payload are matching of lhs and rhs |
| 3389 | return func.cmpOptionals(lhs, rhs, ty, op); | 3408 | return func.cmpOptionals(lhs, rhs, ty, op); |
| 3390 | } | 3409 | } |
| 3391 | } else if (isByRef(ty, func.target)) { | 3410 | } else if (isByRef(ty, mod)) { |
| 3392 | return func.cmpBigInt(lhs, rhs, ty, op); | 3411 | return func.cmpBigInt(lhs, rhs, ty, op); |
| 3393 | } else if (ty.isAnyFloat() and ty.floatBits(func.target) == 16) { | 3412 | } else if (ty.isAnyFloat() and ty.floatBits(func.target) == 16) { |
| 3394 | return func.cmpFloat16(lhs, rhs, op); | 3413 | return func.cmpFloat16(lhs, rhs, op); |
| ... | @@ -3401,13 +3420,13 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO | ... | @@ -3401,13 +3420,13 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO |
| 3401 | 3420 | ||
| 3402 | const signedness: std.builtin.Signedness = blk: { | 3421 | const signedness: std.builtin.Signedness = blk: { |
| 3403 | // by default we tell the operand type is unsigned (i.e. bools and enum values) | 3422 | // by default we tell the operand type is unsigned (i.e. bools and enum values) |
| 3404 | if (ty.zigTypeTag() != .Int) break :blk .unsigned; | 3423 | if (ty.zigTypeTag(mod) != .Int) break :blk .unsigned; |
| 3405 | 3424 | ||
| 3406 | // incase of an actual integer, we emit the correct signedness | 3425 | // incase of an actual integer, we emit the correct signedness |
| 3407 | break :blk ty.intInfo(func.target).signedness; | 3426 | break :blk ty.intInfo(mod).signedness; |
| 3408 | }; | 3427 | }; |
| 3409 | const opcode: wasm.Opcode = buildOpcode(.{ | 3428 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 3410 | .valtype1 = typeToValtype(ty, func.target), | 3429 | .valtype1 = typeToValtype(ty, mod), |
| 3411 | .op = switch (op) { | 3430 | .op = switch (op) { |
| 3412 | .lt => .lt, | 3431 | .lt => .lt, |
| 3413 | .lte => .le, | 3432 | .lte => .le, |
| ... | @@ -3464,11 +3483,12 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3464,11 +3483,12 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3464 | } | 3483 | } |
| 3465 | 3484 | ||
| 3466 | fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 3485 | fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3486 | const mod = func.bin_file.base.options.module.?; | ||
| 3467 | const br = func.air.instructions.items(.data)[inst].br; | 3487 | const br = func.air.instructions.items(.data)[inst].br; |
| 3468 | const block = func.blocks.get(br.block_inst).?; | 3488 | const block = func.blocks.get(br.block_inst).?; |
| 3469 | 3489 | ||
| 3470 | // if operand has codegen bits we should break with a value | 3490 | // if operand has codegen bits we should break with a value |
| 3471 | if (func.air.typeOf(br.operand).hasRuntimeBitsIgnoreComptime()) { | 3491 | if (func.air.typeOf(br.operand).hasRuntimeBitsIgnoreComptime(mod)) { |
| 3472 | const operand = try func.resolveInst(br.operand); | 3492 | const operand = try func.resolveInst(br.operand); |
| 3473 | try func.lowerToStack(operand); | 3493 | try func.lowerToStack(operand); |
| 3474 | 3494 | ||
| ... | @@ -3490,16 +3510,17 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3490,16 +3510,17 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3490 | 3510 | ||
| 3491 | const operand = try func.resolveInst(ty_op.operand); | 3511 | const operand = try func.resolveInst(ty_op.operand); |
| 3492 | const operand_ty = func.air.typeOf(ty_op.operand); | 3512 | const operand_ty = func.air.typeOf(ty_op.operand); |
| 3513 | const mod = func.bin_file.base.options.module.?; | ||
| 3493 | 3514 | ||
| 3494 | const result = result: { | 3515 | const result = result: { |
| 3495 | if (operand_ty.zigTypeTag() == .Bool) { | 3516 | if (operand_ty.zigTypeTag(mod) == .Bool) { |
| 3496 | try func.emitWValue(operand); | 3517 | try func.emitWValue(operand); |
| 3497 | try func.addTag(.i32_eqz); | 3518 | try func.addTag(.i32_eqz); |
| 3498 | const not_tmp = try func.allocLocal(operand_ty); | 3519 | const not_tmp = try func.allocLocal(operand_ty); |
| 3499 | try func.addLabel(.local_set, not_tmp.local.value); | 3520 | try func.addLabel(.local_set, not_tmp.local.value); |
| 3500 | break :result not_tmp; | 3521 | break :result not_tmp; |
| 3501 | } else { | 3522 | } else { |
| 3502 | const operand_bits = operand_ty.intInfo(func.target).bits; | 3523 | const operand_bits = operand_ty.intInfo(mod).bits; |
| 3503 | const wasm_bits = toWasmBits(operand_bits) orelse { | 3524 | const wasm_bits = toWasmBits(operand_bits) orelse { |
| 3504 | return func.fail("TODO: Implement binary NOT for integer with bitsize '{d}'", .{operand_bits}); | 3525 | return func.fail("TODO: Implement binary NOT for integer with bitsize '{d}'", .{operand_bits}); |
| 3505 | }; | 3526 | }; |
| ... | @@ -3566,16 +3587,17 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3566,16 +3587,17 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3566 | } | 3587 | } |
| 3567 | 3588 | ||
| 3568 | fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) InnerError!WValue { | 3589 | fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) InnerError!WValue { |
| 3590 | const mod = func.bin_file.base.options.module.?; | ||
| 3569 | // if we bitcast a float to or from an integer we must use the 'reinterpret' instruction | 3591 | // if we bitcast a float to or from an integer we must use the 'reinterpret' instruction |
| 3570 | if (!(wanted_ty.isAnyFloat() or given_ty.isAnyFloat())) return operand; | 3592 | if (!(wanted_ty.isAnyFloat() or given_ty.isAnyFloat())) return operand; |
| 3571 | if (wanted_ty.tag() == .f16 or given_ty.tag() == .f16) return operand; | 3593 | if (wanted_ty.tag() == .f16 or given_ty.tag() == .f16) return operand; |
| 3572 | if (wanted_ty.bitSize(func.target) > 64) return operand; | 3594 | if (wanted_ty.bitSize(mod) > 64) return operand; |
| 3573 | assert((wanted_ty.isInt() and given_ty.isAnyFloat()) or (wanted_ty.isAnyFloat() and given_ty.isInt())); | 3595 | assert((wanted_ty.isInt(mod) and given_ty.isAnyFloat()) or (wanted_ty.isAnyFloat() and given_ty.isInt(mod))); |
| 3574 | 3596 | ||
| 3575 | const opcode = buildOpcode(.{ | 3597 | const opcode = buildOpcode(.{ |
| 3576 | .op = .reinterpret, | 3598 | .op = .reinterpret, |
| 3577 | .valtype1 = typeToValtype(wanted_ty, func.target), | 3599 | .valtype1 = typeToValtype(wanted_ty, mod), |
| 3578 | .valtype2 = typeToValtype(given_ty, func.target), | 3600 | .valtype2 = typeToValtype(given_ty, mod), |
| 3579 | }); | 3601 | }); |
| 3580 | try func.emitWValue(operand); | 3602 | try func.emitWValue(operand); |
| 3581 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); | 3603 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| ... | @@ -3609,19 +3631,20 @@ fn structFieldPtr( | ... | @@ -3609,19 +3631,20 @@ fn structFieldPtr( |
| 3609 | struct_ty: Type, | 3631 | struct_ty: Type, |
| 3610 | index: u32, | 3632 | index: u32, |
| 3611 | ) InnerError!WValue { | 3633 | ) InnerError!WValue { |
| 3634 | const mod = func.bin_file.base.options.module.?; | ||
| 3612 | const result_ty = func.air.typeOfIndex(inst); | 3635 | const result_ty = func.air.typeOfIndex(inst); |
| 3613 | const offset = switch (struct_ty.containerLayout()) { | 3636 | const offset = switch (struct_ty.containerLayout()) { |
| 3614 | .Packed => switch (struct_ty.zigTypeTag()) { | 3637 | .Packed => switch (struct_ty.zigTypeTag(mod)) { |
| 3615 | .Struct => offset: { | 3638 | .Struct => offset: { |
| 3616 | if (result_ty.ptrInfo().data.host_size != 0) { | 3639 | if (result_ty.ptrInfo().data.host_size != 0) { |
| 3617 | break :offset @as(u32, 0); | 3640 | break :offset @as(u32, 0); |
| 3618 | } | 3641 | } |
| 3619 | break :offset struct_ty.packedStructFieldByteOffset(index, func.target); | 3642 | break :offset struct_ty.packedStructFieldByteOffset(index, mod); |
| 3620 | }, | 3643 | }, |
| 3621 | .Union => 0, | 3644 | .Union => 0, |
| 3622 | else => unreachable, | 3645 | else => unreachable, |
| 3623 | }, | 3646 | }, |
| 3624 | else => struct_ty.structFieldOffset(index, func.target), | 3647 | else => struct_ty.structFieldOffset(index, mod), |
| 3625 | }; | 3648 | }; |
| 3626 | // save a load and store when we can simply reuse the operand | 3649 | // save a load and store when we can simply reuse the operand |
| 3627 | if (offset == 0) { | 3650 | if (offset == 0) { |
| ... | @@ -3636,6 +3659,7 @@ fn structFieldPtr( | ... | @@ -3636,6 +3659,7 @@ fn structFieldPtr( |
| 3636 | } | 3659 | } |
| 3637 | 3660 | ||
| 3638 | fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 3661 | fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3662 | const mod = func.bin_file.base.options.module.?; | ||
| 3639 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; | 3663 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; |
| 3640 | const struct_field = func.air.extraData(Air.StructField, ty_pl.payload).data; | 3664 | const struct_field = func.air.extraData(Air.StructField, ty_pl.payload).data; |
| 3641 | 3665 | ||
| ... | @@ -3643,15 +3667,15 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3643,15 +3667,15 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3643 | const operand = try func.resolveInst(struct_field.struct_operand); | 3667 | const operand = try func.resolveInst(struct_field.struct_operand); |
| 3644 | const field_index = struct_field.field_index; | 3668 | const field_index = struct_field.field_index; |
| 3645 | const field_ty = struct_ty.structFieldType(field_index); | 3669 | const field_ty = struct_ty.structFieldType(field_index); |
| 3646 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) return func.finishAir(inst, .none, &.{struct_field.struct_operand}); | 3670 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return func.finishAir(inst, .none, &.{struct_field.struct_operand}); |
| 3647 | 3671 | ||
| 3648 | const result = switch (struct_ty.containerLayout()) { | 3672 | const result = switch (struct_ty.containerLayout()) { |
| 3649 | .Packed => switch (struct_ty.zigTypeTag()) { | 3673 | .Packed => switch (struct_ty.zigTypeTag(mod)) { |
| 3650 | .Struct => result: { | 3674 | .Struct => result: { |
| 3651 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 3675 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 3652 | const offset = struct_obj.packedFieldBitOffset(func.target, field_index); | 3676 | const offset = struct_obj.packedFieldBitOffset(mod, field_index); |
| 3653 | const backing_ty = struct_obj.backing_int_ty; | 3677 | const backing_ty = struct_obj.backing_int_ty; |
| 3654 | const wasm_bits = toWasmBits(backing_ty.intInfo(func.target).bits) orelse { | 3678 | const wasm_bits = toWasmBits(backing_ty.intInfo(mod).bits) orelse { |
| 3655 | return func.fail("TODO: airStructFieldVal for packed structs larger than 128 bits", .{}); | 3679 | return func.fail("TODO: airStructFieldVal for packed structs larger than 128 bits", .{}); |
| 3656 | }; | 3680 | }; |
| 3657 | const const_wvalue = if (wasm_bits == 32) | 3681 | const const_wvalue = if (wasm_bits == 32) |
| ... | @@ -3667,25 +3691,17 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3667,25 +3691,17 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3667 | else | 3691 | else |
| 3668 | try func.binOp(operand, const_wvalue, backing_ty, .shr); | 3692 | try func.binOp(operand, const_wvalue, backing_ty, .shr); |
| 3669 | 3693 | ||
| 3670 | if (field_ty.zigTypeTag() == .Float) { | 3694 | if (field_ty.zigTypeTag(mod) == .Float) { |
| 3671 | var payload: Type.Payload.Bits = .{ | 3695 | const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod))); |
| 3672 | .base = .{ .tag = .int_unsigned }, | ||
| 3673 | .data = @intCast(u16, field_ty.bitSize(func.target)), | ||
| 3674 | }; | ||
| 3675 | const int_type = Type.initPayload(&payload.base); | ||
| 3676 | const truncated = try func.trunc(shifted_value, int_type, backing_ty); | 3696 | const truncated = try func.trunc(shifted_value, int_type, backing_ty); |
| 3677 | const bitcasted = try func.bitcast(field_ty, int_type, truncated); | 3697 | const bitcasted = try func.bitcast(field_ty, int_type, truncated); |
| 3678 | break :result try bitcasted.toLocal(func, field_ty); | 3698 | break :result try bitcasted.toLocal(func, field_ty); |
| 3679 | } else if (field_ty.isPtrAtRuntime() and struct_obj.fields.count() == 1) { | 3699 | } else if (field_ty.isPtrAtRuntime(mod) and struct_obj.fields.count() == 1) { |
| 3680 | // In this case we do not have to perform any transformations, | 3700 | // In this case we do not have to perform any transformations, |
| 3681 | // we can simply reuse the operand. | 3701 | // we can simply reuse the operand. |
| 3682 | break :result func.reuseOperand(struct_field.struct_operand, operand); | 3702 | break :result func.reuseOperand(struct_field.struct_operand, operand); |
| 3683 | } else if (field_ty.isPtrAtRuntime()) { | 3703 | } else if (field_ty.isPtrAtRuntime(mod)) { |
| 3684 | var payload: Type.Payload.Bits = .{ | 3704 | const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod))); |
| 3685 | .base = .{ .tag = .int_unsigned }, | ||
| 3686 | .data = @intCast(u16, field_ty.bitSize(func.target)), | ||
| 3687 | }; | ||
| 3688 | const int_type = Type.initPayload(&payload.base); | ||
| 3689 | const truncated = try func.trunc(shifted_value, int_type, backing_ty); | 3705 | const truncated = try func.trunc(shifted_value, int_type, backing_ty); |
| 3690 | break :result try truncated.toLocal(func, field_ty); | 3706 | break :result try truncated.toLocal(func, field_ty); |
| 3691 | } | 3707 | } |
| ... | @@ -3693,8 +3709,8 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3693,8 +3709,8 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3693 | break :result try truncated.toLocal(func, field_ty); | 3709 | break :result try truncated.toLocal(func, field_ty); |
| 3694 | }, | 3710 | }, |
| 3695 | .Union => result: { | 3711 | .Union => result: { |
| 3696 | if (isByRef(struct_ty, func.target)) { | 3712 | if (isByRef(struct_ty, mod)) { |
| 3697 | if (!isByRef(field_ty, func.target)) { | 3713 | if (!isByRef(field_ty, mod)) { |
| 3698 | const val = try func.load(operand, field_ty, 0); | 3714 | const val = try func.load(operand, field_ty, 0); |
| 3699 | break :result try val.toLocal(func, field_ty); | 3715 | break :result try val.toLocal(func, field_ty); |
| 3700 | } else { | 3716 | } else { |
| ... | @@ -3704,26 +3720,14 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3704,26 +3720,14 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3704 | } | 3720 | } |
| 3705 | } | 3721 | } |
| 3706 | 3722 | ||
| 3707 | var payload: Type.Payload.Bits = .{ | 3723 | const union_int_type = try mod.intType(.unsigned, @intCast(u16, struct_ty.bitSize(mod))); |
| 3708 | .base = .{ .tag = .int_unsigned }, | 3724 | if (field_ty.zigTypeTag(mod) == .Float) { |
| 3709 | .data = @intCast(u16, struct_ty.bitSize(func.target)), | 3725 | const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod))); |
| 3710 | }; | ||
| 3711 | const union_int_type = Type.initPayload(&payload.base); | ||
| 3712 | if (field_ty.zigTypeTag() == .Float) { | ||
| 3713 | var int_payload: Type.Payload.Bits = .{ | ||
| 3714 | .base = .{ .tag = .int_unsigned }, | ||
| 3715 | .data = @intCast(u16, field_ty.bitSize(func.target)), | ||
| 3716 | }; | ||
| 3717 | const int_type = Type.initPayload(&int_payload.base); | ||
| 3718 | const truncated = try func.trunc(operand, int_type, union_int_type); | 3726 | const truncated = try func.trunc(operand, int_type, union_int_type); |
| 3719 | const bitcasted = try func.bitcast(field_ty, int_type, truncated); | 3727 | const bitcasted = try func.bitcast(field_ty, int_type, truncated); |
| 3720 | break :result try bitcasted.toLocal(func, field_ty); | 3728 | break :result try bitcasted.toLocal(func, field_ty); |
| 3721 | } else if (field_ty.isPtrAtRuntime()) { | 3729 | } else if (field_ty.isPtrAtRuntime(mod)) { |
| 3722 | var int_payload: Type.Payload.Bits = .{ | 3730 | const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod))); |
| 3723 | .base = .{ .tag = .int_unsigned }, | ||
| 3724 | .data = @intCast(u16, field_ty.bitSize(func.target)), | ||
| 3725 | }; | ||
| 3726 | const int_type = Type.initPayload(&int_payload.base); | ||
| 3727 | const truncated = try func.trunc(operand, int_type, union_int_type); | 3731 | const truncated = try func.trunc(operand, int_type, union_int_type); |
| 3728 | break :result try truncated.toLocal(func, field_ty); | 3732 | break :result try truncated.toLocal(func, field_ty); |
| 3729 | } | 3733 | } |
| ... | @@ -3733,11 +3737,10 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3733,11 +3737,10 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3733 | else => unreachable, | 3737 | else => unreachable, |
| 3734 | }, | 3738 | }, |
| 3735 | else => result: { | 3739 | else => result: { |
| 3736 | const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, func.target)) orelse { | 3740 | const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, mod)) orelse { |
| 3737 | const module = func.bin_file.base.options.module.?; | 3741 | return func.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(mod)}); |
| 3738 | return func.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(module)}); | ||
| 3739 | }; | 3742 | }; |
| 3740 | if (isByRef(field_ty, func.target)) { | 3743 | if (isByRef(field_ty, mod)) { |
| 3741 | switch (operand) { | 3744 | switch (operand) { |
| 3742 | .stack_offset => |stack_offset| { | 3745 | .stack_offset => |stack_offset| { |
| 3743 | break :result WValue{ .stack_offset = .{ .value = stack_offset.value + offset, .references = 1 } }; | 3746 | break :result WValue{ .stack_offset = .{ .value = stack_offset.value + offset, .references = 1 } }; |
| ... | @@ -3754,6 +3757,7 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3754,6 +3757,7 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3754 | } | 3757 | } |
| 3755 | 3758 | ||
| 3756 | fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 3759 | fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3760 | const mod = func.bin_file.base.options.module.?; | ||
| 3757 | // result type is always 'noreturn' | 3761 | // result type is always 'noreturn' |
| 3758 | const blocktype = wasm.block_empty; | 3762 | const blocktype = wasm.block_empty; |
| 3759 | const pl_op = func.air.instructions.items(.data)[inst].pl_op; | 3763 | const pl_op = func.air.instructions.items(.data)[inst].pl_op; |
| ... | @@ -3787,7 +3791,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3787,7 +3791,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3787 | errdefer func.gpa.free(values); | 3791 | errdefer func.gpa.free(values); |
| 3788 | 3792 | ||
| 3789 | for (items, 0..) |ref, i| { | 3793 | for (items, 0..) |ref, i| { |
| 3790 | const item_val = func.air.value(ref).?; | 3794 | const item_val = func.air.value(ref, mod).?; |
| 3791 | const int_val = func.valueAsI32(item_val, target_ty); | 3795 | const int_val = func.valueAsI32(item_val, target_ty); |
| 3792 | if (lowest_maybe == null or int_val < lowest_maybe.?) { | 3796 | if (lowest_maybe == null or int_val < lowest_maybe.?) { |
| 3793 | lowest_maybe = int_val; | 3797 | lowest_maybe = int_val; |
| ... | @@ -3810,7 +3814,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3810,7 +3814,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3810 | // When the target is an integer size larger than u32, we have no way to use the value | 3814 | // When the target is an integer size larger than u32, we have no way to use the value |
| 3811 | // as an index, therefore we also use an if/else-chain for those cases. | 3815 | // as an index, therefore we also use an if/else-chain for those cases. |
| 3812 | // TODO: Benchmark this to find a proper value, LLVM seems to draw the line at '40~45'. | 3816 | // TODO: Benchmark this to find a proper value, LLVM seems to draw the line at '40~45'. |
| 3813 | const is_sparse = highest - lowest > 50 or target_ty.bitSize(func.target) > 32; | 3817 | const is_sparse = highest - lowest > 50 or target_ty.bitSize(mod) > 32; |
| 3814 | 3818 | ||
| 3815 | const else_body = func.air.extra[extra_index..][0..switch_br.data.else_body_len]; | 3819 | const else_body = func.air.extra[extra_index..][0..switch_br.data.else_body_len]; |
| 3816 | const has_else_body = else_body.len != 0; | 3820 | const has_else_body = else_body.len != 0; |
| ... | @@ -3855,7 +3859,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3855,7 +3859,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3855 | // for errors that are not present in any branch. This is fine as this default | 3859 | // for errors that are not present in any branch. This is fine as this default |
| 3856 | // case will never be hit for those cases but we do save runtime cost and size | 3860 | // case will never be hit for those cases but we do save runtime cost and size |
| 3857 | // by using a jump table for this instead of if-else chains. | 3861 | // by using a jump table for this instead of if-else chains. |
| 3858 | break :blk if (has_else_body or target_ty.zigTypeTag() == .ErrorSet) case_i else unreachable; | 3862 | break :blk if (has_else_body or target_ty.zigTypeTag(mod) == .ErrorSet) case_i else unreachable; |
| 3859 | }; | 3863 | }; |
| 3860 | func.mir_extra.appendAssumeCapacity(idx); | 3864 | func.mir_extra.appendAssumeCapacity(idx); |
| 3861 | } else if (has_else_body) { | 3865 | } else if (has_else_body) { |
| ... | @@ -3866,10 +3870,10 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3866,10 +3870,10 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3866 | 3870 | ||
| 3867 | const signedness: std.builtin.Signedness = blk: { | 3871 | const signedness: std.builtin.Signedness = blk: { |
| 3868 | // by default we tell the operand type is unsigned (i.e. bools and enum values) | 3872 | // by default we tell the operand type is unsigned (i.e. bools and enum values) |
| 3869 | if (target_ty.zigTypeTag() != .Int) break :blk .unsigned; | 3873 | if (target_ty.zigTypeTag(mod) != .Int) break :blk .unsigned; |
| 3870 | 3874 | ||
| 3871 | // incase of an actual integer, we emit the correct signedness | 3875 | // incase of an actual integer, we emit the correct signedness |
| 3872 | break :blk target_ty.intInfo(func.target).signedness; | 3876 | break :blk target_ty.intInfo(mod).signedness; |
| 3873 | }; | 3877 | }; |
| 3874 | 3878 | ||
| 3875 | try func.branches.ensureUnusedCapacity(func.gpa, case_list.items.len + @boolToInt(has_else_body)); | 3879 | try func.branches.ensureUnusedCapacity(func.gpa, case_list.items.len + @boolToInt(has_else_body)); |
| ... | @@ -3882,7 +3886,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3882,7 +3886,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3882 | const val = try func.lowerConstant(case.values[0].value, target_ty); | 3886 | const val = try func.lowerConstant(case.values[0].value, target_ty); |
| 3883 | try func.emitWValue(val); | 3887 | try func.emitWValue(val); |
| 3884 | const opcode = buildOpcode(.{ | 3888 | const opcode = buildOpcode(.{ |
| 3885 | .valtype1 = typeToValtype(target_ty, func.target), | 3889 | .valtype1 = typeToValtype(target_ty, mod), |
| 3886 | .op = .ne, // not equal, because we want to jump out of this block if it does not match the condition. | 3890 | .op = .ne, // not equal, because we want to jump out of this block if it does not match the condition. |
| 3887 | .signedness = signedness, | 3891 | .signedness = signedness, |
| 3888 | }); | 3892 | }); |
| ... | @@ -3896,7 +3900,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3896,7 +3900,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3896 | const val = try func.lowerConstant(value.value, target_ty); | 3900 | const val = try func.lowerConstant(value.value, target_ty); |
| 3897 | try func.emitWValue(val); | 3901 | try func.emitWValue(val); |
| 3898 | const opcode = buildOpcode(.{ | 3902 | const opcode = buildOpcode(.{ |
| 3899 | .valtype1 = typeToValtype(target_ty, func.target), | 3903 | .valtype1 = typeToValtype(target_ty, mod), |
| 3900 | .op = .eq, | 3904 | .op = .eq, |
| 3901 | .signedness = signedness, | 3905 | .signedness = signedness, |
| 3902 | }); | 3906 | }); |
| ... | @@ -3933,6 +3937,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3933,6 +3937,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3933 | } | 3937 | } |
| 3934 | 3938 | ||
| 3935 | fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!void { | 3939 | fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!void { |
| 3940 | const mod = func.bin_file.base.options.module.?; | ||
| 3936 | const un_op = func.air.instructions.items(.data)[inst].un_op; | 3941 | const un_op = func.air.instructions.items(.data)[inst].un_op; |
| 3937 | const operand = try func.resolveInst(un_op); | 3942 | const operand = try func.resolveInst(un_op); |
| 3938 | const err_union_ty = func.air.typeOf(un_op); | 3943 | const err_union_ty = func.air.typeOf(un_op); |
| ... | @@ -3948,10 +3953,10 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro | ... | @@ -3948,10 +3953,10 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro |
| 3948 | } | 3953 | } |
| 3949 | 3954 | ||
| 3950 | try func.emitWValue(operand); | 3955 | try func.emitWValue(operand); |
| 3951 | if (pl_ty.hasRuntimeBitsIgnoreComptime()) { | 3956 | if (pl_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3952 | try func.addMemArg(.i32_load16_u, .{ | 3957 | try func.addMemArg(.i32_load16_u, .{ |
| 3953 | .offset = operand.offset() + @intCast(u32, errUnionErrorOffset(pl_ty, func.target)), | 3958 | .offset = operand.offset() + @intCast(u32, errUnionErrorOffset(pl_ty, mod)), |
| 3954 | .alignment = Type.anyerror.abiAlignment(func.target), | 3959 | .alignment = Type.anyerror.abiAlignment(mod), |
| 3955 | }); | 3960 | }); |
| 3956 | } | 3961 | } |
| 3957 | 3962 | ||
| ... | @@ -3967,6 +3972,7 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro | ... | @@ -3967,6 +3972,7 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro |
| 3967 | } | 3972 | } |
| 3968 | 3973 | ||
| 3969 | fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void { | 3974 | fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void { |
| 3975 | const mod = func.bin_file.base.options.module.?; | ||
| 3970 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 3976 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 3971 | 3977 | ||
| 3972 | const operand = try func.resolveInst(ty_op.operand); | 3978 | const operand = try func.resolveInst(ty_op.operand); |
| ... | @@ -3975,15 +3981,15 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo | ... | @@ -3975,15 +3981,15 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo |
| 3975 | const payload_ty = err_ty.errorUnionPayload(); | 3981 | const payload_ty = err_ty.errorUnionPayload(); |
| 3976 | 3982 | ||
| 3977 | const result = result: { | 3983 | const result = result: { |
| 3978 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 3984 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3979 | if (op_is_ptr) { | 3985 | if (op_is_ptr) { |
| 3980 | break :result func.reuseOperand(ty_op.operand, operand); | 3986 | break :result func.reuseOperand(ty_op.operand, operand); |
| 3981 | } | 3987 | } |
| 3982 | break :result WValue{ .none = {} }; | 3988 | break :result WValue{ .none = {} }; |
| 3983 | } | 3989 | } |
| 3984 | 3990 | ||
| 3985 | const pl_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, func.target)); | 3991 | const pl_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod)); |
| 3986 | if (op_is_ptr or isByRef(payload_ty, func.target)) { | 3992 | if (op_is_ptr or isByRef(payload_ty, mod)) { |
| 3987 | break :result try func.buildPointerOffset(operand, pl_offset, .new); | 3993 | break :result try func.buildPointerOffset(operand, pl_offset, .new); |
| 3988 | } | 3994 | } |
| 3989 | 3995 | ||
| ... | @@ -3994,6 +4000,7 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo | ... | @@ -3994,6 +4000,7 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo |
| 3994 | } | 4000 | } |
| 3995 | 4001 | ||
| 3996 | fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void { | 4002 | fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void { |
| 4003 | const mod = func.bin_file.base.options.module.?; | ||
| 3997 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 4004 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 3998 | 4005 | ||
| 3999 | const operand = try func.resolveInst(ty_op.operand); | 4006 | const operand = try func.resolveInst(ty_op.operand); |
| ... | @@ -4006,17 +4013,18 @@ fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) | ... | @@ -4006,17 +4013,18 @@ fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) |
| 4006 | break :result WValue{ .imm32 = 0 }; | 4013 | break :result WValue{ .imm32 = 0 }; |
| 4007 | } | 4014 | } |
| 4008 | 4015 | ||
| 4009 | if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime()) { | 4016 | if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4010 | break :result func.reuseOperand(ty_op.operand, operand); | 4017 | break :result func.reuseOperand(ty_op.operand, operand); |
| 4011 | } | 4018 | } |
| 4012 | 4019 | ||
| 4013 | const error_val = try func.load(operand, Type.anyerror, @intCast(u32, errUnionErrorOffset(payload_ty, func.target))); | 4020 | const error_val = try func.load(operand, Type.anyerror, @intCast(u32, errUnionErrorOffset(payload_ty, mod))); |
| 4014 | break :result try error_val.toLocal(func, Type.anyerror); | 4021 | break :result try error_val.toLocal(func, Type.anyerror); |
| 4015 | }; | 4022 | }; |
| 4016 | func.finishAir(inst, result, &.{ty_op.operand}); | 4023 | func.finishAir(inst, result, &.{ty_op.operand}); |
| 4017 | } | 4024 | } |
| 4018 | 4025 | ||
| 4019 | fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 4026 | fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4027 | const mod = func.bin_file.base.options.module.?; | ||
| 4020 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 4028 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 4021 | 4029 | ||
| 4022 | const operand = try func.resolveInst(ty_op.operand); | 4030 | const operand = try func.resolveInst(ty_op.operand); |
| ... | @@ -4024,18 +4032,18 @@ fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void | ... | @@ -4024,18 +4032,18 @@ fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void |
| 4024 | 4032 | ||
| 4025 | const pl_ty = func.air.typeOf(ty_op.operand); | 4033 | const pl_ty = func.air.typeOf(ty_op.operand); |
| 4026 | const result = result: { | 4034 | const result = result: { |
| 4027 | if (!pl_ty.hasRuntimeBitsIgnoreComptime()) { | 4035 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4028 | break :result func.reuseOperand(ty_op.operand, operand); | 4036 | break :result func.reuseOperand(ty_op.operand, operand); |
| 4029 | } | 4037 | } |
| 4030 | 4038 | ||
| 4031 | const err_union = try func.allocStack(err_ty); | 4039 | const err_union = try func.allocStack(err_ty); |
| 4032 | const payload_ptr = try func.buildPointerOffset(err_union, @intCast(u32, errUnionPayloadOffset(pl_ty, func.target)), .new); | 4040 | const payload_ptr = try func.buildPointerOffset(err_union, @intCast(u32, errUnionPayloadOffset(pl_ty, mod)), .new); |
| 4033 | try func.store(payload_ptr, operand, pl_ty, 0); | 4041 | try func.store(payload_ptr, operand, pl_ty, 0); |
| 4034 | 4042 | ||
| 4035 | // ensure we also write '0' to the error part, so any present stack value gets overwritten by it. | 4043 | // ensure we also write '0' to the error part, so any present stack value gets overwritten by it. |
| 4036 | try func.emitWValue(err_union); | 4044 | try func.emitWValue(err_union); |
| 4037 | try func.addImm32(0); | 4045 | try func.addImm32(0); |
| 4038 | const err_val_offset = @intCast(u32, errUnionErrorOffset(pl_ty, func.target)); | 4046 | const err_val_offset = @intCast(u32, errUnionErrorOffset(pl_ty, mod)); |
| 4039 | try func.addMemArg(.i32_store16, .{ .offset = err_union.offset() + err_val_offset, .alignment = 2 }); | 4047 | try func.addMemArg(.i32_store16, .{ .offset = err_union.offset() + err_val_offset, .alignment = 2 }); |
| 4040 | break :result err_union; | 4048 | break :result err_union; |
| 4041 | }; | 4049 | }; |
| ... | @@ -4043,6 +4051,7 @@ fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void | ... | @@ -4043,6 +4051,7 @@ fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void |
| 4043 | } | 4051 | } |
| 4044 | 4052 | ||
| 4045 | fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 4053 | fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4054 | const mod = func.bin_file.base.options.module.?; | ||
| 4046 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 4055 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 4047 | 4056 | ||
| 4048 | const operand = try func.resolveInst(ty_op.operand); | 4057 | const operand = try func.resolveInst(ty_op.operand); |
| ... | @@ -4050,17 +4059,17 @@ fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4050,17 +4059,17 @@ fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4050 | const pl_ty = err_ty.errorUnionPayload(); | 4059 | const pl_ty = err_ty.errorUnionPayload(); |
| 4051 | 4060 | ||
| 4052 | const result = result: { | 4061 | const result = result: { |
| 4053 | if (!pl_ty.hasRuntimeBitsIgnoreComptime()) { | 4062 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4054 | break :result func.reuseOperand(ty_op.operand, operand); | 4063 | break :result func.reuseOperand(ty_op.operand, operand); |
| 4055 | } | 4064 | } |
| 4056 | 4065 | ||
| 4057 | const err_union = try func.allocStack(err_ty); | 4066 | const err_union = try func.allocStack(err_ty); |
| 4058 | // store error value | 4067 | // store error value |
| 4059 | try func.store(err_union, operand, Type.anyerror, @intCast(u32, errUnionErrorOffset(pl_ty, func.target))); | 4068 | try func.store(err_union, operand, Type.anyerror, @intCast(u32, errUnionErrorOffset(pl_ty, mod))); |
| 4060 | 4069 | ||
| 4061 | // write 'undefined' to the payload | 4070 | // write 'undefined' to the payload |
| 4062 | const payload_ptr = try func.buildPointerOffset(err_union, @intCast(u32, errUnionPayloadOffset(pl_ty, func.target)), .new); | 4071 | const payload_ptr = try func.buildPointerOffset(err_union, @intCast(u32, errUnionPayloadOffset(pl_ty, mod)), .new); |
| 4063 | const len = @intCast(u32, err_ty.errorUnionPayload().abiSize(func.target)); | 4072 | const len = @intCast(u32, err_ty.errorUnionPayload().abiSize(mod)); |
| 4064 | try func.memset(Type.u8, payload_ptr, .{ .imm32 = len }, .{ .imm32 = 0xaa }); | 4073 | try func.memset(Type.u8, payload_ptr, .{ .imm32 = len }, .{ .imm32 = 0xaa }); |
| 4065 | 4074 | ||
| 4066 | break :result err_union; | 4075 | break :result err_union; |
| ... | @@ -4074,15 +4083,16 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4074,15 +4083,16 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4074 | const ty = func.air.getRefType(ty_op.ty); | 4083 | const ty = func.air.getRefType(ty_op.ty); |
| 4075 | const operand = try func.resolveInst(ty_op.operand); | 4084 | const operand = try func.resolveInst(ty_op.operand); |
| 4076 | const operand_ty = func.air.typeOf(ty_op.operand); | 4085 | const operand_ty = func.air.typeOf(ty_op.operand); |
| 4077 | if (ty.zigTypeTag() == .Vector or operand_ty.zigTypeTag() == .Vector) { | 4086 | const mod = func.bin_file.base.options.module.?; |
| 4087 | if (ty.zigTypeTag(mod) == .Vector or operand_ty.zigTypeTag(mod) == .Vector) { | ||
| 4078 | return func.fail("todo Wasm intcast for vectors", .{}); | 4088 | return func.fail("todo Wasm intcast for vectors", .{}); |
| 4079 | } | 4089 | } |
| 4080 | if (ty.abiSize(func.target) > 16 or operand_ty.abiSize(func.target) > 16) { | 4090 | if (ty.abiSize(mod) > 16 or operand_ty.abiSize(mod) > 16) { |
| 4081 | return func.fail("todo Wasm intcast for bitsize > 128", .{}); | 4091 | return func.fail("todo Wasm intcast for bitsize > 128", .{}); |
| 4082 | } | 4092 | } |
| 4083 | 4093 | ||
| 4084 | const op_bits = toWasmBits(@intCast(u16, operand_ty.bitSize(func.target))).?; | 4094 | const op_bits = toWasmBits(@intCast(u16, operand_ty.bitSize(mod))).?; |
| 4085 | const wanted_bits = toWasmBits(@intCast(u16, ty.bitSize(func.target))).?; | 4095 | const wanted_bits = toWasmBits(@intCast(u16, ty.bitSize(mod))).?; |
| 4086 | const result = if (op_bits == wanted_bits) | 4096 | const result = if (op_bits == wanted_bits) |
| 4087 | func.reuseOperand(ty_op.operand, operand) | 4097 | func.reuseOperand(ty_op.operand, operand) |
| 4088 | else | 4098 | else |
| ... | @@ -4096,8 +4106,9 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4096,8 +4106,9 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4096 | /// Asserts type's bitsize <= 128 | 4106 | /// Asserts type's bitsize <= 128 |
| 4097 | /// NOTE: May leave the result on the top of the stack. | 4107 | /// NOTE: May leave the result on the top of the stack. |
| 4098 | fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue { | 4108 | fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue { |
| 4099 | const given_bitsize = @intCast(u16, given.bitSize(func.target)); | 4109 | const mod = func.bin_file.base.options.module.?; |
| 4100 | const wanted_bitsize = @intCast(u16, wanted.bitSize(func.target)); | 4110 | const given_bitsize = @intCast(u16, given.bitSize(mod)); |
| 4111 | const wanted_bitsize = @intCast(u16, wanted.bitSize(mod)); | ||
| 4101 | assert(given_bitsize <= 128); | 4112 | assert(given_bitsize <= 128); |
| 4102 | assert(wanted_bitsize <= 128); | 4113 | assert(wanted_bitsize <= 128); |
| 4103 | 4114 | ||
| ... | @@ -4110,7 +4121,7 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro | ... | @@ -4110,7 +4121,7 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro |
| 4110 | try func.addTag(.i32_wrap_i64); | 4121 | try func.addTag(.i32_wrap_i64); |
| 4111 | } else if (op_bits == 32 and wanted_bits > 32 and wanted_bits <= 64) { | 4122 | } else if (op_bits == 32 and wanted_bits > 32 and wanted_bits <= 64) { |
| 4112 | try func.emitWValue(operand); | 4123 | try func.emitWValue(operand); |
| 4113 | try func.addTag(if (wanted.isSignedInt()) .i64_extend_i32_s else .i64_extend_i32_u); | 4124 | try func.addTag(if (wanted.isSignedInt(mod)) .i64_extend_i32_s else .i64_extend_i32_u); |
| 4114 | } else if (wanted_bits == 128) { | 4125 | } else if (wanted_bits == 128) { |
| 4115 | // for 128bit integers we store the integer in the virtual stack, rather than a local | 4126 | // for 128bit integers we store the integer in the virtual stack, rather than a local |
| 4116 | const stack_ptr = try func.allocStack(wanted); | 4127 | const stack_ptr = try func.allocStack(wanted); |
| ... | @@ -4119,14 +4130,14 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro | ... | @@ -4119,14 +4130,14 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro |
| 4119 | // for 32 bit integers, we first coerce the value into a 64 bit integer before storing it | 4130 | // for 32 bit integers, we first coerce the value into a 64 bit integer before storing it |
| 4120 | // meaning less store operations are required. | 4131 | // meaning less store operations are required. |
| 4121 | const lhs = if (op_bits == 32) blk: { | 4132 | const lhs = if (op_bits == 32) blk: { |
| 4122 | break :blk try func.intcast(operand, given, if (wanted.isSignedInt()) Type.i64 else Type.u64); | 4133 | break :blk try func.intcast(operand, given, if (wanted.isSignedInt(mod)) Type.i64 else Type.u64); |
| 4123 | } else operand; | 4134 | } else operand; |
| 4124 | 4135 | ||
| 4125 | // store msb first | 4136 | // store msb first |
| 4126 | try func.store(.{ .stack = {} }, lhs, Type.u64, 0 + stack_ptr.offset()); | 4137 | try func.store(.{ .stack = {} }, lhs, Type.u64, 0 + stack_ptr.offset()); |
| 4127 | 4138 | ||
| 4128 | // For signed integers we shift msb by 63 (64bit integer - 1 sign bit) and store remaining value | 4139 | // For signed integers we shift msb by 63 (64bit integer - 1 sign bit) and store remaining value |
| 4129 | if (wanted.isSignedInt()) { | 4140 | if (wanted.isSignedInt(mod)) { |
| 4130 | try func.emitWValue(stack_ptr); | 4141 | try func.emitWValue(stack_ptr); |
| 4131 | const shr = try func.binOp(lhs, .{ .imm64 = 63 }, Type.i64, .shr); | 4142 | const shr = try func.binOp(lhs, .{ .imm64 = 63 }, Type.i64, .shr); |
| 4132 | try func.store(.{ .stack = {} }, shr, Type.u64, 8 + stack_ptr.offset()); | 4143 | try func.store(.{ .stack = {} }, shr, Type.u64, 8 + stack_ptr.offset()); |
| ... | @@ -4154,16 +4165,16 @@ fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind: | ... | @@ -4154,16 +4165,16 @@ fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind: |
| 4154 | /// For a given type and operand, checks if it's considered `null`. | 4165 | /// For a given type and operand, checks if it's considered `null`. |
| 4155 | /// NOTE: Leaves the result on the stack | 4166 | /// NOTE: Leaves the result on the stack |
| 4156 | fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcode) InnerError!WValue { | 4167 | fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcode) InnerError!WValue { |
| 4168 | const mod = func.bin_file.base.options.module.?; | ||
| 4157 | try func.emitWValue(operand); | 4169 | try func.emitWValue(operand); |
| 4158 | var buf: Type.Payload.ElemType = undefined; | 4170 | var buf: Type.Payload.ElemType = undefined; |
| 4159 | const payload_ty = optional_ty.optionalChild(&buf); | 4171 | const payload_ty = optional_ty.optionalChild(&buf); |
| 4160 | if (!optional_ty.optionalReprIsPayload()) { | 4172 | if (!optional_ty.optionalReprIsPayload(mod)) { |
| 4161 | // When payload is zero-bits, we can treat operand as a value, rather than | 4173 | // When payload is zero-bits, we can treat operand as a value, rather than |
| 4162 | // a pointer to the stack value | 4174 | // a pointer to the stack value |
| 4163 | if (payload_ty.hasRuntimeBitsIgnoreComptime()) { | 4175 | if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4164 | const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse { | 4176 | const offset = std.math.cast(u32, payload_ty.abiSize(mod)) orelse { |
| 4165 | const module = func.bin_file.base.options.module.?; | 4177 | return func.fail("Optional type {} too big to fit into stack frame", .{optional_ty.fmt(mod)}); |
| 4166 | return func.fail("Optional type {} too big to fit into stack frame", .{optional_ty.fmt(module)}); | ||
| 4167 | }; | 4178 | }; |
| 4168 | try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 }); | 4179 | try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 }); |
| 4169 | } | 4180 | } |
| ... | @@ -4183,18 +4194,19 @@ fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcod | ... | @@ -4183,18 +4194,19 @@ fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcod |
| 4183 | } | 4194 | } |
| 4184 | 4195 | ||
| 4185 | fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 4196 | fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4197 | const mod = func.bin_file.base.options.module.?; | ||
| 4186 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 4198 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 4187 | const opt_ty = func.air.typeOf(ty_op.operand); | 4199 | const opt_ty = func.air.typeOf(ty_op.operand); |
| 4188 | const payload_ty = func.air.typeOfIndex(inst); | 4200 | const payload_ty = func.air.typeOfIndex(inst); |
| 4189 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 4201 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4190 | return func.finishAir(inst, .none, &.{ty_op.operand}); | 4202 | return func.finishAir(inst, .none, &.{ty_op.operand}); |
| 4191 | } | 4203 | } |
| 4192 | 4204 | ||
| 4193 | const result = result: { | 4205 | const result = result: { |
| 4194 | const operand = try func.resolveInst(ty_op.operand); | 4206 | const operand = try func.resolveInst(ty_op.operand); |
| 4195 | if (opt_ty.optionalReprIsPayload()) break :result func.reuseOperand(ty_op.operand, operand); | 4207 | if (opt_ty.optionalReprIsPayload(mod)) break :result func.reuseOperand(ty_op.operand, operand); |
| 4196 | 4208 | ||
| 4197 | if (isByRef(payload_ty, func.target)) { | 4209 | if (isByRef(payload_ty, mod)) { |
| 4198 | break :result try func.buildPointerOffset(operand, 0, .new); | 4210 | break :result try func.buildPointerOffset(operand, 0, .new); |
| 4199 | } | 4211 | } |
| 4200 | 4212 | ||
| ... | @@ -4209,10 +4221,11 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4209,10 +4221,11 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4209 | const operand = try func.resolveInst(ty_op.operand); | 4221 | const operand = try func.resolveInst(ty_op.operand); |
| 4210 | const opt_ty = func.air.typeOf(ty_op.operand).childType(); | 4222 | const opt_ty = func.air.typeOf(ty_op.operand).childType(); |
| 4211 | 4223 | ||
| 4224 | const mod = func.bin_file.base.options.module.?; | ||
| 4212 | const result = result: { | 4225 | const result = result: { |
| 4213 | var buf: Type.Payload.ElemType = undefined; | 4226 | var buf: Type.Payload.ElemType = undefined; |
| 4214 | const payload_ty = opt_ty.optionalChild(&buf); | 4227 | const payload_ty = opt_ty.optionalChild(&buf); |
| 4215 | if (!payload_ty.hasRuntimeBitsIgnoreComptime() or opt_ty.optionalReprIsPayload()) { | 4228 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or opt_ty.optionalReprIsPayload(mod)) { |
| 4216 | break :result func.reuseOperand(ty_op.operand, operand); | 4229 | break :result func.reuseOperand(ty_op.operand, operand); |
| 4217 | } | 4230 | } |
| 4218 | 4231 | ||
| ... | @@ -4222,22 +4235,22 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4222,22 +4235,22 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4222 | } | 4235 | } |
| 4223 | 4236 | ||
| 4224 | fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 4237 | fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4238 | const mod = func.bin_file.base.options.module.?; | ||
| 4225 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 4239 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 4226 | const operand = try func.resolveInst(ty_op.operand); | 4240 | const operand = try func.resolveInst(ty_op.operand); |
| 4227 | const opt_ty = func.air.typeOf(ty_op.operand).childType(); | 4241 | const opt_ty = func.air.typeOf(ty_op.operand).childType(); |
| 4228 | var buf: Type.Payload.ElemType = undefined; | 4242 | var buf: Type.Payload.ElemType = undefined; |
| 4229 | const payload_ty = opt_ty.optionalChild(&buf); | 4243 | const payload_ty = opt_ty.optionalChild(&buf); |
| 4230 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 4244 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4231 | return func.fail("TODO: Implement OptionalPayloadPtrSet for optional with zero-sized type {}", .{payload_ty.fmtDebug()}); | 4245 | return func.fail("TODO: Implement OptionalPayloadPtrSet for optional with zero-sized type {}", .{payload_ty.fmtDebug()}); |
| 4232 | } | 4246 | } |
| 4233 | 4247 | ||
| 4234 | if (opt_ty.optionalReprIsPayload()) { | 4248 | if (opt_ty.optionalReprIsPayload(mod)) { |
| 4235 | return func.finishAir(inst, operand, &.{ty_op.operand}); | 4249 | return func.finishAir(inst, operand, &.{ty_op.operand}); |
| 4236 | } | 4250 | } |
| 4237 | 4251 | ||
| 4238 | const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse { | 4252 | const offset = std.math.cast(u32, payload_ty.abiSize(mod)) orelse { |
| 4239 | const module = func.bin_file.base.options.module.?; | 4253 | return func.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(mod)}); |
| 4240 | return func.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(module)}); | ||
| 4241 | }; | 4254 | }; |
| 4242 | 4255 | ||
| 4243 | try func.emitWValue(operand); | 4256 | try func.emitWValue(operand); |
| ... | @@ -4251,9 +4264,10 @@ fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi | ... | @@ -4251,9 +4264,10 @@ fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi |
| 4251 | fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 4264 | fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4252 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 4265 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 4253 | const payload_ty = func.air.typeOf(ty_op.operand); | 4266 | const payload_ty = func.air.typeOf(ty_op.operand); |
| 4267 | const mod = func.bin_file.base.options.module.?; | ||
| 4254 | 4268 | ||
| 4255 | const result = result: { | 4269 | const result = result: { |
| 4256 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 4270 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4257 | const non_null_bit = try func.allocStack(Type.initTag(.u1)); | 4271 | const non_null_bit = try func.allocStack(Type.initTag(.u1)); |
| 4258 | try func.emitWValue(non_null_bit); | 4272 | try func.emitWValue(non_null_bit); |
| 4259 | try func.addImm32(1); | 4273 | try func.addImm32(1); |
| ... | @@ -4263,12 +4277,11 @@ fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4263,12 +4277,11 @@ fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4263 | 4277 | ||
| 4264 | const operand = try func.resolveInst(ty_op.operand); | 4278 | const operand = try func.resolveInst(ty_op.operand); |
| 4265 | const op_ty = func.air.typeOfIndex(inst); | 4279 | const op_ty = func.air.typeOfIndex(inst); |
| 4266 | if (op_ty.optionalReprIsPayload()) { | 4280 | if (op_ty.optionalReprIsPayload(mod)) { |
| 4267 | break :result func.reuseOperand(ty_op.operand, operand); | 4281 | break :result func.reuseOperand(ty_op.operand, operand); |
| 4268 | } | 4282 | } |
| 4269 | const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse { | 4283 | const offset = std.math.cast(u32, payload_ty.abiSize(mod)) orelse { |
| 4270 | const module = func.bin_file.base.options.module.?; | 4284 | return func.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(mod)}); |
| 4271 | return func.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(module)}); | ||
| 4272 | }; | 4285 | }; |
| 4273 | 4286 | ||
| 4274 | // Create optional type, set the non-null bit, and store the operand inside the optional type | 4287 | // Create optional type, set the non-null bit, and store the operand inside the optional type |
| ... | @@ -4314,7 +4327,8 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4314,7 +4327,8 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4314 | const slice = try func.resolveInst(bin_op.lhs); | 4327 | const slice = try func.resolveInst(bin_op.lhs); |
| 4315 | const index = try func.resolveInst(bin_op.rhs); | 4328 | const index = try func.resolveInst(bin_op.rhs); |
| 4316 | const elem_ty = slice_ty.childType(); | 4329 | const elem_ty = slice_ty.childType(); |
| 4317 | const elem_size = elem_ty.abiSize(func.target); | 4330 | const mod = func.bin_file.base.options.module.?; |
| 4331 | const elem_size = elem_ty.abiSize(mod); | ||
| 4318 | 4332 | ||
| 4319 | // load pointer onto stack | 4333 | // load pointer onto stack |
| 4320 | _ = try func.load(slice, Type.usize, 0); | 4334 | _ = try func.load(slice, Type.usize, 0); |
| ... | @@ -4328,7 +4342,7 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4328,7 +4342,7 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4328 | const result_ptr = try func.allocLocal(Type.usize); | 4342 | const result_ptr = try func.allocLocal(Type.usize); |
| 4329 | try func.addLabel(.local_set, result_ptr.local.value); | 4343 | try func.addLabel(.local_set, result_ptr.local.value); |
| 4330 | 4344 | ||
| 4331 | const result = if (!isByRef(elem_ty, func.target)) result: { | 4345 | const result = if (!isByRef(elem_ty, mod)) result: { |
| 4332 | const elem_val = try func.load(result_ptr, elem_ty, 0); | 4346 | const elem_val = try func.load(result_ptr, elem_ty, 0); |
| 4333 | break :result try elem_val.toLocal(func, elem_ty); | 4347 | break :result try elem_val.toLocal(func, elem_ty); |
| 4334 | } else result_ptr; | 4348 | } else result_ptr; |
| ... | @@ -4341,7 +4355,8 @@ fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4341,7 +4355,8 @@ fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4341 | const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data; | 4355 | const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4342 | 4356 | ||
| 4343 | const elem_ty = func.air.getRefType(ty_pl.ty).childType(); | 4357 | const elem_ty = func.air.getRefType(ty_pl.ty).childType(); |
| 4344 | const elem_size = elem_ty.abiSize(func.target); | 4358 | const mod = func.bin_file.base.options.module.?; |
| 4359 | const elem_size = elem_ty.abiSize(mod); | ||
| 4345 | 4360 | ||
| 4346 | const slice = try func.resolveInst(bin_op.lhs); | 4361 | const slice = try func.resolveInst(bin_op.lhs); |
| 4347 | const index = try func.resolveInst(bin_op.rhs); | 4362 | const index = try func.resolveInst(bin_op.rhs); |
| ... | @@ -4389,13 +4404,14 @@ fn airTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4389,13 +4404,14 @@ fn airTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4389 | /// Truncates a given operand to a given type, discarding any overflown bits. | 4404 | /// Truncates a given operand to a given type, discarding any overflown bits. |
| 4390 | /// NOTE: Resulting value is left on the stack. | 4405 | /// NOTE: Resulting value is left on the stack. |
| 4391 | fn trunc(func: *CodeGen, operand: WValue, wanted_ty: Type, given_ty: Type) InnerError!WValue { | 4406 | fn trunc(func: *CodeGen, operand: WValue, wanted_ty: Type, given_ty: Type) InnerError!WValue { |
| 4392 | const given_bits = @intCast(u16, given_ty.bitSize(func.target)); | 4407 | const mod = func.bin_file.base.options.module.?; |
| 4408 | const given_bits = @intCast(u16, given_ty.bitSize(mod)); | ||
| 4393 | if (toWasmBits(given_bits) == null) { | 4409 | if (toWasmBits(given_bits) == null) { |
| 4394 | return func.fail("TODO: Implement wasm integer truncation for integer bitsize: {d}", .{given_bits}); | 4410 | return func.fail("TODO: Implement wasm integer truncation for integer bitsize: {d}", .{given_bits}); |
| 4395 | } | 4411 | } |
| 4396 | 4412 | ||
| 4397 | var result = try func.intcast(operand, given_ty, wanted_ty); | 4413 | var result = try func.intcast(operand, given_ty, wanted_ty); |
| 4398 | const wanted_bits = @intCast(u16, wanted_ty.bitSize(func.target)); | 4414 | const wanted_bits = @intCast(u16, wanted_ty.bitSize(mod)); |
| 4399 | const wasm_bits = toWasmBits(wanted_bits).?; | 4415 | const wasm_bits = toWasmBits(wanted_bits).?; |
| 4400 | if (wasm_bits != wanted_bits) { | 4416 | if (wasm_bits != wanted_bits) { |
| 4401 | result = try func.wrapOperand(result, wanted_ty); | 4417 | result = try func.wrapOperand(result, wanted_ty); |
| ... | @@ -4412,6 +4428,7 @@ fn airBoolToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4412,6 +4428,7 @@ fn airBoolToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4412 | } | 4428 | } |
| 4413 | 4429 | ||
| 4414 | fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 4430 | fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4431 | const mod = func.bin_file.base.options.module.?; | ||
| 4415 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 4432 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 4416 | 4433 | ||
| 4417 | const operand = try func.resolveInst(ty_op.operand); | 4434 | const operand = try func.resolveInst(ty_op.operand); |
| ... | @@ -4422,7 +4439,7 @@ fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4422,7 +4439,7 @@ fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4422 | const slice_local = try func.allocStack(slice_ty); | 4439 | const slice_local = try func.allocStack(slice_ty); |
| 4423 | 4440 | ||
| 4424 | // store the array ptr in the slice | 4441 | // store the array ptr in the slice |
| 4425 | if (array_ty.hasRuntimeBitsIgnoreComptime()) { | 4442 | if (array_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4426 | try func.store(slice_local, operand, Type.usize, 0); | 4443 | try func.store(slice_local, operand, Type.usize, 0); |
| 4427 | } | 4444 | } |
| 4428 | 4445 | ||
| ... | @@ -4454,7 +4471,8 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4454,7 +4471,8 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4454 | const ptr = try func.resolveInst(bin_op.lhs); | 4471 | const ptr = try func.resolveInst(bin_op.lhs); |
| 4455 | const index = try func.resolveInst(bin_op.rhs); | 4472 | const index = try func.resolveInst(bin_op.rhs); |
| 4456 | const elem_ty = ptr_ty.childType(); | 4473 | const elem_ty = ptr_ty.childType(); |
| 4457 | const elem_size = elem_ty.abiSize(func.target); | 4474 | const mod = func.bin_file.base.options.module.?; |
| 4475 | const elem_size = elem_ty.abiSize(mod); | ||
| 4458 | 4476 | ||
| 4459 | // load pointer onto the stack | 4477 | // load pointer onto the stack |
| 4460 | if (ptr_ty.isSlice()) { | 4478 | if (ptr_ty.isSlice()) { |
| ... | @@ -4472,7 +4490,7 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4472,7 +4490,7 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4472 | const elem_result = val: { | 4490 | const elem_result = val: { |
| 4473 | var result = try func.allocLocal(Type.usize); | 4491 | var result = try func.allocLocal(Type.usize); |
| 4474 | try func.addLabel(.local_set, result.local.value); | 4492 | try func.addLabel(.local_set, result.local.value); |
| 4475 | if (isByRef(elem_ty, func.target)) { | 4493 | if (isByRef(elem_ty, mod)) { |
| 4476 | break :val result; | 4494 | break :val result; |
| 4477 | } | 4495 | } |
| 4478 | defer result.free(func); // only free if it's not returned like above | 4496 | defer result.free(func); // only free if it's not returned like above |
| ... | @@ -4489,7 +4507,8 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4489,7 +4507,8 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4489 | 4507 | ||
| 4490 | const ptr_ty = func.air.typeOf(bin_op.lhs); | 4508 | const ptr_ty = func.air.typeOf(bin_op.lhs); |
| 4491 | const elem_ty = func.air.getRefType(ty_pl.ty).childType(); | 4509 | const elem_ty = func.air.getRefType(ty_pl.ty).childType(); |
| 4492 | const elem_size = elem_ty.abiSize(func.target); | 4510 | const mod = func.bin_file.base.options.module.?; |
| 4511 | const elem_size = elem_ty.abiSize(mod); | ||
| 4493 | 4512 | ||
| 4494 | const ptr = try func.resolveInst(bin_op.lhs); | 4513 | const ptr = try func.resolveInst(bin_op.lhs); |
| 4495 | const index = try func.resolveInst(bin_op.rhs); | 4514 | const index = try func.resolveInst(bin_op.rhs); |
| ... | @@ -4513,6 +4532,7 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4513,6 +4532,7 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4513 | } | 4532 | } |
| 4514 | 4533 | ||
| 4515 | fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | 4534 | fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 4535 | const mod = func.bin_file.base.options.module.?; | ||
| 4516 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; | 4536 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; |
| 4517 | const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data; | 4537 | const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4518 | 4538 | ||
| ... | @@ -4524,13 +4544,13 @@ fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | ... | @@ -4524,13 +4544,13 @@ fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 4524 | else => ptr_ty.childType(), | 4544 | else => ptr_ty.childType(), |
| 4525 | }; | 4545 | }; |
| 4526 | 4546 | ||
| 4527 | const valtype = typeToValtype(Type.usize, func.target); | 4547 | const valtype = typeToValtype(Type.usize, mod); |
| 4528 | const mul_opcode = buildOpcode(.{ .valtype1 = valtype, .op = .mul }); | 4548 | const mul_opcode = buildOpcode(.{ .valtype1 = valtype, .op = .mul }); |
| 4529 | const bin_opcode = buildOpcode(.{ .valtype1 = valtype, .op = op }); | 4549 | const bin_opcode = buildOpcode(.{ .valtype1 = valtype, .op = op }); |
| 4530 | 4550 | ||
| 4531 | try func.lowerToStack(ptr); | 4551 | try func.lowerToStack(ptr); |
| 4532 | try func.emitWValue(offset); | 4552 | try func.emitWValue(offset); |
| 4533 | try func.addImm32(@bitCast(i32, @intCast(u32, pointee_ty.abiSize(func.target)))); | 4553 | try func.addImm32(@bitCast(i32, @intCast(u32, pointee_ty.abiSize(mod)))); |
| 4534 | try func.addTag(Mir.Inst.Tag.fromOpcode(mul_opcode)); | 4554 | try func.addTag(Mir.Inst.Tag.fromOpcode(mul_opcode)); |
| 4535 | try func.addTag(Mir.Inst.Tag.fromOpcode(bin_opcode)); | 4555 | try func.addTag(Mir.Inst.Tag.fromOpcode(bin_opcode)); |
| 4536 | 4556 | ||
| ... | @@ -4572,7 +4592,8 @@ fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void | ... | @@ -4572,7 +4592,8 @@ fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void |
| 4572 | /// this to wasm's memset instruction. When the feature is not present, | 4592 | /// this to wasm's memset instruction. When the feature is not present, |
| 4573 | /// we implement it manually. | 4593 | /// we implement it manually. |
| 4574 | fn memset(func: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue) InnerError!void { | 4594 | fn memset(func: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue) InnerError!void { |
| 4575 | const abi_size = @intCast(u32, elem_ty.abiSize(func.target)); | 4595 | const mod = func.bin_file.base.options.module.?; |
| 4596 | const abi_size = @intCast(u32, elem_ty.abiSize(mod)); | ||
| 4576 | 4597 | ||
| 4577 | // When bulk_memory is enabled, we lower it to wasm's memset instruction. | 4598 | // When bulk_memory is enabled, we lower it to wasm's memset instruction. |
| 4578 | // If not, we lower it ourselves. | 4599 | // If not, we lower it ourselves. |
| ... | @@ -4666,24 +4687,25 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4666,24 +4687,25 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4666 | const array = try func.resolveInst(bin_op.lhs); | 4687 | const array = try func.resolveInst(bin_op.lhs); |
| 4667 | const index = try func.resolveInst(bin_op.rhs); | 4688 | const index = try func.resolveInst(bin_op.rhs); |
| 4668 | const elem_ty = array_ty.childType(); | 4689 | const elem_ty = array_ty.childType(); |
| 4669 | const elem_size = elem_ty.abiSize(func.target); | 4690 | const mod = func.bin_file.base.options.module.?; |
| 4691 | const elem_size = elem_ty.abiSize(mod); | ||
| 4670 | 4692 | ||
| 4671 | if (isByRef(array_ty, func.target)) { | 4693 | if (isByRef(array_ty, mod)) { |
| 4672 | try func.lowerToStack(array); | 4694 | try func.lowerToStack(array); |
| 4673 | try func.emitWValue(index); | 4695 | try func.emitWValue(index); |
| 4674 | try func.addImm32(@bitCast(i32, @intCast(u32, elem_size))); | 4696 | try func.addImm32(@bitCast(i32, @intCast(u32, elem_size))); |
| 4675 | try func.addTag(.i32_mul); | 4697 | try func.addTag(.i32_mul); |
| 4676 | try func.addTag(.i32_add); | 4698 | try func.addTag(.i32_add); |
| 4677 | } else { | 4699 | } else { |
| 4678 | std.debug.assert(array_ty.zigTypeTag() == .Vector); | 4700 | std.debug.assert(array_ty.zigTypeTag(mod) == .Vector); |
| 4679 | 4701 | ||
| 4680 | switch (index) { | 4702 | switch (index) { |
| 4681 | inline .imm32, .imm64 => |lane| { | 4703 | inline .imm32, .imm64 => |lane| { |
| 4682 | const opcode: wasm.SimdOpcode = switch (elem_ty.bitSize(func.target)) { | 4704 | const opcode: wasm.SimdOpcode = switch (elem_ty.bitSize(mod)) { |
| 4683 | 8 => if (elem_ty.isSignedInt()) .i8x16_extract_lane_s else .i8x16_extract_lane_u, | 4705 | 8 => if (elem_ty.isSignedInt(mod)) .i8x16_extract_lane_s else .i8x16_extract_lane_u, |
| 4684 | 16 => if (elem_ty.isSignedInt()) .i16x8_extract_lane_s else .i16x8_extract_lane_u, | 4706 | 16 => if (elem_ty.isSignedInt(mod)) .i16x8_extract_lane_s else .i16x8_extract_lane_u, |
| 4685 | 32 => if (elem_ty.isInt()) .i32x4_extract_lane else .f32x4_extract_lane, | 4707 | 32 => if (elem_ty.isInt(mod)) .i32x4_extract_lane else .f32x4_extract_lane, |
| 4686 | 64 => if (elem_ty.isInt()) .i64x2_extract_lane else .f64x2_extract_lane, | 4708 | 64 => if (elem_ty.isInt(mod)) .i64x2_extract_lane else .f64x2_extract_lane, |
| 4687 | else => unreachable, | 4709 | else => unreachable, |
| 4688 | }; | 4710 | }; |
| 4689 | 4711 | ||
| ... | @@ -4715,7 +4737,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4715,7 +4737,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4715 | var result = try func.allocLocal(Type.usize); | 4737 | var result = try func.allocLocal(Type.usize); |
| 4716 | try func.addLabel(.local_set, result.local.value); | 4738 | try func.addLabel(.local_set, result.local.value); |
| 4717 | 4739 | ||
| 4718 | if (isByRef(elem_ty, func.target)) { | 4740 | if (isByRef(elem_ty, mod)) { |
| 4719 | break :val result; | 4741 | break :val result; |
| 4720 | } | 4742 | } |
| 4721 | defer result.free(func); // only free if no longer needed and not returned like above | 4743 | defer result.free(func); // only free if no longer needed and not returned like above |
| ... | @@ -4733,17 +4755,18 @@ fn airFloatToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4733,17 +4755,18 @@ fn airFloatToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4733 | const operand = try func.resolveInst(ty_op.operand); | 4755 | const operand = try func.resolveInst(ty_op.operand); |
| 4734 | const dest_ty = func.air.typeOfIndex(inst); | 4756 | const dest_ty = func.air.typeOfIndex(inst); |
| 4735 | const op_ty = func.air.typeOf(ty_op.operand); | 4757 | const op_ty = func.air.typeOf(ty_op.operand); |
| 4758 | const mod = func.bin_file.base.options.module.?; | ||
| 4736 | 4759 | ||
| 4737 | if (op_ty.abiSize(func.target) > 8) { | 4760 | if (op_ty.abiSize(mod) > 8) { |
| 4738 | return func.fail("TODO: floatToInt for integers/floats with bitsize larger than 64 bits", .{}); | 4761 | return func.fail("TODO: floatToInt for integers/floats with bitsize larger than 64 bits", .{}); |
| 4739 | } | 4762 | } |
| 4740 | 4763 | ||
| 4741 | try func.emitWValue(operand); | 4764 | try func.emitWValue(operand); |
| 4742 | const op = buildOpcode(.{ | 4765 | const op = buildOpcode(.{ |
| 4743 | .op = .trunc, | 4766 | .op = .trunc, |
| 4744 | .valtype1 = typeToValtype(dest_ty, func.target), | 4767 | .valtype1 = typeToValtype(dest_ty, mod), |
| 4745 | .valtype2 = typeToValtype(op_ty, func.target), | 4768 | .valtype2 = typeToValtype(op_ty, mod), |
| 4746 | .signedness = if (dest_ty.isSignedInt()) .signed else .unsigned, | 4769 | .signedness = if (dest_ty.isSignedInt(mod)) .signed else .unsigned, |
| 4747 | }); | 4770 | }); |
| 4748 | try func.addTag(Mir.Inst.Tag.fromOpcode(op)); | 4771 | try func.addTag(Mir.Inst.Tag.fromOpcode(op)); |
| 4749 | const wrapped = try func.wrapOperand(.{ .stack = {} }, dest_ty); | 4772 | const wrapped = try func.wrapOperand(.{ .stack = {} }, dest_ty); |
| ... | @@ -4757,17 +4780,18 @@ fn airIntToFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4757,17 +4780,18 @@ fn airIntToFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4757 | const operand = try func.resolveInst(ty_op.operand); | 4780 | const operand = try func.resolveInst(ty_op.operand); |
| 4758 | const dest_ty = func.air.typeOfIndex(inst); | 4781 | const dest_ty = func.air.typeOfIndex(inst); |
| 4759 | const op_ty = func.air.typeOf(ty_op.operand); | 4782 | const op_ty = func.air.typeOf(ty_op.operand); |
| 4783 | const mod = func.bin_file.base.options.module.?; | ||
| 4760 | 4784 | ||
| 4761 | if (op_ty.abiSize(func.target) > 8) { | 4785 | if (op_ty.abiSize(mod) > 8) { |
| 4762 | return func.fail("TODO: intToFloat for integers/floats with bitsize larger than 64 bits", .{}); | 4786 | return func.fail("TODO: intToFloat for integers/floats with bitsize larger than 64 bits", .{}); |
| 4763 | } | 4787 | } |
| 4764 | 4788 | ||
| 4765 | try func.emitWValue(operand); | 4789 | try func.emitWValue(operand); |
| 4766 | const op = buildOpcode(.{ | 4790 | const op = buildOpcode(.{ |
| 4767 | .op = .convert, | 4791 | .op = .convert, |
| 4768 | .valtype1 = typeToValtype(dest_ty, func.target), | 4792 | .valtype1 = typeToValtype(dest_ty, mod), |
| 4769 | .valtype2 = typeToValtype(op_ty, func.target), | 4793 | .valtype2 = typeToValtype(op_ty, mod), |
| 4770 | .signedness = if (op_ty.isSignedInt()) .signed else .unsigned, | 4794 | .signedness = if (op_ty.isSignedInt(mod)) .signed else .unsigned, |
| 4771 | }); | 4795 | }); |
| 4772 | try func.addTag(Mir.Inst.Tag.fromOpcode(op)); | 4796 | try func.addTag(Mir.Inst.Tag.fromOpcode(op)); |
| 4773 | 4797 | ||
| ... | @@ -4777,18 +4801,19 @@ fn airIntToFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4777,18 +4801,19 @@ fn airIntToFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4777 | } | 4801 | } |
| 4778 | 4802 | ||
| 4779 | fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 4803 | fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4804 | const mod = func.bin_file.base.options.module.?; | ||
| 4780 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 4805 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 4781 | const operand = try func.resolveInst(ty_op.operand); | 4806 | const operand = try func.resolveInst(ty_op.operand); |
| 4782 | const ty = func.air.typeOfIndex(inst); | 4807 | const ty = func.air.typeOfIndex(inst); |
| 4783 | const elem_ty = ty.childType(); | 4808 | const elem_ty = ty.childType(); |
| 4784 | 4809 | ||
| 4785 | if (determineSimdStoreStrategy(ty, func.target) == .direct) blk: { | 4810 | if (determineSimdStoreStrategy(ty, mod) == .direct) blk: { |
| 4786 | switch (operand) { | 4811 | switch (operand) { |
| 4787 | // when the operand lives in the linear memory section, we can directly | 4812 | // when the operand lives in the linear memory section, we can directly |
| 4788 | // load and splat the value at once. Meaning we do not first have to load | 4813 | // load and splat the value at once. Meaning we do not first have to load |
| 4789 | // the scalar value onto the stack. | 4814 | // the scalar value onto the stack. |
| 4790 | .stack_offset, .memory, .memory_offset => { | 4815 | .stack_offset, .memory, .memory_offset => { |
| 4791 | const opcode = switch (elem_ty.bitSize(func.target)) { | 4816 | const opcode = switch (elem_ty.bitSize(mod)) { |
| 4792 | 8 => std.wasm.simdOpcode(.v128_load8_splat), | 4817 | 8 => std.wasm.simdOpcode(.v128_load8_splat), |
| 4793 | 16 => std.wasm.simdOpcode(.v128_load16_splat), | 4818 | 16 => std.wasm.simdOpcode(.v128_load16_splat), |
| 4794 | 32 => std.wasm.simdOpcode(.v128_load32_splat), | 4819 | 32 => std.wasm.simdOpcode(.v128_load32_splat), |
| ... | @@ -4803,18 +4828,18 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4803,18 +4828,18 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4803 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ | 4828 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 4804 | opcode, | 4829 | opcode, |
| 4805 | operand.offset(), | 4830 | operand.offset(), |
| 4806 | elem_ty.abiAlignment(func.target), | 4831 | elem_ty.abiAlignment(mod), |
| 4807 | }); | 4832 | }); |
| 4808 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); | 4833 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 4809 | try func.addLabel(.local_set, result.local.value); | 4834 | try func.addLabel(.local_set, result.local.value); |
| 4810 | return func.finishAir(inst, result, &.{ty_op.operand}); | 4835 | return func.finishAir(inst, result, &.{ty_op.operand}); |
| 4811 | }, | 4836 | }, |
| 4812 | .local => { | 4837 | .local => { |
| 4813 | const opcode = switch (elem_ty.bitSize(func.target)) { | 4838 | const opcode = switch (elem_ty.bitSize(mod)) { |
| 4814 | 8 => std.wasm.simdOpcode(.i8x16_splat), | 4839 | 8 => std.wasm.simdOpcode(.i8x16_splat), |
| 4815 | 16 => std.wasm.simdOpcode(.i16x8_splat), | 4840 | 16 => std.wasm.simdOpcode(.i16x8_splat), |
| 4816 | 32 => if (elem_ty.isInt()) std.wasm.simdOpcode(.i32x4_splat) else std.wasm.simdOpcode(.f32x4_splat), | 4841 | 32 => if (elem_ty.isInt(mod)) std.wasm.simdOpcode(.i32x4_splat) else std.wasm.simdOpcode(.f32x4_splat), |
| 4817 | 64 => if (elem_ty.isInt()) std.wasm.simdOpcode(.i64x2_splat) else std.wasm.simdOpcode(.f64x2_splat), | 4842 | 64 => if (elem_ty.isInt(mod)) std.wasm.simdOpcode(.i64x2_splat) else std.wasm.simdOpcode(.f64x2_splat), |
| 4818 | else => break :blk, // Cannot make use of simd-instructions | 4843 | else => break :blk, // Cannot make use of simd-instructions |
| 4819 | }; | 4844 | }; |
| 4820 | const result = try func.allocLocal(ty); | 4845 | const result = try func.allocLocal(ty); |
| ... | @@ -4828,14 +4853,14 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4828,14 +4853,14 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4828 | else => unreachable, | 4853 | else => unreachable, |
| 4829 | } | 4854 | } |
| 4830 | } | 4855 | } |
| 4831 | const elem_size = elem_ty.bitSize(func.target); | 4856 | const elem_size = elem_ty.bitSize(mod); |
| 4832 | const vector_len = @intCast(usize, ty.vectorLen()); | 4857 | const vector_len = @intCast(usize, ty.vectorLen()); |
| 4833 | if ((!std.math.isPowerOfTwo(elem_size) or elem_size % 8 != 0) and vector_len > 1) { | 4858 | if ((!std.math.isPowerOfTwo(elem_size) or elem_size % 8 != 0) and vector_len > 1) { |
| 4834 | return func.fail("TODO: WebAssembly `@splat` for arbitrary element bitsize {d}", .{elem_size}); | 4859 | return func.fail("TODO: WebAssembly `@splat` for arbitrary element bitsize {d}", .{elem_size}); |
| 4835 | } | 4860 | } |
| 4836 | 4861 | ||
| 4837 | const result = try func.allocStack(ty); | 4862 | const result = try func.allocStack(ty); |
| 4838 | const elem_byte_size = @intCast(u32, elem_ty.abiSize(func.target)); | 4863 | const elem_byte_size = @intCast(u32, elem_ty.abiSize(mod)); |
| 4839 | var index: usize = 0; | 4864 | var index: usize = 0; |
| 4840 | var offset: u32 = 0; | 4865 | var offset: u32 = 0; |
| 4841 | while (index < vector_len) : (index += 1) { | 4866 | while (index < vector_len) : (index += 1) { |
| ... | @@ -4855,6 +4880,7 @@ fn airSelect(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4855,6 +4880,7 @@ fn airSelect(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4855 | } | 4880 | } |
| 4856 | 4881 | ||
| 4857 | fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 4882 | fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4883 | const mod = func.bin_file.base.options.module.?; | ||
| 4858 | const inst_ty = func.air.typeOfIndex(inst); | 4884 | const inst_ty = func.air.typeOfIndex(inst); |
| 4859 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; | 4885 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; |
| 4860 | const extra = func.air.extraData(Air.Shuffle, ty_pl.payload).data; | 4886 | const extra = func.air.extraData(Air.Shuffle, ty_pl.payload).data; |
| ... | @@ -4865,16 +4891,15 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4865,16 +4891,15 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4865 | const mask_len = extra.mask_len; | 4891 | const mask_len = extra.mask_len; |
| 4866 | 4892 | ||
| 4867 | const child_ty = inst_ty.childType(); | 4893 | const child_ty = inst_ty.childType(); |
| 4868 | const elem_size = child_ty.abiSize(func.target); | 4894 | const elem_size = child_ty.abiSize(mod); |
| 4869 | 4895 | ||
| 4870 | const module = func.bin_file.base.options.module.?; | ||
| 4871 | // TODO: One of them could be by ref; handle in loop | 4896 | // TODO: One of them could be by ref; handle in loop |
| 4872 | if (isByRef(func.air.typeOf(extra.a), func.target) or isByRef(inst_ty, func.target)) { | 4897 | if (isByRef(func.air.typeOf(extra.a), mod) or isByRef(inst_ty, mod)) { |
| 4873 | const result = try func.allocStack(inst_ty); | 4898 | const result = try func.allocStack(inst_ty); |
| 4874 | 4899 | ||
| 4875 | for (0..mask_len) |index| { | 4900 | for (0..mask_len) |index| { |
| 4876 | var buf: Value.ElemValueBuffer = undefined; | 4901 | var buf: Value.ElemValueBuffer = undefined; |
| 4877 | const value = mask.elemValueBuffer(module, index, &buf).toSignedInt(func.target); | 4902 | const value = mask.elemValueBuffer(mod, index, &buf).toSignedInt(mod); |
| 4878 | 4903 | ||
| 4879 | try func.emitWValue(result); | 4904 | try func.emitWValue(result); |
| 4880 | 4905 | ||
| ... | @@ -4895,7 +4920,7 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4895,7 +4920,7 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4895 | var lanes = std.mem.asBytes(operands[1..]); | 4920 | var lanes = std.mem.asBytes(operands[1..]); |
| 4896 | for (0..@intCast(usize, mask_len)) |index| { | 4921 | for (0..@intCast(usize, mask_len)) |index| { |
| 4897 | var buf: Value.ElemValueBuffer = undefined; | 4922 | var buf: Value.ElemValueBuffer = undefined; |
| 4898 | const mask_elem = mask.elemValueBuffer(module, index, &buf).toSignedInt(func.target); | 4923 | const mask_elem = mask.elemValueBuffer(mod, index, &buf).toSignedInt(mod); |
| 4899 | const base_index = if (mask_elem >= 0) | 4924 | const base_index = if (mask_elem >= 0) |
| 4900 | @intCast(u8, @intCast(i64, elem_size) * mask_elem) | 4925 | @intCast(u8, @intCast(i64, elem_size) * mask_elem) |
| 4901 | else | 4926 | else |
| ... | @@ -4930,13 +4955,14 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4930,13 +4955,14 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4930 | const result_ty = func.air.typeOfIndex(inst); | 4955 | const result_ty = func.air.typeOfIndex(inst); |
| 4931 | const len = @intCast(usize, result_ty.arrayLen()); | 4956 | const len = @intCast(usize, result_ty.arrayLen()); |
| 4932 | const elements = @ptrCast([]const Air.Inst.Ref, func.air.extra[ty_pl.payload..][0..len]); | 4957 | const elements = @ptrCast([]const Air.Inst.Ref, func.air.extra[ty_pl.payload..][0..len]); |
| 4958 | const mod = func.bin_file.base.options.module.?; | ||
| 4933 | 4959 | ||
| 4934 | const result: WValue = result_value: { | 4960 | const result: WValue = result_value: { |
| 4935 | switch (result_ty.zigTypeTag()) { | 4961 | switch (result_ty.zigTypeTag(mod)) { |
| 4936 | .Array => { | 4962 | .Array => { |
| 4937 | const result = try func.allocStack(result_ty); | 4963 | const result = try func.allocStack(result_ty); |
| 4938 | const elem_ty = result_ty.childType(); | 4964 | const elem_ty = result_ty.childType(); |
| 4939 | const elem_size = @intCast(u32, elem_ty.abiSize(func.target)); | 4965 | const elem_size = @intCast(u32, elem_ty.abiSize(mod)); |
| 4940 | const sentinel = if (result_ty.sentinel()) |sent| blk: { | 4966 | const sentinel = if (result_ty.sentinel()) |sent| blk: { |
| 4941 | break :blk try func.lowerConstant(sent, elem_ty); | 4967 | break :blk try func.lowerConstant(sent, elem_ty); |
| 4942 | } else null; | 4968 | } else null; |
| ... | @@ -4944,7 +4970,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4944,7 +4970,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4944 | // When the element type is by reference, we must copy the entire | 4970 | // When the element type is by reference, we must copy the entire |
| 4945 | // value. It is therefore safer to move the offset pointer and store | 4971 | // value. It is therefore safer to move the offset pointer and store |
| 4946 | // each value individually, instead of using store offsets. | 4972 | // each value individually, instead of using store offsets. |
| 4947 | if (isByRef(elem_ty, func.target)) { | 4973 | if (isByRef(elem_ty, mod)) { |
| 4948 | // copy stack pointer into a temporary local, which is | 4974 | // copy stack pointer into a temporary local, which is |
| 4949 | // moved for each element to store each value in the right position. | 4975 | // moved for each element to store each value in the right position. |
| 4950 | const offset = try func.buildPointerOffset(result, 0, .new); | 4976 | const offset = try func.buildPointerOffset(result, 0, .new); |
| ... | @@ -4974,7 +5000,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4974,7 +5000,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4974 | }, | 5000 | }, |
| 4975 | .Struct => switch (result_ty.containerLayout()) { | 5001 | .Struct => switch (result_ty.containerLayout()) { |
| 4976 | .Packed => { | 5002 | .Packed => { |
| 4977 | if (isByRef(result_ty, func.target)) { | 5003 | if (isByRef(result_ty, mod)) { |
| 4978 | return func.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{}); | 5004 | return func.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{}); |
| 4979 | } | 5005 | } |
| 4980 | const struct_obj = result_ty.castTag(.@"struct").?.data; | 5006 | const struct_obj = result_ty.castTag(.@"struct").?.data; |
| ... | @@ -4983,7 +5009,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4983,7 +5009,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4983 | 5009 | ||
| 4984 | // ensure the result is zero'd | 5010 | // ensure the result is zero'd |
| 4985 | const result = try func.allocLocal(backing_type); | 5011 | const result = try func.allocLocal(backing_type); |
| 4986 | if (struct_obj.backing_int_ty.bitSize(func.target) <= 32) | 5012 | if (struct_obj.backing_int_ty.bitSize(mod) <= 32) |
| 4987 | try func.addImm32(0) | 5013 | try func.addImm32(0) |
| 4988 | else | 5014 | else |
| 4989 | try func.addImm64(0); | 5015 | try func.addImm64(0); |
| ... | @@ -4992,20 +5018,16 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4992,20 +5018,16 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4992 | var current_bit: u16 = 0; | 5018 | var current_bit: u16 = 0; |
| 4993 | for (elements, 0..) |elem, elem_index| { | 5019 | for (elements, 0..) |elem, elem_index| { |
| 4994 | const field = fields[elem_index]; | 5020 | const field = fields[elem_index]; |
| 4995 | if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue; | 5021 | if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 4996 | 5022 | ||
| 4997 | const shift_val = if (struct_obj.backing_int_ty.bitSize(func.target) <= 32) | 5023 | const shift_val = if (struct_obj.backing_int_ty.bitSize(mod) <= 32) |
| 4998 | WValue{ .imm32 = current_bit } | 5024 | WValue{ .imm32 = current_bit } |
| 4999 | else | 5025 | else |
| 5000 | WValue{ .imm64 = current_bit }; | 5026 | WValue{ .imm64 = current_bit }; |
| 5001 | 5027 | ||
| 5002 | const value = try func.resolveInst(elem); | 5028 | const value = try func.resolveInst(elem); |
| 5003 | const value_bit_size = @intCast(u16, field.ty.bitSize(func.target)); | 5029 | const value_bit_size = @intCast(u16, field.ty.bitSize(mod)); |
| 5004 | var int_ty_payload: Type.Payload.Bits = .{ | 5030 | const int_ty = try mod.intType(.unsigned, value_bit_size); |
| 5005 | .base = .{ .tag = .int_unsigned }, | ||
| 5006 | .data = value_bit_size, | ||
| 5007 | }; | ||
| 5008 | const int_ty = Type.initPayload(&int_ty_payload.base); | ||
| 5009 | 5031 | ||
| 5010 | // load our current result on stack so we can perform all transformations | 5032 | // load our current result on stack so we can perform all transformations |
| 5011 | // using only stack values. Saving the cost of loads and stores. | 5033 | // using only stack values. Saving the cost of loads and stores. |
| ... | @@ -5027,10 +5049,10 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5027,10 +5049,10 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5027 | const result = try func.allocStack(result_ty); | 5049 | const result = try func.allocStack(result_ty); |
| 5028 | const offset = try func.buildPointerOffset(result, 0, .new); // pointer to offset | 5050 | const offset = try func.buildPointerOffset(result, 0, .new); // pointer to offset |
| 5029 | for (elements, 0..) |elem, elem_index| { | 5051 | for (elements, 0..) |elem, elem_index| { |
| 5030 | if (result_ty.structFieldValueComptime(elem_index) != null) continue; | 5052 | if (result_ty.structFieldValueComptime(mod, elem_index) != null) continue; |
| 5031 | 5053 | ||
| 5032 | const elem_ty = result_ty.structFieldType(elem_index); | 5054 | const elem_ty = result_ty.structFieldType(elem_index); |
| 5033 | const elem_size = @intCast(u32, elem_ty.abiSize(func.target)); | 5055 | const elem_size = @intCast(u32, elem_ty.abiSize(mod)); |
| 5034 | const value = try func.resolveInst(elem); | 5056 | const value = try func.resolveInst(elem); |
| 5035 | try func.store(offset, value, elem_ty, 0); | 5057 | try func.store(offset, value, elem_ty, 0); |
| 5036 | 5058 | ||
| ... | @@ -5058,12 +5080,13 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5058,12 +5080,13 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5058 | } | 5080 | } |
| 5059 | 5081 | ||
| 5060 | fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 5082 | fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5083 | const mod = func.bin_file.base.options.module.?; | ||
| 5061 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; | 5084 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; |
| 5062 | const extra = func.air.extraData(Air.UnionInit, ty_pl.payload).data; | 5085 | const extra = func.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 5063 | 5086 | ||
| 5064 | const result = result: { | 5087 | const result = result: { |
| 5065 | const union_ty = func.air.typeOfIndex(inst); | 5088 | const union_ty = func.air.typeOfIndex(inst); |
| 5066 | const layout = union_ty.unionGetLayout(func.target); | 5089 | const layout = union_ty.unionGetLayout(mod); |
| 5067 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | 5090 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 5068 | const field = union_obj.fields.values()[extra.field_index]; | 5091 | const field = union_obj.fields.values()[extra.field_index]; |
| 5069 | const field_name = union_obj.fields.keys()[extra.field_index]; | 5092 | const field_name = union_obj.fields.keys()[extra.field_index]; |
| ... | @@ -5082,15 +5105,15 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5082,15 +5105,15 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5082 | if (layout.tag_size == 0) { | 5105 | if (layout.tag_size == 0) { |
| 5083 | break :result WValue{ .none = {} }; | 5106 | break :result WValue{ .none = {} }; |
| 5084 | } | 5107 | } |
| 5085 | assert(!isByRef(union_ty, func.target)); | 5108 | assert(!isByRef(union_ty, mod)); |
| 5086 | break :result tag_int; | 5109 | break :result tag_int; |
| 5087 | } | 5110 | } |
| 5088 | 5111 | ||
| 5089 | if (isByRef(union_ty, func.target)) { | 5112 | if (isByRef(union_ty, mod)) { |
| 5090 | const result_ptr = try func.allocStack(union_ty); | 5113 | const result_ptr = try func.allocStack(union_ty); |
| 5091 | const payload = try func.resolveInst(extra.init); | 5114 | const payload = try func.resolveInst(extra.init); |
| 5092 | if (layout.tag_align >= layout.payload_align) { | 5115 | if (layout.tag_align >= layout.payload_align) { |
| 5093 | if (isByRef(field.ty, func.target)) { | 5116 | if (isByRef(field.ty, mod)) { |
| 5094 | const payload_ptr = try func.buildPointerOffset(result_ptr, layout.tag_size, .new); | 5117 | const payload_ptr = try func.buildPointerOffset(result_ptr, layout.tag_size, .new); |
| 5095 | try func.store(payload_ptr, payload, field.ty, 0); | 5118 | try func.store(payload_ptr, payload, field.ty, 0); |
| 5096 | } else { | 5119 | } else { |
| ... | @@ -5114,26 +5137,14 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5114,26 +5137,14 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5114 | break :result result_ptr; | 5137 | break :result result_ptr; |
| 5115 | } else { | 5138 | } else { |
| 5116 | const operand = try func.resolveInst(extra.init); | 5139 | const operand = try func.resolveInst(extra.init); |
| 5117 | var payload: Type.Payload.Bits = .{ | 5140 | const union_int_type = try mod.intType(.unsigned, @intCast(u16, union_ty.bitSize(mod))); |
| 5118 | .base = .{ .tag = .int_unsigned }, | 5141 | if (field.ty.zigTypeTag(mod) == .Float) { |
| 5119 | .data = @intCast(u16, union_ty.bitSize(func.target)), | 5142 | const int_type = try mod.intType(.unsigned, @intCast(u16, field.ty.bitSize(mod))); |
| 5120 | }; | ||
| 5121 | const union_int_type = Type.initPayload(&payload.base); | ||
| 5122 | if (field.ty.zigTypeTag() == .Float) { | ||
| 5123 | var int_payload: Type.Payload.Bits = .{ | ||
| 5124 | .base = .{ .tag = .int_unsigned }, | ||
| 5125 | .data = @intCast(u16, field.ty.bitSize(func.target)), | ||
| 5126 | }; | ||
| 5127 | const int_type = Type.initPayload(&int_payload.base); | ||
| 5128 | const bitcasted = try func.bitcast(field.ty, int_type, operand); | 5143 | const bitcasted = try func.bitcast(field.ty, int_type, operand); |
| 5129 | const casted = try func.trunc(bitcasted, int_type, union_int_type); | 5144 | const casted = try func.trunc(bitcasted, int_type, union_int_type); |
| 5130 | break :result try casted.toLocal(func, field.ty); | 5145 | break :result try casted.toLocal(func, field.ty); |
| 5131 | } else if (field.ty.isPtrAtRuntime()) { | 5146 | } else if (field.ty.isPtrAtRuntime(mod)) { |
| 5132 | var int_payload: Type.Payload.Bits = .{ | 5147 | const int_type = try mod.intType(.unsigned, @intCast(u16, field.ty.bitSize(mod))); |
| 5133 | .base = .{ .tag = .int_unsigned }, | ||
| 5134 | .data = @intCast(u16, field.ty.bitSize(func.target)), | ||
| 5135 | }; | ||
| 5136 | const int_type = Type.initPayload(&int_payload.base); | ||
| 5137 | const casted = try func.intcast(operand, int_type, union_int_type); | 5148 | const casted = try func.intcast(operand, int_type, union_int_type); |
| 5138 | break :result try casted.toLocal(func, field.ty); | 5149 | break :result try casted.toLocal(func, field.ty); |
| 5139 | } | 5150 | } |
| ... | @@ -5171,7 +5182,8 @@ fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -5171,7 +5182,8 @@ fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void { |
| 5171 | } | 5182 | } |
| 5172 | 5183 | ||
| 5173 | fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue { | 5184 | fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue { |
| 5174 | assert(operand_ty.hasRuntimeBitsIgnoreComptime()); | 5185 | const mod = func.bin_file.base.options.module.?; |
| 5186 | assert(operand_ty.hasRuntimeBitsIgnoreComptime(mod)); | ||
| 5175 | assert(op == .eq or op == .neq); | 5187 | assert(op == .eq or op == .neq); |
| 5176 | var buf: Type.Payload.ElemType = undefined; | 5188 | var buf: Type.Payload.ElemType = undefined; |
| 5177 | const payload_ty = operand_ty.optionalChild(&buf); | 5189 | const payload_ty = operand_ty.optionalChild(&buf); |
| ... | @@ -5189,7 +5201,7 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: | ... | @@ -5189,7 +5201,7 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: |
| 5189 | 5201 | ||
| 5190 | _ = try func.load(lhs, payload_ty, 0); | 5202 | _ = try func.load(lhs, payload_ty, 0); |
| 5191 | _ = try func.load(rhs, payload_ty, 0); | 5203 | _ = try func.load(rhs, payload_ty, 0); |
| 5192 | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, func.target) }); | 5204 | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, mod) }); |
| 5193 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); | 5205 | try func.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| 5194 | try func.addLabel(.br_if, 0); | 5206 | try func.addLabel(.br_if, 0); |
| 5195 | 5207 | ||
| ... | @@ -5207,10 +5219,11 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: | ... | @@ -5207,10 +5219,11 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: |
| 5207 | /// NOTE: Leaves the result of the comparison on top of the stack. | 5219 | /// NOTE: Leaves the result of the comparison on top of the stack. |
| 5208 | /// TODO: Lower this to compiler_rt call when bitsize > 128 | 5220 | /// TODO: Lower this to compiler_rt call when bitsize > 128 |
| 5209 | fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue { | 5221 | fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue { |
| 5210 | assert(operand_ty.abiSize(func.target) >= 16); | 5222 | const mod = func.bin_file.base.options.module.?; |
| 5223 | assert(operand_ty.abiSize(mod) >= 16); | ||
| 5211 | assert(!(lhs != .stack and rhs == .stack)); | 5224 | assert(!(lhs != .stack and rhs == .stack)); |
| 5212 | if (operand_ty.bitSize(func.target) > 128) { | 5225 | if (operand_ty.bitSize(mod) > 128) { |
| 5213 | return func.fail("TODO: Support cmpBigInt for integer bitsize: '{d}'", .{operand_ty.bitSize(func.target)}); | 5226 | return func.fail("TODO: Support cmpBigInt for integer bitsize: '{d}'", .{operand_ty.bitSize(mod)}); |
| 5214 | } | 5227 | } |
| 5215 | 5228 | ||
| 5216 | var lhs_high_bit = try (try func.load(lhs, Type.u64, 0)).toLocal(func, Type.u64); | 5229 | var lhs_high_bit = try (try func.load(lhs, Type.u64, 0)).toLocal(func, Type.u64); |
| ... | @@ -5233,7 +5246,7 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std | ... | @@ -5233,7 +5246,7 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std |
| 5233 | } | 5246 | } |
| 5234 | }, | 5247 | }, |
| 5235 | else => { | 5248 | else => { |
| 5236 | const ty = if (operand_ty.isSignedInt()) Type.i64 else Type.u64; | 5249 | const ty = if (operand_ty.isSignedInt(mod)) Type.i64 else Type.u64; |
| 5237 | // leave those value on top of the stack for '.select' | 5250 | // leave those value on top of the stack for '.select' |
| 5238 | const lhs_low_bit = try func.load(lhs, Type.u64, 8); | 5251 | const lhs_low_bit = try func.load(lhs, Type.u64, 8); |
| 5239 | const rhs_low_bit = try func.load(rhs, Type.u64, 8); | 5252 | const rhs_low_bit = try func.load(rhs, Type.u64, 8); |
| ... | @@ -5248,10 +5261,11 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std | ... | @@ -5248,10 +5261,11 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std |
| 5248 | } | 5261 | } |
| 5249 | 5262 | ||
| 5250 | fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 5263 | fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5264 | const mod = func.bin_file.base.options.module.?; | ||
| 5251 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 5265 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 5252 | const un_ty = func.air.typeOf(bin_op.lhs).childType(); | 5266 | const un_ty = func.air.typeOf(bin_op.lhs).childType(); |
| 5253 | const tag_ty = func.air.typeOf(bin_op.rhs); | 5267 | const tag_ty = func.air.typeOf(bin_op.rhs); |
| 5254 | const layout = un_ty.unionGetLayout(func.target); | 5268 | const layout = un_ty.unionGetLayout(mod); |
| 5255 | if (layout.tag_size == 0) return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs }); | 5269 | if (layout.tag_size == 0) return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs }); |
| 5256 | 5270 | ||
| 5257 | const union_ptr = try func.resolveInst(bin_op.lhs); | 5271 | const union_ptr = try func.resolveInst(bin_op.lhs); |
| ... | @@ -5271,11 +5285,12 @@ fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5271,11 +5285,12 @@ fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5271 | } | 5285 | } |
| 5272 | 5286 | ||
| 5273 | fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 5287 | fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5288 | const mod = func.bin_file.base.options.module.?; | ||
| 5274 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 5289 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 5275 | 5290 | ||
| 5276 | const un_ty = func.air.typeOf(ty_op.operand); | 5291 | const un_ty = func.air.typeOf(ty_op.operand); |
| 5277 | const tag_ty = func.air.typeOfIndex(inst); | 5292 | const tag_ty = func.air.typeOfIndex(inst); |
| 5278 | const layout = un_ty.unionGetLayout(func.target); | 5293 | const layout = un_ty.unionGetLayout(mod); |
| 5279 | if (layout.tag_size == 0) return func.finishAir(inst, .none, &.{ty_op.operand}); | 5294 | if (layout.tag_size == 0) return func.finishAir(inst, .none, &.{ty_op.operand}); |
| 5280 | 5295 | ||
| 5281 | const operand = try func.resolveInst(ty_op.operand); | 5296 | const operand = try func.resolveInst(ty_op.operand); |
| ... | @@ -5375,6 +5390,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro | ... | @@ -5375,6 +5390,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro |
| 5375 | } | 5390 | } |
| 5376 | 5391 | ||
| 5377 | fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 5392 | fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5393 | const mod = func.bin_file.base.options.module.?; | ||
| 5378 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 5394 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 5379 | 5395 | ||
| 5380 | const err_set_ty = func.air.typeOf(ty_op.operand).childType(); | 5396 | const err_set_ty = func.air.typeOf(ty_op.operand).childType(); |
| ... | @@ -5386,26 +5402,27 @@ fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi | ... | @@ -5386,26 +5402,27 @@ fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi |
| 5386 | operand, | 5402 | operand, |
| 5387 | .{ .imm32 = 0 }, | 5403 | .{ .imm32 = 0 }, |
| 5388 | Type.anyerror, | 5404 | Type.anyerror, |
| 5389 | @intCast(u32, errUnionErrorOffset(payload_ty, func.target)), | 5405 | @intCast(u32, errUnionErrorOffset(payload_ty, mod)), |
| 5390 | ); | 5406 | ); |
| 5391 | 5407 | ||
| 5392 | const result = result: { | 5408 | const result = result: { |
| 5393 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 5409 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5394 | break :result func.reuseOperand(ty_op.operand, operand); | 5410 | break :result func.reuseOperand(ty_op.operand, operand); |
| 5395 | } | 5411 | } |
| 5396 | 5412 | ||
| 5397 | break :result try func.buildPointerOffset(operand, @intCast(u32, errUnionPayloadOffset(payload_ty, func.target)), .new); | 5413 | break :result try func.buildPointerOffset(operand, @intCast(u32, errUnionPayloadOffset(payload_ty, mod)), .new); |
| 5398 | }; | 5414 | }; |
| 5399 | func.finishAir(inst, result, &.{ty_op.operand}); | 5415 | func.finishAir(inst, result, &.{ty_op.operand}); |
| 5400 | } | 5416 | } |
| 5401 | 5417 | ||
| 5402 | fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 5418 | fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5419 | const mod = func.bin_file.base.options.module.?; | ||
| 5403 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; | 5420 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; |
| 5404 | const extra = func.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | 5421 | const extra = func.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 5405 | 5422 | ||
| 5406 | const field_ptr = try func.resolveInst(extra.field_ptr); | 5423 | const field_ptr = try func.resolveInst(extra.field_ptr); |
| 5407 | const parent_ty = func.air.getRefType(ty_pl.ty).childType(); | 5424 | const parent_ty = func.air.getRefType(ty_pl.ty).childType(); |
| 5408 | const field_offset = parent_ty.structFieldOffset(extra.field_index, func.target); | 5425 | const field_offset = parent_ty.structFieldOffset(extra.field_index, mod); |
| 5409 | 5426 | ||
| 5410 | const result = if (field_offset != 0) result: { | 5427 | const result = if (field_offset != 0) result: { |
| 5411 | const base = try func.buildPointerOffset(field_ptr, 0, .new); | 5428 | const base = try func.buildPointerOffset(field_ptr, 0, .new); |
| ... | @@ -5428,6 +5445,7 @@ fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue | ... | @@ -5428,6 +5445,7 @@ fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue |
| 5428 | } | 5445 | } |
| 5429 | 5446 | ||
| 5430 | fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 5447 | fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5448 | const mod = func.bin_file.base.options.module.?; | ||
| 5431 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 5449 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 5432 | const dst = try func.resolveInst(bin_op.lhs); | 5450 | const dst = try func.resolveInst(bin_op.lhs); |
| 5433 | const dst_ty = func.air.typeOf(bin_op.lhs); | 5451 | const dst_ty = func.air.typeOf(bin_op.lhs); |
| ... | @@ -5437,16 +5455,16 @@ fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5437,16 +5455,16 @@ fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5437 | const len = switch (dst_ty.ptrSize()) { | 5455 | const len = switch (dst_ty.ptrSize()) { |
| 5438 | .Slice => blk: { | 5456 | .Slice => blk: { |
| 5439 | const slice_len = try func.sliceLen(dst); | 5457 | const slice_len = try func.sliceLen(dst); |
| 5440 | if (ptr_elem_ty.abiSize(func.target) != 1) { | 5458 | if (ptr_elem_ty.abiSize(mod) != 1) { |
| 5441 | try func.emitWValue(slice_len); | 5459 | try func.emitWValue(slice_len); |
| 5442 | try func.emitWValue(.{ .imm32 = @intCast(u32, ptr_elem_ty.abiSize(func.target)) }); | 5460 | try func.emitWValue(.{ .imm32 = @intCast(u32, ptr_elem_ty.abiSize(mod)) }); |
| 5443 | try func.addTag(.i32_mul); | 5461 | try func.addTag(.i32_mul); |
| 5444 | try func.addLabel(.local_set, slice_len.local.value); | 5462 | try func.addLabel(.local_set, slice_len.local.value); |
| 5445 | } | 5463 | } |
| 5446 | break :blk slice_len; | 5464 | break :blk slice_len; |
| 5447 | }, | 5465 | }, |
| 5448 | .One => @as(WValue, .{ | 5466 | .One => @as(WValue, .{ |
| 5449 | .imm32 = @intCast(u32, ptr_elem_ty.arrayLen() * ptr_elem_ty.childType().abiSize(func.target)), | 5467 | .imm32 = @intCast(u32, ptr_elem_ty.arrayLen() * ptr_elem_ty.childType().abiSize(mod)), |
| 5450 | }), | 5468 | }), |
| 5451 | .C, .Many => unreachable, | 5469 | .C, .Many => unreachable, |
| 5452 | }; | 5470 | }; |
| ... | @@ -5472,12 +5490,13 @@ fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5472,12 +5490,13 @@ fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5472 | const operand = try func.resolveInst(ty_op.operand); | 5490 | const operand = try func.resolveInst(ty_op.operand); |
| 5473 | const op_ty = func.air.typeOf(ty_op.operand); | 5491 | const op_ty = func.air.typeOf(ty_op.operand); |
| 5474 | const result_ty = func.air.typeOfIndex(inst); | 5492 | const result_ty = func.air.typeOfIndex(inst); |
| 5493 | const mod = func.bin_file.base.options.module.?; | ||
| 5475 | 5494 | ||
| 5476 | if (op_ty.zigTypeTag() == .Vector) { | 5495 | if (op_ty.zigTypeTag(mod) == .Vector) { |
| 5477 | return func.fail("TODO: Implement @popCount for vectors", .{}); | 5496 | return func.fail("TODO: Implement @popCount for vectors", .{}); |
| 5478 | } | 5497 | } |
| 5479 | 5498 | ||
| 5480 | const int_info = op_ty.intInfo(func.target); | 5499 | const int_info = op_ty.intInfo(mod); |
| 5481 | const bits = int_info.bits; | 5500 | const bits = int_info.bits; |
| 5482 | const wasm_bits = toWasmBits(bits) orelse { | 5501 | const wasm_bits = toWasmBits(bits) orelse { |
| 5483 | return func.fail("TODO: Implement @popCount for integers with bitsize '{d}'", .{bits}); | 5502 | return func.fail("TODO: Implement @popCount for integers with bitsize '{d}'", .{bits}); |
| ... | @@ -5527,7 +5546,8 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5527,7 +5546,8 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5527 | // to make a copy of the ptr+value but can point towards them directly. | 5546 | // to make a copy of the ptr+value but can point towards them directly. |
| 5528 | const error_table_symbol = try func.bin_file.getErrorTableSymbol(); | 5547 | const error_table_symbol = try func.bin_file.getErrorTableSymbol(); |
| 5529 | const name_ty = Type.initTag(.const_slice_u8_sentinel_0); | 5548 | const name_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 5530 | const abi_size = name_ty.abiSize(func.target); | 5549 | const mod = func.bin_file.base.options.module.?; |
| 5550 | const abi_size = name_ty.abiSize(mod); | ||
| 5531 | 5551 | ||
| 5532 | const error_name_value: WValue = .{ .memory = error_table_symbol }; // emitting this will create a relocation | 5552 | const error_name_value: WValue = .{ .memory = error_table_symbol }; // emitting this will create a relocation |
| 5533 | try func.emitWValue(error_name_value); | 5553 | try func.emitWValue(error_name_value); |
| ... | @@ -5566,12 +5586,13 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro | ... | @@ -5566,12 +5586,13 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro |
| 5566 | const lhs_op = try func.resolveInst(extra.lhs); | 5586 | const lhs_op = try func.resolveInst(extra.lhs); |
| 5567 | const rhs_op = try func.resolveInst(extra.rhs); | 5587 | const rhs_op = try func.resolveInst(extra.rhs); |
| 5568 | const lhs_ty = func.air.typeOf(extra.lhs); | 5588 | const lhs_ty = func.air.typeOf(extra.lhs); |
| 5589 | const mod = func.bin_file.base.options.module.?; | ||
| 5569 | 5590 | ||
| 5570 | if (lhs_ty.zigTypeTag() == .Vector) { | 5591 | if (lhs_ty.zigTypeTag(mod) == .Vector) { |
| 5571 | return func.fail("TODO: Implement overflow arithmetic for vectors", .{}); | 5592 | return func.fail("TODO: Implement overflow arithmetic for vectors", .{}); |
| 5572 | } | 5593 | } |
| 5573 | 5594 | ||
| 5574 | const int_info = lhs_ty.intInfo(func.target); | 5595 | const int_info = lhs_ty.intInfo(mod); |
| 5575 | const is_signed = int_info.signedness == .signed; | 5596 | const is_signed = int_info.signedness == .signed; |
| 5576 | const wasm_bits = toWasmBits(int_info.bits) orelse { | 5597 | const wasm_bits = toWasmBits(int_info.bits) orelse { |
| 5577 | return func.fail("TODO: Implement {{add/sub}}_with_overflow for integer bitsize: {d}", .{int_info.bits}); | 5598 | return func.fail("TODO: Implement {{add/sub}}_with_overflow for integer bitsize: {d}", .{int_info.bits}); |
| ... | @@ -5630,15 +5651,16 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro | ... | @@ -5630,15 +5651,16 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro |
| 5630 | 5651 | ||
| 5631 | const result_ptr = try func.allocStack(func.air.typeOfIndex(inst)); | 5652 | const result_ptr = try func.allocStack(func.air.typeOfIndex(inst)); |
| 5632 | try func.store(result_ptr, result, lhs_ty, 0); | 5653 | try func.store(result_ptr, result, lhs_ty, 0); |
| 5633 | const offset = @intCast(u32, lhs_ty.abiSize(func.target)); | 5654 | const offset = @intCast(u32, lhs_ty.abiSize(mod)); |
| 5634 | try func.store(result_ptr, overflow_local, Type.initTag(.u1), offset); | 5655 | try func.store(result_ptr, overflow_local, Type.initTag(.u1), offset); |
| 5635 | 5656 | ||
| 5636 | func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs }); | 5657 | func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs }); |
| 5637 | } | 5658 | } |
| 5638 | 5659 | ||
| 5639 | fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, result_ty: Type, op: Op) InnerError!WValue { | 5660 | fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, result_ty: Type, op: Op) InnerError!WValue { |
| 5661 | const mod = func.bin_file.base.options.module.?; | ||
| 5640 | assert(op == .add or op == .sub); | 5662 | assert(op == .add or op == .sub); |
| 5641 | const int_info = ty.intInfo(func.target); | 5663 | const int_info = ty.intInfo(mod); |
| 5642 | const is_signed = int_info.signedness == .signed; | 5664 | const is_signed = int_info.signedness == .signed; |
| 5643 | if (int_info.bits != 128) { | 5665 | if (int_info.bits != 128) { |
| 5644 | return func.fail("TODO: Implement @{{add/sub}}WithOverflow for integer bitsize '{d}'", .{int_info.bits}); | 5666 | return func.fail("TODO: Implement @{{add/sub}}WithOverflow for integer bitsize '{d}'", .{int_info.bits}); |
| ... | @@ -5701,6 +5723,7 @@ fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, | ... | @@ -5701,6 +5723,7 @@ fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, |
| 5701 | } | 5723 | } |
| 5702 | 5724 | ||
| 5703 | fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 5725 | fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5726 | const mod = func.bin_file.base.options.module.?; | ||
| 5704 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; | 5727 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; |
| 5705 | const extra = func.air.extraData(Air.Bin, ty_pl.payload).data; | 5728 | const extra = func.air.extraData(Air.Bin, ty_pl.payload).data; |
| 5706 | 5729 | ||
| ... | @@ -5709,11 +5732,11 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5709,11 +5732,11 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5709 | const lhs_ty = func.air.typeOf(extra.lhs); | 5732 | const lhs_ty = func.air.typeOf(extra.lhs); |
| 5710 | const rhs_ty = func.air.typeOf(extra.rhs); | 5733 | const rhs_ty = func.air.typeOf(extra.rhs); |
| 5711 | 5734 | ||
| 5712 | if (lhs_ty.zigTypeTag() == .Vector) { | 5735 | if (lhs_ty.zigTypeTag(mod) == .Vector) { |
| 5713 | return func.fail("TODO: Implement overflow arithmetic for vectors", .{}); | 5736 | return func.fail("TODO: Implement overflow arithmetic for vectors", .{}); |
| 5714 | } | 5737 | } |
| 5715 | 5738 | ||
| 5716 | const int_info = lhs_ty.intInfo(func.target); | 5739 | const int_info = lhs_ty.intInfo(mod); |
| 5717 | const is_signed = int_info.signedness == .signed; | 5740 | const is_signed = int_info.signedness == .signed; |
| 5718 | const wasm_bits = toWasmBits(int_info.bits) orelse { | 5741 | const wasm_bits = toWasmBits(int_info.bits) orelse { |
| 5719 | return func.fail("TODO: Implement shl_with_overflow for integer bitsize: {d}", .{int_info.bits}); | 5742 | return func.fail("TODO: Implement shl_with_overflow for integer bitsize: {d}", .{int_info.bits}); |
| ... | @@ -5721,7 +5744,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5721,7 +5744,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5721 | 5744 | ||
| 5722 | // Ensure rhs is coerced to lhs as they must have the same WebAssembly types | 5745 | // Ensure rhs is coerced to lhs as they must have the same WebAssembly types |
| 5723 | // before we can perform any binary operation. | 5746 | // before we can perform any binary operation. |
| 5724 | const rhs_wasm_bits = toWasmBits(rhs_ty.intInfo(func.target).bits).?; | 5747 | const rhs_wasm_bits = toWasmBits(rhs_ty.intInfo(mod).bits).?; |
| 5725 | const rhs_final = if (wasm_bits != rhs_wasm_bits) blk: { | 5748 | const rhs_final = if (wasm_bits != rhs_wasm_bits) blk: { |
| 5726 | const rhs_casted = try func.intcast(rhs, rhs_ty, lhs_ty); | 5749 | const rhs_casted = try func.intcast(rhs, rhs_ty, lhs_ty); |
| 5727 | break :blk try rhs_casted.toLocal(func, lhs_ty); | 5750 | break :blk try rhs_casted.toLocal(func, lhs_ty); |
| ... | @@ -5750,7 +5773,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5750,7 +5773,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5750 | 5773 | ||
| 5751 | const result_ptr = try func.allocStack(func.air.typeOfIndex(inst)); | 5774 | const result_ptr = try func.allocStack(func.air.typeOfIndex(inst)); |
| 5752 | try func.store(result_ptr, result, lhs_ty, 0); | 5775 | try func.store(result_ptr, result, lhs_ty, 0); |
| 5753 | const offset = @intCast(u32, lhs_ty.abiSize(func.target)); | 5776 | const offset = @intCast(u32, lhs_ty.abiSize(mod)); |
| 5754 | try func.store(result_ptr, overflow_local, Type.initTag(.u1), offset); | 5777 | try func.store(result_ptr, overflow_local, Type.initTag(.u1), offset); |
| 5755 | 5778 | ||
| 5756 | func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs }); | 5779 | func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs }); |
| ... | @@ -5763,8 +5786,9 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5763,8 +5786,9 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5763 | const lhs = try func.resolveInst(extra.lhs); | 5786 | const lhs = try func.resolveInst(extra.lhs); |
| 5764 | const rhs = try func.resolveInst(extra.rhs); | 5787 | const rhs = try func.resolveInst(extra.rhs); |
| 5765 | const lhs_ty = func.air.typeOf(extra.lhs); | 5788 | const lhs_ty = func.air.typeOf(extra.lhs); |
| 5789 | const mod = func.bin_file.base.options.module.?; | ||
| 5766 | 5790 | ||
| 5767 | if (lhs_ty.zigTypeTag() == .Vector) { | 5791 | if (lhs_ty.zigTypeTag(mod) == .Vector) { |
| 5768 | return func.fail("TODO: Implement overflow arithmetic for vectors", .{}); | 5792 | return func.fail("TODO: Implement overflow arithmetic for vectors", .{}); |
| 5769 | } | 5793 | } |
| 5770 | 5794 | ||
| ... | @@ -5773,7 +5797,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5773,7 +5797,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5773 | var overflow_bit = try func.ensureAllocLocal(Type.initTag(.u1)); | 5797 | var overflow_bit = try func.ensureAllocLocal(Type.initTag(.u1)); |
| 5774 | defer overflow_bit.free(func); | 5798 | defer overflow_bit.free(func); |
| 5775 | 5799 | ||
| 5776 | const int_info = lhs_ty.intInfo(func.target); | 5800 | const int_info = lhs_ty.intInfo(mod); |
| 5777 | const wasm_bits = toWasmBits(int_info.bits) orelse { | 5801 | const wasm_bits = toWasmBits(int_info.bits) orelse { |
| 5778 | return func.fail("TODO: Implement `@mulWithOverflow` for integer bitsize: {d}", .{int_info.bits}); | 5802 | return func.fail("TODO: Implement `@mulWithOverflow` for integer bitsize: {d}", .{int_info.bits}); |
| 5779 | }; | 5803 | }; |
| ... | @@ -5924,7 +5948,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5924,7 +5948,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5924 | 5948 | ||
| 5925 | const result_ptr = try func.allocStack(func.air.typeOfIndex(inst)); | 5949 | const result_ptr = try func.allocStack(func.air.typeOfIndex(inst)); |
| 5926 | try func.store(result_ptr, bin_op_local, lhs_ty, 0); | 5950 | try func.store(result_ptr, bin_op_local, lhs_ty, 0); |
| 5927 | const offset = @intCast(u32, lhs_ty.abiSize(func.target)); | 5951 | const offset = @intCast(u32, lhs_ty.abiSize(mod)); |
| 5928 | try func.store(result_ptr, overflow_bit, Type.initTag(.u1), offset); | 5952 | try func.store(result_ptr, overflow_bit, Type.initTag(.u1), offset); |
| 5929 | 5953 | ||
| 5930 | func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs }); | 5954 | func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs }); |
| ... | @@ -5934,11 +5958,12 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerE | ... | @@ -5934,11 +5958,12 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerE |
| 5934 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 5958 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 5935 | 5959 | ||
| 5936 | const ty = func.air.typeOfIndex(inst); | 5960 | const ty = func.air.typeOfIndex(inst); |
| 5937 | if (ty.zigTypeTag() == .Vector) { | 5961 | const mod = func.bin_file.base.options.module.?; |
| 5962 | if (ty.zigTypeTag(mod) == .Vector) { | ||
| 5938 | return func.fail("TODO: `@maximum` and `@minimum` for vectors", .{}); | 5963 | return func.fail("TODO: `@maximum` and `@minimum` for vectors", .{}); |
| 5939 | } | 5964 | } |
| 5940 | 5965 | ||
| 5941 | if (ty.abiSize(func.target) > 16) { | 5966 | if (ty.abiSize(mod) > 16) { |
| 5942 | return func.fail("TODO: `@maximum` and `@minimum` for types larger than 16 bytes", .{}); | 5967 | return func.fail("TODO: `@maximum` and `@minimum` for types larger than 16 bytes", .{}); |
| 5943 | } | 5968 | } |
| 5944 | 5969 | ||
| ... | @@ -5954,7 +5979,7 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerE | ... | @@ -5954,7 +5979,7 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerE |
| 5954 | try func.addTag(.select); | 5979 | try func.addTag(.select); |
| 5955 | 5980 | ||
| 5956 | // store result in local | 5981 | // store result in local |
| 5957 | const result_ty = if (isByRef(ty, func.target)) Type.u32 else ty; | 5982 | const result_ty = if (isByRef(ty, mod)) Type.u32 else ty; |
| 5958 | const result = try func.allocLocal(result_ty); | 5983 | const result = try func.allocLocal(result_ty); |
| 5959 | try func.addLabel(.local_set, result.local.value); | 5984 | try func.addLabel(.local_set, result.local.value); |
| 5960 | func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs }); | 5985 | func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs }); |
| ... | @@ -5965,7 +5990,8 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5965,7 +5990,8 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5965 | const bin_op = func.air.extraData(Air.Bin, pl_op.payload).data; | 5990 | const bin_op = func.air.extraData(Air.Bin, pl_op.payload).data; |
| 5966 | 5991 | ||
| 5967 | const ty = func.air.typeOfIndex(inst); | 5992 | const ty = func.air.typeOfIndex(inst); |
| 5968 | if (ty.zigTypeTag() == .Vector) { | 5993 | const mod = func.bin_file.base.options.module.?; |
| 5994 | if (ty.zigTypeTag(mod) == .Vector) { | ||
| 5969 | return func.fail("TODO: `@mulAdd` for vectors", .{}); | 5995 | return func.fail("TODO: `@mulAdd` for vectors", .{}); |
| 5970 | } | 5996 | } |
| 5971 | 5997 | ||
| ... | @@ -5998,12 +6024,13 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5998,12 +6024,13 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5998 | 6024 | ||
| 5999 | const ty = func.air.typeOf(ty_op.operand); | 6025 | const ty = func.air.typeOf(ty_op.operand); |
| 6000 | const result_ty = func.air.typeOfIndex(inst); | 6026 | const result_ty = func.air.typeOfIndex(inst); |
| 6001 | if (ty.zigTypeTag() == .Vector) { | 6027 | const mod = func.bin_file.base.options.module.?; |
| 6028 | if (ty.zigTypeTag(mod) == .Vector) { | ||
| 6002 | return func.fail("TODO: `@clz` for vectors", .{}); | 6029 | return func.fail("TODO: `@clz` for vectors", .{}); |
| 6003 | } | 6030 | } |
| 6004 | 6031 | ||
| 6005 | const operand = try func.resolveInst(ty_op.operand); | 6032 | const operand = try func.resolveInst(ty_op.operand); |
| 6006 | const int_info = ty.intInfo(func.target); | 6033 | const int_info = ty.intInfo(mod); |
| 6007 | const wasm_bits = toWasmBits(int_info.bits) orelse { | 6034 | const wasm_bits = toWasmBits(int_info.bits) orelse { |
| 6008 | return func.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits}); | 6035 | return func.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits}); |
| 6009 | }; | 6036 | }; |
| ... | @@ -6051,12 +6078,13 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6051,12 +6078,13 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6051 | const ty = func.air.typeOf(ty_op.operand); | 6078 | const ty = func.air.typeOf(ty_op.operand); |
| 6052 | const result_ty = func.air.typeOfIndex(inst); | 6079 | const result_ty = func.air.typeOfIndex(inst); |
| 6053 | 6080 | ||
| 6054 | if (ty.zigTypeTag() == .Vector) { | 6081 | const mod = func.bin_file.base.options.module.?; |
| 6082 | if (ty.zigTypeTag(mod) == .Vector) { | ||
| 6055 | return func.fail("TODO: `@ctz` for vectors", .{}); | 6083 | return func.fail("TODO: `@ctz` for vectors", .{}); |
| 6056 | } | 6084 | } |
| 6057 | 6085 | ||
| 6058 | const operand = try func.resolveInst(ty_op.operand); | 6086 | const operand = try func.resolveInst(ty_op.operand); |
| 6059 | const int_info = ty.intInfo(func.target); | 6087 | const int_info = ty.intInfo(mod); |
| 6060 | const wasm_bits = toWasmBits(int_info.bits) orelse { | 6088 | const wasm_bits = toWasmBits(int_info.bits) orelse { |
| 6061 | return func.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits}); | 6089 | return func.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits}); |
| 6062 | }; | 6090 | }; |
| ... | @@ -6174,12 +6202,13 @@ fn lowerTry( | ... | @@ -6174,12 +6202,13 @@ fn lowerTry( |
| 6174 | err_union_ty: Type, | 6202 | err_union_ty: Type, |
| 6175 | operand_is_ptr: bool, | 6203 | operand_is_ptr: bool, |
| 6176 | ) InnerError!WValue { | 6204 | ) InnerError!WValue { |
| 6205 | const mod = func.bin_file.base.options.module.?; | ||
| 6177 | if (operand_is_ptr) { | 6206 | if (operand_is_ptr) { |
| 6178 | return func.fail("TODO: lowerTry for pointers", .{}); | 6207 | return func.fail("TODO: lowerTry for pointers", .{}); |
| 6179 | } | 6208 | } |
| 6180 | 6209 | ||
| 6181 | const pl_ty = err_union_ty.errorUnionPayload(); | 6210 | const pl_ty = err_union_ty.errorUnionPayload(); |
| 6182 | const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime(); | 6211 | const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime(mod); |
| 6183 | 6212 | ||
| 6184 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { | 6213 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { |
| 6185 | // Block we can jump out of when error is not set | 6214 | // Block we can jump out of when error is not set |
| ... | @@ -6188,10 +6217,10 @@ fn lowerTry( | ... | @@ -6188,10 +6217,10 @@ fn lowerTry( |
| 6188 | // check if the error tag is set for the error union. | 6217 | // check if the error tag is set for the error union. |
| 6189 | try func.emitWValue(err_union); | 6218 | try func.emitWValue(err_union); |
| 6190 | if (pl_has_bits) { | 6219 | if (pl_has_bits) { |
| 6191 | const err_offset = @intCast(u32, errUnionErrorOffset(pl_ty, func.target)); | 6220 | const err_offset = @intCast(u32, errUnionErrorOffset(pl_ty, mod)); |
| 6192 | try func.addMemArg(.i32_load16_u, .{ | 6221 | try func.addMemArg(.i32_load16_u, .{ |
| 6193 | .offset = err_union.offset() + err_offset, | 6222 | .offset = err_union.offset() + err_offset, |
| 6194 | .alignment = Type.anyerror.abiAlignment(func.target), | 6223 | .alignment = Type.anyerror.abiAlignment(mod), |
| 6195 | }); | 6224 | }); |
| 6196 | } | 6225 | } |
| 6197 | try func.addTag(.i32_eqz); | 6226 | try func.addTag(.i32_eqz); |
| ... | @@ -6213,8 +6242,8 @@ fn lowerTry( | ... | @@ -6213,8 +6242,8 @@ fn lowerTry( |
| 6213 | return WValue{ .none = {} }; | 6242 | return WValue{ .none = {} }; |
| 6214 | } | 6243 | } |
| 6215 | 6244 | ||
| 6216 | const pl_offset = @intCast(u32, errUnionPayloadOffset(pl_ty, func.target)); | 6245 | const pl_offset = @intCast(u32, errUnionPayloadOffset(pl_ty, mod)); |
| 6217 | if (isByRef(pl_ty, func.target)) { | 6246 | if (isByRef(pl_ty, mod)) { |
| 6218 | return buildPointerOffset(func, err_union, pl_offset, .new); | 6247 | return buildPointerOffset(func, err_union, pl_offset, .new); |
| 6219 | } | 6248 | } |
| 6220 | const payload = try func.load(err_union, pl_ty, pl_offset); | 6249 | const payload = try func.load(err_union, pl_ty, pl_offset); |
| ... | @@ -6226,11 +6255,12 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6226,11 +6255,12 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6226 | 6255 | ||
| 6227 | const ty = func.air.typeOfIndex(inst); | 6256 | const ty = func.air.typeOfIndex(inst); |
| 6228 | const operand = try func.resolveInst(ty_op.operand); | 6257 | const operand = try func.resolveInst(ty_op.operand); |
| 6258 | const mod = func.bin_file.base.options.module.?; | ||
| 6229 | 6259 | ||
| 6230 | if (ty.zigTypeTag() == .Vector) { | 6260 | if (ty.zigTypeTag(mod) == .Vector) { |
| 6231 | return func.fail("TODO: @byteSwap for vectors", .{}); | 6261 | return func.fail("TODO: @byteSwap for vectors", .{}); |
| 6232 | } | 6262 | } |
| 6233 | const int_info = ty.intInfo(func.target); | 6263 | const int_info = ty.intInfo(mod); |
| 6234 | 6264 | ||
| 6235 | // bytes are no-op | 6265 | // bytes are no-op |
| 6236 | if (int_info.bits == 8) { | 6266 | if (int_info.bits == 8) { |
| ... | @@ -6292,13 +6322,14 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6292,13 +6322,14 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6292 | } | 6322 | } |
| 6293 | 6323 | ||
| 6294 | fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 6324 | fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6325 | const mod = func.bin_file.base.options.module.?; | ||
| 6295 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 6326 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 6296 | 6327 | ||
| 6297 | const ty = func.air.typeOfIndex(inst); | 6328 | const ty = func.air.typeOfIndex(inst); |
| 6298 | const lhs = try func.resolveInst(bin_op.lhs); | 6329 | const lhs = try func.resolveInst(bin_op.lhs); |
| 6299 | const rhs = try func.resolveInst(bin_op.rhs); | 6330 | const rhs = try func.resolveInst(bin_op.rhs); |
| 6300 | 6331 | ||
| 6301 | const result = if (ty.isSignedInt()) | 6332 | const result = if (ty.isSignedInt(mod)) |
| 6302 | try func.divSigned(lhs, rhs, ty) | 6333 | try func.divSigned(lhs, rhs, ty) |
| 6303 | else | 6334 | else |
| 6304 | try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty); | 6335 | try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty); |
| ... | @@ -6306,13 +6337,14 @@ fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6306,13 +6337,14 @@ fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6306 | } | 6337 | } |
| 6307 | 6338 | ||
| 6308 | fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 6339 | fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6340 | const mod = func.bin_file.base.options.module.?; | ||
| 6309 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 6341 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 6310 | 6342 | ||
| 6311 | const ty = func.air.typeOfIndex(inst); | 6343 | const ty = func.air.typeOfIndex(inst); |
| 6312 | const lhs = try func.resolveInst(bin_op.lhs); | 6344 | const lhs = try func.resolveInst(bin_op.lhs); |
| 6313 | const rhs = try func.resolveInst(bin_op.rhs); | 6345 | const rhs = try func.resolveInst(bin_op.rhs); |
| 6314 | 6346 | ||
| 6315 | const div_result = if (ty.isSignedInt()) | 6347 | const div_result = if (ty.isSignedInt(mod)) |
| 6316 | try func.divSigned(lhs, rhs, ty) | 6348 | try func.divSigned(lhs, rhs, ty) |
| 6317 | else | 6349 | else |
| 6318 | try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty); | 6350 | try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty); |
| ... | @@ -6328,15 +6360,16 @@ fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6328,15 +6360,16 @@ fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6328 | fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 6360 | fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6329 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 6361 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 6330 | 6362 | ||
| 6363 | const mod = func.bin_file.base.options.module.?; | ||
| 6331 | const ty = func.air.typeOfIndex(inst); | 6364 | const ty = func.air.typeOfIndex(inst); |
| 6332 | const lhs = try func.resolveInst(bin_op.lhs); | 6365 | const lhs = try func.resolveInst(bin_op.lhs); |
| 6333 | const rhs = try func.resolveInst(bin_op.rhs); | 6366 | const rhs = try func.resolveInst(bin_op.rhs); |
| 6334 | 6367 | ||
| 6335 | if (ty.isUnsignedInt()) { | 6368 | if (ty.isUnsignedInt(mod)) { |
| 6336 | const result = try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty); | 6369 | const result = try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty); |
| 6337 | return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs }); | 6370 | return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs }); |
| 6338 | } else if (ty.isSignedInt()) { | 6371 | } else if (ty.isSignedInt(mod)) { |
| 6339 | const int_bits = ty.intInfo(func.target).bits; | 6372 | const int_bits = ty.intInfo(mod).bits; |
| 6340 | const wasm_bits = toWasmBits(int_bits) orelse { | 6373 | const wasm_bits = toWasmBits(int_bits) orelse { |
| 6341 | return func.fail("TODO: `@divFloor` for signed integers larger than '{d}' bits", .{int_bits}); | 6374 | return func.fail("TODO: `@divFloor` for signed integers larger than '{d}' bits", .{int_bits}); |
| 6342 | }; | 6375 | }; |
| ... | @@ -6414,7 +6447,8 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6414,7 +6447,8 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6414 | } | 6447 | } |
| 6415 | 6448 | ||
| 6416 | fn divSigned(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type) InnerError!WValue { | 6449 | fn divSigned(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type) InnerError!WValue { |
| 6417 | const int_bits = ty.intInfo(func.target).bits; | 6450 | const mod = func.bin_file.base.options.module.?; |
| 6451 | const int_bits = ty.intInfo(mod).bits; | ||
| 6418 | const wasm_bits = toWasmBits(int_bits) orelse { | 6452 | const wasm_bits = toWasmBits(int_bits) orelse { |
| 6419 | return func.fail("TODO: Implement signed division for integers with bitsize '{d}'", .{int_bits}); | 6453 | return func.fail("TODO: Implement signed division for integers with bitsize '{d}'", .{int_bits}); |
| 6420 | }; | 6454 | }; |
| ... | @@ -6441,7 +6475,8 @@ fn divSigned(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type) InnerError!WVal | ... | @@ -6441,7 +6475,8 @@ fn divSigned(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type) InnerError!WVal |
| 6441 | /// Retrieves the absolute value of a signed integer | 6475 | /// Retrieves the absolute value of a signed integer |
| 6442 | /// NOTE: Leaves the result value on the stack. | 6476 | /// NOTE: Leaves the result value on the stack. |
| 6443 | fn signAbsValue(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue { | 6477 | fn signAbsValue(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue { |
| 6444 | const int_bits = ty.intInfo(func.target).bits; | 6478 | const mod = func.bin_file.base.options.module.?; |
| 6479 | const int_bits = ty.intInfo(mod).bits; | ||
| 6445 | const wasm_bits = toWasmBits(int_bits) orelse { | 6480 | const wasm_bits = toWasmBits(int_bits) orelse { |
| 6446 | return func.fail("TODO: signAbsValue for signed integers larger than '{d}' bits", .{int_bits}); | 6481 | return func.fail("TODO: signAbsValue for signed integers larger than '{d}' bits", .{int_bits}); |
| 6447 | }; | 6482 | }; |
| ... | @@ -6476,11 +6511,12 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | ... | @@ -6476,11 +6511,12 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 6476 | assert(op == .add or op == .sub); | 6511 | assert(op == .add or op == .sub); |
| 6477 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 6512 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 6478 | 6513 | ||
| 6514 | const mod = func.bin_file.base.options.module.?; | ||
| 6479 | const ty = func.air.typeOfIndex(inst); | 6515 | const ty = func.air.typeOfIndex(inst); |
| 6480 | const lhs = try func.resolveInst(bin_op.lhs); | 6516 | const lhs = try func.resolveInst(bin_op.lhs); |
| 6481 | const rhs = try func.resolveInst(bin_op.rhs); | 6517 | const rhs = try func.resolveInst(bin_op.rhs); |
| 6482 | 6518 | ||
| 6483 | const int_info = ty.intInfo(func.target); | 6519 | const int_info = ty.intInfo(mod); |
| 6484 | const is_signed = int_info.signedness == .signed; | 6520 | const is_signed = int_info.signedness == .signed; |
| 6485 | 6521 | ||
| 6486 | if (int_info.bits > 64) { | 6522 | if (int_info.bits > 64) { |
| ... | @@ -6523,7 +6559,8 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | ... | @@ -6523,7 +6559,8 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 6523 | } | 6559 | } |
| 6524 | 6560 | ||
| 6525 | fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op: Op) InnerError!WValue { | 6561 | fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op: Op) InnerError!WValue { |
| 6526 | const int_info = ty.intInfo(func.target); | 6562 | const mod = func.bin_file.base.options.module.?; |
| 6563 | const int_info = ty.intInfo(mod); | ||
| 6527 | const wasm_bits = toWasmBits(int_info.bits).?; | 6564 | const wasm_bits = toWasmBits(int_info.bits).?; |
| 6528 | const is_wasm_bits = wasm_bits == int_info.bits; | 6565 | const is_wasm_bits = wasm_bits == int_info.bits; |
| 6529 | 6566 | ||
| ... | @@ -6588,8 +6625,9 @@ fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type, | ... | @@ -6588,8 +6625,9 @@ fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type, |
| 6588 | fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 6625 | fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6589 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 6626 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 6590 | 6627 | ||
| 6628 | const mod = func.bin_file.base.options.module.?; | ||
| 6591 | const ty = func.air.typeOfIndex(inst); | 6629 | const ty = func.air.typeOfIndex(inst); |
| 6592 | const int_info = ty.intInfo(func.target); | 6630 | const int_info = ty.intInfo(mod); |
| 6593 | const is_signed = int_info.signedness == .signed; | 6631 | const is_signed = int_info.signedness == .signed; |
| 6594 | if (int_info.bits > 64) { | 6632 | if (int_info.bits > 64) { |
| 6595 | return func.fail("TODO: Saturating shifting left for integers with bitsize '{d}'", .{int_info.bits}); | 6633 | return func.fail("TODO: Saturating shifting left for integers with bitsize '{d}'", .{int_info.bits}); |
| ... | @@ -6707,12 +6745,13 @@ fn callIntrinsic( | ... | @@ -6707,12 +6745,13 @@ fn callIntrinsic( |
| 6707 | }; | 6745 | }; |
| 6708 | 6746 | ||
| 6709 | // Always pass over C-ABI | 6747 | // Always pass over C-ABI |
| 6710 | var func_type = try genFunctype(func.gpa, .C, param_types, return_type, func.target); | 6748 | const mod = func.bin_file.base.options.module.?; |
| 6749 | var func_type = try genFunctype(func.gpa, .C, param_types, return_type, mod); | ||
| 6711 | defer func_type.deinit(func.gpa); | 6750 | defer func_type.deinit(func.gpa); |
| 6712 | const func_type_index = try func.bin_file.putOrGetFuncType(func_type); | 6751 | const func_type_index = try func.bin_file.putOrGetFuncType(func_type); |
| 6713 | try func.bin_file.addOrUpdateImport(name, symbol_index, null, func_type_index); | 6752 | try func.bin_file.addOrUpdateImport(name, symbol_index, null, func_type_index); |
| 6714 | 6753 | ||
| 6715 | const want_sret_param = firstParamSRet(.C, return_type, func.target); | 6754 | const want_sret_param = firstParamSRet(.C, return_type, mod); |
| 6716 | // if we want return as first param, we allocate a pointer to stack, | 6755 | // if we want return as first param, we allocate a pointer to stack, |
| 6717 | // and emit it as our first argument | 6756 | // and emit it as our first argument |
| 6718 | const sret = if (want_sret_param) blk: { | 6757 | const sret = if (want_sret_param) blk: { |
| ... | @@ -6724,14 +6763,14 @@ fn callIntrinsic( | ... | @@ -6724,14 +6763,14 @@ fn callIntrinsic( |
| 6724 | // Lower all arguments to the stack before we call our function | 6763 | // Lower all arguments to the stack before we call our function |
| 6725 | for (args, 0..) |arg, arg_i| { | 6764 | for (args, 0..) |arg, arg_i| { |
| 6726 | assert(!(want_sret_param and arg == .stack)); | 6765 | assert(!(want_sret_param and arg == .stack)); |
| 6727 | assert(param_types[arg_i].hasRuntimeBitsIgnoreComptime()); | 6766 | assert(param_types[arg_i].hasRuntimeBitsIgnoreComptime(mod)); |
| 6728 | try func.lowerArg(.C, param_types[arg_i], arg); | 6767 | try func.lowerArg(.C, param_types[arg_i], arg); |
| 6729 | } | 6768 | } |
| 6730 | 6769 | ||
| 6731 | // Actually call our intrinsic | 6770 | // Actually call our intrinsic |
| 6732 | try func.addLabel(.call, symbol_index); | 6771 | try func.addLabel(.call, symbol_index); |
| 6733 | 6772 | ||
| 6734 | if (!return_type.hasRuntimeBitsIgnoreComptime()) { | 6773 | if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6735 | return WValue.none; | 6774 | return WValue.none; |
| 6736 | } else if (return_type.isNoReturn()) { | 6775 | } else if (return_type.isNoReturn()) { |
| 6737 | try func.addTag(.@"unreachable"); | 6776 | try func.addTag(.@"unreachable"); |
| ... | @@ -6759,15 +6798,15 @@ fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6759,15 +6798,15 @@ fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6759 | } | 6798 | } |
| 6760 | 6799 | ||
| 6761 | fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { | 6800 | fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { |
| 6801 | const mod = func.bin_file.base.options.module.?; | ||
| 6762 | const enum_decl_index = enum_ty.getOwnerDecl(); | 6802 | const enum_decl_index = enum_ty.getOwnerDecl(); |
| 6763 | const module = func.bin_file.base.options.module.?; | ||
| 6764 | 6803 | ||
| 6765 | var arena_allocator = std.heap.ArenaAllocator.init(func.gpa); | 6804 | var arena_allocator = std.heap.ArenaAllocator.init(func.gpa); |
| 6766 | defer arena_allocator.deinit(); | 6805 | defer arena_allocator.deinit(); |
| 6767 | const arena = arena_allocator.allocator(); | 6806 | const arena = arena_allocator.allocator(); |
| 6768 | 6807 | ||
| 6769 | const fqn = try module.declPtr(enum_decl_index).getFullyQualifiedName(module); | 6808 | const fqn = try mod.declPtr(enum_decl_index).getFullyQualifiedName(mod); |
| 6770 | defer module.gpa.free(fqn); | 6809 | defer mod.gpa.free(fqn); |
| 6771 | const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn}); | 6810 | const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn}); |
| 6772 | 6811 | ||
| 6773 | // check if we already generated code for this. | 6812 | // check if we already generated code for this. |
| ... | @@ -6775,10 +6814,9 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { | ... | @@ -6775,10 +6814,9 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { |
| 6775 | return loc.index; | 6814 | return loc.index; |
| 6776 | } | 6815 | } |
| 6777 | 6816 | ||
| 6778 | var int_tag_type_buffer: Type.Payload.Bits = undefined; | 6817 | const int_tag_ty = enum_ty.intTagType(); |
| 6779 | const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer); | ||
| 6780 | 6818 | ||
| 6781 | if (int_tag_ty.bitSize(func.target) > 64) { | 6819 | if (int_tag_ty.bitSize(mod) > 64) { |
| 6782 | return func.fail("TODO: Implement @tagName for enums with tag size larger than 64 bits", .{}); | 6820 | return func.fail("TODO: Implement @tagName for enums with tag size larger than 64 bits", .{}); |
| 6783 | } | 6821 | } |
| 6784 | 6822 | ||
| ... | @@ -6806,9 +6844,9 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { | ... | @@ -6806,9 +6844,9 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { |
| 6806 | .data = @intCast(u64, tag_name.len), | 6844 | .data = @intCast(u64, tag_name.len), |
| 6807 | }; | 6845 | }; |
| 6808 | const name_ty = Type.initPayload(&name_ty_payload.base); | 6846 | const name_ty = Type.initPayload(&name_ty_payload.base); |
| 6809 | const string_bytes = &module.string_literal_bytes; | 6847 | const string_bytes = &mod.string_literal_bytes; |
| 6810 | try string_bytes.ensureUnusedCapacity(module.gpa, tag_name.len); | 6848 | try string_bytes.ensureUnusedCapacity(mod.gpa, tag_name.len); |
| 6811 | const gop = try module.string_literal_table.getOrPutContextAdapted(module.gpa, tag_name, Module.StringLiteralAdapter{ | 6849 | const gop = try mod.string_literal_table.getOrPutContextAdapted(mod.gpa, tag_name, Module.StringLiteralAdapter{ |
| 6812 | .bytes = string_bytes, | 6850 | .bytes = string_bytes, |
| 6813 | }, Module.StringLiteralContext{ | 6851 | }, Module.StringLiteralContext{ |
| 6814 | .bytes = string_bytes, | 6852 | .bytes = string_bytes, |
| ... | @@ -6929,7 +6967,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { | ... | @@ -6929,7 +6967,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { |
| 6929 | try writer.writeByte(std.wasm.opcode(.end)); | 6967 | try writer.writeByte(std.wasm.opcode(.end)); |
| 6930 | 6968 | ||
| 6931 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); | 6969 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 6932 | const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty}, slice_ty, func.target); | 6970 | const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty}, slice_ty, mod); |
| 6933 | return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs); | 6971 | return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs); |
| 6934 | } | 6972 | } |
| 6935 | 6973 | ||
| ... | @@ -6944,11 +6982,11 @@ fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6944,11 +6982,11 @@ fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6944 | var values = try std.ArrayList(u32).initCapacity(func.gpa, names.len); | 6982 | var values = try std.ArrayList(u32).initCapacity(func.gpa, names.len); |
| 6945 | defer values.deinit(); | 6983 | defer values.deinit(); |
| 6946 | 6984 | ||
| 6947 | const module = func.bin_file.base.options.module.?; | 6985 | const mod = func.bin_file.base.options.module.?; |
| 6948 | var lowest: ?u32 = null; | 6986 | var lowest: ?u32 = null; |
| 6949 | var highest: ?u32 = null; | 6987 | var highest: ?u32 = null; |
| 6950 | for (names) |name| { | 6988 | for (names) |name| { |
| 6951 | const err_int = module.global_error_set.get(name).?; | 6989 | const err_int = mod.global_error_set.get(name).?; |
| 6952 | if (lowest) |*l| { | 6990 | if (lowest) |*l| { |
| 6953 | if (err_int < l.*) { | 6991 | if (err_int < l.*) { |
| 6954 | l.* = err_int; | 6992 | l.* = err_int; |
| ... | @@ -7019,6 +7057,7 @@ inline fn useAtomicFeature(func: *const CodeGen) bool { | ... | @@ -7019,6 +7057,7 @@ inline fn useAtomicFeature(func: *const CodeGen) bool { |
| 7019 | } | 7057 | } |
| 7020 | 7058 | ||
| 7021 | fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 7059 | fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7060 | const mod = func.bin_file.base.options.module.?; | ||
| 7022 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; | 7061 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; |
| 7023 | const extra = func.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | 7062 | const extra = func.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| 7024 | 7063 | ||
| ... | @@ -7037,7 +7076,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7037,7 +7076,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7037 | try func.emitWValue(ptr_operand); | 7076 | try func.emitWValue(ptr_operand); |
| 7038 | try func.lowerToStack(expected_val); | 7077 | try func.lowerToStack(expected_val); |
| 7039 | try func.lowerToStack(new_val); | 7078 | try func.lowerToStack(new_val); |
| 7040 | try func.addAtomicMemArg(switch (ty.abiSize(func.target)) { | 7079 | try func.addAtomicMemArg(switch (ty.abiSize(mod)) { |
| 7041 | 1 => .i32_atomic_rmw8_cmpxchg_u, | 7080 | 1 => .i32_atomic_rmw8_cmpxchg_u, |
| 7042 | 2 => .i32_atomic_rmw16_cmpxchg_u, | 7081 | 2 => .i32_atomic_rmw16_cmpxchg_u, |
| 7043 | 4 => .i32_atomic_rmw_cmpxchg, | 7082 | 4 => .i32_atomic_rmw_cmpxchg, |
| ... | @@ -7045,14 +7084,14 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7045,14 +7084,14 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7045 | else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}), | 7084 | else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}), |
| 7046 | }, .{ | 7085 | }, .{ |
| 7047 | .offset = ptr_operand.offset(), | 7086 | .offset = ptr_operand.offset(), |
| 7048 | .alignment = ty.abiAlignment(func.target), | 7087 | .alignment = ty.abiAlignment(mod), |
| 7049 | }); | 7088 | }); |
| 7050 | try func.addLabel(.local_tee, val_local.local.value); | 7089 | try func.addLabel(.local_tee, val_local.local.value); |
| 7051 | _ = try func.cmp(.stack, expected_val, ty, .eq); | 7090 | _ = try func.cmp(.stack, expected_val, ty, .eq); |
| 7052 | try func.addLabel(.local_set, cmp_result.local.value); | 7091 | try func.addLabel(.local_set, cmp_result.local.value); |
| 7053 | break :val val_local; | 7092 | break :val val_local; |
| 7054 | } else val: { | 7093 | } else val: { |
| 7055 | if (ty.abiSize(func.target) > 8) { | 7094 | if (ty.abiSize(mod) > 8) { |
| 7056 | return func.fail("TODO: Implement `@cmpxchg` for types larger than abi size of 8 bytes", .{}); | 7095 | return func.fail("TODO: Implement `@cmpxchg` for types larger than abi size of 8 bytes", .{}); |
| 7057 | } | 7096 | } |
| 7058 | const ptr_val = try WValue.toLocal(try func.load(ptr_operand, ty, 0), func, ty); | 7097 | const ptr_val = try WValue.toLocal(try func.load(ptr_operand, ty, 0), func, ty); |
| ... | @@ -7068,7 +7107,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7068,7 +7107,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7068 | break :val ptr_val; | 7107 | break :val ptr_val; |
| 7069 | }; | 7108 | }; |
| 7070 | 7109 | ||
| 7071 | const result_ptr = if (isByRef(result_ty, func.target)) val: { | 7110 | const result_ptr = if (isByRef(result_ty, mod)) val: { |
| 7072 | try func.emitWValue(cmp_result); | 7111 | try func.emitWValue(cmp_result); |
| 7073 | try func.addImm32(-1); | 7112 | try func.addImm32(-1); |
| 7074 | try func.addTag(.i32_xor); | 7113 | try func.addTag(.i32_xor); |
| ... | @@ -7076,7 +7115,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7076,7 +7115,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7076 | try func.addTag(.i32_and); | 7115 | try func.addTag(.i32_and); |
| 7077 | const and_result = try WValue.toLocal(.stack, func, Type.bool); | 7116 | const and_result = try WValue.toLocal(.stack, func, Type.bool); |
| 7078 | const result_ptr = try func.allocStack(result_ty); | 7117 | const result_ptr = try func.allocStack(result_ty); |
| 7079 | try func.store(result_ptr, and_result, Type.bool, @intCast(u32, ty.abiSize(func.target))); | 7118 | try func.store(result_ptr, and_result, Type.bool, @intCast(u32, ty.abiSize(mod))); |
| 7080 | try func.store(result_ptr, ptr_val, ty, 0); | 7119 | try func.store(result_ptr, ptr_val, ty, 0); |
| 7081 | break :val result_ptr; | 7120 | break :val result_ptr; |
| 7082 | } else val: { | 7121 | } else val: { |
| ... | @@ -7091,12 +7130,13 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7091,12 +7130,13 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7091 | } | 7130 | } |
| 7092 | 7131 | ||
| 7093 | fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 7132 | fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7133 | const mod = func.bin_file.base.options.module.?; | ||
| 7094 | const atomic_load = func.air.instructions.items(.data)[inst].atomic_load; | 7134 | const atomic_load = func.air.instructions.items(.data)[inst].atomic_load; |
| 7095 | const ptr = try func.resolveInst(atomic_load.ptr); | 7135 | const ptr = try func.resolveInst(atomic_load.ptr); |
| 7096 | const ty = func.air.typeOfIndex(inst); | 7136 | const ty = func.air.typeOfIndex(inst); |
| 7097 | 7137 | ||
| 7098 | if (func.useAtomicFeature()) { | 7138 | if (func.useAtomicFeature()) { |
| 7099 | const tag: wasm.AtomicsOpcode = switch (ty.abiSize(func.target)) { | 7139 | const tag: wasm.AtomicsOpcode = switch (ty.abiSize(mod)) { |
| 7100 | 1 => .i32_atomic_load8_u, | 7140 | 1 => .i32_atomic_load8_u, |
| 7101 | 2 => .i32_atomic_load16_u, | 7141 | 2 => .i32_atomic_load16_u, |
| 7102 | 4 => .i32_atomic_load, | 7142 | 4 => .i32_atomic_load, |
| ... | @@ -7106,7 +7146,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7106,7 +7146,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7106 | try func.emitWValue(ptr); | 7146 | try func.emitWValue(ptr); |
| 7107 | try func.addAtomicMemArg(tag, .{ | 7147 | try func.addAtomicMemArg(tag, .{ |
| 7108 | .offset = ptr.offset(), | 7148 | .offset = ptr.offset(), |
| 7109 | .alignment = ty.abiAlignment(func.target), | 7149 | .alignment = ty.abiAlignment(mod), |
| 7110 | }); | 7150 | }); |
| 7111 | } else { | 7151 | } else { |
| 7112 | _ = try func.load(ptr, ty, 0); | 7152 | _ = try func.load(ptr, ty, 0); |
| ... | @@ -7117,6 +7157,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7117,6 +7157,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7117 | } | 7157 | } |
| 7118 | 7158 | ||
| 7119 | fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 7159 | fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7160 | const mod = func.bin_file.base.options.module.?; | ||
| 7120 | const pl_op = func.air.instructions.items(.data)[inst].pl_op; | 7161 | const pl_op = func.air.instructions.items(.data)[inst].pl_op; |
| 7121 | const extra = func.air.extraData(Air.AtomicRmw, pl_op.payload).data; | 7162 | const extra = func.air.extraData(Air.AtomicRmw, pl_op.payload).data; |
| 7122 | 7163 | ||
| ... | @@ -7140,7 +7181,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7140,7 +7181,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7140 | try func.emitWValue(ptr); | 7181 | try func.emitWValue(ptr); |
| 7141 | try func.emitWValue(value); | 7182 | try func.emitWValue(value); |
| 7142 | if (op == .Nand) { | 7183 | if (op == .Nand) { |
| 7143 | const wasm_bits = toWasmBits(@intCast(u16, ty.bitSize(func.target))).?; | 7184 | const wasm_bits = toWasmBits(@intCast(u16, ty.bitSize(mod))).?; |
| 7144 | 7185 | ||
| 7145 | const and_res = try func.binOp(value, operand, ty, .@"and"); | 7186 | const and_res = try func.binOp(value, operand, ty, .@"and"); |
| 7146 | if (wasm_bits == 32) | 7187 | if (wasm_bits == 32) |
| ... | @@ -7157,7 +7198,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7157,7 +7198,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7157 | try func.addTag(.select); | 7198 | try func.addTag(.select); |
| 7158 | } | 7199 | } |
| 7159 | try func.addAtomicMemArg( | 7200 | try func.addAtomicMemArg( |
| 7160 | switch (ty.abiSize(func.target)) { | 7201 | switch (ty.abiSize(mod)) { |
| 7161 | 1 => .i32_atomic_rmw8_cmpxchg_u, | 7202 | 1 => .i32_atomic_rmw8_cmpxchg_u, |
| 7162 | 2 => .i32_atomic_rmw16_cmpxchg_u, | 7203 | 2 => .i32_atomic_rmw16_cmpxchg_u, |
| 7163 | 4 => .i32_atomic_rmw_cmpxchg, | 7204 | 4 => .i32_atomic_rmw_cmpxchg, |
| ... | @@ -7166,7 +7207,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7166,7 +7207,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7166 | }, | 7207 | }, |
| 7167 | .{ | 7208 | .{ |
| 7168 | .offset = ptr.offset(), | 7209 | .offset = ptr.offset(), |
| 7169 | .alignment = ty.abiAlignment(func.target), | 7210 | .alignment = ty.abiAlignment(mod), |
| 7170 | }, | 7211 | }, |
| 7171 | ); | 7212 | ); |
| 7172 | const select_res = try func.allocLocal(ty); | 7213 | const select_res = try func.allocLocal(ty); |
| ... | @@ -7185,7 +7226,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7185,7 +7226,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7185 | else => { | 7226 | else => { |
| 7186 | try func.emitWValue(ptr); | 7227 | try func.emitWValue(ptr); |
| 7187 | try func.emitWValue(operand); | 7228 | try func.emitWValue(operand); |
| 7188 | const tag: wasm.AtomicsOpcode = switch (ty.abiSize(func.target)) { | 7229 | const tag: wasm.AtomicsOpcode = switch (ty.abiSize(mod)) { |
| 7189 | 1 => switch (op) { | 7230 | 1 => switch (op) { |
| 7190 | .Xchg => .i32_atomic_rmw8_xchg_u, | 7231 | .Xchg => .i32_atomic_rmw8_xchg_u, |
| 7191 | .Add => .i32_atomic_rmw8_add_u, | 7232 | .Add => .i32_atomic_rmw8_add_u, |
| ... | @@ -7226,7 +7267,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7226,7 +7267,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7226 | }; | 7267 | }; |
| 7227 | try func.addAtomicMemArg(tag, .{ | 7268 | try func.addAtomicMemArg(tag, .{ |
| 7228 | .offset = ptr.offset(), | 7269 | .offset = ptr.offset(), |
| 7229 | .alignment = ty.abiAlignment(func.target), | 7270 | .alignment = ty.abiAlignment(mod), |
| 7230 | }); | 7271 | }); |
| 7231 | const result = try WValue.toLocal(.stack, func, ty); | 7272 | const result = try WValue.toLocal(.stack, func, ty); |
| 7232 | return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand }); | 7273 | return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand }); |
| ... | @@ -7255,7 +7296,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7255,7 +7296,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7255 | .Xor => .xor, | 7296 | .Xor => .xor, |
| 7256 | else => unreachable, | 7297 | else => unreachable, |
| 7257 | }); | 7298 | }); |
| 7258 | if (ty.isInt() and (op == .Add or op == .Sub)) { | 7299 | if (ty.isInt(mod) and (op == .Add or op == .Sub)) { |
| 7259 | _ = try func.wrapOperand(.stack, ty); | 7300 | _ = try func.wrapOperand(.stack, ty); |
| 7260 | } | 7301 | } |
| 7261 | try func.store(.stack, .stack, ty, ptr.offset()); | 7302 | try func.store(.stack, .stack, ty, ptr.offset()); |
| ... | @@ -7271,7 +7312,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7271,7 +7312,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7271 | try func.store(.stack, .stack, ty, ptr.offset()); | 7312 | try func.store(.stack, .stack, ty, ptr.offset()); |
| 7272 | }, | 7313 | }, |
| 7273 | .Nand => { | 7314 | .Nand => { |
| 7274 | const wasm_bits = toWasmBits(@intCast(u16, ty.bitSize(func.target))).?; | 7315 | const wasm_bits = toWasmBits(@intCast(u16, ty.bitSize(mod))).?; |
| 7275 | 7316 | ||
| 7276 | try func.emitWValue(ptr); | 7317 | try func.emitWValue(ptr); |
| 7277 | const and_res = try func.binOp(result, operand, ty, .@"and"); | 7318 | const and_res = try func.binOp(result, operand, ty, .@"and"); |
| ... | @@ -7302,6 +7343,7 @@ fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7302,6 +7343,7 @@ fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7302 | } | 7343 | } |
| 7303 | 7344 | ||
| 7304 | fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 7345 | fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7346 | const mod = func.bin_file.base.options.module.?; | ||
| 7305 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; | 7347 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 7306 | 7348 | ||
| 7307 | const ptr = try func.resolveInst(bin_op.lhs); | 7349 | const ptr = try func.resolveInst(bin_op.lhs); |
| ... | @@ -7310,7 +7352,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7310,7 +7352,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7310 | const ty = ptr_ty.childType(); | 7352 | const ty = ptr_ty.childType(); |
| 7311 | 7353 | ||
| 7312 | if (func.useAtomicFeature()) { | 7354 | if (func.useAtomicFeature()) { |
| 7313 | const tag: wasm.AtomicsOpcode = switch (ty.abiSize(func.target)) { | 7355 | const tag: wasm.AtomicsOpcode = switch (ty.abiSize(mod)) { |
| 7314 | 1 => .i32_atomic_store8, | 7356 | 1 => .i32_atomic_store8, |
| 7315 | 2 => .i32_atomic_store16, | 7357 | 2 => .i32_atomic_store16, |
| 7316 | 4 => .i32_atomic_store, | 7358 | 4 => .i32_atomic_store, |
| ... | @@ -7321,7 +7363,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7321,7 +7363,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7321 | try func.lowerToStack(operand); | 7363 | try func.lowerToStack(operand); |
| 7322 | try func.addAtomicMemArg(tag, .{ | 7364 | try func.addAtomicMemArg(tag, .{ |
| 7323 | .offset = ptr.offset(), | 7365 | .offset = ptr.offset(), |
| 7324 | .alignment = ty.abiAlignment(func.target), | 7366 | .alignment = ty.abiAlignment(mod), |
| 7325 | }); | 7367 | }); |
| 7326 | } else { | 7368 | } else { |
| 7327 | try func.store(ptr, operand, ty, 0); | 7369 | try func.store(ptr, operand, ty, 0); |
src/arch/wasm/abi.zig+22-19| ... | @@ -5,9 +5,11 @@ | ... | @@ -5,9 +5,11 @@ |
| 5 | //! Note: Above mentioned document is not an official specification, therefore called a convention. | 5 | //! Note: Above mentioned document is not an official specification, therefore called a convention. |
| 6 | 6 | ||
| 7 | const std = @import("std"); | 7 | const std = @import("std"); |
| 8 | const Type = @import("../../type.zig").Type; | ||
| 9 | const Target = std.Target; | 8 | const Target = std.Target; |
| 10 | 9 | ||
| 10 | const Type = @import("../../type.zig").Type; | ||
| 11 | const Module = @import("../../Module.zig"); | ||
| 12 | |||
| 11 | /// Defines how to pass a type as part of a function signature, | 13 | /// Defines how to pass a type as part of a function signature, |
| 12 | /// both for parameters as well as return values. | 14 | /// both for parameters as well as return values. |
| 13 | pub const Class = enum { direct, indirect, none }; | 15 | pub const Class = enum { direct, indirect, none }; |
| ... | @@ -19,12 +21,13 @@ const direct: [2]Class = .{ .direct, .none }; | ... | @@ -19,12 +21,13 @@ const direct: [2]Class = .{ .direct, .none }; |
| 19 | /// Classifies a given Zig type to determine how they must be passed | 21 | /// Classifies a given Zig type to determine how they must be passed |
| 20 | /// or returned as value within a wasm function. | 22 | /// or returned as value within a wasm function. |
| 21 | /// When all elements result in `.none`, no value must be passed in or returned. | 23 | /// When all elements result in `.none`, no value must be passed in or returned. |
| 22 | pub fn classifyType(ty: Type, target: Target) [2]Class { | 24 | pub fn classifyType(ty: Type, mod: *const Module) [2]Class { |
| 23 | if (!ty.hasRuntimeBitsIgnoreComptime()) return none; | 25 | const target = mod.getTarget(); |
| 24 | switch (ty.zigTypeTag()) { | 26 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return none; |
| 27 | switch (ty.zigTypeTag(mod)) { | ||
| 25 | .Struct => { | 28 | .Struct => { |
| 26 | if (ty.containerLayout() == .Packed) { | 29 | if (ty.containerLayout() == .Packed) { |
| 27 | if (ty.bitSize(target) <= 64) return direct; | 30 | if (ty.bitSize(mod) <= 64) return direct; |
| 28 | return .{ .direct, .direct }; | 31 | return .{ .direct, .direct }; |
| 29 | } | 32 | } |
| 30 | // When the struct type is non-scalar | 33 | // When the struct type is non-scalar |
| ... | @@ -32,14 +35,14 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { | ... | @@ -32,14 +35,14 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { |
| 32 | // When the struct's alignment is non-natural | 35 | // When the struct's alignment is non-natural |
| 33 | const field = ty.structFields().values()[0]; | 36 | const field = ty.structFields().values()[0]; |
| 34 | if (field.abi_align != 0) { | 37 | if (field.abi_align != 0) { |
| 35 | if (field.abi_align > field.ty.abiAlignment(target)) { | 38 | if (field.abi_align > field.ty.abiAlignment(mod)) { |
| 36 | return memory; | 39 | return memory; |
| 37 | } | 40 | } |
| 38 | } | 41 | } |
| 39 | return classifyType(field.ty, target); | 42 | return classifyType(field.ty, mod); |
| 40 | }, | 43 | }, |
| 41 | .Int, .Enum, .ErrorSet, .Vector => { | 44 | .Int, .Enum, .ErrorSet, .Vector => { |
| 42 | const int_bits = ty.intInfo(target).bits; | 45 | const int_bits = ty.intInfo(mod).bits; |
| 43 | if (int_bits <= 64) return direct; | 46 | if (int_bits <= 64) return direct; |
| 44 | if (int_bits <= 128) return .{ .direct, .direct }; | 47 | if (int_bits <= 128) return .{ .direct, .direct }; |
| 45 | return memory; | 48 | return memory; |
| ... | @@ -53,7 +56,7 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { | ... | @@ -53,7 +56,7 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { |
| 53 | .Bool => return direct, | 56 | .Bool => return direct, |
| 54 | .Array => return memory, | 57 | .Array => return memory, |
| 55 | .Optional => { | 58 | .Optional => { |
| 56 | std.debug.assert(ty.isPtrLikeOptional()); | 59 | std.debug.assert(ty.isPtrLikeOptional(mod)); |
| 57 | return direct; | 60 | return direct; |
| 58 | }, | 61 | }, |
| 59 | .Pointer => { | 62 | .Pointer => { |
| ... | @@ -62,13 +65,13 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { | ... | @@ -62,13 +65,13 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { |
| 62 | }, | 65 | }, |
| 63 | .Union => { | 66 | .Union => { |
| 64 | if (ty.containerLayout() == .Packed) { | 67 | if (ty.containerLayout() == .Packed) { |
| 65 | if (ty.bitSize(target) <= 64) return direct; | 68 | if (ty.bitSize(mod) <= 64) return direct; |
| 66 | return .{ .direct, .direct }; | 69 | return .{ .direct, .direct }; |
| 67 | } | 70 | } |
| 68 | const layout = ty.unionGetLayout(target); | 71 | const layout = ty.unionGetLayout(mod); |
| 69 | std.debug.assert(layout.tag_size == 0); | 72 | std.debug.assert(layout.tag_size == 0); |
| 70 | if (ty.unionFields().count() > 1) return memory; | 73 | if (ty.unionFields().count() > 1) return memory; |
| 71 | return classifyType(ty.unionFields().values()[0].ty, target); | 74 | return classifyType(ty.unionFields().values()[0].ty, mod); |
| 72 | }, | 75 | }, |
| 73 | .ErrorUnion, | 76 | .ErrorUnion, |
| 74 | .Frame, | 77 | .Frame, |
| ... | @@ -90,29 +93,29 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { | ... | @@ -90,29 +93,29 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { |
| 90 | /// Returns the scalar type a given type can represent. | 93 | /// Returns the scalar type a given type can represent. |
| 91 | /// Asserts given type can be represented as scalar, such as | 94 | /// Asserts given type can be represented as scalar, such as |
| 92 | /// a struct with a single scalar field. | 95 | /// a struct with a single scalar field. |
| 93 | pub fn scalarType(ty: Type, target: std.Target) Type { | 96 | pub fn scalarType(ty: Type, mod: *const Module) Type { |
| 94 | switch (ty.zigTypeTag()) { | 97 | switch (ty.zigTypeTag(mod)) { |
| 95 | .Struct => { | 98 | .Struct => { |
| 96 | switch (ty.containerLayout()) { | 99 | switch (ty.containerLayout()) { |
| 97 | .Packed => { | 100 | .Packed => { |
| 98 | const struct_obj = ty.castTag(.@"struct").?.data; | 101 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 99 | return scalarType(struct_obj.backing_int_ty, target); | 102 | return scalarType(struct_obj.backing_int_ty, mod); |
| 100 | }, | 103 | }, |
| 101 | else => { | 104 | else => { |
| 102 | std.debug.assert(ty.structFieldCount() == 1); | 105 | std.debug.assert(ty.structFieldCount() == 1); |
| 103 | return scalarType(ty.structFieldType(0), target); | 106 | return scalarType(ty.structFieldType(0), mod); |
| 104 | }, | 107 | }, |
| 105 | } | 108 | } |
| 106 | }, | 109 | }, |
| 107 | .Union => { | 110 | .Union => { |
| 108 | if (ty.containerLayout() != .Packed) { | 111 | if (ty.containerLayout() != .Packed) { |
| 109 | const layout = ty.unionGetLayout(target); | 112 | const layout = ty.unionGetLayout(mod); |
| 110 | if (layout.payload_size == 0 and layout.tag_size != 0) { | 113 | if (layout.payload_size == 0 and layout.tag_size != 0) { |
| 111 | return scalarType(ty.unionTagTypeSafety().?, target); | 114 | return scalarType(ty.unionTagTypeSafety().?, mod); |
| 112 | } | 115 | } |
| 113 | std.debug.assert(ty.unionFields().count() == 1); | 116 | std.debug.assert(ty.unionFields().count() == 1); |
| 114 | } | 117 | } |
| 115 | return scalarType(ty.unionFields().values()[0].ty, target); | 118 | return scalarType(ty.unionFields().values()[0].ty, mod); |
| 116 | }, | 119 | }, |
| 117 | else => return ty, | 120 | else => return ty, |
| 118 | } | 121 | } |
src/arch/x86_64/CodeGen.zig+407-367| ... | @@ -605,14 +605,14 @@ const FrameAlloc = struct { | ... | @@ -605,14 +605,14 @@ const FrameAlloc = struct { |
| 605 | .ref_count = 0, | 605 | .ref_count = 0, |
| 606 | }; | 606 | }; |
| 607 | } | 607 | } |
| 608 | fn initType(ty: Type, target: Target) FrameAlloc { | 608 | fn initType(ty: Type, mod: *const Module) FrameAlloc { |
| 609 | return init(.{ .size = ty.abiSize(target), .alignment = ty.abiAlignment(target) }); | 609 | return init(.{ .size = ty.abiSize(mod), .alignment = ty.abiAlignment(mod) }); |
| 610 | } | 610 | } |
| 611 | }; | 611 | }; |
| 612 | 612 | ||
| 613 | const StackAllocation = struct { | 613 | const StackAllocation = struct { |
| 614 | inst: ?Air.Inst.Index, | 614 | inst: ?Air.Inst.Index, |
| 615 | /// TODO do we need size? should be determined by inst.ty.abiSize(self.target.*) | 615 | /// TODO do we need size? should be determined by inst.ty.abiSize(mod) |
| 616 | size: u32, | 616 | size: u32, |
| 617 | }; | 617 | }; |
| 618 | 618 | ||
| ... | @@ -714,12 +714,12 @@ pub fn generate( | ... | @@ -714,12 +714,12 @@ pub fn generate( |
| 714 | function.args = call_info.args; | 714 | function.args = call_info.args; |
| 715 | function.ret_mcv = call_info.return_value; | 715 | function.ret_mcv = call_info.return_value; |
| 716 | function.frame_allocs.set(@enumToInt(FrameIndex.ret_addr), FrameAlloc.init(.{ | 716 | function.frame_allocs.set(@enumToInt(FrameIndex.ret_addr), FrameAlloc.init(.{ |
| 717 | .size = Type.usize.abiSize(function.target.*), | 717 | .size = Type.usize.abiSize(mod), |
| 718 | .alignment = @min(Type.usize.abiAlignment(function.target.*), call_info.stack_align), | 718 | .alignment = @min(Type.usize.abiAlignment(mod), call_info.stack_align), |
| 719 | })); | 719 | })); |
| 720 | function.frame_allocs.set(@enumToInt(FrameIndex.base_ptr), FrameAlloc.init(.{ | 720 | function.frame_allocs.set(@enumToInt(FrameIndex.base_ptr), FrameAlloc.init(.{ |
| 721 | .size = Type.usize.abiSize(function.target.*), | 721 | .size = Type.usize.abiSize(mod), |
| 722 | .alignment = @min(Type.usize.abiAlignment(function.target.*) * 2, call_info.stack_align), | 722 | .alignment = @min(Type.usize.abiAlignment(mod) * 2, call_info.stack_align), |
| 723 | })); | 723 | })); |
| 724 | function.frame_allocs.set( | 724 | function.frame_allocs.set( |
| 725 | @enumToInt(FrameIndex.args_frame), | 725 | @enumToInt(FrameIndex.args_frame), |
| ... | @@ -1565,6 +1565,7 @@ fn asmMemoryRegisterImmediate( | ... | @@ -1565,6 +1565,7 @@ fn asmMemoryRegisterImmediate( |
| 1565 | } | 1565 | } |
| 1566 | 1566 | ||
| 1567 | fn gen(self: *Self) InnerError!void { | 1567 | fn gen(self: *Self) InnerError!void { |
| 1568 | const mod = self.bin_file.options.module.?; | ||
| 1568 | const cc = self.fn_type.fnCallingConvention(); | 1569 | const cc = self.fn_type.fnCallingConvention(); |
| 1569 | if (cc != .Naked) { | 1570 | if (cc != .Naked) { |
| 1570 | try self.asmRegister(.{ ._, .push }, .rbp); | 1571 | try self.asmRegister(.{ ._, .push }, .rbp); |
| ... | @@ -1582,7 +1583,7 @@ fn gen(self: *Self) InnerError!void { | ... | @@ -1582,7 +1583,7 @@ fn gen(self: *Self) InnerError!void { |
| 1582 | // register which the callee is free to clobber. Therefore, we purposely | 1583 | // register which the callee is free to clobber. Therefore, we purposely |
| 1583 | // spill it to stack immediately. | 1584 | // spill it to stack immediately. |
| 1584 | const frame_index = | 1585 | const frame_index = |
| 1585 | try self.allocFrameIndex(FrameAlloc.initType(Type.usize, self.target.*)); | 1586 | try self.allocFrameIndex(FrameAlloc.initType(Type.usize, mod)); |
| 1586 | try self.genSetMem( | 1587 | try self.genSetMem( |
| 1587 | .{ .frame = frame_index }, | 1588 | .{ .frame = frame_index }, |
| 1588 | 0, | 1589 | 0, |
| ... | @@ -1999,7 +2000,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -1999,7 +2000,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 1999 | } | 2000 | } |
| 2000 | 2001 | ||
| 2001 | fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { | 2002 | fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2002 | switch (lazy_sym.ty.zigTypeTag()) { | 2003 | const mod = self.bin_file.options.module.?; |
| 2004 | switch (lazy_sym.ty.zigTypeTag(mod)) { | ||
| 2003 | .Enum => { | 2005 | .Enum => { |
| 2004 | const enum_ty = lazy_sym.ty; | 2006 | const enum_ty = lazy_sym.ty; |
| 2005 | wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(self.bin_file.options.module.?)}); | 2007 | wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(self.bin_file.options.module.?)}); |
| ... | @@ -2127,8 +2129,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live | ... | @@ -2127,8 +2129,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live |
| 2127 | tomb_bits >>= 1; | 2129 | tomb_bits >>= 1; |
| 2128 | if (!dies) continue; | 2130 | if (!dies) continue; |
| 2129 | const op_int = @enumToInt(op); | 2131 | const op_int = @enumToInt(op); |
| 2130 | if (op_int < Air.Inst.Ref.typed_value_map.len) continue; | 2132 | if (op_int < Air.ref_start_index) continue; |
| 2131 | const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len); | 2133 | const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index); |
| 2132 | self.processDeath(op_index); | 2134 | self.processDeath(op_index); |
| 2133 | } | 2135 | } |
| 2134 | self.finishAirResult(inst, result); | 2136 | self.finishAirResult(inst, result); |
| ... | @@ -2252,14 +2254,14 @@ fn allocFrameIndex(self: *Self, alloc: FrameAlloc) !FrameIndex { | ... | @@ -2252,14 +2254,14 @@ fn allocFrameIndex(self: *Self, alloc: FrameAlloc) !FrameIndex { |
| 2252 | 2254 | ||
| 2253 | /// Use a pointer instruction as the basis for allocating stack memory. | 2255 | /// Use a pointer instruction as the basis for allocating stack memory. |
| 2254 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex { | 2256 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex { |
| 2257 | const mod = self.bin_file.options.module.?; | ||
| 2255 | const ptr_ty = self.air.typeOfIndex(inst); | 2258 | const ptr_ty = self.air.typeOfIndex(inst); |
| 2256 | const val_ty = ptr_ty.childType(); | 2259 | const val_ty = ptr_ty.childType(); |
| 2257 | return self.allocFrameIndex(FrameAlloc.init(.{ | 2260 | return self.allocFrameIndex(FrameAlloc.init(.{ |
| 2258 | .size = math.cast(u32, val_ty.abiSize(self.target.*)) orelse { | 2261 | .size = math.cast(u32, val_ty.abiSize(mod)) orelse { |
| 2259 | const mod = self.bin_file.options.module.?; | ||
| 2260 | return self.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(mod)}); | 2262 | return self.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(mod)}); |
| 2261 | }, | 2263 | }, |
| 2262 | .alignment = @max(ptr_ty.ptrAlignment(self.target.*), 1), | 2264 | .alignment = @max(ptr_ty.ptrAlignment(mod), 1), |
| 2263 | })); | 2265 | })); |
| 2264 | } | 2266 | } |
| 2265 | 2267 | ||
| ... | @@ -2272,19 +2274,19 @@ fn allocTempRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool) !MCValue { | ... | @@ -2272,19 +2274,19 @@ fn allocTempRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool) !MCValue { |
| 2272 | } | 2274 | } |
| 2273 | 2275 | ||
| 2274 | fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue { | 2276 | fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue { |
| 2275 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) orelse { | 2277 | const mod = self.bin_file.options.module.?; |
| 2276 | const mod = self.bin_file.options.module.?; | 2278 | const abi_size = math.cast(u32, ty.abiSize(mod)) orelse { |
| 2277 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)}); | 2279 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)}); |
| 2278 | }; | 2280 | }; |
| 2279 | 2281 | ||
| 2280 | if (reg_ok) need_mem: { | 2282 | if (reg_ok) need_mem: { |
| 2281 | if (abi_size <= @as(u32, switch (ty.zigTypeTag()) { | 2283 | if (abi_size <= @as(u32, switch (ty.zigTypeTag(mod)) { |
| 2282 | .Float => switch (ty.floatBits(self.target.*)) { | 2284 | .Float => switch (ty.floatBits(self.target.*)) { |
| 2283 | 16, 32, 64, 128 => 16, | 2285 | 16, 32, 64, 128 => 16, |
| 2284 | 80 => break :need_mem, | 2286 | 80 => break :need_mem, |
| 2285 | else => unreachable, | 2287 | else => unreachable, |
| 2286 | }, | 2288 | }, |
| 2287 | .Vector => switch (ty.childType().zigTypeTag()) { | 2289 | .Vector => switch (ty.childType().zigTypeTag(mod)) { |
| 2288 | .Float => switch (ty.childType().floatBits(self.target.*)) { | 2290 | .Float => switch (ty.childType().floatBits(self.target.*)) { |
| 2289 | 16, 32, 64, 128 => if (self.hasFeature(.avx)) 32 else 16, | 2291 | 16, 32, 64, 128 => if (self.hasFeature(.avx)) 32 else 16, |
| 2290 | 80 => break :need_mem, | 2292 | 80 => break :need_mem, |
| ... | @@ -2294,18 +2296,18 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b | ... | @@ -2294,18 +2296,18 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b |
| 2294 | }, | 2296 | }, |
| 2295 | else => 8, | 2297 | else => 8, |
| 2296 | })) { | 2298 | })) { |
| 2297 | if (self.register_manager.tryAllocReg(inst, regClassForType(ty))) |reg| { | 2299 | if (self.register_manager.tryAllocReg(inst, regClassForType(ty, mod))) |reg| { |
| 2298 | return MCValue{ .register = registerAlias(reg, abi_size) }; | 2300 | return MCValue{ .register = registerAlias(reg, abi_size) }; |
| 2299 | } | 2301 | } |
| 2300 | } | 2302 | } |
| 2301 | } | 2303 | } |
| 2302 | 2304 | ||
| 2303 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ty, self.target.*)); | 2305 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ty, mod)); |
| 2304 | return .{ .load_frame = .{ .index = frame_index } }; | 2306 | return .{ .load_frame = .{ .index = frame_index } }; |
| 2305 | } | 2307 | } |
| 2306 | 2308 | ||
| 2307 | fn regClassForType(ty: Type) RegisterManager.RegisterBitSet { | 2309 | fn regClassForType(ty: Type, mod: *const Module) RegisterManager.RegisterBitSet { |
| 2308 | return switch (ty.zigTypeTag()) { | 2310 | return switch (ty.zigTypeTag(mod)) { |
| 2309 | .Float, .Vector => sse, | 2311 | .Float, .Vector => sse, |
| 2310 | else => gp, | 2312 | else => gp, |
| 2311 | }; | 2313 | }; |
| ... | @@ -2449,7 +2451,8 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void { | ... | @@ -2449,7 +2451,8 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void { |
| 2449 | /// allocated. A second call to `copyToTmpRegister` may return the same register. | 2451 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 2450 | /// This can have a side effect of spilling instructions to the stack to free up a register. | 2452 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 2451 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { | 2453 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 2452 | const reg = try self.register_manager.allocReg(null, regClassForType(ty)); | 2454 | const mod = self.bin_file.options.module.?; |
| 2455 | const reg = try self.register_manager.allocReg(null, regClassForType(ty, mod)); | ||
| 2453 | try self.genSetReg(reg, ty, mcv); | 2456 | try self.genSetReg(reg, ty, mcv); |
| 2454 | return reg; | 2457 | return reg; |
| 2455 | } | 2458 | } |
| ... | @@ -2464,7 +2467,8 @@ fn copyToRegisterWithInstTracking( | ... | @@ -2464,7 +2467,8 @@ fn copyToRegisterWithInstTracking( |
| 2464 | ty: Type, | 2467 | ty: Type, |
| 2465 | mcv: MCValue, | 2468 | mcv: MCValue, |
| 2466 | ) !MCValue { | 2469 | ) !MCValue { |
| 2467 | const reg: Register = try self.register_manager.allocReg(reg_owner, regClassForType(ty)); | 2470 | const mod = self.bin_file.options.module.?; |
| 2471 | const reg: Register = try self.register_manager.allocReg(reg_owner, regClassForType(ty, mod)); | ||
| 2468 | try self.genSetReg(reg, ty, mcv); | 2472 | try self.genSetReg(reg, ty, mcv); |
| 2469 | return MCValue{ .register = reg }; | 2473 | return MCValue{ .register = reg }; |
| 2470 | } | 2474 | } |
| ... | @@ -2618,14 +2622,15 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2618,14 +2622,15 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { |
| 2618 | } | 2622 | } |
| 2619 | 2623 | ||
| 2620 | fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { | 2624 | fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 2625 | const mod = self.bin_file.options.module.?; | ||
| 2621 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2626 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2622 | const result: MCValue = result: { | 2627 | const result: MCValue = result: { |
| 2623 | const src_ty = self.air.typeOf(ty_op.operand); | 2628 | const src_ty = self.air.typeOf(ty_op.operand); |
| 2624 | const src_int_info = src_ty.intInfo(self.target.*); | 2629 | const src_int_info = src_ty.intInfo(mod); |
| 2625 | 2630 | ||
| 2626 | const dst_ty = self.air.typeOfIndex(inst); | 2631 | const dst_ty = self.air.typeOfIndex(inst); |
| 2627 | const dst_int_info = dst_ty.intInfo(self.target.*); | 2632 | const dst_int_info = dst_ty.intInfo(mod); |
| 2628 | const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*)); | 2633 | const abi_size = @intCast(u32, dst_ty.abiSize(mod)); |
| 2629 | 2634 | ||
| 2630 | const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty; | 2635 | const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty; |
| 2631 | const extend = switch (src_int_info.signedness) { | 2636 | const extend = switch (src_int_info.signedness) { |
| ... | @@ -2670,14 +2675,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2670,14 +2675,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 2670 | 2675 | ||
| 2671 | const high_bits = src_int_info.bits % 64; | 2676 | const high_bits = src_int_info.bits % 64; |
| 2672 | if (high_bits > 0) { | 2677 | if (high_bits > 0) { |
| 2673 | var high_pl = Type.Payload.Bits{ | 2678 | const high_ty = try mod.intType(extend, high_bits); |
| 2674 | .base = .{ .tag = switch (extend) { | ||
| 2675 | .signed => .int_signed, | ||
| 2676 | .unsigned => .int_unsigned, | ||
| 2677 | } }, | ||
| 2678 | .data = high_bits, | ||
| 2679 | }; | ||
| 2680 | const high_ty = Type.initPayload(&high_pl.base); | ||
| 2681 | try self.truncateRegister(high_ty, high_reg); | 2679 | try self.truncateRegister(high_ty, high_reg); |
| 2682 | try self.genCopy(Type.usize, high_mcv, .{ .register = high_reg }); | 2680 | try self.genCopy(Type.usize, high_mcv, .{ .register = high_reg }); |
| 2683 | } | 2681 | } |
| ... | @@ -2706,12 +2704,13 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2706,12 +2704,13 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 2706 | } | 2704 | } |
| 2707 | 2705 | ||
| 2708 | fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { | 2706 | fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 2707 | const mod = self.bin_file.options.module.?; | ||
| 2709 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2708 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2710 | 2709 | ||
| 2711 | const dst_ty = self.air.typeOfIndex(inst); | 2710 | const dst_ty = self.air.typeOfIndex(inst); |
| 2712 | const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*)); | 2711 | const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod)); |
| 2713 | const src_ty = self.air.typeOf(ty_op.operand); | 2712 | const src_ty = self.air.typeOf(ty_op.operand); |
| 2714 | const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*)); | 2713 | const src_abi_size = @intCast(u32, src_ty.abiSize(mod)); |
| 2715 | 2714 | ||
| 2716 | const result = result: { | 2715 | const result = result: { |
| 2717 | const src_mcv = try self.resolveInst(ty_op.operand); | 2716 | const src_mcv = try self.resolveInst(ty_op.operand); |
| ... | @@ -2724,10 +2723,10 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2724,10 +2723,10 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 2724 | else | 2723 | else |
| 2725 | try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv); | 2724 | try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv); |
| 2726 | 2725 | ||
| 2727 | if (dst_ty.zigTypeTag() == .Vector) { | 2726 | if (dst_ty.zigTypeTag(mod) == .Vector) { |
| 2728 | assert(src_ty.zigTypeTag() == .Vector and dst_ty.vectorLen() == src_ty.vectorLen()); | 2727 | assert(src_ty.zigTypeTag(mod) == .Vector and dst_ty.vectorLen() == src_ty.vectorLen()); |
| 2729 | const dst_info = dst_ty.childType().intInfo(self.target.*); | 2728 | const dst_info = dst_ty.childType().intInfo(mod); |
| 2730 | const src_info = src_ty.childType().intInfo(self.target.*); | 2729 | const src_info = src_ty.childType().intInfo(mod); |
| 2731 | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_info.bits) { | 2730 | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_info.bits) { |
| 2732 | 8 => switch (src_info.bits) { | 2731 | 8 => switch (src_info.bits) { |
| 2733 | 16 => switch (dst_ty.vectorLen()) { | 2732 | 16 => switch (dst_ty.vectorLen()) { |
| ... | @@ -2775,7 +2774,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2775,7 +2774,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 2775 | }, | 2774 | }, |
| 2776 | }; | 2775 | }; |
| 2777 | const full_ty = Type.initPayload(&full_pl.base); | 2776 | const full_ty = Type.initPayload(&full_pl.base); |
| 2778 | const full_abi_size = @intCast(u32, full_ty.abiSize(self.target.*)); | 2777 | const full_abi_size = @intCast(u32, full_ty.abiSize(mod)); |
| 2779 | 2778 | ||
| 2780 | const splat_mcv = try self.genTypedValue(.{ .ty = full_ty, .val = splat_val }); | 2779 | const splat_mcv = try self.genTypedValue(.{ .ty = full_ty, .val = splat_val }); |
| 2781 | const splat_addr_mcv: MCValue = switch (splat_mcv) { | 2780 | const splat_addr_mcv: MCValue = switch (splat_mcv) { |
| ... | @@ -2831,6 +2830,7 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2831,6 +2830,7 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 2831 | } | 2830 | } |
| 2832 | 2831 | ||
| 2833 | fn airSlice(self: *Self, inst: Air.Inst.Index) !void { | 2832 | fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 2833 | const mod = self.bin_file.options.module.?; | ||
| 2834 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2834 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2835 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 2835 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2836 | 2836 | ||
| ... | @@ -2840,11 +2840,11 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2840,11 +2840,11 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 2840 | const len = try self.resolveInst(bin_op.rhs); | 2840 | const len = try self.resolveInst(bin_op.rhs); |
| 2841 | const len_ty = self.air.typeOf(bin_op.rhs); | 2841 | const len_ty = self.air.typeOf(bin_op.rhs); |
| 2842 | 2842 | ||
| 2843 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, self.target.*)); | 2843 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, mod)); |
| 2844 | try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr); | 2844 | try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr); |
| 2845 | try self.genSetMem( | 2845 | try self.genSetMem( |
| 2846 | .{ .frame = frame_index }, | 2846 | .{ .frame = frame_index }, |
| 2847 | @intCast(i32, ptr_ty.abiSize(self.target.*)), | 2847 | @intCast(i32, ptr_ty.abiSize(mod)), |
| 2848 | len_ty, | 2848 | len_ty, |
| 2849 | len, | 2849 | len, |
| 2850 | ); | 2850 | ); |
| ... | @@ -2873,23 +2873,24 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void | ... | @@ -2873,23 +2873,24 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void |
| 2873 | } | 2873 | } |
| 2874 | 2874 | ||
| 2875 | fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 { | 2875 | fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 { |
| 2876 | const mod = self.bin_file.options.module.?; | ||
| 2876 | const air_tag = self.air.instructions.items(.tag); | 2877 | const air_tag = self.air.instructions.items(.tag); |
| 2877 | const air_data = self.air.instructions.items(.data); | 2878 | const air_data = self.air.instructions.items(.data); |
| 2878 | 2879 | ||
| 2879 | const dst_ty = self.air.typeOf(dst_air); | 2880 | const dst_ty = self.air.typeOf(dst_air); |
| 2880 | const dst_info = dst_ty.intInfo(self.target.*); | 2881 | const dst_info = dst_ty.intInfo(mod); |
| 2881 | if (Air.refToIndex(dst_air)) |inst| { | 2882 | if (Air.refToIndex(dst_air)) |inst| { |
| 2882 | switch (air_tag[inst]) { | 2883 | switch (air_tag[inst]) { |
| 2883 | .constant => { | 2884 | .constant => { |
| 2884 | const src_val = self.air.values[air_data[inst].ty_pl.payload]; | 2885 | const src_val = self.air.values[air_data[inst].ty_pl.payload]; |
| 2885 | var space: Value.BigIntSpace = undefined; | 2886 | var space: Value.BigIntSpace = undefined; |
| 2886 | const src_int = src_val.toBigInt(&space, self.target.*); | 2887 | const src_int = src_val.toBigInt(&space, mod); |
| 2887 | return @intCast(u16, src_int.bitCountTwosComp()) + | 2888 | return @intCast(u16, src_int.bitCountTwosComp()) + |
| 2888 | @boolToInt(src_int.positive and dst_info.signedness == .signed); | 2889 | @boolToInt(src_int.positive and dst_info.signedness == .signed); |
| 2889 | }, | 2890 | }, |
| 2890 | .intcast => { | 2891 | .intcast => { |
| 2891 | const src_ty = self.air.typeOf(air_data[inst].ty_op.operand); | 2892 | const src_ty = self.air.typeOf(air_data[inst].ty_op.operand); |
| 2892 | const src_info = src_ty.intInfo(self.target.*); | 2893 | const src_info = src_ty.intInfo(mod); |
| 2893 | return @min(switch (src_info.signedness) { | 2894 | return @min(switch (src_info.signedness) { |
| 2894 | .signed => switch (dst_info.signedness) { | 2895 | .signed => switch (dst_info.signedness) { |
| 2895 | .signed => src_info.bits, | 2896 | .signed => src_info.bits, |
| ... | @@ -2908,20 +2909,18 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 { | ... | @@ -2908,20 +2909,18 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 { |
| 2908 | } | 2909 | } |
| 2909 | 2910 | ||
| 2910 | fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { | 2911 | fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 2912 | const mod = self.bin_file.options.module.?; | ||
| 2911 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 2913 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2912 | const result = result: { | 2914 | const result = result: { |
| 2913 | const tag = self.air.instructions.items(.tag)[inst]; | 2915 | const tag = self.air.instructions.items(.tag)[inst]; |
| 2914 | const dst_ty = self.air.typeOfIndex(inst); | 2916 | const dst_ty = self.air.typeOfIndex(inst); |
| 2915 | switch (dst_ty.zigTypeTag()) { | 2917 | switch (dst_ty.zigTypeTag(mod)) { |
| 2916 | .Float, .Vector => break :result try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs), | 2918 | .Float, .Vector => break :result try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs), |
| 2917 | else => {}, | 2919 | else => {}, |
| 2918 | } | 2920 | } |
| 2919 | 2921 | ||
| 2920 | const dst_info = dst_ty.intInfo(self.target.*); | 2922 | const dst_info = dst_ty.intInfo(mod); |
| 2921 | var src_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dst_info.signedness) { | 2923 | const src_ty = try mod.intType(dst_info.signedness, switch (tag) { |
| 2922 | .signed => .int_signed, | ||
| 2923 | .unsigned => .int_unsigned, | ||
| 2924 | } }, .data = switch (tag) { | ||
| 2925 | else => unreachable, | 2924 | else => unreachable, |
| 2926 | .mul, .mulwrap => math.max3( | 2925 | .mul, .mulwrap => math.max3( |
| 2927 | self.activeIntBits(bin_op.lhs), | 2926 | self.activeIntBits(bin_op.lhs), |
| ... | @@ -2929,8 +2928,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2929,8 +2928,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 2929 | dst_info.bits / 2, | 2928 | dst_info.bits / 2, |
| 2930 | ), | 2929 | ), |
| 2931 | .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_info.bits, | 2930 | .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_info.bits, |
| 2932 | } }; | 2931 | }); |
| 2933 | const src_ty = Type.initPayload(&src_pl.base); | ||
| 2934 | 2932 | ||
| 2935 | try self.spillEflagsIfOccupied(); | 2933 | try self.spillEflagsIfOccupied(); |
| 2936 | try self.spillRegisters(&.{ .rax, .rdx }); | 2934 | try self.spillRegisters(&.{ .rax, .rdx }); |
| ... | @@ -2942,6 +2940,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2942,6 +2940,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 2942 | } | 2940 | } |
| 2943 | 2941 | ||
| 2944 | fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | 2942 | fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2943 | const mod = self.bin_file.options.module.?; | ||
| 2945 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 2944 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2946 | const ty = self.air.typeOf(bin_op.lhs); | 2945 | const ty = self.air.typeOf(bin_op.lhs); |
| 2947 | 2946 | ||
| ... | @@ -2968,7 +2967,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2968,7 +2967,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2968 | 2967 | ||
| 2969 | const reg_bits = self.regBitSize(ty); | 2968 | const reg_bits = self.regBitSize(ty); |
| 2970 | const reg_extra_bits = self.regExtraBits(ty); | 2969 | const reg_extra_bits = self.regExtraBits(ty); |
| 2971 | const cc: Condition = if (ty.isSignedInt()) cc: { | 2970 | const cc: Condition = if (ty.isSignedInt(mod)) cc: { |
| 2972 | if (reg_extra_bits > 0) { | 2971 | if (reg_extra_bits > 0) { |
| 2973 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); | 2972 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); |
| 2974 | } | 2973 | } |
| ... | @@ -2994,7 +2993,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2994,7 +2993,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2994 | break :cc .o; | 2993 | break :cc .o; |
| 2995 | } else cc: { | 2994 | } else cc: { |
| 2996 | try self.genSetReg(limit_reg, ty, .{ | 2995 | try self.genSetReg(limit_reg, ty, .{ |
| 2997 | .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - ty.bitSize(self.target.*)), | 2996 | .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - ty.bitSize(mod)), |
| 2998 | }); | 2997 | }); |
| 2999 | 2998 | ||
| 3000 | try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv); | 2999 | try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv); |
| ... | @@ -3005,14 +3004,14 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3005,14 +3004,14 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3005 | break :cc .c; | 3004 | break :cc .c; |
| 3006 | }; | 3005 | }; |
| 3007 | 3006 | ||
| 3008 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); | 3007 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(mod)), 2); |
| 3009 | try self.asmCmovccRegisterRegister( | 3008 | try self.asmCmovccRegisterRegister( |
| 3010 | registerAlias(dst_reg, cmov_abi_size), | 3009 | registerAlias(dst_reg, cmov_abi_size), |
| 3011 | registerAlias(limit_reg, cmov_abi_size), | 3010 | registerAlias(limit_reg, cmov_abi_size), |
| 3012 | cc, | 3011 | cc, |
| 3013 | ); | 3012 | ); |
| 3014 | 3013 | ||
| 3015 | if (reg_extra_bits > 0 and ty.isSignedInt()) { | 3014 | if (reg_extra_bits > 0 and ty.isSignedInt(mod)) { |
| 3016 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); | 3015 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); |
| 3017 | } | 3016 | } |
| 3018 | 3017 | ||
| ... | @@ -3020,6 +3019,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3020,6 +3019,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3020 | } | 3019 | } |
| 3021 | 3020 | ||
| 3022 | fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { | 3021 | fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3022 | const mod = self.bin_file.options.module.?; | ||
| 3023 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 3023 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 3024 | const ty = self.air.typeOf(bin_op.lhs); | 3024 | const ty = self.air.typeOf(bin_op.lhs); |
| 3025 | 3025 | ||
| ... | @@ -3046,7 +3046,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3046,7 +3046,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3046 | 3046 | ||
| 3047 | const reg_bits = self.regBitSize(ty); | 3047 | const reg_bits = self.regBitSize(ty); |
| 3048 | const reg_extra_bits = self.regExtraBits(ty); | 3048 | const reg_extra_bits = self.regExtraBits(ty); |
| 3049 | const cc: Condition = if (ty.isSignedInt()) cc: { | 3049 | const cc: Condition = if (ty.isSignedInt(mod)) cc: { |
| 3050 | if (reg_extra_bits > 0) { | 3050 | if (reg_extra_bits > 0) { |
| 3051 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); | 3051 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); |
| 3052 | } | 3052 | } |
| ... | @@ -3076,14 +3076,14 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3076,14 +3076,14 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3076 | break :cc .c; | 3076 | break :cc .c; |
| 3077 | }; | 3077 | }; |
| 3078 | 3078 | ||
| 3079 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); | 3079 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(mod)), 2); |
| 3080 | try self.asmCmovccRegisterRegister( | 3080 | try self.asmCmovccRegisterRegister( |
| 3081 | registerAlias(dst_reg, cmov_abi_size), | 3081 | registerAlias(dst_reg, cmov_abi_size), |
| 3082 | registerAlias(limit_reg, cmov_abi_size), | 3082 | registerAlias(limit_reg, cmov_abi_size), |
| 3083 | cc, | 3083 | cc, |
| 3084 | ); | 3084 | ); |
| 3085 | 3085 | ||
| 3086 | if (reg_extra_bits > 0 and ty.isSignedInt()) { | 3086 | if (reg_extra_bits > 0 and ty.isSignedInt(mod)) { |
| 3087 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); | 3087 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); |
| 3088 | } | 3088 | } |
| 3089 | 3089 | ||
| ... | @@ -3091,6 +3091,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3091,6 +3091,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3091 | } | 3091 | } |
| 3092 | 3092 | ||
| 3093 | fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { | 3093 | fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3094 | const mod = self.bin_file.options.module.?; | ||
| 3094 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 3095 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 3095 | const ty = self.air.typeOf(bin_op.lhs); | 3096 | const ty = self.air.typeOf(bin_op.lhs); |
| 3096 | 3097 | ||
| ... | @@ -3118,7 +3119,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3118,7 +3119,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3118 | defer self.register_manager.unlockReg(limit_lock); | 3119 | defer self.register_manager.unlockReg(limit_lock); |
| 3119 | 3120 | ||
| 3120 | const reg_bits = self.regBitSize(ty); | 3121 | const reg_bits = self.regBitSize(ty); |
| 3121 | const cc: Condition = if (ty.isSignedInt()) cc: { | 3122 | const cc: Condition = if (ty.isSignedInt(mod)) cc: { |
| 3122 | try self.genSetReg(limit_reg, ty, lhs_mcv); | 3123 | try self.genSetReg(limit_reg, ty, lhs_mcv); |
| 3123 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv); | 3124 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv); |
| 3124 | try self.genShiftBinOpMir(.{ ._, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); | 3125 | try self.genShiftBinOpMir(.{ ._, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| ... | @@ -3134,7 +3135,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3134,7 +3135,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3134 | }; | 3135 | }; |
| 3135 | 3136 | ||
| 3136 | const dst_mcv = try self.genMulDivBinOp(.mul, inst, ty, ty, lhs_mcv, rhs_mcv); | 3137 | const dst_mcv = try self.genMulDivBinOp(.mul, inst, ty, ty, lhs_mcv, rhs_mcv); |
| 3137 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); | 3138 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(mod)), 2); |
| 3138 | try self.asmCmovccRegisterRegister( | 3139 | try self.asmCmovccRegisterRegister( |
| 3139 | registerAlias(dst_mcv.register, cmov_abi_size), | 3140 | registerAlias(dst_mcv.register, cmov_abi_size), |
| 3140 | registerAlias(limit_reg, cmov_abi_size), | 3141 | registerAlias(limit_reg, cmov_abi_size), |
| ... | @@ -3145,12 +3146,13 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3145,12 +3146,13 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3145 | } | 3146 | } |
| 3146 | 3147 | ||
| 3147 | fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | 3148 | fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3149 | const mod = self.bin_file.options.module.?; | ||
| 3148 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 3150 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 3149 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 3151 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3150 | const result: MCValue = result: { | 3152 | const result: MCValue = result: { |
| 3151 | const tag = self.air.instructions.items(.tag)[inst]; | 3153 | const tag = self.air.instructions.items(.tag)[inst]; |
| 3152 | const ty = self.air.typeOf(bin_op.lhs); | 3154 | const ty = self.air.typeOf(bin_op.lhs); |
| 3153 | switch (ty.zigTypeTag()) { | 3155 | switch (ty.zigTypeTag(mod)) { |
| 3154 | .Vector => return self.fail("TODO implement add/sub with overflow for Vector type", .{}), | 3156 | .Vector => return self.fail("TODO implement add/sub with overflow for Vector type", .{}), |
| 3155 | .Int => { | 3157 | .Int => { |
| 3156 | try self.spillEflagsIfOccupied(); | 3158 | try self.spillEflagsIfOccupied(); |
| ... | @@ -3160,7 +3162,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3160,7 +3162,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3160 | .sub_with_overflow => .sub, | 3162 | .sub_with_overflow => .sub, |
| 3161 | else => unreachable, | 3163 | else => unreachable, |
| 3162 | }, bin_op.lhs, bin_op.rhs); | 3164 | }, bin_op.lhs, bin_op.rhs); |
| 3163 | const int_info = ty.intInfo(self.target.*); | 3165 | const int_info = ty.intInfo(mod); |
| 3164 | const cc: Condition = switch (int_info.signedness) { | 3166 | const cc: Condition = switch (int_info.signedness) { |
| 3165 | .unsigned => .c, | 3167 | .unsigned => .c, |
| 3166 | .signed => .o, | 3168 | .signed => .o, |
| ... | @@ -3177,16 +3179,16 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3177,16 +3179,16 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3177 | } | 3179 | } |
| 3178 | 3180 | ||
| 3179 | const frame_index = | 3181 | const frame_index = |
| 3180 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*)); | 3182 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod)); |
| 3181 | try self.genSetMem( | 3183 | try self.genSetMem( |
| 3182 | .{ .frame = frame_index }, | 3184 | .{ .frame = frame_index }, |
| 3183 | @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)), | 3185 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), |
| 3184 | Type.u1, | 3186 | Type.u1, |
| 3185 | .{ .eflags = cc }, | 3187 | .{ .eflags = cc }, |
| 3186 | ); | 3188 | ); |
| 3187 | try self.genSetMem( | 3189 | try self.genSetMem( |
| 3188 | .{ .frame = frame_index }, | 3190 | .{ .frame = frame_index }, |
| 3189 | @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)), | 3191 | @intCast(i32, tuple_ty.structFieldOffset(0, mod)), |
| 3190 | ty, | 3192 | ty, |
| 3191 | partial_mcv, | 3193 | partial_mcv, |
| 3192 | ); | 3194 | ); |
| ... | @@ -3194,7 +3196,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3194,7 +3196,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3194 | } | 3196 | } |
| 3195 | 3197 | ||
| 3196 | const frame_index = | 3198 | const frame_index = |
| 3197 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*)); | 3199 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod)); |
| 3198 | try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc); | 3200 | try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc); |
| 3199 | break :result .{ .load_frame = .{ .index = frame_index } }; | 3201 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 3200 | }, | 3202 | }, |
| ... | @@ -3205,12 +3207,13 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3205,12 +3207,13 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3205 | } | 3207 | } |
| 3206 | 3208 | ||
| 3207 | fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | 3209 | fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3210 | const mod = self.bin_file.options.module.?; | ||
| 3208 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 3211 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 3209 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 3212 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3210 | const result: MCValue = result: { | 3213 | const result: MCValue = result: { |
| 3211 | const lhs_ty = self.air.typeOf(bin_op.lhs); | 3214 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| 3212 | const rhs_ty = self.air.typeOf(bin_op.rhs); | 3215 | const rhs_ty = self.air.typeOf(bin_op.rhs); |
| 3213 | switch (lhs_ty.zigTypeTag()) { | 3216 | switch (lhs_ty.zigTypeTag(mod)) { |
| 3214 | .Vector => return self.fail("TODO implement shl with overflow for Vector type", .{}), | 3217 | .Vector => return self.fail("TODO implement shl with overflow for Vector type", .{}), |
| 3215 | .Int => { | 3218 | .Int => { |
| 3216 | try self.spillEflagsIfOccupied(); | 3219 | try self.spillEflagsIfOccupied(); |
| ... | @@ -3219,7 +3222,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3219,7 +3222,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3219 | const lhs = try self.resolveInst(bin_op.lhs); | 3222 | const lhs = try self.resolveInst(bin_op.lhs); |
| 3220 | const rhs = try self.resolveInst(bin_op.rhs); | 3223 | const rhs = try self.resolveInst(bin_op.rhs); |
| 3221 | 3224 | ||
| 3222 | const int_info = lhs_ty.intInfo(self.target.*); | 3225 | const int_info = lhs_ty.intInfo(mod); |
| 3223 | 3226 | ||
| 3224 | const partial_mcv = try self.genShiftBinOp(.shl, null, lhs, rhs, lhs_ty, rhs_ty); | 3227 | const partial_mcv = try self.genShiftBinOp(.shl, null, lhs, rhs, lhs_ty, rhs_ty); |
| 3225 | const partial_lock = switch (partial_mcv) { | 3228 | const partial_lock = switch (partial_mcv) { |
| ... | @@ -3249,16 +3252,16 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3249,16 +3252,16 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3249 | } | 3252 | } |
| 3250 | 3253 | ||
| 3251 | const frame_index = | 3254 | const frame_index = |
| 3252 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*)); | 3255 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod)); |
| 3253 | try self.genSetMem( | 3256 | try self.genSetMem( |
| 3254 | .{ .frame = frame_index }, | 3257 | .{ .frame = frame_index }, |
| 3255 | @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)), | 3258 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), |
| 3256 | tuple_ty.structFieldType(1), | 3259 | tuple_ty.structFieldType(1), |
| 3257 | .{ .eflags = cc }, | 3260 | .{ .eflags = cc }, |
| 3258 | ); | 3261 | ); |
| 3259 | try self.genSetMem( | 3262 | try self.genSetMem( |
| 3260 | .{ .frame = frame_index }, | 3263 | .{ .frame = frame_index }, |
| 3261 | @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)), | 3264 | @intCast(i32, tuple_ty.structFieldOffset(0, mod)), |
| 3262 | tuple_ty.structFieldType(0), | 3265 | tuple_ty.structFieldType(0), |
| 3263 | partial_mcv, | 3266 | partial_mcv, |
| 3264 | ); | 3267 | ); |
| ... | @@ -3266,7 +3269,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3266,7 +3269,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3266 | } | 3269 | } |
| 3267 | 3270 | ||
| 3268 | const frame_index = | 3271 | const frame_index = |
| 3269 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*)); | 3272 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod)); |
| 3270 | try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc); | 3273 | try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc); |
| 3271 | break :result .{ .load_frame = .{ .index = frame_index } }; | 3274 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 3272 | }, | 3275 | }, |
| ... | @@ -3283,6 +3286,7 @@ fn genSetFrameTruncatedOverflowCompare( | ... | @@ -3283,6 +3286,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3283 | src_mcv: MCValue, | 3286 | src_mcv: MCValue, |
| 3284 | overflow_cc: ?Condition, | 3287 | overflow_cc: ?Condition, |
| 3285 | ) !void { | 3288 | ) !void { |
| 3289 | const mod = self.bin_file.options.module.?; | ||
| 3286 | const src_lock = switch (src_mcv) { | 3290 | const src_lock = switch (src_mcv) { |
| 3287 | .register => |reg| self.register_manager.lockReg(reg), | 3291 | .register => |reg| self.register_manager.lockReg(reg), |
| 3288 | else => null, | 3292 | else => null, |
| ... | @@ -3290,22 +3294,12 @@ fn genSetFrameTruncatedOverflowCompare( | ... | @@ -3290,22 +3294,12 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3290 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); | 3294 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 3291 | 3295 | ||
| 3292 | const ty = tuple_ty.structFieldType(0); | 3296 | const ty = tuple_ty.structFieldType(0); |
| 3293 | const int_info = ty.intInfo(self.target.*); | 3297 | const int_info = ty.intInfo(mod); |
| 3294 | 3298 | ||
| 3295 | var hi_limb_pl = Type.Payload.Bits{ | 3299 | const hi_limb_bits = (int_info.bits - 1) % 64 + 1; |
| 3296 | .base = .{ .tag = switch (int_info.signedness) { | 3300 | const hi_limb_ty = try mod.intType(int_info.signedness, hi_limb_bits); |
| 3297 | .signed => .int_signed, | ||
| 3298 | .unsigned => .int_unsigned, | ||
| 3299 | } }, | ||
| 3300 | .data = (int_info.bits - 1) % 64 + 1, | ||
| 3301 | }; | ||
| 3302 | const hi_limb_ty = Type.initPayload(&hi_limb_pl.base); | ||
| 3303 | 3301 | ||
| 3304 | var rest_pl = Type.Payload.Bits{ | 3302 | const rest_ty = try mod.intType(.unsigned, int_info.bits - hi_limb_bits); |
| 3305 | .base = .{ .tag = .int_unsigned }, | ||
| 3306 | .data = int_info.bits - hi_limb_pl.data, | ||
| 3307 | }; | ||
| 3308 | const rest_ty = Type.initPayload(&rest_pl.base); | ||
| 3309 | 3303 | ||
| 3310 | const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, gp); | 3304 | const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, gp); |
| 3311 | const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs); | 3305 | const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs); |
| ... | @@ -3335,7 +3329,7 @@ fn genSetFrameTruncatedOverflowCompare( | ... | @@ -3335,7 +3329,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3335 | ); | 3329 | ); |
| 3336 | } | 3330 | } |
| 3337 | 3331 | ||
| 3338 | const payload_off = @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)); | 3332 | const payload_off = @intCast(i32, tuple_ty.structFieldOffset(0, mod)); |
| 3339 | if (hi_limb_off > 0) try self.genSetMem(.{ .frame = frame_index }, payload_off, rest_ty, src_mcv); | 3333 | if (hi_limb_off > 0) try self.genSetMem(.{ .frame = frame_index }, payload_off, rest_ty, src_mcv); |
| 3340 | try self.genSetMem( | 3334 | try self.genSetMem( |
| 3341 | .{ .frame = frame_index }, | 3335 | .{ .frame = frame_index }, |
| ... | @@ -3345,23 +3339,24 @@ fn genSetFrameTruncatedOverflowCompare( | ... | @@ -3345,23 +3339,24 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3345 | ); | 3339 | ); |
| 3346 | try self.genSetMem( | 3340 | try self.genSetMem( |
| 3347 | .{ .frame = frame_index }, | 3341 | .{ .frame = frame_index }, |
| 3348 | @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)), | 3342 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), |
| 3349 | tuple_ty.structFieldType(1), | 3343 | tuple_ty.structFieldType(1), |
| 3350 | if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne }, | 3344 | if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne }, |
| 3351 | ); | 3345 | ); |
| 3352 | } | 3346 | } |
| 3353 | 3347 | ||
| 3354 | fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | 3348 | fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3349 | const mod = self.bin_file.options.module.?; | ||
| 3355 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 3350 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 3356 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 3351 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3357 | const dst_ty = self.air.typeOf(bin_op.lhs); | 3352 | const dst_ty = self.air.typeOf(bin_op.lhs); |
| 3358 | const result: MCValue = switch (dst_ty.zigTypeTag()) { | 3353 | const result: MCValue = switch (dst_ty.zigTypeTag(mod)) { |
| 3359 | .Vector => return self.fail("TODO implement mul_with_overflow for Vector type", .{}), | 3354 | .Vector => return self.fail("TODO implement mul_with_overflow for Vector type", .{}), |
| 3360 | .Int => result: { | 3355 | .Int => result: { |
| 3361 | try self.spillEflagsIfOccupied(); | 3356 | try self.spillEflagsIfOccupied(); |
| 3362 | try self.spillRegisters(&.{ .rax, .rdx }); | 3357 | try self.spillRegisters(&.{ .rax, .rdx }); |
| 3363 | 3358 | ||
| 3364 | const dst_info = dst_ty.intInfo(self.target.*); | 3359 | const dst_info = dst_ty.intInfo(mod); |
| 3365 | const cc: Condition = switch (dst_info.signedness) { | 3360 | const cc: Condition = switch (dst_info.signedness) { |
| 3366 | .unsigned => .c, | 3361 | .unsigned => .c, |
| 3367 | .signed => .o, | 3362 | .signed => .o, |
| ... | @@ -3369,11 +3364,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3369,11 +3364,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3369 | 3364 | ||
| 3370 | const lhs_active_bits = self.activeIntBits(bin_op.lhs); | 3365 | const lhs_active_bits = self.activeIntBits(bin_op.lhs); |
| 3371 | const rhs_active_bits = self.activeIntBits(bin_op.rhs); | 3366 | const rhs_active_bits = self.activeIntBits(bin_op.rhs); |
| 3372 | var src_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dst_info.signedness) { | 3367 | const src_bits = math.max3(lhs_active_bits, rhs_active_bits, dst_info.bits / 2); |
| 3373 | .signed => .int_signed, | 3368 | const src_ty = try mod.intType(dst_info.signedness, src_bits); |
| 3374 | .unsigned => .int_unsigned, | ||
| 3375 | } }, .data = math.max3(lhs_active_bits, rhs_active_bits, dst_info.bits / 2) }; | ||
| 3376 | const src_ty = Type.initPayload(&src_pl.base); | ||
| 3377 | 3369 | ||
| 3378 | const lhs = try self.resolveInst(bin_op.lhs); | 3370 | const lhs = try self.resolveInst(bin_op.lhs); |
| 3379 | const rhs = try self.resolveInst(bin_op.rhs); | 3371 | const rhs = try self.resolveInst(bin_op.rhs); |
| ... | @@ -3391,26 +3383,26 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3391,26 +3383,26 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3391 | break :result .{ .register_overflow = .{ .reg = reg, .eflags = cc } }; | 3383 | break :result .{ .register_overflow = .{ .reg = reg, .eflags = cc } }; |
| 3392 | } else { | 3384 | } else { |
| 3393 | const frame_index = | 3385 | const frame_index = |
| 3394 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*)); | 3386 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod)); |
| 3395 | try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc); | 3387 | try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc); |
| 3396 | break :result .{ .load_frame = .{ .index = frame_index } }; | 3388 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 3397 | }, | 3389 | }, |
| 3398 | else => { | 3390 | else => { |
| 3399 | // For now, this is the only supported multiply that doesn't fit in a register. | 3391 | // For now, this is the only supported multiply that doesn't fit in a register. |
| 3400 | assert(dst_info.bits <= 128 and src_pl.data == 64); | 3392 | assert(dst_info.bits <= 128 and src_bits == 64); |
| 3401 | 3393 | ||
| 3402 | const frame_index = | 3394 | const frame_index = |
| 3403 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*)); | 3395 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod)); |
| 3404 | if (dst_info.bits >= lhs_active_bits + rhs_active_bits) { | 3396 | if (dst_info.bits >= lhs_active_bits + rhs_active_bits) { |
| 3405 | try self.genSetMem( | 3397 | try self.genSetMem( |
| 3406 | .{ .frame = frame_index }, | 3398 | .{ .frame = frame_index }, |
| 3407 | @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)), | 3399 | @intCast(i32, tuple_ty.structFieldOffset(0, mod)), |
| 3408 | tuple_ty.structFieldType(0), | 3400 | tuple_ty.structFieldType(0), |
| 3409 | partial_mcv, | 3401 | partial_mcv, |
| 3410 | ); | 3402 | ); |
| 3411 | try self.genSetMem( | 3403 | try self.genSetMem( |
| 3412 | .{ .frame = frame_index }, | 3404 | .{ .frame = frame_index }, |
| 3413 | @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)), | 3405 | @intCast(i32, tuple_ty.structFieldOffset(1, mod)), |
| 3414 | tuple_ty.structFieldType(1), | 3406 | tuple_ty.structFieldType(1), |
| 3415 | .{ .immediate = 0 }, // cc being set is impossible | 3407 | .{ .immediate = 0 }, // cc being set is impossible |
| 3416 | ); | 3408 | ); |
| ... | @@ -3433,7 +3425,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3433,7 +3425,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3433 | /// Clobbers .rax and .rdx registers. | 3425 | /// Clobbers .rax and .rdx registers. |
| 3434 | /// Quotient is saved in .rax and remainder in .rdx. | 3426 | /// Quotient is saved in .rax and remainder in .rdx. |
| 3435 | fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue, rhs: MCValue) !void { | 3427 | fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue, rhs: MCValue) !void { |
| 3436 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 3428 | const mod = self.bin_file.options.module.?; |
| 3429 | const abi_size = @intCast(u32, ty.abiSize(mod)); | ||
| 3437 | if (abi_size > 8) { | 3430 | if (abi_size > 8) { |
| 3438 | return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{}); | 3431 | return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{}); |
| 3439 | } | 3432 | } |
| ... | @@ -3472,8 +3465,9 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue | ... | @@ -3472,8 +3465,9 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue |
| 3472 | /// Always returns a register. | 3465 | /// Always returns a register. |
| 3473 | /// Clobbers .rax and .rdx registers. | 3466 | /// Clobbers .rax and .rdx registers. |
| 3474 | fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue { | 3467 | fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue { |
| 3475 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 3468 | const mod = self.bin_file.options.module.?; |
| 3476 | const int_info = ty.intInfo(self.target.*); | 3469 | const abi_size = @intCast(u32, ty.abiSize(mod)); |
| 3470 | const int_info = ty.intInfo(mod); | ||
| 3477 | const dividend: Register = switch (lhs) { | 3471 | const dividend: Register = switch (lhs) { |
| 3478 | .register => |reg| reg, | 3472 | .register => |reg| reg, |
| 3479 | else => try self.copyToTmpRegister(ty, lhs), | 3473 | else => try self.copyToTmpRegister(ty, lhs), |
| ... | @@ -3585,6 +3579,7 @@ fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3585,6 +3579,7 @@ fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3585 | } | 3579 | } |
| 3586 | 3580 | ||
| 3587 | fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | 3581 | fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3582 | const mod = self.bin_file.options.module.?; | ||
| 3588 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3583 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3589 | const result = result: { | 3584 | const result = result: { |
| 3590 | const dst_ty = self.air.typeOfIndex(inst); | 3585 | const dst_ty = self.air.typeOfIndex(inst); |
| ... | @@ -3592,7 +3587,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3592,7 +3587,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3592 | const opt_ty = src_ty.childType(); | 3587 | const opt_ty = src_ty.childType(); |
| 3593 | const src_mcv = try self.resolveInst(ty_op.operand); | 3588 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 3594 | 3589 | ||
| 3595 | if (opt_ty.optionalReprIsPayload()) { | 3590 | if (opt_ty.optionalReprIsPayload(mod)) { |
| 3596 | break :result if (self.liveness.isUnused(inst)) | 3591 | break :result if (self.liveness.isUnused(inst)) |
| 3597 | .unreach | 3592 | .unreach |
| 3598 | else if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) | 3593 | else if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| ... | @@ -3610,7 +3605,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3610,7 +3605,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3610 | try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv); | 3605 | try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv); |
| 3611 | 3606 | ||
| 3612 | const pl_ty = dst_ty.childType(); | 3607 | const pl_ty = dst_ty.childType(); |
| 3613 | const pl_abi_size = @intCast(i32, pl_ty.abiSize(self.target.*)); | 3608 | const pl_abi_size = @intCast(i32, pl_ty.abiSize(mod)); |
| 3614 | try self.genSetMem(.{ .reg = dst_mcv.getReg().? }, pl_abi_size, Type.bool, .{ .immediate = 1 }); | 3609 | try self.genSetMem(.{ .reg = dst_mcv.getReg().? }, pl_abi_size, Type.bool, .{ .immediate = 1 }); |
| 3615 | break :result if (self.liveness.isUnused(inst)) .unreach else dst_mcv; | 3610 | break :result if (self.liveness.isUnused(inst)) .unreach else dst_mcv; |
| 3616 | }; | 3611 | }; |
| ... | @@ -3618,6 +3613,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3618,6 +3613,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3618 | } | 3613 | } |
| 3619 | 3614 | ||
| 3620 | fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | 3615 | fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 3616 | const mod = self.bin_file.options.module.?; | ||
| 3621 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3617 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3622 | const err_union_ty = self.air.typeOf(ty_op.operand); | 3618 | const err_union_ty = self.air.typeOf(ty_op.operand); |
| 3623 | const err_ty = err_union_ty.errorUnionSet(); | 3619 | const err_ty = err_union_ty.errorUnionSet(); |
| ... | @@ -3629,11 +3625,11 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3629,11 +3625,11 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 3629 | break :result MCValue{ .immediate = 0 }; | 3625 | break :result MCValue{ .immediate = 0 }; |
| 3630 | } | 3626 | } |
| 3631 | 3627 | ||
| 3632 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 3628 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3633 | break :result operand; | 3629 | break :result operand; |
| 3634 | } | 3630 | } |
| 3635 | 3631 | ||
| 3636 | const err_off = errUnionErrorOffset(payload_ty, self.target.*); | 3632 | const err_off = errUnionErrorOffset(payload_ty, mod); |
| 3637 | switch (operand) { | 3633 | switch (operand) { |
| 3638 | .register => |reg| { | 3634 | .register => |reg| { |
| 3639 | // TODO reuse operand | 3635 | // TODO reuse operand |
| ... | @@ -3678,12 +3674,13 @@ fn genUnwrapErrorUnionPayloadMir( | ... | @@ -3678,12 +3674,13 @@ fn genUnwrapErrorUnionPayloadMir( |
| 3678 | err_union_ty: Type, | 3674 | err_union_ty: Type, |
| 3679 | err_union: MCValue, | 3675 | err_union: MCValue, |
| 3680 | ) !MCValue { | 3676 | ) !MCValue { |
| 3677 | const mod = self.bin_file.options.module.?; | ||
| 3681 | const payload_ty = err_union_ty.errorUnionPayload(); | 3678 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 3682 | 3679 | ||
| 3683 | const result: MCValue = result: { | 3680 | const result: MCValue = result: { |
| 3684 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result .none; | 3681 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; |
| 3685 | 3682 | ||
| 3686 | const payload_off = errUnionPayloadOffset(payload_ty, self.target.*); | 3683 | const payload_off = errUnionPayloadOffset(payload_ty, mod); |
| 3687 | switch (err_union) { | 3684 | switch (err_union) { |
| 3688 | .load_frame => |frame_addr| break :result .{ .load_frame = .{ | 3685 | .load_frame => |frame_addr| break :result .{ .load_frame = .{ |
| 3689 | .index = frame_addr.index, | 3686 | .index = frame_addr.index, |
| ... | @@ -3720,6 +3717,7 @@ fn genUnwrapErrorUnionPayloadMir( | ... | @@ -3720,6 +3717,7 @@ fn genUnwrapErrorUnionPayloadMir( |
| 3720 | 3717 | ||
| 3721 | // *(E!T) -> E | 3718 | // *(E!T) -> E |
| 3722 | fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { | 3719 | fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3720 | const mod = self.bin_file.options.module.?; | ||
| 3723 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3721 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3724 | 3722 | ||
| 3725 | const src_ty = self.air.typeOf(ty_op.operand); | 3723 | const src_ty = self.air.typeOf(ty_op.operand); |
| ... | @@ -3739,8 +3737,8 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3739,8 +3737,8 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3739 | const eu_ty = src_ty.childType(); | 3737 | const eu_ty = src_ty.childType(); |
| 3740 | const pl_ty = eu_ty.errorUnionPayload(); | 3738 | const pl_ty = eu_ty.errorUnionPayload(); |
| 3741 | const err_ty = eu_ty.errorUnionSet(); | 3739 | const err_ty = eu_ty.errorUnionSet(); |
| 3742 | const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*)); | 3740 | const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod)); |
| 3743 | const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*)); | 3741 | const err_abi_size = @intCast(u32, err_ty.abiSize(mod)); |
| 3744 | try self.asmRegisterMemory( | 3742 | try self.asmRegisterMemory( |
| 3745 | .{ ._, .mov }, | 3743 | .{ ._, .mov }, |
| 3746 | registerAlias(dst_reg, err_abi_size), | 3744 | registerAlias(dst_reg, err_abi_size), |
| ... | @@ -3755,6 +3753,7 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3755,6 +3753,7 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3755 | 3753 | ||
| 3756 | // *(E!T) -> *T | 3754 | // *(E!T) -> *T |
| 3757 | fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { | 3755 | fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3756 | const mod = self.bin_file.options.module.?; | ||
| 3758 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3757 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3759 | 3758 | ||
| 3760 | const src_ty = self.air.typeOf(ty_op.operand); | 3759 | const src_ty = self.air.typeOf(ty_op.operand); |
| ... | @@ -3777,8 +3776,8 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3777,8 +3776,8 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3777 | 3776 | ||
| 3778 | const eu_ty = src_ty.childType(); | 3777 | const eu_ty = src_ty.childType(); |
| 3779 | const pl_ty = eu_ty.errorUnionPayload(); | 3778 | const pl_ty = eu_ty.errorUnionPayload(); |
| 3780 | const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*)); | 3779 | const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod)); |
| 3781 | const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*)); | 3780 | const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod)); |
| 3782 | try self.asmRegisterMemory( | 3781 | try self.asmRegisterMemory( |
| 3783 | .{ ._, .lea }, | 3782 | .{ ._, .lea }, |
| 3784 | registerAlias(dst_reg, dst_abi_size), | 3783 | registerAlias(dst_reg, dst_abi_size), |
| ... | @@ -3789,6 +3788,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3789,6 +3788,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3789 | } | 3788 | } |
| 3790 | 3789 | ||
| 3791 | fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | 3790 | fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3791 | const mod = self.bin_file.options.module.?; | ||
| 3792 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3792 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3793 | const result: MCValue = result: { | 3793 | const result: MCValue = result: { |
| 3794 | const src_ty = self.air.typeOf(ty_op.operand); | 3794 | const src_ty = self.air.typeOf(ty_op.operand); |
| ... | @@ -3803,8 +3803,8 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3803,8 +3803,8 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3803 | const eu_ty = src_ty.childType(); | 3803 | const eu_ty = src_ty.childType(); |
| 3804 | const pl_ty = eu_ty.errorUnionPayload(); | 3804 | const pl_ty = eu_ty.errorUnionPayload(); |
| 3805 | const err_ty = eu_ty.errorUnionSet(); | 3805 | const err_ty = eu_ty.errorUnionSet(); |
| 3806 | const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*)); | 3806 | const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod)); |
| 3807 | const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*)); | 3807 | const err_abi_size = @intCast(u32, err_ty.abiSize(mod)); |
| 3808 | try self.asmMemoryImmediate( | 3808 | try self.asmMemoryImmediate( |
| 3809 | .{ ._, .mov }, | 3809 | .{ ._, .mov }, |
| 3810 | Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{ | 3810 | Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{ |
| ... | @@ -3824,8 +3824,8 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3824,8 +3824,8 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3824 | const dst_lock = self.register_manager.lockReg(dst_reg); | 3824 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 3825 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 3825 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 3826 | 3826 | ||
| 3827 | const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*)); | 3827 | const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod)); |
| 3828 | const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*)); | 3828 | const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod)); |
| 3829 | try self.asmRegisterMemory( | 3829 | try self.asmRegisterMemory( |
| 3830 | .{ ._, .lea }, | 3830 | .{ ._, .lea }, |
| 3831 | registerAlias(dst_reg, dst_abi_size), | 3831 | registerAlias(dst_reg, dst_abi_size), |
| ... | @@ -3853,14 +3853,15 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3853,14 +3853,15 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { |
| 3853 | } | 3853 | } |
| 3854 | 3854 | ||
| 3855 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | 3855 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 3856 | const mod = self.bin_file.options.module.?; | ||
| 3856 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3857 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3857 | const result: MCValue = result: { | 3858 | const result: MCValue = result: { |
| 3858 | const pl_ty = self.air.typeOf(ty_op.operand); | 3859 | const pl_ty = self.air.typeOf(ty_op.operand); |
| 3859 | if (!pl_ty.hasRuntimeBits()) break :result .{ .immediate = 1 }; | 3860 | if (!pl_ty.hasRuntimeBits(mod)) break :result .{ .immediate = 1 }; |
| 3860 | 3861 | ||
| 3861 | const opt_ty = self.air.typeOfIndex(inst); | 3862 | const opt_ty = self.air.typeOfIndex(inst); |
| 3862 | const pl_mcv = try self.resolveInst(ty_op.operand); | 3863 | const pl_mcv = try self.resolveInst(ty_op.operand); |
| 3863 | const same_repr = opt_ty.optionalReprIsPayload(); | 3864 | const same_repr = opt_ty.optionalReprIsPayload(mod); |
| 3864 | if (same_repr and self.reuseOperand(inst, ty_op.operand, 0, pl_mcv)) break :result pl_mcv; | 3865 | if (same_repr and self.reuseOperand(inst, ty_op.operand, 0, pl_mcv)) break :result pl_mcv; |
| 3865 | 3866 | ||
| 3866 | const pl_lock: ?RegisterLock = switch (pl_mcv) { | 3867 | const pl_lock: ?RegisterLock = switch (pl_mcv) { |
| ... | @@ -3873,7 +3874,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3873,7 +3874,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 3873 | try self.genCopy(pl_ty, opt_mcv, pl_mcv); | 3874 | try self.genCopy(pl_ty, opt_mcv, pl_mcv); |
| 3874 | 3875 | ||
| 3875 | if (!same_repr) { | 3876 | if (!same_repr) { |
| 3876 | const pl_abi_size = @intCast(i32, pl_ty.abiSize(self.target.*)); | 3877 | const pl_abi_size = @intCast(i32, pl_ty.abiSize(mod)); |
| 3877 | switch (opt_mcv) { | 3878 | switch (opt_mcv) { |
| 3878 | else => unreachable, | 3879 | else => unreachable, |
| 3879 | 3880 | ||
| ... | @@ -3900,6 +3901,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3900,6 +3901,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 3900 | 3901 | ||
| 3901 | /// T to E!T | 3902 | /// T to E!T |
| 3902 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { | 3903 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 3904 | const mod = self.bin_file.options.module.?; | ||
| 3903 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3905 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3904 | 3906 | ||
| 3905 | const eu_ty = self.air.getRefType(ty_op.ty); | 3907 | const eu_ty = self.air.getRefType(ty_op.ty); |
| ... | @@ -3908,11 +3910,11 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3908,11 +3910,11 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 3908 | const operand = try self.resolveInst(ty_op.operand); | 3910 | const operand = try self.resolveInst(ty_op.operand); |
| 3909 | 3911 | ||
| 3910 | const result: MCValue = result: { | 3912 | const result: MCValue = result: { |
| 3911 | if (!pl_ty.hasRuntimeBitsIgnoreComptime()) break :result .{ .immediate = 0 }; | 3913 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .{ .immediate = 0 }; |
| 3912 | 3914 | ||
| 3913 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, self.target.*)); | 3915 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod)); |
| 3914 | const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*)); | 3916 | const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod)); |
| 3915 | const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*)); | 3917 | const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod)); |
| 3916 | try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand); | 3918 | try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand); |
| 3917 | try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 }); | 3919 | try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 }); |
| 3918 | break :result .{ .load_frame = .{ .index = frame_index } }; | 3920 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| ... | @@ -3922,6 +3924,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3922,6 +3924,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 3922 | 3924 | ||
| 3923 | /// E to E!T | 3925 | /// E to E!T |
| 3924 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | 3926 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 3927 | const mod = self.bin_file.options.module.?; | ||
| 3925 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3928 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3926 | 3929 | ||
| 3927 | const eu_ty = self.air.getRefType(ty_op.ty); | 3930 | const eu_ty = self.air.getRefType(ty_op.ty); |
| ... | @@ -3929,11 +3932,11 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3929,11 +3932,11 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 3929 | const err_ty = eu_ty.errorUnionSet(); | 3932 | const err_ty = eu_ty.errorUnionSet(); |
| 3930 | 3933 | ||
| 3931 | const result: MCValue = result: { | 3934 | const result: MCValue = result: { |
| 3932 | if (!pl_ty.hasRuntimeBitsIgnoreComptime()) break :result try self.resolveInst(ty_op.operand); | 3935 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result try self.resolveInst(ty_op.operand); |
| 3933 | 3936 | ||
| 3934 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, self.target.*)); | 3937 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod)); |
| 3935 | const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*)); | 3938 | const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod)); |
| 3936 | const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*)); | 3939 | const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod)); |
| 3937 | try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef); | 3940 | try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef); |
| 3938 | const operand = try self.resolveInst(ty_op.operand); | 3941 | const operand = try self.resolveInst(ty_op.operand); |
| 3939 | try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand); | 3942 | try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand); |
| ... | @@ -3974,6 +3977,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3974,6 +3977,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 3974 | } | 3977 | } |
| 3975 | 3978 | ||
| 3976 | fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { | 3979 | fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3980 | const mod = self.bin_file.options.module.?; | ||
| 3977 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3981 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3978 | 3982 | ||
| 3979 | const src_ty = self.air.typeOf(ty_op.operand); | 3983 | const src_ty = self.air.typeOf(ty_op.operand); |
| ... | @@ -3994,7 +3998,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3994,7 +3998,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3994 | const dst_lock = self.register_manager.lockReg(dst_reg); | 3998 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 3995 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 3999 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 3996 | 4000 | ||
| 3997 | const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*)); | 4001 | const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod)); |
| 3998 | try self.asmRegisterMemory( | 4002 | try self.asmRegisterMemory( |
| 3999 | .{ ._, .lea }, | 4003 | .{ ._, .lea }, |
| 4000 | registerAlias(dst_reg, dst_abi_size), | 4004 | registerAlias(dst_reg, dst_abi_size), |
| ... | @@ -4041,6 +4045,7 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi | ... | @@ -4041,6 +4045,7 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi |
| 4041 | } | 4045 | } |
| 4042 | 4046 | ||
| 4043 | fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { | 4047 | fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 4048 | const mod = self.bin_file.options.module.?; | ||
| 4044 | const slice_ty = self.air.typeOf(lhs); | 4049 | const slice_ty = self.air.typeOf(lhs); |
| 4045 | const slice_mcv = try self.resolveInst(lhs); | 4050 | const slice_mcv = try self.resolveInst(lhs); |
| 4046 | const slice_mcv_lock: ?RegisterLock = switch (slice_mcv) { | 4051 | const slice_mcv_lock: ?RegisterLock = switch (slice_mcv) { |
| ... | @@ -4050,7 +4055,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { | ... | @@ -4050,7 +4055,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 4050 | defer if (slice_mcv_lock) |lock| self.register_manager.unlockReg(lock); | 4055 | defer if (slice_mcv_lock) |lock| self.register_manager.unlockReg(lock); |
| 4051 | 4056 | ||
| 4052 | const elem_ty = slice_ty.childType(); | 4057 | const elem_ty = slice_ty.childType(); |
| 4053 | const elem_size = elem_ty.abiSize(self.target.*); | 4058 | const elem_size = elem_ty.abiSize(mod); |
| 4054 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 4059 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 4055 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); | 4060 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); |
| 4056 | 4061 | ||
| ... | @@ -4097,6 +4102,7 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4097,6 +4102,7 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4097 | } | 4102 | } |
| 4098 | 4103 | ||
| 4099 | fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | 4104 | fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4105 | const mod = self.bin_file.options.module.?; | ||
| 4100 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 4106 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 4101 | 4107 | ||
| 4102 | const array_ty = self.air.typeOf(bin_op.lhs); | 4108 | const array_ty = self.air.typeOf(bin_op.lhs); |
| ... | @@ -4108,7 +4114,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4108,7 +4114,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4108 | defer if (array_lock) |lock| self.register_manager.unlockReg(lock); | 4114 | defer if (array_lock) |lock| self.register_manager.unlockReg(lock); |
| 4109 | 4115 | ||
| 4110 | const elem_ty = array_ty.childType(); | 4116 | const elem_ty = array_ty.childType(); |
| 4111 | const elem_abi_size = elem_ty.abiSize(self.target.*); | 4117 | const elem_abi_size = elem_ty.abiSize(mod); |
| 4112 | 4118 | ||
| 4113 | const index_ty = self.air.typeOf(bin_op.rhs); | 4119 | const index_ty = self.air.typeOf(bin_op.rhs); |
| 4114 | const index = try self.resolveInst(bin_op.rhs); | 4120 | const index = try self.resolveInst(bin_op.rhs); |
| ... | @@ -4125,7 +4131,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4125,7 +4131,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4125 | const addr_reg = try self.register_manager.allocReg(null, gp); | 4131 | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 4126 | switch (array) { | 4132 | switch (array) { |
| 4127 | .register => { | 4133 | .register => { |
| 4128 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, self.target.*)); | 4134 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod)); |
| 4129 | try self.genSetMem(.{ .frame = frame_index }, 0, array_ty, array); | 4135 | try self.genSetMem(.{ .frame = frame_index }, 0, array_ty, array); |
| 4130 | try self.asmRegisterMemory( | 4136 | try self.asmRegisterMemory( |
| 4131 | .{ ._, .lea }, | 4137 | .{ ._, .lea }, |
| ... | @@ -4162,14 +4168,15 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4162,14 +4168,15 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4162 | } | 4168 | } |
| 4163 | 4169 | ||
| 4164 | fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { | 4170 | fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4171 | const mod = self.bin_file.options.module.?; | ||
| 4165 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 4172 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 4166 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 4173 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 4167 | 4174 | ||
| 4168 | // this is identical to the `airPtrElemPtr` codegen expect here an | 4175 | // this is identical to the `airPtrElemPtr` codegen expect here an |
| 4169 | // additional `mov` is needed at the end to get the actual value | 4176 | // additional `mov` is needed at the end to get the actual value |
| 4170 | 4177 | ||
| 4171 | const elem_ty = ptr_ty.elemType2(); | 4178 | const elem_ty = ptr_ty.elemType2(mod); |
| 4172 | const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | 4179 | const elem_abi_size = @intCast(u32, elem_ty.abiSize(mod)); |
| 4173 | const index_ty = self.air.typeOf(bin_op.rhs); | 4180 | const index_ty = self.air.typeOf(bin_op.rhs); |
| 4174 | const index_mcv = try self.resolveInst(bin_op.rhs); | 4181 | const index_mcv = try self.resolveInst(bin_op.rhs); |
| 4175 | const index_lock = switch (index_mcv) { | 4182 | const index_lock = switch (index_mcv) { |
| ... | @@ -4207,6 +4214,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4207,6 +4214,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4207 | } | 4214 | } |
| 4208 | 4215 | ||
| 4209 | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { | 4216 | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4217 | const mod = self.bin_file.options.module.?; | ||
| 4210 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 4218 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 4211 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 4219 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4212 | 4220 | ||
| ... | @@ -4218,8 +4226,8 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4218,8 +4226,8 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4218 | }; | 4226 | }; |
| 4219 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); | 4227 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); |
| 4220 | 4228 | ||
| 4221 | const elem_ty = ptr_ty.elemType2(); | 4229 | const elem_ty = ptr_ty.elemType2(mod); |
| 4222 | const elem_abi_size = elem_ty.abiSize(self.target.*); | 4230 | const elem_abi_size = elem_ty.abiSize(mod); |
| 4223 | const index_ty = self.air.typeOf(extra.rhs); | 4231 | const index_ty = self.air.typeOf(extra.rhs); |
| 4224 | const index = try self.resolveInst(extra.rhs); | 4232 | const index = try self.resolveInst(extra.rhs); |
| 4225 | const index_lock: ?RegisterLock = switch (index) { | 4233 | const index_lock: ?RegisterLock = switch (index) { |
| ... | @@ -4239,11 +4247,12 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4239,11 +4247,12 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4239 | } | 4247 | } |
| 4240 | 4248 | ||
| 4241 | fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { | 4249 | fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 4250 | const mod = self.bin_file.options.module.?; | ||
| 4242 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 4251 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 4243 | const ptr_union_ty = self.air.typeOf(bin_op.lhs); | 4252 | const ptr_union_ty = self.air.typeOf(bin_op.lhs); |
| 4244 | const union_ty = ptr_union_ty.childType(); | 4253 | const union_ty = ptr_union_ty.childType(); |
| 4245 | const tag_ty = self.air.typeOf(bin_op.rhs); | 4254 | const tag_ty = self.air.typeOf(bin_op.rhs); |
| 4246 | const layout = union_ty.unionGetLayout(self.target.*); | 4255 | const layout = union_ty.unionGetLayout(mod); |
| 4247 | 4256 | ||
| 4248 | if (layout.tag_size == 0) { | 4257 | if (layout.tag_size == 0) { |
| 4249 | return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none }); | 4258 | return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none }); |
| ... | @@ -4284,11 +4293,12 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4284,11 +4293,12 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 4284 | } | 4293 | } |
| 4285 | 4294 | ||
| 4286 | fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { | 4295 | fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 4296 | const mod = self.bin_file.options.module.?; | ||
| 4287 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 4297 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4288 | 4298 | ||
| 4289 | const tag_ty = self.air.typeOfIndex(inst); | 4299 | const tag_ty = self.air.typeOfIndex(inst); |
| 4290 | const union_ty = self.air.typeOf(ty_op.operand); | 4300 | const union_ty = self.air.typeOf(ty_op.operand); |
| 4291 | const layout = union_ty.unionGetLayout(self.target.*); | 4301 | const layout = union_ty.unionGetLayout(mod); |
| 4292 | 4302 | ||
| 4293 | if (layout.tag_size == 0) { | 4303 | if (layout.tag_size == 0) { |
| 4294 | return self.finishAir(inst, .none, .{ ty_op.operand, .none, .none }); | 4304 | return self.finishAir(inst, .none, .{ ty_op.operand, .none, .none }); |
| ... | @@ -4302,7 +4312,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4302,7 +4312,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 4302 | }; | 4312 | }; |
| 4303 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); | 4313 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); |
| 4304 | 4314 | ||
| 4305 | const tag_abi_size = tag_ty.abiSize(self.target.*); | 4315 | const tag_abi_size = tag_ty.abiSize(mod); |
| 4306 | const dst_mcv: MCValue = blk: { | 4316 | const dst_mcv: MCValue = blk: { |
| 4307 | switch (operand) { | 4317 | switch (operand) { |
| 4308 | .load_frame => |frame_addr| { | 4318 | .load_frame => |frame_addr| { |
| ... | @@ -4337,6 +4347,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4337,6 +4347,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 4337 | } | 4347 | } |
| 4338 | 4348 | ||
| 4339 | fn airClz(self: *Self, inst: Air.Inst.Index) !void { | 4349 | fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4350 | const mod = self.bin_file.options.module.?; | ||
| 4340 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 4351 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4341 | const result = result: { | 4352 | const result = result: { |
| 4342 | const dst_ty = self.air.typeOfIndex(inst); | 4353 | const dst_ty = self.air.typeOfIndex(inst); |
| ... | @@ -4358,7 +4369,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4358,7 +4369,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4358 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 4369 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 4359 | defer self.register_manager.unlockReg(dst_lock); | 4370 | defer self.register_manager.unlockReg(dst_lock); |
| 4360 | 4371 | ||
| 4361 | const src_bits = src_ty.bitSize(self.target.*); | 4372 | const src_bits = src_ty.bitSize(mod); |
| 4362 | if (self.hasFeature(.lzcnt)) { | 4373 | if (self.hasFeature(.lzcnt)) { |
| 4363 | if (src_bits <= 8) { | 4374 | if (src_bits <= 8) { |
| 4364 | const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv); | 4375 | const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv); |
| ... | @@ -4405,7 +4416,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4405,7 +4416,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4405 | } | 4416 | } |
| 4406 | 4417 | ||
| 4407 | if (src_bits > 64) | 4418 | if (src_bits > 64) |
| 4408 | return self.fail("TODO airClz of {}", .{src_ty.fmt(self.bin_file.options.module.?)}); | 4419 | return self.fail("TODO airClz of {}", .{src_ty.fmt(mod)}); |
| 4409 | if (math.isPowerOfTwo(src_bits)) { | 4420 | if (math.isPowerOfTwo(src_bits)) { |
| 4410 | const imm_reg = try self.copyToTmpRegister(dst_ty, .{ | 4421 | const imm_reg = try self.copyToTmpRegister(dst_ty, .{ |
| 4411 | .immediate = src_bits ^ (src_bits - 1), | 4422 | .immediate = src_bits ^ (src_bits - 1), |
| ... | @@ -4422,7 +4433,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4422,7 +4433,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4422 | try self.genBinOpMir(.{ ._, .bsr }, Type.u16, dst_mcv, .{ .register = wide_reg }); | 4433 | try self.genBinOpMir(.{ ._, .bsr }, Type.u16, dst_mcv, .{ .register = wide_reg }); |
| 4423 | } else try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv); | 4434 | } else try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv); |
| 4424 | 4435 | ||
| 4425 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); | 4436 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(mod)), 2); |
| 4426 | try self.asmCmovccRegisterRegister( | 4437 | try self.asmCmovccRegisterRegister( |
| 4427 | registerAlias(dst_reg, cmov_abi_size), | 4438 | registerAlias(dst_reg, cmov_abi_size), |
| 4428 | registerAlias(imm_reg, cmov_abi_size), | 4439 | registerAlias(imm_reg, cmov_abi_size), |
| ... | @@ -4449,7 +4460,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4449,7 +4460,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4449 | .{ .register = wide_reg }, | 4460 | .{ .register = wide_reg }, |
| 4450 | ); | 4461 | ); |
| 4451 | 4462 | ||
| 4452 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); | 4463 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(mod)), 2); |
| 4453 | try self.asmCmovccRegisterRegister( | 4464 | try self.asmCmovccRegisterRegister( |
| 4454 | registerAlias(imm_reg, cmov_abi_size), | 4465 | registerAlias(imm_reg, cmov_abi_size), |
| 4455 | registerAlias(dst_reg, cmov_abi_size), | 4466 | registerAlias(dst_reg, cmov_abi_size), |
| ... | @@ -4465,11 +4476,12 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4465,11 +4476,12 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4465 | } | 4476 | } |
| 4466 | 4477 | ||
| 4467 | fn airCtz(self: *Self, inst: Air.Inst.Index) !void { | 4478 | fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4479 | const mod = self.bin_file.options.module.?; | ||
| 4468 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 4480 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4469 | const result = result: { | 4481 | const result = result: { |
| 4470 | const dst_ty = self.air.typeOfIndex(inst); | 4482 | const dst_ty = self.air.typeOfIndex(inst); |
| 4471 | const src_ty = self.air.typeOf(ty_op.operand); | 4483 | const src_ty = self.air.typeOf(ty_op.operand); |
| 4472 | const src_bits = src_ty.bitSize(self.target.*); | 4484 | const src_bits = src_ty.bitSize(mod); |
| 4473 | 4485 | ||
| 4474 | const src_mcv = try self.resolveInst(ty_op.operand); | 4486 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 4475 | const mat_src_mcv = switch (src_mcv) { | 4487 | const mat_src_mcv = switch (src_mcv) { |
| ... | @@ -4548,7 +4560,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4548,7 +4560,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4548 | try self.genBinOpMir(.{ ._, .bsf }, Type.u16, dst_mcv, .{ .register = wide_reg }); | 4560 | try self.genBinOpMir(.{ ._, .bsf }, Type.u16, dst_mcv, .{ .register = wide_reg }); |
| 4549 | } else try self.genBinOpMir(.{ ._, .bsf }, src_ty, dst_mcv, mat_src_mcv); | 4561 | } else try self.genBinOpMir(.{ ._, .bsf }, src_ty, dst_mcv, mat_src_mcv); |
| 4550 | 4562 | ||
| 4551 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); | 4563 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(mod)), 2); |
| 4552 | try self.asmCmovccRegisterRegister( | 4564 | try self.asmCmovccRegisterRegister( |
| 4553 | registerAlias(dst_reg, cmov_abi_size), | 4565 | registerAlias(dst_reg, cmov_abi_size), |
| 4554 | registerAlias(width_reg, cmov_abi_size), | 4566 | registerAlias(width_reg, cmov_abi_size), |
| ... | @@ -4560,10 +4572,11 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4560,10 +4572,11 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4560 | } | 4572 | } |
| 4561 | 4573 | ||
| 4562 | fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { | 4574 | fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 4575 | const mod = self.bin_file.options.module.?; | ||
| 4563 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 4576 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4564 | const result: MCValue = result: { | 4577 | const result: MCValue = result: { |
| 4565 | const src_ty = self.air.typeOf(ty_op.operand); | 4578 | const src_ty = self.air.typeOf(ty_op.operand); |
| 4566 | const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*)); | 4579 | const src_abi_size = @intCast(u32, src_ty.abiSize(mod)); |
| 4567 | const src_mcv = try self.resolveInst(ty_op.operand); | 4580 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 4568 | 4581 | ||
| 4569 | if (self.hasFeature(.popcnt)) { | 4582 | if (self.hasFeature(.popcnt)) { |
| ... | @@ -4729,6 +4742,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m | ... | @@ -4729,6 +4742,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m |
| 4729 | } | 4742 | } |
| 4730 | 4743 | ||
| 4731 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { | 4744 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 4745 | const mod = self.bin_file.options.module.?; | ||
| 4732 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 4746 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4733 | 4747 | ||
| 4734 | const src_ty = self.air.typeOf(ty_op.operand); | 4748 | const src_ty = self.air.typeOf(ty_op.operand); |
| ... | @@ -4738,7 +4752,7 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4738,7 +4752,7 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 4738 | switch (self.regExtraBits(src_ty)) { | 4752 | switch (self.regExtraBits(src_ty)) { |
| 4739 | 0 => {}, | 4753 | 0 => {}, |
| 4740 | else => |extra| try self.genBinOpMir( | 4754 | else => |extra| try self.genBinOpMir( |
| 4741 | if (src_ty.isSignedInt()) .{ ._r, .sa } else .{ ._r, .sh }, | 4755 | if (src_ty.isSignedInt(mod)) .{ ._r, .sa } else .{ ._r, .sh }, |
| 4742 | src_ty, | 4756 | src_ty, |
| 4743 | dst_mcv, | 4757 | dst_mcv, |
| 4744 | .{ .immediate = extra }, | 4758 | .{ .immediate = extra }, |
| ... | @@ -4749,10 +4763,11 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4749,10 +4763,11 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 4749 | } | 4763 | } |
| 4750 | 4764 | ||
| 4751 | fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { | 4765 | fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 4766 | const mod = self.bin_file.options.module.?; | ||
| 4752 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 4767 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4753 | 4768 | ||
| 4754 | const src_ty = self.air.typeOf(ty_op.operand); | 4769 | const src_ty = self.air.typeOf(ty_op.operand); |
| 4755 | const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*)); | 4770 | const src_abi_size = @intCast(u32, src_ty.abiSize(mod)); |
| 4756 | const src_mcv = try self.resolveInst(ty_op.operand); | 4771 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 4757 | 4772 | ||
| 4758 | const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, false); | 4773 | const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, false); |
| ... | @@ -4847,7 +4862,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4847,7 +4862,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 4847 | switch (self.regExtraBits(src_ty)) { | 4862 | switch (self.regExtraBits(src_ty)) { |
| 4848 | 0 => {}, | 4863 | 0 => {}, |
| 4849 | else => |extra| try self.genBinOpMir( | 4864 | else => |extra| try self.genBinOpMir( |
| 4850 | if (src_ty.isSignedInt()) .{ ._r, .sa } else .{ ._r, .sh }, | 4865 | if (src_ty.isSignedInt(mod)) .{ ._r, .sa } else .{ ._r, .sh }, |
| 4851 | src_ty, | 4866 | src_ty, |
| 4852 | dst_mcv, | 4867 | dst_mcv, |
| 4853 | .{ .immediate = extra }, | 4868 | .{ .immediate = extra }, |
| ... | @@ -4858,17 +4873,18 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4858,17 +4873,18 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 4858 | } | 4873 | } |
| 4859 | 4874 | ||
| 4860 | fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { | 4875 | fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4876 | const mod = self.bin_file.options.module.?; | ||
| 4861 | const tag = self.air.instructions.items(.tag)[inst]; | 4877 | const tag = self.air.instructions.items(.tag)[inst]; |
| 4862 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 4878 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4863 | const ty = self.air.typeOf(un_op); | 4879 | const ty = self.air.typeOf(un_op); |
| 4864 | const abi_size: u32 = switch (ty.abiSize(self.target.*)) { | 4880 | const abi_size: u32 = switch (ty.abiSize(mod)) { |
| 4865 | 1...16 => 16, | 4881 | 1...16 => 16, |
| 4866 | 17...32 => 32, | 4882 | 17...32 => 32, |
| 4867 | else => return self.fail("TODO implement airFloatSign for {}", .{ | 4883 | else => return self.fail("TODO implement airFloatSign for {}", .{ |
| 4868 | ty.fmt(self.bin_file.options.module.?), | 4884 | ty.fmt(self.bin_file.options.module.?), |
| 4869 | }), | 4885 | }), |
| 4870 | }; | 4886 | }; |
| 4871 | const scalar_bits = ty.scalarType().floatBits(self.target.*); | 4887 | const scalar_bits = ty.scalarType(mod).floatBits(self.target.*); |
| 4872 | 4888 | ||
| 4873 | const src_mcv = try self.resolveInst(un_op); | 4889 | const src_mcv = try self.resolveInst(un_op); |
| 4874 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; | 4890 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| ... | @@ -4905,21 +4921,17 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4905,21 +4921,17 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4905 | var stack align(@alignOf(ExpectedContents)) = | 4921 | var stack align(@alignOf(ExpectedContents)) = |
| 4906 | std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator()); | 4922 | std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator()); |
| 4907 | 4923 | ||
| 4908 | var int_pl = Type.Payload.Bits{ | ||
| 4909 | .base = .{ .tag = .int_signed }, | ||
| 4910 | .data = scalar_bits, | ||
| 4911 | }; | ||
| 4912 | var vec_pl = Type.Payload.Array{ | 4924 | var vec_pl = Type.Payload.Array{ |
| 4913 | .base = .{ .tag = .vector }, | 4925 | .base = .{ .tag = .vector }, |
| 4914 | .data = .{ | 4926 | .data = .{ |
| 4915 | .len = @divExact(abi_size * 8, scalar_bits), | 4927 | .len = @divExact(abi_size * 8, scalar_bits), |
| 4916 | .elem_type = Type.initPayload(&int_pl.base), | 4928 | .elem_type = try mod.intType(.signed, scalar_bits), |
| 4917 | }, | 4929 | }, |
| 4918 | }; | 4930 | }; |
| 4919 | const vec_ty = Type.initPayload(&vec_pl.base); | 4931 | const vec_ty = Type.initPayload(&vec_pl.base); |
| 4920 | const sign_val = switch (tag) { | 4932 | const sign_val = switch (tag) { |
| 4921 | .neg => try vec_ty.minInt(stack.get(), self.target.*), | 4933 | .neg => try vec_ty.minInt(stack.get(), mod), |
| 4922 | .fabs => try vec_ty.maxInt(stack.get(), self.target.*), | 4934 | .fabs => try vec_ty.maxInt(stack.get(), mod), |
| 4923 | else => unreachable, | 4935 | else => unreachable, |
| 4924 | }; | 4936 | }; |
| 4925 | 4937 | ||
| ... | @@ -5008,17 +5020,18 @@ fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void { | ... | @@ -5008,17 +5020,18 @@ fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void { |
| 5008 | } | 5020 | } |
| 5009 | 5021 | ||
| 5010 | fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4) !void { | 5022 | fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4) !void { |
| 5023 | const mod = self.bin_file.options.module.?; | ||
| 5011 | if (!self.hasFeature(.sse4_1)) | 5024 | if (!self.hasFeature(.sse4_1)) |
| 5012 | return self.fail("TODO implement genRound without sse4_1 feature", .{}); | 5025 | return self.fail("TODO implement genRound without sse4_1 feature", .{}); |
| 5013 | 5026 | ||
| 5014 | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag()) { | 5027 | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) { |
| 5015 | .Float => switch (ty.floatBits(self.target.*)) { | 5028 | .Float => switch (ty.floatBits(self.target.*)) { |
| 5016 | 32 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round }, | 5029 | 32 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round }, |
| 5017 | 64 => if (self.hasFeature(.avx)) .{ .v_sd, .round } else .{ ._sd, .round }, | 5030 | 64 => if (self.hasFeature(.avx)) .{ .v_sd, .round } else .{ ._sd, .round }, |
| 5018 | 16, 80, 128 => null, | 5031 | 16, 80, 128 => null, |
| 5019 | else => unreachable, | 5032 | else => unreachable, |
| 5020 | }, | 5033 | }, |
| 5021 | .Vector => switch (ty.childType().zigTypeTag()) { | 5034 | .Vector => switch (ty.childType().zigTypeTag(mod)) { |
| 5022 | .Float => switch (ty.childType().floatBits(self.target.*)) { | 5035 | .Float => switch (ty.childType().floatBits(self.target.*)) { |
| 5023 | 32 => switch (ty.vectorLen()) { | 5036 | 32 => switch (ty.vectorLen()) { |
| 5024 | 1 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round }, | 5037 | 1 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round }, |
| ... | @@ -5041,7 +5054,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4 | ... | @@ -5041,7 +5054,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4 |
| 5041 | })) |tag| tag else return self.fail("TODO implement genRound for {}", .{ | 5054 | })) |tag| tag else return self.fail("TODO implement genRound for {}", .{ |
| 5042 | ty.fmt(self.bin_file.options.module.?), | 5055 | ty.fmt(self.bin_file.options.module.?), |
| 5043 | }); | 5056 | }); |
| 5044 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 5057 | const abi_size = @intCast(u32, ty.abiSize(mod)); |
| 5045 | const dst_alias = registerAlias(dst_reg, abi_size); | 5058 | const dst_alias = registerAlias(dst_reg, abi_size); |
| 5046 | switch (mir_tag[0]) { | 5059 | switch (mir_tag[0]) { |
| 5047 | .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate( | 5060 | .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate( |
| ... | @@ -5078,9 +5091,10 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4 | ... | @@ -5078,9 +5091,10 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4 |
| 5078 | } | 5091 | } |
| 5079 | 5092 | ||
| 5080 | fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | 5093 | fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5094 | const mod = self.bin_file.options.module.?; | ||
| 5081 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 5095 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 5082 | const ty = self.air.typeOf(un_op); | 5096 | const ty = self.air.typeOf(un_op); |
| 5083 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 5097 | const abi_size = @intCast(u32, ty.abiSize(mod)); |
| 5084 | 5098 | ||
| 5085 | const src_mcv = try self.resolveInst(un_op); | 5099 | const src_mcv = try self.resolveInst(un_op); |
| 5086 | const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv)) | 5100 | const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv)) |
| ... | @@ -5092,7 +5106,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5092,7 +5106,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5092 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 5106 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 5093 | 5107 | ||
| 5094 | const result: MCValue = result: { | 5108 | const result: MCValue = result: { |
| 5095 | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag()) { | 5109 | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) { |
| 5096 | .Float => switch (ty.floatBits(self.target.*)) { | 5110 | .Float => switch (ty.floatBits(self.target.*)) { |
| 5097 | 16 => if (self.hasFeature(.f16c)) { | 5111 | 16 => if (self.hasFeature(.f16c)) { |
| 5098 | const mat_src_reg = if (src_mcv.isRegister()) | 5112 | const mat_src_reg = if (src_mcv.isRegister()) |
| ... | @@ -5114,7 +5128,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5114,7 +5128,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5114 | 80, 128 => null, | 5128 | 80, 128 => null, |
| 5115 | else => unreachable, | 5129 | else => unreachable, |
| 5116 | }, | 5130 | }, |
| 5117 | .Vector => switch (ty.childType().zigTypeTag()) { | 5131 | .Vector => switch (ty.childType().zigTypeTag(mod)) { |
| 5118 | .Float => switch (ty.childType().floatBits(self.target.*)) { | 5132 | .Float => switch (ty.childType().floatBits(self.target.*)) { |
| 5119 | 16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen()) { | 5133 | 16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen()) { |
| 5120 | 1 => { | 5134 | 1 => { |
| ... | @@ -5186,7 +5200,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5186,7 +5200,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5186 | }, | 5200 | }, |
| 5187 | else => unreachable, | 5201 | else => unreachable, |
| 5188 | })) |tag| tag else return self.fail("TODO implement airSqrt for {}", .{ | 5202 | })) |tag| tag else return self.fail("TODO implement airSqrt for {}", .{ |
| 5189 | ty.fmt(self.bin_file.options.module.?), | 5203 | ty.fmt(mod), |
| 5190 | }); | 5204 | }); |
| 5191 | switch (mir_tag[0]) { | 5205 | switch (mir_tag[0]) { |
| 5192 | .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory( | 5206 | .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory( |
| ... | @@ -5274,10 +5288,11 @@ fn reuseOperandAdvanced( | ... | @@ -5274,10 +5288,11 @@ fn reuseOperandAdvanced( |
| 5274 | } | 5288 | } |
| 5275 | 5289 | ||
| 5276 | fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void { | 5290 | fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void { |
| 5291 | const mod = self.bin_file.options.module.?; | ||
| 5277 | const ptr_info = ptr_ty.ptrInfo().data; | 5292 | const ptr_info = ptr_ty.ptrInfo().data; |
| 5278 | 5293 | ||
| 5279 | const val_ty = ptr_info.pointee_type; | 5294 | const val_ty = ptr_info.pointee_type; |
| 5280 | const val_abi_size = @intCast(u32, val_ty.abiSize(self.target.*)); | 5295 | const val_abi_size = @intCast(u32, val_ty.abiSize(mod)); |
| 5281 | const limb_abi_size: u32 = @min(val_abi_size, 8); | 5296 | const limb_abi_size: u32 = @min(val_abi_size, 8); |
| 5282 | const limb_abi_bits = limb_abi_size * 8; | 5297 | const limb_abi_bits = limb_abi_size * 8; |
| 5283 | const val_byte_off = @intCast(i32, ptr_info.bit_offset / limb_abi_bits * limb_abi_size); | 5298 | const val_byte_off = @intCast(i32, ptr_info.bit_offset / limb_abi_bits * limb_abi_size); |
| ... | @@ -5382,20 +5397,21 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro | ... | @@ -5382,20 +5397,21 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro |
| 5382 | } | 5397 | } |
| 5383 | 5398 | ||
| 5384 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | 5399 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 5400 | const mod = self.bin_file.options.module.?; | ||
| 5385 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 5401 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5386 | const elem_ty = self.air.typeOfIndex(inst); | 5402 | const elem_ty = self.air.typeOfIndex(inst); |
| 5387 | const result: MCValue = result: { | 5403 | const result: MCValue = result: { |
| 5388 | if (!elem_ty.hasRuntimeBitsIgnoreComptime()) break :result .none; | 5404 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; |
| 5389 | 5405 | ||
| 5390 | try self.spillRegisters(&.{ .rdi, .rsi, .rcx }); | 5406 | try self.spillRegisters(&.{ .rdi, .rsi, .rcx }); |
| 5391 | const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx }); | 5407 | const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx }); |
| 5392 | defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); | 5408 | defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); |
| 5393 | 5409 | ||
| 5394 | const ptr_ty = self.air.typeOf(ty_op.operand); | 5410 | const ptr_ty = self.air.typeOf(ty_op.operand); |
| 5395 | const elem_size = elem_ty.abiSize(self.target.*); | 5411 | const elem_size = elem_ty.abiSize(mod); |
| 5396 | 5412 | ||
| 5397 | const elem_rc = regClassForType(elem_ty); | 5413 | const elem_rc = regClassForType(elem_ty, mod); |
| 5398 | const ptr_rc = regClassForType(ptr_ty); | 5414 | const ptr_rc = regClassForType(ptr_ty, mod); |
| 5399 | 5415 | ||
| 5400 | const ptr_mcv = try self.resolveInst(ty_op.operand); | 5416 | const ptr_mcv = try self.resolveInst(ty_op.operand); |
| 5401 | const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and | 5417 | const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and |
| ... | @@ -5416,13 +5432,14 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5416,13 +5432,14 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 5416 | } | 5432 | } |
| 5417 | 5433 | ||
| 5418 | fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void { | 5434 | fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void { |
| 5435 | const mod = self.bin_file.options.module.?; | ||
| 5419 | const ptr_info = ptr_ty.ptrInfo().data; | 5436 | const ptr_info = ptr_ty.ptrInfo().data; |
| 5420 | const src_ty = ptr_ty.childType(); | 5437 | const src_ty = ptr_ty.childType(); |
| 5421 | 5438 | ||
| 5422 | const limb_abi_size: u16 = @min(ptr_info.host_size, 8); | 5439 | const limb_abi_size: u16 = @min(ptr_info.host_size, 8); |
| 5423 | const limb_abi_bits = limb_abi_size * 8; | 5440 | const limb_abi_bits = limb_abi_size * 8; |
| 5424 | 5441 | ||
| 5425 | const src_bit_size = src_ty.bitSize(self.target.*); | 5442 | const src_bit_size = src_ty.bitSize(mod); |
| 5426 | const src_byte_off = @intCast(i32, ptr_info.bit_offset / limb_abi_bits * limb_abi_size); | 5443 | const src_byte_off = @intCast(i32, ptr_info.bit_offset / limb_abi_bits * limb_abi_size); |
| 5427 | const src_bit_off = ptr_info.bit_offset % limb_abi_bits; | 5444 | const src_bit_off = ptr_info.bit_offset % limb_abi_bits; |
| 5428 | 5445 | ||
| ... | @@ -5555,14 +5572,15 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { | ... | @@ -5555,14 +5572,15 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { |
| 5555 | } | 5572 | } |
| 5556 | 5573 | ||
| 5557 | fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { | 5574 | fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { |
| 5575 | const mod = self.bin_file.options.module.?; | ||
| 5558 | const ptr_field_ty = self.air.typeOfIndex(inst); | 5576 | const ptr_field_ty = self.air.typeOfIndex(inst); |
| 5559 | const ptr_container_ty = self.air.typeOf(operand); | 5577 | const ptr_container_ty = self.air.typeOf(operand); |
| 5560 | const container_ty = ptr_container_ty.childType(); | 5578 | const container_ty = ptr_container_ty.childType(); |
| 5561 | const field_offset = @intCast(i32, switch (container_ty.containerLayout()) { | 5579 | const field_offset = @intCast(i32, switch (container_ty.containerLayout()) { |
| 5562 | .Auto, .Extern => container_ty.structFieldOffset(index, self.target.*), | 5580 | .Auto, .Extern => container_ty.structFieldOffset(index, mod), |
| 5563 | .Packed => if (container_ty.zigTypeTag() == .Struct and | 5581 | .Packed => if (container_ty.zigTypeTag(mod) == .Struct and |
| 5564 | ptr_field_ty.ptrInfo().data.host_size == 0) | 5582 | ptr_field_ty.ptrInfo().data.host_size == 0) |
| 5565 | container_ty.packedStructFieldByteOffset(index, self.target.*) | 5583 | container_ty.packedStructFieldByteOffset(index, mod) |
| 5566 | else | 5584 | else |
| 5567 | 0, | 5585 | 0, |
| 5568 | }); | 5586 | }); |
| ... | @@ -5577,6 +5595,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 | ... | @@ -5577,6 +5595,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 |
| 5577 | } | 5595 | } |
| 5578 | 5596 | ||
| 5579 | fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | 5597 | fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5598 | const mod = self.bin_file.options.module.?; | ||
| 5580 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 5599 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 5581 | const extra = self.air.extraData(Air.StructField, ty_pl.payload).data; | 5600 | const extra = self.air.extraData(Air.StructField, ty_pl.payload).data; |
| 5582 | const result: MCValue = result: { | 5601 | const result: MCValue = result: { |
| ... | @@ -5584,17 +5603,17 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5584,17 +5603,17 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5584 | const index = extra.field_index; | 5603 | const index = extra.field_index; |
| 5585 | 5604 | ||
| 5586 | const container_ty = self.air.typeOf(operand); | 5605 | const container_ty = self.air.typeOf(operand); |
| 5587 | const container_rc = regClassForType(container_ty); | 5606 | const container_rc = regClassForType(container_ty, mod); |
| 5588 | const field_ty = container_ty.structFieldType(index); | 5607 | const field_ty = container_ty.structFieldType(index); |
| 5589 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) break :result .none; | 5608 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; |
| 5590 | const field_rc = regClassForType(field_ty); | 5609 | const field_rc = regClassForType(field_ty, mod); |
| 5591 | const field_is_gp = field_rc.supersetOf(gp); | 5610 | const field_is_gp = field_rc.supersetOf(gp); |
| 5592 | 5611 | ||
| 5593 | const src_mcv = try self.resolveInst(operand); | 5612 | const src_mcv = try self.resolveInst(operand); |
| 5594 | const field_off = switch (container_ty.containerLayout()) { | 5613 | const field_off = switch (container_ty.containerLayout()) { |
| 5595 | .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, self.target.*) * 8), | 5614 | .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, mod) * 8), |
| 5596 | .Packed => if (container_ty.castTag(.@"struct")) |struct_obj| | 5615 | .Packed => if (container_ty.castTag(.@"struct")) |struct_obj| |
| 5597 | struct_obj.data.packedFieldBitOffset(self.target.*, index) | 5616 | struct_obj.data.packedFieldBitOffset(mod, index) |
| 5598 | else | 5617 | else |
| 5599 | 0, | 5618 | 0, |
| 5600 | }; | 5619 | }; |
| ... | @@ -5611,7 +5630,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5611,7 +5630,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5611 | break :result dst_mcv; | 5630 | break :result dst_mcv; |
| 5612 | } | 5631 | } |
| 5613 | 5632 | ||
| 5614 | const field_abi_size = @intCast(u32, field_ty.abiSize(self.target.*)); | 5633 | const field_abi_size = @intCast(u32, field_ty.abiSize(mod)); |
| 5615 | const limb_abi_size: u32 = @min(field_abi_size, 8); | 5634 | const limb_abi_size: u32 = @min(field_abi_size, 8); |
| 5616 | const limb_abi_bits = limb_abi_size * 8; | 5635 | const limb_abi_bits = limb_abi_size * 8; |
| 5617 | const field_byte_off = @intCast(i32, field_off / limb_abi_bits * limb_abi_size); | 5636 | const field_byte_off = @intCast(i32, field_off / limb_abi_bits * limb_abi_size); |
| ... | @@ -5733,12 +5752,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5733,12 +5752,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5733 | } | 5752 | } |
| 5734 | 5753 | ||
| 5735 | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | 5754 | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 5755 | const mod = self.bin_file.options.module.?; | ||
| 5736 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 5756 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 5737 | const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | 5757 | const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 5738 | 5758 | ||
| 5739 | const inst_ty = self.air.typeOfIndex(inst); | 5759 | const inst_ty = self.air.typeOfIndex(inst); |
| 5740 | const parent_ty = inst_ty.childType(); | 5760 | const parent_ty = inst_ty.childType(); |
| 5741 | const field_offset = @intCast(i32, parent_ty.structFieldOffset(extra.field_index, self.target.*)); | 5761 | const field_offset = @intCast(i32, parent_ty.structFieldOffset(extra.field_index, mod)); |
| 5742 | 5762 | ||
| 5743 | const src_mcv = try self.resolveInst(extra.field_ptr); | 5763 | const src_mcv = try self.resolveInst(extra.field_ptr); |
| 5744 | const dst_mcv = if (src_mcv.isRegisterOffset() and | 5764 | const dst_mcv = if (src_mcv.isRegisterOffset() and |
| ... | @@ -5751,9 +5771,10 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5751,9 +5771,10 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 5751 | } | 5771 | } |
| 5752 | 5772 | ||
| 5753 | fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue { | 5773 | fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue { |
| 5774 | const mod = self.bin_file.options.module.?; | ||
| 5754 | const src_ty = self.air.typeOf(src_air); | 5775 | const src_ty = self.air.typeOf(src_air); |
| 5755 | const src_mcv = try self.resolveInst(src_air); | 5776 | const src_mcv = try self.resolveInst(src_air); |
| 5756 | if (src_ty.zigTypeTag() == .Vector) { | 5777 | if (src_ty.zigTypeTag(mod) == .Vector) { |
| 5757 | return self.fail("TODO implement genUnOp for {}", .{src_ty.fmt(self.bin_file.options.module.?)}); | 5778 | return self.fail("TODO implement genUnOp for {}", .{src_ty.fmt(self.bin_file.options.module.?)}); |
| 5758 | } | 5779 | } |
| 5759 | 5780 | ||
| ... | @@ -5786,28 +5807,22 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: | ... | @@ -5786,28 +5807,22 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: |
| 5786 | 5807 | ||
| 5787 | switch (tag) { | 5808 | switch (tag) { |
| 5788 | .not => { | 5809 | .not => { |
| 5789 | const limb_abi_size = @intCast(u16, @min(src_ty.abiSize(self.target.*), 8)); | 5810 | const limb_abi_size = @intCast(u16, @min(src_ty.abiSize(mod), 8)); |
| 5790 | const int_info = if (src_ty.tag() == .bool) | 5811 | const int_info = if (src_ty.tag() == .bool) |
| 5791 | std.builtin.Type.Int{ .signedness = .unsigned, .bits = 1 } | 5812 | std.builtin.Type.Int{ .signedness = .unsigned, .bits = 1 } |
| 5792 | else | 5813 | else |
| 5793 | src_ty.intInfo(self.target.*); | 5814 | src_ty.intInfo(mod); |
| 5794 | var byte_off: i32 = 0; | 5815 | var byte_off: i32 = 0; |
| 5795 | while (byte_off * 8 < int_info.bits) : (byte_off += limb_abi_size) { | 5816 | while (byte_off * 8 < int_info.bits) : (byte_off += limb_abi_size) { |
| 5796 | var limb_pl = Type.Payload.Bits{ | 5817 | const limb_bits = @intCast(u16, @min(int_info.bits - byte_off * 8, limb_abi_size * 8)); |
| 5797 | .base = .{ .tag = switch (int_info.signedness) { | 5818 | const limb_ty = try mod.intType(int_info.signedness, limb_bits); |
| 5798 | .signed => .int_signed, | ||
| 5799 | .unsigned => .int_unsigned, | ||
| 5800 | } }, | ||
| 5801 | .data = @intCast(u16, @min(int_info.bits - byte_off * 8, limb_abi_size * 8)), | ||
| 5802 | }; | ||
| 5803 | const limb_ty = Type.initPayload(&limb_pl.base); | ||
| 5804 | const limb_mcv = switch (byte_off) { | 5819 | const limb_mcv = switch (byte_off) { |
| 5805 | 0 => dst_mcv, | 5820 | 0 => dst_mcv, |
| 5806 | else => dst_mcv.address().offset(byte_off).deref(), | 5821 | else => dst_mcv.address().offset(byte_off).deref(), |
| 5807 | }; | 5822 | }; |
| 5808 | 5823 | ||
| 5809 | if (limb_pl.base.tag == .int_unsigned and self.regExtraBits(limb_ty) > 0) { | 5824 | if (int_info.signedness == .unsigned and self.regExtraBits(limb_ty) > 0) { |
| 5810 | const mask = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - limb_pl.data); | 5825 | const mask = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - limb_bits); |
| 5811 | try self.genBinOpMir(.{ ._, .xor }, limb_ty, limb_mcv, .{ .immediate = mask }); | 5826 | try self.genBinOpMir(.{ ._, .xor }, limb_ty, limb_mcv, .{ .immediate = mask }); |
| 5812 | } else try self.genUnOpMir(.{ ._, .not }, limb_ty, limb_mcv); | 5827 | } else try self.genUnOpMir(.{ ._, .not }, limb_ty, limb_mcv); |
| 5813 | } | 5828 | } |
| ... | @@ -5819,7 +5834,8 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: | ... | @@ -5819,7 +5834,8 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: |
| 5819 | } | 5834 | } |
| 5820 | 5835 | ||
| 5821 | fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void { | 5836 | fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void { |
| 5822 | const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*)); | 5837 | const mod = self.bin_file.options.module.?; |
| 5838 | const abi_size = @intCast(u32, dst_ty.abiSize(mod)); | ||
| 5823 | if (abi_size > 8) return self.fail("TODO implement {} for {}", .{ | 5839 | if (abi_size > 8) return self.fail("TODO implement {} for {}", .{ |
| 5824 | mir_tag, | 5840 | mir_tag, |
| 5825 | dst_ty.fmt(self.bin_file.options.module.?), | 5841 | dst_ty.fmt(self.bin_file.options.module.?), |
| ... | @@ -5866,6 +5882,7 @@ fn genShiftBinOpMir( | ... | @@ -5866,6 +5882,7 @@ fn genShiftBinOpMir( |
| 5866 | lhs_mcv: MCValue, | 5882 | lhs_mcv: MCValue, |
| 5867 | shift_mcv: MCValue, | 5883 | shift_mcv: MCValue, |
| 5868 | ) !void { | 5884 | ) !void { |
| 5885 | const mod = self.bin_file.options.module.?; | ||
| 5869 | const rhs_mcv: MCValue = rhs: { | 5886 | const rhs_mcv: MCValue = rhs: { |
| 5870 | switch (shift_mcv) { | 5887 | switch (shift_mcv) { |
| 5871 | .immediate => |imm| switch (imm) { | 5888 | .immediate => |imm| switch (imm) { |
| ... | @@ -5880,7 +5897,7 @@ fn genShiftBinOpMir( | ... | @@ -5880,7 +5897,7 @@ fn genShiftBinOpMir( |
| 5880 | break :rhs .{ .register = .rcx }; | 5897 | break :rhs .{ .register = .rcx }; |
| 5881 | }; | 5898 | }; |
| 5882 | 5899 | ||
| 5883 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 5900 | const abi_size = @intCast(u32, ty.abiSize(mod)); |
| 5884 | if (abi_size <= 8) { | 5901 | if (abi_size <= 8) { |
| 5885 | switch (lhs_mcv) { | 5902 | switch (lhs_mcv) { |
| 5886 | .register => |lhs_reg| switch (rhs_mcv) { | 5903 | .register => |lhs_reg| switch (rhs_mcv) { |
| ... | @@ -6099,13 +6116,14 @@ fn genShiftBinOp( | ... | @@ -6099,13 +6116,14 @@ fn genShiftBinOp( |
| 6099 | lhs_ty: Type, | 6116 | lhs_ty: Type, |
| 6100 | rhs_ty: Type, | 6117 | rhs_ty: Type, |
| 6101 | ) !MCValue { | 6118 | ) !MCValue { |
| 6102 | if (lhs_ty.zigTypeTag() == .Vector) { | 6119 | const mod = self.bin_file.options.module.?; |
| 6120 | if (lhs_ty.zigTypeTag(mod) == .Vector) { | ||
| 6103 | return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()}); | 6121 | return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()}); |
| 6104 | } | 6122 | } |
| 6105 | 6123 | ||
| 6106 | assert(rhs_ty.abiSize(self.target.*) == 1); | 6124 | assert(rhs_ty.abiSize(mod) == 1); |
| 6107 | 6125 | ||
| 6108 | const lhs_abi_size = lhs_ty.abiSize(self.target.*); | 6126 | const lhs_abi_size = lhs_ty.abiSize(mod); |
| 6109 | if (lhs_abi_size > 16) { | 6127 | if (lhs_abi_size > 16) { |
| 6110 | return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()}); | 6128 | return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()}); |
| 6111 | } | 6129 | } |
| ... | @@ -6136,7 +6154,7 @@ fn genShiftBinOp( | ... | @@ -6136,7 +6154,7 @@ fn genShiftBinOp( |
| 6136 | break :dst dst_mcv; | 6154 | break :dst dst_mcv; |
| 6137 | }; | 6155 | }; |
| 6138 | 6156 | ||
| 6139 | const signedness = lhs_ty.intInfo(self.target.*).signedness; | 6157 | const signedness = lhs_ty.intInfo(mod).signedness; |
| 6140 | try self.genShiftBinOpMir(switch (air_tag) { | 6158 | try self.genShiftBinOpMir(switch (air_tag) { |
| 6141 | .shl, .shl_exact => switch (signedness) { | 6159 | .shl, .shl_exact => switch (signedness) { |
| 6142 | .signed => .{ ._l, .sa }, | 6160 | .signed => .{ ._l, .sa }, |
| ... | @@ -6163,11 +6181,12 @@ fn genMulDivBinOp( | ... | @@ -6163,11 +6181,12 @@ fn genMulDivBinOp( |
| 6163 | lhs: MCValue, | 6181 | lhs: MCValue, |
| 6164 | rhs: MCValue, | 6182 | rhs: MCValue, |
| 6165 | ) !MCValue { | 6183 | ) !MCValue { |
| 6166 | if (dst_ty.zigTypeTag() == .Vector or dst_ty.zigTypeTag() == .Float) { | 6184 | const mod = self.bin_file.options.module.?; |
| 6185 | if (dst_ty.zigTypeTag(mod) == .Vector or dst_ty.zigTypeTag(mod) == .Float) { | ||
| 6167 | return self.fail("TODO implement genMulDivBinOp for {}", .{dst_ty.fmtDebug()}); | 6186 | return self.fail("TODO implement genMulDivBinOp for {}", .{dst_ty.fmtDebug()}); |
| 6168 | } | 6187 | } |
| 6169 | const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*)); | 6188 | const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod)); |
| 6170 | const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*)); | 6189 | const src_abi_size = @intCast(u32, src_ty.abiSize(mod)); |
| 6171 | if (switch (tag) { | 6190 | if (switch (tag) { |
| 6172 | else => unreachable, | 6191 | else => unreachable, |
| 6173 | .mul, .mulwrap => dst_abi_size != src_abi_size and dst_abi_size != src_abi_size * 2, | 6192 | .mul, .mulwrap => dst_abi_size != src_abi_size and dst_abi_size != src_abi_size * 2, |
| ... | @@ -6184,7 +6203,7 @@ fn genMulDivBinOp( | ... | @@ -6184,7 +6203,7 @@ fn genMulDivBinOp( |
| 6184 | const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx }); | 6203 | const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx }); |
| 6185 | defer for (reg_locks) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock); | 6204 | defer for (reg_locks) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock); |
| 6186 | 6205 | ||
| 6187 | const signedness = ty.intInfo(self.target.*).signedness; | 6206 | const signedness = ty.intInfo(mod).signedness; |
| 6188 | switch (tag) { | 6207 | switch (tag) { |
| 6189 | .mul, | 6208 | .mul, |
| 6190 | .mulwrap, | 6209 | .mulwrap, |
| ... | @@ -6338,13 +6357,14 @@ fn genBinOp( | ... | @@ -6338,13 +6357,14 @@ fn genBinOp( |
| 6338 | lhs_air: Air.Inst.Ref, | 6357 | lhs_air: Air.Inst.Ref, |
| 6339 | rhs_air: Air.Inst.Ref, | 6358 | rhs_air: Air.Inst.Ref, |
| 6340 | ) !MCValue { | 6359 | ) !MCValue { |
| 6360 | const mod = self.bin_file.options.module.?; | ||
| 6341 | const lhs_ty = self.air.typeOf(lhs_air); | 6361 | const lhs_ty = self.air.typeOf(lhs_air); |
| 6342 | const rhs_ty = self.air.typeOf(rhs_air); | 6362 | const rhs_ty = self.air.typeOf(rhs_air); |
| 6343 | const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*)); | 6363 | const abi_size = @intCast(u32, lhs_ty.abiSize(mod)); |
| 6344 | 6364 | ||
| 6345 | const maybe_mask_reg = switch (air_tag) { | 6365 | const maybe_mask_reg = switch (air_tag) { |
| 6346 | else => null, | 6366 | else => null, |
| 6347 | .max, .min => if (lhs_ty.scalarType().isRuntimeFloat()) registerAlias( | 6367 | .max, .min => if (lhs_ty.scalarType(mod).isRuntimeFloat()) registerAlias( |
| 6348 | if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: { | 6368 | if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: { |
| 6349 | try self.register_manager.getReg(.xmm0, null); | 6369 | try self.register_manager.getReg(.xmm0, null); |
| 6350 | break :mask .xmm0; | 6370 | break :mask .xmm0; |
| ... | @@ -6384,7 +6404,7 @@ fn genBinOp( | ... | @@ -6384,7 +6404,7 @@ fn genBinOp( |
| 6384 | 6404 | ||
| 6385 | else => false, | 6405 | else => false, |
| 6386 | }; | 6406 | }; |
| 6387 | const vec_op = switch (lhs_ty.zigTypeTag()) { | 6407 | const vec_op = switch (lhs_ty.zigTypeTag(mod)) { |
| 6388 | else => false, | 6408 | else => false, |
| 6389 | .Float, .Vector => true, | 6409 | .Float, .Vector => true, |
| 6390 | }; | 6410 | }; |
| ... | @@ -6456,7 +6476,7 @@ fn genBinOp( | ... | @@ -6456,7 +6476,7 @@ fn genBinOp( |
| 6456 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 6476 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 6457 | defer self.register_manager.unlockReg(tmp_lock); | 6477 | defer self.register_manager.unlockReg(tmp_lock); |
| 6458 | 6478 | ||
| 6459 | const elem_size = lhs_ty.elemType2().abiSize(self.target.*); | 6479 | const elem_size = lhs_ty.elemType2(mod).abiSize(mod); |
| 6460 | try self.genIntMulComplexOpMir(rhs_ty, tmp_mcv, .{ .immediate = elem_size }); | 6480 | try self.genIntMulComplexOpMir(rhs_ty, tmp_mcv, .{ .immediate = elem_size }); |
| 6461 | try self.genBinOpMir( | 6481 | try self.genBinOpMir( |
| 6462 | switch (air_tag) { | 6482 | switch (air_tag) { |
| ... | @@ -6506,7 +6526,7 @@ fn genBinOp( | ... | @@ -6506,7 +6526,7 @@ fn genBinOp( |
| 6506 | 6526 | ||
| 6507 | try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, dst_mcv, mat_src_mcv); | 6527 | try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, dst_mcv, mat_src_mcv); |
| 6508 | 6528 | ||
| 6509 | const int_info = lhs_ty.intInfo(self.target.*); | 6529 | const int_info = lhs_ty.intInfo(mod); |
| 6510 | const cc: Condition = switch (int_info.signedness) { | 6530 | const cc: Condition = switch (int_info.signedness) { |
| 6511 | .unsigned => switch (air_tag) { | 6531 | .unsigned => switch (air_tag) { |
| 6512 | .min => .a, | 6532 | .min => .a, |
| ... | @@ -6520,7 +6540,7 @@ fn genBinOp( | ... | @@ -6520,7 +6540,7 @@ fn genBinOp( |
| 6520 | }, | 6540 | }, |
| 6521 | }; | 6541 | }; |
| 6522 | 6542 | ||
| 6523 | const cmov_abi_size = @max(@intCast(u32, lhs_ty.abiSize(self.target.*)), 2); | 6543 | const cmov_abi_size = @max(@intCast(u32, lhs_ty.abiSize(mod)), 2); |
| 6524 | const tmp_reg = switch (dst_mcv) { | 6544 | const tmp_reg = switch (dst_mcv) { |
| 6525 | .register => |reg| reg, | 6545 | .register => |reg| reg, |
| 6526 | else => try self.copyToTmpRegister(lhs_ty, dst_mcv), | 6546 | else => try self.copyToTmpRegister(lhs_ty, dst_mcv), |
| ... | @@ -6581,7 +6601,7 @@ fn genBinOp( | ... | @@ -6581,7 +6601,7 @@ fn genBinOp( |
| 6581 | } | 6601 | } |
| 6582 | 6602 | ||
| 6583 | const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size); | 6603 | const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size); |
| 6584 | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) { | 6604 | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 6585 | else => unreachable, | 6605 | else => unreachable, |
| 6586 | .Float => switch (lhs_ty.floatBits(self.target.*)) { | 6606 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 6587 | 16 => if (self.hasFeature(.f16c)) { | 6607 | 16 => if (self.hasFeature(.f16c)) { |
| ... | @@ -6657,9 +6677,9 @@ fn genBinOp( | ... | @@ -6657,9 +6677,9 @@ fn genBinOp( |
| 6657 | 80, 128 => null, | 6677 | 80, 128 => null, |
| 6658 | else => unreachable, | 6678 | else => unreachable, |
| 6659 | }, | 6679 | }, |
| 6660 | .Vector => switch (lhs_ty.childType().zigTypeTag()) { | 6680 | .Vector => switch (lhs_ty.childType().zigTypeTag(mod)) { |
| 6661 | else => null, | 6681 | else => null, |
| 6662 | .Int => switch (lhs_ty.childType().intInfo(self.target.*).bits) { | 6682 | .Int => switch (lhs_ty.childType().intInfo(mod).bits) { |
| 6663 | 8 => switch (lhs_ty.vectorLen()) { | 6683 | 8 => switch (lhs_ty.vectorLen()) { |
| 6664 | 1...16 => switch (air_tag) { | 6684 | 1...16 => switch (air_tag) { |
| 6665 | .add, | 6685 | .add, |
| ... | @@ -6671,7 +6691,7 @@ fn genBinOp( | ... | @@ -6671,7 +6691,7 @@ fn genBinOp( |
| 6671 | .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" }, | 6691 | .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" }, |
| 6672 | .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" }, | 6692 | .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" }, |
| 6673 | .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor }, | 6693 | .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor }, |
| 6674 | .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6694 | .min => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6675 | .signed => if (self.hasFeature(.avx)) | 6695 | .signed => if (self.hasFeature(.avx)) |
| 6676 | .{ .vp_b, .mins } | 6696 | .{ .vp_b, .mins } |
| 6677 | else if (self.hasFeature(.sse4_1)) | 6697 | else if (self.hasFeature(.sse4_1)) |
| ... | @@ -6685,7 +6705,7 @@ fn genBinOp( | ... | @@ -6685,7 +6705,7 @@ fn genBinOp( |
| 6685 | else | 6705 | else |
| 6686 | null, | 6706 | null, |
| 6687 | }, | 6707 | }, |
| 6688 | .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6708 | .max => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6689 | .signed => if (self.hasFeature(.avx)) | 6709 | .signed => if (self.hasFeature(.avx)) |
| 6690 | .{ .vp_b, .maxs } | 6710 | .{ .vp_b, .maxs } |
| 6691 | else if (self.hasFeature(.sse4_1)) | 6711 | else if (self.hasFeature(.sse4_1)) |
| ... | @@ -6711,11 +6731,11 @@ fn genBinOp( | ... | @@ -6711,11 +6731,11 @@ fn genBinOp( |
| 6711 | .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null, | 6731 | .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null, |
| 6712 | .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null, | 6732 | .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null, |
| 6713 | .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null, | 6733 | .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null, |
| 6714 | .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6734 | .min => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6715 | .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .mins } else null, | 6735 | .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .mins } else null, |
| 6716 | .unsigned => if (self.hasFeature(.avx)) .{ .vp_b, .minu } else null, | 6736 | .unsigned => if (self.hasFeature(.avx)) .{ .vp_b, .minu } else null, |
| 6717 | }, | 6737 | }, |
| 6718 | .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6738 | .max => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6719 | .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .maxs } else null, | 6739 | .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .maxs } else null, |
| 6720 | .unsigned => if (self.hasFeature(.avx2)) .{ .vp_b, .maxu } else null, | 6740 | .unsigned => if (self.hasFeature(.avx2)) .{ .vp_b, .maxu } else null, |
| 6721 | }, | 6741 | }, |
| ... | @@ -6737,7 +6757,7 @@ fn genBinOp( | ... | @@ -6737,7 +6757,7 @@ fn genBinOp( |
| 6737 | .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" }, | 6757 | .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" }, |
| 6738 | .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" }, | 6758 | .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" }, |
| 6739 | .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor }, | 6759 | .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor }, |
| 6740 | .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6760 | .min => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6741 | .signed => if (self.hasFeature(.avx)) | 6761 | .signed => if (self.hasFeature(.avx)) |
| 6742 | .{ .vp_w, .mins } | 6762 | .{ .vp_w, .mins } |
| 6743 | else | 6763 | else |
| ... | @@ -6747,7 +6767,7 @@ fn genBinOp( | ... | @@ -6747,7 +6767,7 @@ fn genBinOp( |
| 6747 | else | 6767 | else |
| 6748 | .{ .p_w, .minu }, | 6768 | .{ .p_w, .minu }, |
| 6749 | }, | 6769 | }, |
| 6750 | .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6770 | .max => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6751 | .signed => if (self.hasFeature(.avx)) | 6771 | .signed => if (self.hasFeature(.avx)) |
| 6752 | .{ .vp_w, .maxs } | 6772 | .{ .vp_w, .maxs } |
| 6753 | else | 6773 | else |
| ... | @@ -6772,11 +6792,11 @@ fn genBinOp( | ... | @@ -6772,11 +6792,11 @@ fn genBinOp( |
| 6772 | .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null, | 6792 | .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null, |
| 6773 | .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null, | 6793 | .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null, |
| 6774 | .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null, | 6794 | .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null, |
| 6775 | .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6795 | .min => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6776 | .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .mins } else null, | 6796 | .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .mins } else null, |
| 6777 | .unsigned => if (self.hasFeature(.avx)) .{ .vp_w, .minu } else null, | 6797 | .unsigned => if (self.hasFeature(.avx)) .{ .vp_w, .minu } else null, |
| 6778 | }, | 6798 | }, |
| 6779 | .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6799 | .max => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6780 | .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .maxs } else null, | 6800 | .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .maxs } else null, |
| 6781 | .unsigned => if (self.hasFeature(.avx2)) .{ .vp_w, .maxu } else null, | 6801 | .unsigned => if (self.hasFeature(.avx2)) .{ .vp_w, .maxu } else null, |
| 6782 | }, | 6802 | }, |
| ... | @@ -6803,7 +6823,7 @@ fn genBinOp( | ... | @@ -6803,7 +6823,7 @@ fn genBinOp( |
| 6803 | .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" }, | 6823 | .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" }, |
| 6804 | .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" }, | 6824 | .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" }, |
| 6805 | .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor }, | 6825 | .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor }, |
| 6806 | .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6826 | .min => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6807 | .signed => if (self.hasFeature(.avx)) | 6827 | .signed => if (self.hasFeature(.avx)) |
| 6808 | .{ .vp_d, .mins } | 6828 | .{ .vp_d, .mins } |
| 6809 | else if (self.hasFeature(.sse4_1)) | 6829 | else if (self.hasFeature(.sse4_1)) |
| ... | @@ -6817,7 +6837,7 @@ fn genBinOp( | ... | @@ -6817,7 +6837,7 @@ fn genBinOp( |
| 6817 | else | 6837 | else |
| 6818 | null, | 6838 | null, |
| 6819 | }, | 6839 | }, |
| 6820 | .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6840 | .max => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6821 | .signed => if (self.hasFeature(.avx)) | 6841 | .signed => if (self.hasFeature(.avx)) |
| 6822 | .{ .vp_d, .maxs } | 6842 | .{ .vp_d, .maxs } |
| 6823 | else if (self.hasFeature(.sse4_1)) | 6843 | else if (self.hasFeature(.sse4_1)) |
| ... | @@ -6846,11 +6866,11 @@ fn genBinOp( | ... | @@ -6846,11 +6866,11 @@ fn genBinOp( |
| 6846 | .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null, | 6866 | .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null, |
| 6847 | .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null, | 6867 | .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null, |
| 6848 | .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null, | 6868 | .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null, |
| 6849 | .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6869 | .min => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6850 | .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .mins } else null, | 6870 | .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .mins } else null, |
| 6851 | .unsigned => if (self.hasFeature(.avx)) .{ .vp_d, .minu } else null, | 6871 | .unsigned => if (self.hasFeature(.avx)) .{ .vp_d, .minu } else null, |
| 6852 | }, | 6872 | }, |
| 6853 | .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) { | 6873 | .max => switch (lhs_ty.childType().intInfo(mod).signedness) { |
| 6854 | .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .maxs } else null, | 6874 | .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .maxs } else null, |
| 6855 | .unsigned => if (self.hasFeature(.avx2)) .{ .vp_d, .maxu } else null, | 6875 | .unsigned => if (self.hasFeature(.avx2)) .{ .vp_d, .maxu } else null, |
| 6856 | }, | 6876 | }, |
| ... | @@ -7206,14 +7226,14 @@ fn genBinOp( | ... | @@ -7206,14 +7226,14 @@ fn genBinOp( |
| 7206 | const rhs_copy_reg = registerAlias(src_mcv.getReg().?, abi_size); | 7226 | const rhs_copy_reg = registerAlias(src_mcv.getReg().?, abi_size); |
| 7207 | 7227 | ||
| 7208 | try self.asmRegisterRegisterRegisterImmediate( | 7228 | try self.asmRegisterRegisterRegisterImmediate( |
| 7209 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) { | 7229 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7210 | .Float => switch (lhs_ty.floatBits(self.target.*)) { | 7230 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7211 | 32 => .{ .v_ss, .cmp }, | 7231 | 32 => .{ .v_ss, .cmp }, |
| 7212 | 64 => .{ .v_sd, .cmp }, | 7232 | 64 => .{ .v_sd, .cmp }, |
| 7213 | 16, 80, 128 => null, | 7233 | 16, 80, 128 => null, |
| 7214 | else => unreachable, | 7234 | else => unreachable, |
| 7215 | }, | 7235 | }, |
| 7216 | .Vector => switch (lhs_ty.childType().zigTypeTag()) { | 7236 | .Vector => switch (lhs_ty.childType().zigTypeTag(mod)) { |
| 7217 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { | 7237 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { |
| 7218 | 32 => switch (lhs_ty.vectorLen()) { | 7238 | 32 => switch (lhs_ty.vectorLen()) { |
| 7219 | 1 => .{ .v_ss, .cmp }, | 7239 | 1 => .{ .v_ss, .cmp }, |
| ... | @@ -7240,14 +7260,14 @@ fn genBinOp( | ... | @@ -7240,14 +7260,14 @@ fn genBinOp( |
| 7240 | Immediate.u(3), // unord | 7260 | Immediate.u(3), // unord |
| 7241 | ); | 7261 | ); |
| 7242 | try self.asmRegisterRegisterRegisterRegister( | 7262 | try self.asmRegisterRegisterRegisterRegister( |
| 7243 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) { | 7263 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7244 | .Float => switch (lhs_ty.floatBits(self.target.*)) { | 7264 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7245 | 32 => .{ .v_ps, .blendv }, | 7265 | 32 => .{ .v_ps, .blendv }, |
| 7246 | 64 => .{ .v_pd, .blendv }, | 7266 | 64 => .{ .v_pd, .blendv }, |
| 7247 | 16, 80, 128 => null, | 7267 | 16, 80, 128 => null, |
| 7248 | else => unreachable, | 7268 | else => unreachable, |
| 7249 | }, | 7269 | }, |
| 7250 | .Vector => switch (lhs_ty.childType().zigTypeTag()) { | 7270 | .Vector => switch (lhs_ty.childType().zigTypeTag(mod)) { |
| 7251 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { | 7271 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { |
| 7252 | 32 => switch (lhs_ty.vectorLen()) { | 7272 | 32 => switch (lhs_ty.vectorLen()) { |
| 7253 | 1...8 => .{ .v_ps, .blendv }, | 7273 | 1...8 => .{ .v_ps, .blendv }, |
| ... | @@ -7274,14 +7294,14 @@ fn genBinOp( | ... | @@ -7274,14 +7294,14 @@ fn genBinOp( |
| 7274 | } else { | 7294 | } else { |
| 7275 | const has_blend = self.hasFeature(.sse4_1); | 7295 | const has_blend = self.hasFeature(.sse4_1); |
| 7276 | try self.asmRegisterRegisterImmediate( | 7296 | try self.asmRegisterRegisterImmediate( |
| 7277 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) { | 7297 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7278 | .Float => switch (lhs_ty.floatBits(self.target.*)) { | 7298 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7279 | 32 => .{ ._ss, .cmp }, | 7299 | 32 => .{ ._ss, .cmp }, |
| 7280 | 64 => .{ ._sd, .cmp }, | 7300 | 64 => .{ ._sd, .cmp }, |
| 7281 | 16, 80, 128 => null, | 7301 | 16, 80, 128 => null, |
| 7282 | else => unreachable, | 7302 | else => unreachable, |
| 7283 | }, | 7303 | }, |
| 7284 | .Vector => switch (lhs_ty.childType().zigTypeTag()) { | 7304 | .Vector => switch (lhs_ty.childType().zigTypeTag(mod)) { |
| 7285 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { | 7305 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { |
| 7286 | 32 => switch (lhs_ty.vectorLen()) { | 7306 | 32 => switch (lhs_ty.vectorLen()) { |
| 7287 | 1 => .{ ._ss, .cmp }, | 7307 | 1 => .{ ._ss, .cmp }, |
| ... | @@ -7307,14 +7327,14 @@ fn genBinOp( | ... | @@ -7307,14 +7327,14 @@ fn genBinOp( |
| 7307 | Immediate.u(if (has_blend) 3 else 7), // unord, ord | 7327 | Immediate.u(if (has_blend) 3 else 7), // unord, ord |
| 7308 | ); | 7328 | ); |
| 7309 | if (has_blend) try self.asmRegisterRegisterRegister( | 7329 | if (has_blend) try self.asmRegisterRegisterRegister( |
| 7310 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) { | 7330 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7311 | .Float => switch (lhs_ty.floatBits(self.target.*)) { | 7331 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7312 | 32 => .{ ._ps, .blendv }, | 7332 | 32 => .{ ._ps, .blendv }, |
| 7313 | 64 => .{ ._pd, .blendv }, | 7333 | 64 => .{ ._pd, .blendv }, |
| 7314 | 16, 80, 128 => null, | 7334 | 16, 80, 128 => null, |
| 7315 | else => unreachable, | 7335 | else => unreachable, |
| 7316 | }, | 7336 | }, |
| 7317 | .Vector => switch (lhs_ty.childType().zigTypeTag()) { | 7337 | .Vector => switch (lhs_ty.childType().zigTypeTag(mod)) { |
| 7318 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { | 7338 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { |
| 7319 | 32 => switch (lhs_ty.vectorLen()) { | 7339 | 32 => switch (lhs_ty.vectorLen()) { |
| 7320 | 1...4 => .{ ._ps, .blendv }, | 7340 | 1...4 => .{ ._ps, .blendv }, |
| ... | @@ -7338,14 +7358,14 @@ fn genBinOp( | ... | @@ -7338,14 +7358,14 @@ fn genBinOp( |
| 7338 | mask_reg, | 7358 | mask_reg, |
| 7339 | ) else { | 7359 | ) else { |
| 7340 | try self.asmRegisterRegister( | 7360 | try self.asmRegisterRegister( |
| 7341 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) { | 7361 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7342 | .Float => switch (lhs_ty.floatBits(self.target.*)) { | 7362 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7343 | 32 => .{ ._ps, .@"and" }, | 7363 | 32 => .{ ._ps, .@"and" }, |
| 7344 | 64 => .{ ._pd, .@"and" }, | 7364 | 64 => .{ ._pd, .@"and" }, |
| 7345 | 16, 80, 128 => null, | 7365 | 16, 80, 128 => null, |
| 7346 | else => unreachable, | 7366 | else => unreachable, |
| 7347 | }, | 7367 | }, |
| 7348 | .Vector => switch (lhs_ty.childType().zigTypeTag()) { | 7368 | .Vector => switch (lhs_ty.childType().zigTypeTag(mod)) { |
| 7349 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { | 7369 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { |
| 7350 | 32 => switch (lhs_ty.vectorLen()) { | 7370 | 32 => switch (lhs_ty.vectorLen()) { |
| 7351 | 1...4 => .{ ._ps, .@"and" }, | 7371 | 1...4 => .{ ._ps, .@"and" }, |
| ... | @@ -7368,14 +7388,14 @@ fn genBinOp( | ... | @@ -7368,14 +7388,14 @@ fn genBinOp( |
| 7368 | mask_reg, | 7388 | mask_reg, |
| 7369 | ); | 7389 | ); |
| 7370 | try self.asmRegisterRegister( | 7390 | try self.asmRegisterRegister( |
| 7371 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) { | 7391 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7372 | .Float => switch (lhs_ty.floatBits(self.target.*)) { | 7392 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7373 | 32 => .{ ._ps, .andn }, | 7393 | 32 => .{ ._ps, .andn }, |
| 7374 | 64 => .{ ._pd, .andn }, | 7394 | 64 => .{ ._pd, .andn }, |
| 7375 | 16, 80, 128 => null, | 7395 | 16, 80, 128 => null, |
| 7376 | else => unreachable, | 7396 | else => unreachable, |
| 7377 | }, | 7397 | }, |
| 7378 | .Vector => switch (lhs_ty.childType().zigTypeTag()) { | 7398 | .Vector => switch (lhs_ty.childType().zigTypeTag(mod)) { |
| 7379 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { | 7399 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { |
| 7380 | 32 => switch (lhs_ty.vectorLen()) { | 7400 | 32 => switch (lhs_ty.vectorLen()) { |
| 7381 | 1...4 => .{ ._ps, .andn }, | 7401 | 1...4 => .{ ._ps, .andn }, |
| ... | @@ -7398,14 +7418,14 @@ fn genBinOp( | ... | @@ -7398,14 +7418,14 @@ fn genBinOp( |
| 7398 | lhs_copy_reg.?, | 7418 | lhs_copy_reg.?, |
| 7399 | ); | 7419 | ); |
| 7400 | try self.asmRegisterRegister( | 7420 | try self.asmRegisterRegister( |
| 7401 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) { | 7421 | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7402 | .Float => switch (lhs_ty.floatBits(self.target.*)) { | 7422 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7403 | 32 => .{ ._ps, .@"or" }, | 7423 | 32 => .{ ._ps, .@"or" }, |
| 7404 | 64 => .{ ._pd, .@"or" }, | 7424 | 64 => .{ ._pd, .@"or" }, |
| 7405 | 16, 80, 128 => null, | 7425 | 16, 80, 128 => null, |
| 7406 | else => unreachable, | 7426 | else => unreachable, |
| 7407 | }, | 7427 | }, |
| 7408 | .Vector => switch (lhs_ty.childType().zigTypeTag()) { | 7428 | .Vector => switch (lhs_ty.childType().zigTypeTag(mod)) { |
| 7409 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { | 7429 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { |
| 7410 | 32 => switch (lhs_ty.vectorLen()) { | 7430 | 32 => switch (lhs_ty.vectorLen()) { |
| 7411 | 1...4 => .{ ._ps, .@"or" }, | 7431 | 1...4 => .{ ._ps, .@"or" }, |
| ... | @@ -7442,7 +7462,8 @@ fn genBinOpMir( | ... | @@ -7442,7 +7462,8 @@ fn genBinOpMir( |
| 7442 | dst_mcv: MCValue, | 7462 | dst_mcv: MCValue, |
| 7443 | src_mcv: MCValue, | 7463 | src_mcv: MCValue, |
| 7444 | ) !void { | 7464 | ) !void { |
| 7445 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 7465 | const mod = self.bin_file.options.module.?; |
| 7466 | const abi_size = @intCast(u32, ty.abiSize(mod)); | ||
| 7446 | switch (dst_mcv) { | 7467 | switch (dst_mcv) { |
| 7447 | .none, | 7468 | .none, |
| 7448 | .unreach, | 7469 | .unreach, |
| ... | @@ -7640,7 +7661,7 @@ fn genBinOpMir( | ... | @@ -7640,7 +7661,7 @@ fn genBinOpMir( |
| 7640 | defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock); | 7661 | defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock); |
| 7641 | 7662 | ||
| 7642 | const ty_signedness = | 7663 | const ty_signedness = |
| 7643 | if (ty.isAbiInt()) ty.intInfo(self.target.*).signedness else .unsigned; | 7664 | if (ty.isAbiInt(mod)) ty.intInfo(mod).signedness else .unsigned; |
| 7644 | const limb_ty = if (abi_size <= 8) ty else switch (ty_signedness) { | 7665 | const limb_ty = if (abi_size <= 8) ty else switch (ty_signedness) { |
| 7645 | .signed => Type.usize, | 7666 | .signed => Type.usize, |
| 7646 | .unsigned => Type.isize, | 7667 | .unsigned => Type.isize, |
| ... | @@ -7796,7 +7817,8 @@ fn genBinOpMir( | ... | @@ -7796,7 +7817,8 @@ fn genBinOpMir( |
| 7796 | /// Performs multi-operand integer multiplication between dst_mcv and src_mcv, storing the result in dst_mcv. | 7817 | /// Performs multi-operand integer multiplication between dst_mcv and src_mcv, storing the result in dst_mcv. |
| 7797 | /// Does not support byte-size operands. | 7818 | /// Does not support byte-size operands. |
| 7798 | fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void { | 7819 | fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void { |
| 7799 | const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*)); | 7820 | const mod = self.bin_file.options.module.?; |
| 7821 | const abi_size = @intCast(u32, dst_ty.abiSize(mod)); | ||
| 7800 | switch (dst_mcv) { | 7822 | switch (dst_mcv) { |
| 7801 | .none, | 7823 | .none, |
| 7802 | .unreach, | 7824 | .unreach, |
| ... | @@ -8022,6 +8044,7 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8022,6 +8044,7 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void { |
| 8022 | } | 8044 | } |
| 8023 | 8045 | ||
| 8024 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { | 8046 | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 8047 | const mod = self.bin_file.options.module.?; | ||
| 8025 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{}); | 8048 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{}); |
| 8026 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 8049 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 8027 | const callee = pl_op.operand; | 8050 | const callee = pl_op.operand; |
| ... | @@ -8029,7 +8052,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -8029,7 +8052,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 8029 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); | 8052 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); |
| 8030 | const ty = self.air.typeOf(callee); | 8053 | const ty = self.air.typeOf(callee); |
| 8031 | 8054 | ||
| 8032 | const fn_ty = switch (ty.zigTypeTag()) { | 8055 | const fn_ty = switch (ty.zigTypeTag(mod)) { |
| 8033 | .Fn => ty, | 8056 | .Fn => ty, |
| 8034 | .Pointer => ty.childType(), | 8057 | .Pointer => ty.childType(), |
| 8035 | else => unreachable, | 8058 | else => unreachable, |
| ... | @@ -8077,7 +8100,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -8077,7 +8100,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 8077 | .none, .unreach => null, | 8100 | .none, .unreach => null, |
| 8078 | .indirect => |reg_off| lock: { | 8101 | .indirect => |reg_off| lock: { |
| 8079 | const ret_ty = fn_ty.fnReturnType(); | 8102 | const ret_ty = fn_ty.fnReturnType(); |
| 8080 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, self.target.*)); | 8103 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod)); |
| 8081 | try self.genSetReg(reg_off.reg, Type.usize, .{ | 8104 | try self.genSetReg(reg_off.reg, Type.usize, .{ |
| 8082 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, | 8105 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, |
| 8083 | }); | 8106 | }); |
| ... | @@ -8100,8 +8123,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -8100,8 +8123,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 8100 | 8123 | ||
| 8101 | // Due to incremental compilation, how function calls are generated depends | 8124 | // Due to incremental compilation, how function calls are generated depends |
| 8102 | // on linking. | 8125 | // on linking. |
| 8103 | const mod = self.bin_file.options.module.?; | 8126 | if (self.air.value(callee, mod)) |func_value| { |
| 8104 | if (self.air.value(callee)) |func_value| { | ||
| 8105 | if (if (func_value.castTag(.function)) |func_payload| | 8127 | if (if (func_value.castTag(.function)) |func_payload| |
| 8106 | func_payload.data.owner_decl | 8128 | func_payload.data.owner_decl |
| 8107 | else if (func_value.castTag(.decl_ref)) |decl_ref_payload| | 8129 | else if (func_value.castTag(.decl_ref)) |decl_ref_payload| |
| ... | @@ -8178,7 +8200,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -8178,7 +8200,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 8178 | return self.fail("TODO implement calling bitcasted functions", .{}); | 8200 | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 8179 | } | 8201 | } |
| 8180 | } else { | 8202 | } else { |
| 8181 | assert(ty.zigTypeTag() == .Pointer); | 8203 | assert(ty.zigTypeTag(mod) == .Pointer); |
| 8182 | const mcv = try self.resolveInst(callee); | 8204 | const mcv = try self.resolveInst(callee); |
| 8183 | try self.genSetReg(.rax, Type.usize, mcv); | 8205 | try self.genSetReg(.rax, Type.usize, mcv); |
| 8184 | try self.asmRegister(.{ ._, .call }, .rax); | 8206 | try self.asmRegister(.{ ._, .call }, .rax); |
| ... | @@ -8234,6 +8256,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8234,6 +8256,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 8234 | } | 8256 | } |
| 8235 | 8257 | ||
| 8236 | fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | 8258 | fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8259 | const mod = self.bin_file.options.module.?; | ||
| 8237 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 8260 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 8238 | const ty = self.air.typeOf(bin_op.lhs); | 8261 | const ty = self.air.typeOf(bin_op.lhs); |
| 8239 | 8262 | ||
| ... | @@ -8255,9 +8278,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -8255,9 +8278,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8255 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); | 8278 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 8256 | 8279 | ||
| 8257 | const result = MCValue{ | 8280 | const result = MCValue{ |
| 8258 | .eflags = switch (ty.zigTypeTag()) { | 8281 | .eflags = switch (ty.zigTypeTag(mod)) { |
| 8259 | else => result: { | 8282 | else => result: { |
| 8260 | const abi_size = @intCast(u16, ty.abiSize(self.target.*)); | 8283 | const abi_size = @intCast(u16, ty.abiSize(mod)); |
| 8261 | const may_flip: enum { | 8284 | const may_flip: enum { |
| 8262 | may_flip, | 8285 | may_flip, |
| 8263 | must_flip, | 8286 | must_flip, |
| ... | @@ -8290,7 +8313,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -8290,7 +8313,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8290 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); | 8313 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 8291 | 8314 | ||
| 8292 | break :result Condition.fromCompareOperator( | 8315 | break :result Condition.fromCompareOperator( |
| 8293 | if (ty.isAbiInt()) ty.intInfo(self.target.*).signedness else .unsigned, | 8316 | if (ty.isAbiInt(mod)) ty.intInfo(mod).signedness else .unsigned, |
| 8294 | result_op: { | 8317 | result_op: { |
| 8295 | const flipped_op = if (flipped) op.reverse() else op; | 8318 | const flipped_op = if (flipped) op.reverse() else op; |
| 8296 | if (abi_size > 8) switch (flipped_op) { | 8319 | if (abi_size > 8) switch (flipped_op) { |
| ... | @@ -8404,7 +8427,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -8404,7 +8427,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8404 | try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg); | 8427 | try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg); |
| 8405 | try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv); | 8428 | try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv); |
| 8406 | } else return self.fail("TODO implement airCmp for {}", .{ | 8429 | } else return self.fail("TODO implement airCmp for {}", .{ |
| 8407 | ty.fmt(self.bin_file.options.module.?), | 8430 | ty.fmt(mod), |
| 8408 | }), | 8431 | }), |
| 8409 | 32 => try self.genBinOpMir( | 8432 | 32 => try self.genBinOpMir( |
| 8410 | .{ ._ss, .ucomi }, | 8433 | .{ ._ss, .ucomi }, |
| ... | @@ -8419,7 +8442,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -8419,7 +8442,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8419 | src_mcv, | 8442 | src_mcv, |
| 8420 | ), | 8443 | ), |
| 8421 | else => return self.fail("TODO implement airCmp for {}", .{ | 8444 | else => return self.fail("TODO implement airCmp for {}", .{ |
| 8422 | ty.fmt(self.bin_file.options.module.?), | 8445 | ty.fmt(mod), |
| 8423 | }), | 8446 | }), |
| 8424 | } | 8447 | } |
| 8425 | 8448 | ||
| ... | @@ -8454,7 +8477,7 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8454,7 +8477,7 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 8454 | self.eflags_inst = inst; | 8477 | self.eflags_inst = inst; |
| 8455 | 8478 | ||
| 8456 | const op_ty = self.air.typeOf(un_op); | 8479 | const op_ty = self.air.typeOf(un_op); |
| 8457 | const op_abi_size = @intCast(u32, op_ty.abiSize(self.target.*)); | 8480 | const op_abi_size = @intCast(u32, op_ty.abiSize(mod)); |
| 8458 | const op_mcv = try self.resolveInst(un_op); | 8481 | const op_mcv = try self.resolveInst(un_op); |
| 8459 | const dst_reg = switch (op_mcv) { | 8482 | const dst_reg = switch (op_mcv) { |
| 8460 | .register => |reg| reg, | 8483 | .register => |reg| reg, |
| ... | @@ -8573,7 +8596,8 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8573,7 +8596,8 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 8573 | } | 8596 | } |
| 8574 | 8597 | ||
| 8575 | fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { | 8598 | fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { |
| 8576 | const abi_size = ty.abiSize(self.target.*); | 8599 | const mod = self.bin_file.options.module.?; |
| 8600 | const abi_size = ty.abiSize(mod); | ||
| 8577 | switch (mcv) { | 8601 | switch (mcv) { |
| 8578 | .eflags => |cc| { | 8602 | .eflags => |cc| { |
| 8579 | // Here we map the opposites since the jump is to the false branch. | 8603 | // Here we map the opposites since the jump is to the false branch. |
| ... | @@ -8646,6 +8670,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8646,6 +8670,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 8646 | } | 8670 | } |
| 8647 | 8671 | ||
| 8648 | fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue { | 8672 | fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue { |
| 8673 | const mod = self.bin_file.options.module.?; | ||
| 8649 | switch (opt_mcv) { | 8674 | switch (opt_mcv) { |
| 8650 | .register_overflow => |ro| return .{ .eflags = ro.eflags.negate() }, | 8675 | .register_overflow => |ro| return .{ .eflags = ro.eflags.negate() }, |
| 8651 | else => {}, | 8676 | else => {}, |
| ... | @@ -8658,10 +8683,10 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC | ... | @@ -8658,10 +8683,10 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 8658 | const pl_ty = opt_ty.optionalChild(&pl_buf); | 8683 | const pl_ty = opt_ty.optionalChild(&pl_buf); |
| 8659 | 8684 | ||
| 8660 | var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; | 8685 | var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 8661 | const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload()) | 8686 | const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod)) |
| 8662 | .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty } | 8687 | .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty } |
| 8663 | else | 8688 | else |
| 8664 | .{ .off = @intCast(i32, pl_ty.abiSize(self.target.*)), .ty = Type.bool }; | 8689 | .{ .off = @intCast(i32, pl_ty.abiSize(mod)), .ty = Type.bool }; |
| 8665 | 8690 | ||
| 8666 | switch (opt_mcv) { | 8691 | switch (opt_mcv) { |
| 8667 | .none, | 8692 | .none, |
| ... | @@ -8681,14 +8706,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC | ... | @@ -8681,14 +8706,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 8681 | 8706 | ||
| 8682 | .register => |opt_reg| { | 8707 | .register => |opt_reg| { |
| 8683 | if (some_info.off == 0) { | 8708 | if (some_info.off == 0) { |
| 8684 | const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*)); | 8709 | const some_abi_size = @intCast(u32, some_info.ty.abiSize(mod)); |
| 8685 | const alias_reg = registerAlias(opt_reg, some_abi_size); | 8710 | const alias_reg = registerAlias(opt_reg, some_abi_size); |
| 8686 | assert(some_abi_size * 8 == alias_reg.bitSize()); | 8711 | assert(some_abi_size * 8 == alias_reg.bitSize()); |
| 8687 | try self.asmRegisterRegister(.{ ._, .@"test" }, alias_reg, alias_reg); | 8712 | try self.asmRegisterRegister(.{ ._, .@"test" }, alias_reg, alias_reg); |
| 8688 | return .{ .eflags = .z }; | 8713 | return .{ .eflags = .z }; |
| 8689 | } | 8714 | } |
| 8690 | assert(some_info.ty.tag() == .bool); | 8715 | assert(some_info.ty.tag() == .bool); |
| 8691 | const opt_abi_size = @intCast(u32, opt_ty.abiSize(self.target.*)); | 8716 | const opt_abi_size = @intCast(u32, opt_ty.abiSize(mod)); |
| 8692 | try self.asmRegisterImmediate( | 8717 | try self.asmRegisterImmediate( |
| 8693 | .{ ._, .bt }, | 8718 | .{ ._, .bt }, |
| 8694 | registerAlias(opt_reg, opt_abi_size), | 8719 | registerAlias(opt_reg, opt_abi_size), |
| ... | @@ -8707,7 +8732,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC | ... | @@ -8707,7 +8732,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 8707 | defer self.register_manager.unlockReg(addr_reg_lock); | 8732 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 8708 | 8733 | ||
| 8709 | try self.genSetReg(addr_reg, Type.usize, opt_mcv.address()); | 8734 | try self.genSetReg(addr_reg, Type.usize, opt_mcv.address()); |
| 8710 | const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*)); | 8735 | const some_abi_size = @intCast(u32, some_info.ty.abiSize(mod)); |
| 8711 | try self.asmMemoryImmediate( | 8736 | try self.asmMemoryImmediate( |
| 8712 | .{ ._, .cmp }, | 8737 | .{ ._, .cmp }, |
| 8713 | Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{ | 8738 | Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{ |
| ... | @@ -8720,7 +8745,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC | ... | @@ -8720,7 +8745,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 8720 | }, | 8745 | }, |
| 8721 | 8746 | ||
| 8722 | .indirect, .load_frame => { | 8747 | .indirect, .load_frame => { |
| 8723 | const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*)); | 8748 | const some_abi_size = @intCast(u32, some_info.ty.abiSize(mod)); |
| 8724 | try self.asmMemoryImmediate( | 8749 | try self.asmMemoryImmediate( |
| 8725 | .{ ._, .cmp }, | 8750 | .{ ._, .cmp }, |
| 8726 | Memory.sib(Memory.PtrSize.fromSize(some_abi_size), switch (opt_mcv) { | 8751 | Memory.sib(Memory.PtrSize.fromSize(some_abi_size), switch (opt_mcv) { |
| ... | @@ -8742,6 +8767,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC | ... | @@ -8742,6 +8767,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 8742 | } | 8767 | } |
| 8743 | 8768 | ||
| 8744 | fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue { | 8769 | fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue { |
| 8770 | const mod = self.bin_file.options.module.?; | ||
| 8745 | try self.spillEflagsIfOccupied(); | 8771 | try self.spillEflagsIfOccupied(); |
| 8746 | self.eflags_inst = inst; | 8772 | self.eflags_inst = inst; |
| 8747 | 8773 | ||
| ... | @@ -8750,10 +8776,10 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) | ... | @@ -8750,10 +8776,10 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) |
| 8750 | const pl_ty = opt_ty.optionalChild(&pl_buf); | 8776 | const pl_ty = opt_ty.optionalChild(&pl_buf); |
| 8751 | 8777 | ||
| 8752 | var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; | 8778 | var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 8753 | const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload()) | 8779 | const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod)) |
| 8754 | .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty } | 8780 | .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty } |
| 8755 | else | 8781 | else |
| 8756 | .{ .off = @intCast(i32, pl_ty.abiSize(self.target.*)), .ty = Type.bool }; | 8782 | .{ .off = @intCast(i32, pl_ty.abiSize(mod)), .ty = Type.bool }; |
| 8757 | 8783 | ||
| 8758 | const ptr_reg = switch (ptr_mcv) { | 8784 | const ptr_reg = switch (ptr_mcv) { |
| 8759 | .register => |reg| reg, | 8785 | .register => |reg| reg, |
| ... | @@ -8762,7 +8788,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) | ... | @@ -8762,7 +8788,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) |
| 8762 | const ptr_lock = self.register_manager.lockReg(ptr_reg); | 8788 | const ptr_lock = self.register_manager.lockReg(ptr_reg); |
| 8763 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); | 8789 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); |
| 8764 | 8790 | ||
| 8765 | const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*)); | 8791 | const some_abi_size = @intCast(u32, some_info.ty.abiSize(mod)); |
| 8766 | try self.asmMemoryImmediate( | 8792 | try self.asmMemoryImmediate( |
| 8767 | .{ ._, .cmp }, | 8793 | .{ ._, .cmp }, |
| 8768 | Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{ | 8794 | Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{ |
| ... | @@ -8775,6 +8801,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) | ... | @@ -8775,6 +8801,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) |
| 8775 | } | 8801 | } |
| 8776 | 8802 | ||
| 8777 | fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue { | 8803 | fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue { |
| 8804 | const mod = self.bin_file.options.module.?; | ||
| 8778 | const err_type = ty.errorUnionSet(); | 8805 | const err_type = ty.errorUnionSet(); |
| 8779 | 8806 | ||
| 8780 | if (err_type.errorSetIsEmpty()) { | 8807 | if (err_type.errorSetIsEmpty()) { |
| ... | @@ -8786,7 +8813,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) ! | ... | @@ -8786,7 +8813,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) ! |
| 8786 | self.eflags_inst = inst; | 8813 | self.eflags_inst = inst; |
| 8787 | } | 8814 | } |
| 8788 | 8815 | ||
| 8789 | const err_off = errUnionErrorOffset(ty.errorUnionPayload(), self.target.*); | 8816 | const err_off = errUnionErrorOffset(ty.errorUnionPayload(), mod); |
| 8790 | switch (operand) { | 8817 | switch (operand) { |
| 8791 | .register => |reg| { | 8818 | .register => |reg| { |
| 8792 | const eu_lock = self.register_manager.lockReg(reg); | 8819 | const eu_lock = self.register_manager.lockReg(reg); |
| ... | @@ -9088,12 +9115,13 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { | ... | @@ -9088,12 +9115,13 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { |
| 9088 | } | 9115 | } |
| 9089 | 9116 | ||
| 9090 | fn airBr(self: *Self, inst: Air.Inst.Index) !void { | 9117 | fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 9118 | const mod = self.bin_file.options.module.?; | ||
| 9091 | const br = self.air.instructions.items(.data)[inst].br; | 9119 | const br = self.air.instructions.items(.data)[inst].br; |
| 9092 | const src_mcv = try self.resolveInst(br.operand); | 9120 | const src_mcv = try self.resolveInst(br.operand); |
| 9093 | 9121 | ||
| 9094 | const block_ty = self.air.typeOfIndex(br.block_inst); | 9122 | const block_ty = self.air.typeOfIndex(br.block_inst); |
| 9095 | const block_unused = | 9123 | const block_unused = |
| 9096 | !block_ty.hasRuntimeBitsIgnoreComptime() or self.liveness.isUnused(br.block_inst); | 9124 | !block_ty.hasRuntimeBitsIgnoreComptime(mod) or self.liveness.isUnused(br.block_inst); |
| 9097 | const block_tracking = self.inst_tracking.getPtr(br.block_inst).?; | 9125 | const block_tracking = self.inst_tracking.getPtr(br.block_inst).?; |
| 9098 | const block_data = self.blocks.getPtr(br.block_inst).?; | 9126 | const block_data = self.blocks.getPtr(br.block_inst).?; |
| 9099 | const first_br = block_data.relocs.items.len == 0; | 9127 | const first_br = block_data.relocs.items.len == 0; |
| ... | @@ -9402,7 +9430,8 @@ const MoveStrategy = union(enum) { | ... | @@ -9402,7 +9430,8 @@ const MoveStrategy = union(enum) { |
| 9402 | }; | 9430 | }; |
| 9403 | }; | 9431 | }; |
| 9404 | fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy { | 9432 | fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy { |
| 9405 | switch (ty.zigTypeTag()) { | 9433 | const mod = self.bin_file.options.module.?; |
| 9434 | switch (ty.zigTypeTag(mod)) { | ||
| 9406 | else => return .{ .move = .{ ._, .mov } }, | 9435 | else => return .{ .move = .{ ._, .mov } }, |
| 9407 | .Float => switch (ty.floatBits(self.target.*)) { | 9436 | .Float => switch (ty.floatBits(self.target.*)) { |
| 9408 | 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ | 9437 | 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ |
| ... | @@ -9419,8 +9448,8 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy { | ... | @@ -9419,8 +9448,8 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy { |
| 9419 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | 9448 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| 9420 | else => {}, | 9449 | else => {}, |
| 9421 | }, | 9450 | }, |
| 9422 | .Vector => switch (ty.childType().zigTypeTag()) { | 9451 | .Vector => switch (ty.childType().zigTypeTag(mod)) { |
| 9423 | .Int => switch (ty.childType().intInfo(self.target.*).bits) { | 9452 | .Int => switch (ty.childType().intInfo(mod).bits) { |
| 9424 | 8 => switch (ty.vectorLen()) { | 9453 | 8 => switch (ty.vectorLen()) { |
| 9425 | 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{ | 9454 | 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{ |
| 9426 | .insert = .{ .vp_b, .insr }, | 9455 | .insert = .{ .vp_b, .insr }, |
| ... | @@ -9647,7 +9676,8 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError | ... | @@ -9647,7 +9676,8 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError |
| 9647 | } | 9676 | } |
| 9648 | 9677 | ||
| 9649 | fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerError!void { | 9678 | fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerError!void { |
| 9650 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 9679 | const mod = self.bin_file.options.module.?; |
| 9680 | const abi_size = @intCast(u32, ty.abiSize(mod)); | ||
| 9651 | if (abi_size * 8 > dst_reg.bitSize()) | 9681 | if (abi_size * 8 > dst_reg.bitSize()) |
| 9652 | return self.fail("genSetReg called with a value larger than dst_reg", .{}); | 9682 | return self.fail("genSetReg called with a value larger than dst_reg", .{}); |
| 9653 | switch (src_mcv) { | 9683 | switch (src_mcv) { |
| ... | @@ -9730,7 +9760,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -9730,7 +9760,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 9730 | .{ .register = try self.copyToTmpRegister(ty, src_mcv) }, | 9760 | .{ .register = try self.copyToTmpRegister(ty, src_mcv) }, |
| 9731 | ), | 9761 | ), |
| 9732 | .sse => try self.asmRegisterRegister( | 9762 | .sse => try self.asmRegisterRegister( |
| 9733 | if (@as(?Mir.Inst.FixedTag, switch (ty.scalarType().zigTypeTag()) { | 9763 | if (@as(?Mir.Inst.FixedTag, switch (ty.scalarType(mod).zigTypeTag(mod)) { |
| 9734 | else => switch (abi_size) { | 9764 | else => switch (abi_size) { |
| 9735 | 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov }, | 9765 | 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov }, |
| 9736 | 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov }, | 9766 | 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov }, |
| ... | @@ -9738,7 +9768,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -9738,7 +9768,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 9738 | 17...32 => if (self.hasFeature(.avx)) .{ .v_, .movdqa } else null, | 9768 | 17...32 => if (self.hasFeature(.avx)) .{ .v_, .movdqa } else null, |
| 9739 | else => null, | 9769 | else => null, |
| 9740 | }, | 9770 | }, |
| 9741 | .Float => switch (ty.scalarType().floatBits(self.target.*)) { | 9771 | .Float => switch (ty.scalarType(mod).floatBits(self.target.*)) { |
| 9742 | 16, 128 => switch (abi_size) { | 9772 | 16, 128 => switch (abi_size) { |
| 9743 | 2...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov }, | 9773 | 2...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov }, |
| 9744 | 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov }, | 9774 | 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov }, |
| ... | @@ -9789,7 +9819,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -9789,7 +9819,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 9789 | .indirect => try self.moveStrategy(ty, false), | 9819 | .indirect => try self.moveStrategy(ty, false), |
| 9790 | .load_frame => |frame_addr| try self.moveStrategy( | 9820 | .load_frame => |frame_addr| try self.moveStrategy( |
| 9791 | ty, | 9821 | ty, |
| 9792 | self.getFrameAddrAlignment(frame_addr) >= ty.abiAlignment(self.target.*), | 9822 | self.getFrameAddrAlignment(frame_addr) >= ty.abiAlignment(mod), |
| 9793 | ), | 9823 | ), |
| 9794 | .lea_frame => .{ .move = .{ ._, .lea } }, | 9824 | .lea_frame => .{ .move = .{ ._, .lea } }, |
| 9795 | else => unreachable, | 9825 | else => unreachable, |
| ... | @@ -9821,7 +9851,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -9821,7 +9851,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 9821 | switch (try self.moveStrategy(ty, mem.isAlignedGeneric( | 9851 | switch (try self.moveStrategy(ty, mem.isAlignedGeneric( |
| 9822 | u32, | 9852 | u32, |
| 9823 | @bitCast(u32, small_addr), | 9853 | @bitCast(u32, small_addr), |
| 9824 | ty.abiAlignment(self.target.*), | 9854 | ty.abiAlignment(mod), |
| 9825 | ))) { | 9855 | ))) { |
| 9826 | .move => |tag| try self.asmRegisterMemory(tag, dst_alias, src_mem), | 9856 | .move => |tag| try self.asmRegisterMemory(tag, dst_alias, src_mem), |
| 9827 | .insert_extract => |ie| try self.asmRegisterMemoryImmediate( | 9857 | .insert_extract => |ie| try self.asmRegisterMemoryImmediate( |
| ... | @@ -9839,7 +9869,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -9839,7 +9869,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 9839 | ), | 9869 | ), |
| 9840 | } | 9870 | } |
| 9841 | }, | 9871 | }, |
| 9842 | .load_direct => |sym_index| switch (ty.zigTypeTag()) { | 9872 | .load_direct => |sym_index| switch (ty.zigTypeTag(mod)) { |
| 9843 | else => { | 9873 | else => { |
| 9844 | const atom_index = try self.owner.getSymbolIndex(self); | 9874 | const atom_index = try self.owner.getSymbolIndex(self); |
| 9845 | _ = try self.addInst(.{ | 9875 | _ = try self.addInst(.{ |
| ... | @@ -9933,7 +9963,8 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -9933,7 +9963,8 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 9933 | } | 9963 | } |
| 9934 | 9964 | ||
| 9935 | fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCValue) InnerError!void { | 9965 | fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCValue) InnerError!void { |
| 9936 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 9966 | const mod = self.bin_file.options.module.?; |
| 9967 | const abi_size = @intCast(u32, ty.abiSize(mod)); | ||
| 9937 | const dst_ptr_mcv: MCValue = switch (base) { | 9968 | const dst_ptr_mcv: MCValue = switch (base) { |
| 9938 | .none => .{ .immediate = @bitCast(u64, @as(i64, disp)) }, | 9969 | .none => .{ .immediate = @bitCast(u64, @as(i64, disp)) }, |
| 9939 | .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } }, | 9970 | .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } }, |
| ... | @@ -9945,7 +9976,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal | ... | @@ -9945,7 +9976,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 9945 | try self.genInlineMemset(dst_ptr_mcv, .{ .immediate = 0xaa }, .{ .immediate = abi_size }), | 9976 | try self.genInlineMemset(dst_ptr_mcv, .{ .immediate = 0xaa }, .{ .immediate = abi_size }), |
| 9946 | .immediate => |imm| switch (abi_size) { | 9977 | .immediate => |imm| switch (abi_size) { |
| 9947 | 1, 2, 4 => { | 9978 | 1, 2, 4 => { |
| 9948 | const immediate = if (ty.isSignedInt()) | 9979 | const immediate = if (ty.isSignedInt(mod)) |
| 9949 | Immediate.s(@truncate(i32, @bitCast(i64, imm))) | 9980 | Immediate.s(@truncate(i32, @bitCast(i64, imm))) |
| 9950 | else | 9981 | else |
| 9951 | Immediate.u(@intCast(u32, imm)); | 9982 | Immediate.u(@intCast(u32, imm)); |
| ... | @@ -9967,7 +9998,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal | ... | @@ -9967,7 +9998,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 9967 | while (offset < abi_size) : (offset += 4) try self.asmMemoryImmediate( | 9998 | while (offset < abi_size) : (offset += 4) try self.asmMemoryImmediate( |
| 9968 | .{ ._, .mov }, | 9999 | .{ ._, .mov }, |
| 9969 | Memory.sib(.dword, .{ .base = base, .disp = disp + offset }), | 10000 | Memory.sib(.dword, .{ .base = base, .disp = disp + offset }), |
| 9970 | if (ty.isSignedInt()) | 10001 | if (ty.isSignedInt(mod)) |
| 9971 | Immediate.s(@truncate( | 10002 | Immediate.s(@truncate( |
| 9972 | i32, | 10003 | i32, |
| 9973 | @bitCast(i64, imm) >> (math.cast(u6, offset * 8) orelse 63), | 10004 | @bitCast(i64, imm) >> (math.cast(u6, offset * 8) orelse 63), |
| ... | @@ -9991,19 +10022,19 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal | ... | @@ -9991,19 +10022,19 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 9991 | .none => mem.isAlignedGeneric( | 10022 | .none => mem.isAlignedGeneric( |
| 9992 | u32, | 10023 | u32, |
| 9993 | @bitCast(u32, disp), | 10024 | @bitCast(u32, disp), |
| 9994 | ty.abiAlignment(self.target.*), | 10025 | ty.abiAlignment(mod), |
| 9995 | ), | 10026 | ), |
| 9996 | .reg => |reg| switch (reg) { | 10027 | .reg => |reg| switch (reg) { |
| 9997 | .es, .cs, .ss, .ds => mem.isAlignedGeneric( | 10028 | .es, .cs, .ss, .ds => mem.isAlignedGeneric( |
| 9998 | u32, | 10029 | u32, |
| 9999 | @bitCast(u32, disp), | 10030 | @bitCast(u32, disp), |
| 10000 | ty.abiAlignment(self.target.*), | 10031 | ty.abiAlignment(mod), |
| 10001 | ), | 10032 | ), |
| 10002 | else => false, | 10033 | else => false, |
| 10003 | }, | 10034 | }, |
| 10004 | .frame => |frame_index| self.getFrameAddrAlignment( | 10035 | .frame => |frame_index| self.getFrameAddrAlignment( |
| 10005 | .{ .index = frame_index, .off = disp }, | 10036 | .{ .index = frame_index, .off = disp }, |
| 10006 | ) >= ty.abiAlignment(self.target.*), | 10037 | ) >= ty.abiAlignment(mod), |
| 10007 | })) { | 10038 | })) { |
| 10008 | .move => |tag| try self.asmMemoryRegister(tag, dst_mem, src_alias), | 10039 | .move => |tag| try self.asmMemoryRegister(tag, dst_mem, src_alias), |
| 10009 | .insert_extract, .vex_insert_extract => |ie| try self.asmMemoryRegisterImmediate( | 10040 | .insert_extract, .vex_insert_extract => |ie| try self.asmMemoryRegisterImmediate( |
| ... | @@ -10017,13 +10048,13 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal | ... | @@ -10017,13 +10048,13 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 10017 | .register_overflow => |ro| { | 10048 | .register_overflow => |ro| { |
| 10018 | try self.genSetMem( | 10049 | try self.genSetMem( |
| 10019 | base, | 10050 | base, |
| 10020 | disp + @intCast(i32, ty.structFieldOffset(0, self.target.*)), | 10051 | disp + @intCast(i32, ty.structFieldOffset(0, mod)), |
| 10021 | ty.structFieldType(0), | 10052 | ty.structFieldType(0), |
| 10022 | .{ .register = ro.reg }, | 10053 | .{ .register = ro.reg }, |
| 10023 | ); | 10054 | ); |
| 10024 | try self.genSetMem( | 10055 | try self.genSetMem( |
| 10025 | base, | 10056 | base, |
| 10026 | disp + @intCast(i32, ty.structFieldOffset(1, self.target.*)), | 10057 | disp + @intCast(i32, ty.structFieldOffset(1, mod)), |
| 10027 | ty.structFieldType(1), | 10058 | ty.structFieldType(1), |
| 10028 | .{ .eflags = ro.eflags }, | 10059 | .{ .eflags = ro.eflags }, |
| 10029 | ); | 10060 | ); |
| ... | @@ -10146,13 +10177,14 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10146,13 +10177,14 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 10146 | } | 10177 | } |
| 10147 | 10178 | ||
| 10148 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | 10179 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 10180 | const mod = self.bin_file.options.module.?; | ||
| 10149 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 10181 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 10150 | const dst_ty = self.air.typeOfIndex(inst); | 10182 | const dst_ty = self.air.typeOfIndex(inst); |
| 10151 | const src_ty = self.air.typeOf(ty_op.operand); | 10183 | const src_ty = self.air.typeOf(ty_op.operand); |
| 10152 | 10184 | ||
| 10153 | const result = result: { | 10185 | const result = result: { |
| 10154 | const dst_rc = regClassForType(dst_ty); | 10186 | const dst_rc = regClassForType(dst_ty, mod); |
| 10155 | const src_rc = regClassForType(src_ty); | 10187 | const src_rc = regClassForType(src_ty, mod); |
| 10156 | const src_mcv = try self.resolveInst(ty_op.operand); | 10188 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 10157 | 10189 | ||
| 10158 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; | 10190 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| ... | @@ -10172,13 +10204,13 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10172,13 +10204,13 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 10172 | }; | 10204 | }; |
| 10173 | 10205 | ||
| 10174 | const dst_signedness = | 10206 | const dst_signedness = |
| 10175 | if (dst_ty.isAbiInt()) dst_ty.intInfo(self.target.*).signedness else .unsigned; | 10207 | if (dst_ty.isAbiInt(mod)) dst_ty.intInfo(mod).signedness else .unsigned; |
| 10176 | const src_signedness = | 10208 | const src_signedness = |
| 10177 | if (src_ty.isAbiInt()) src_ty.intInfo(self.target.*).signedness else .unsigned; | 10209 | if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned; |
| 10178 | if (dst_signedness == src_signedness) break :result dst_mcv; | 10210 | if (dst_signedness == src_signedness) break :result dst_mcv; |
| 10179 | 10211 | ||
| 10180 | const abi_size = @intCast(u16, dst_ty.abiSize(self.target.*)); | 10212 | const abi_size = @intCast(u16, dst_ty.abiSize(mod)); |
| 10181 | const bit_size = @intCast(u16, dst_ty.bitSize(self.target.*)); | 10213 | const bit_size = @intCast(u16, dst_ty.bitSize(mod)); |
| 10182 | if (abi_size * 8 <= bit_size) break :result dst_mcv; | 10214 | if (abi_size * 8 <= bit_size) break :result dst_mcv; |
| 10183 | 10215 | ||
| 10184 | const dst_limbs_len = math.divCeil(i32, bit_size, 64) catch unreachable; | 10216 | const dst_limbs_len = math.divCeil(i32, bit_size, 64) catch unreachable; |
| ... | @@ -10192,14 +10224,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10192,14 +10224,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 10192 | const high_lock = self.register_manager.lockReg(high_reg); | 10224 | const high_lock = self.register_manager.lockReg(high_reg); |
| 10193 | defer if (high_lock) |lock| self.register_manager.unlockReg(lock); | 10225 | defer if (high_lock) |lock| self.register_manager.unlockReg(lock); |
| 10194 | 10226 | ||
| 10195 | var high_pl = Type.Payload.Bits{ | 10227 | const high_ty = try mod.intType(dst_signedness, bit_size % 64); |
| 10196 | .base = .{ .tag = switch (dst_signedness) { | ||
| 10197 | .signed => .int_signed, | ||
| 10198 | .unsigned => .int_unsigned, | ||
| 10199 | } }, | ||
| 10200 | .data = bit_size % 64, | ||
| 10201 | }; | ||
| 10202 | const high_ty = Type.initPayload(&high_pl.base); | ||
| 10203 | 10228 | ||
| 10204 | try self.truncateRegister(high_ty, high_reg); | 10229 | try self.truncateRegister(high_ty, high_reg); |
| 10205 | if (!dst_mcv.isRegister()) try self.genCopy( | 10230 | if (!dst_mcv.isRegister()) try self.genCopy( |
| ... | @@ -10213,6 +10238,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10213,6 +10238,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 10213 | } | 10238 | } |
| 10214 | 10239 | ||
| 10215 | fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { | 10240 | fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 10241 | const mod = self.bin_file.options.module.?; | ||
| 10216 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 10242 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 10217 | 10243 | ||
| 10218 | const slice_ty = self.air.typeOfIndex(inst); | 10244 | const slice_ty = self.air.typeOfIndex(inst); |
| ... | @@ -10221,11 +10247,11 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10221,11 +10247,11 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 10221 | const array_ty = ptr_ty.childType(); | 10247 | const array_ty = ptr_ty.childType(); |
| 10222 | const array_len = array_ty.arrayLen(); | 10248 | const array_len = array_ty.arrayLen(); |
| 10223 | 10249 | ||
| 10224 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, self.target.*)); | 10250 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, mod)); |
| 10225 | try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr); | 10251 | try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr); |
| 10226 | try self.genSetMem( | 10252 | try self.genSetMem( |
| 10227 | .{ .frame = frame_index }, | 10253 | .{ .frame = frame_index }, |
| 10228 | @intCast(i32, ptr_ty.abiSize(self.target.*)), | 10254 | @intCast(i32, ptr_ty.abiSize(mod)), |
| 10229 | Type.usize, | 10255 | Type.usize, |
| 10230 | .{ .immediate = array_len }, | 10256 | .{ .immediate = array_len }, |
| 10231 | ); | 10257 | ); |
| ... | @@ -10235,12 +10261,13 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10235,12 +10261,13 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 10235 | } | 10261 | } |
| 10236 | 10262 | ||
| 10237 | fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { | 10263 | fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 10264 | const mod = self.bin_file.options.module.?; | ||
| 10238 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 10265 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 10239 | 10266 | ||
| 10240 | const src_ty = self.air.typeOf(ty_op.operand); | 10267 | const src_ty = self.air.typeOf(ty_op.operand); |
| 10241 | const src_bits = @intCast(u32, src_ty.bitSize(self.target.*)); | 10268 | const src_bits = @intCast(u32, src_ty.bitSize(mod)); |
| 10242 | const src_signedness = | 10269 | const src_signedness = |
| 10243 | if (src_ty.isAbiInt()) src_ty.intInfo(self.target.*).signedness else .unsigned; | 10270 | if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned; |
| 10244 | const dst_ty = self.air.typeOfIndex(inst); | 10271 | const dst_ty = self.air.typeOfIndex(inst); |
| 10245 | 10272 | ||
| 10246 | const src_size = math.divCeil(u32, @max(switch (src_signedness) { | 10273 | const src_size = math.divCeil(u32, @max(switch (src_signedness) { |
| ... | @@ -10248,7 +10275,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10248,7 +10275,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 10248 | .unsigned => src_bits + 1, | 10275 | .unsigned => src_bits + 1, |
| 10249 | }, 32), 8) catch unreachable; | 10276 | }, 32), 8) catch unreachable; |
| 10250 | if (src_size > 8) return self.fail("TODO implement airIntToFloat from {} to {}", .{ | 10277 | if (src_size > 8) return self.fail("TODO implement airIntToFloat from {} to {}", .{ |
| 10251 | src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?), | 10278 | src_ty.fmt(mod), dst_ty.fmt(mod), |
| 10252 | }); | 10279 | }); |
| 10253 | 10280 | ||
| 10254 | const src_mcv = try self.resolveInst(ty_op.operand); | 10281 | const src_mcv = try self.resolveInst(ty_op.operand); |
| ... | @@ -10261,12 +10288,12 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10261,12 +10288,12 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 10261 | 10288 | ||
| 10262 | if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg); | 10289 | if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg); |
| 10263 | 10290 | ||
| 10264 | const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty)); | 10291 | const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod)); |
| 10265 | const dst_mcv = MCValue{ .register = dst_reg }; | 10292 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 10266 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 10293 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 10267 | defer self.register_manager.unlockReg(dst_lock); | 10294 | defer self.register_manager.unlockReg(dst_lock); |
| 10268 | 10295 | ||
| 10269 | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_ty.zigTypeTag()) { | 10296 | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_ty.zigTypeTag(mod)) { |
| 10270 | .Float => switch (dst_ty.floatBits(self.target.*)) { | 10297 | .Float => switch (dst_ty.floatBits(self.target.*)) { |
| 10271 | 32 => if (self.hasFeature(.avx)) .{ .v_ss, .cvtsi2 } else .{ ._ss, .cvtsi2 }, | 10298 | 32 => if (self.hasFeature(.avx)) .{ .v_ss, .cvtsi2 } else .{ ._ss, .cvtsi2 }, |
| 10272 | 64 => if (self.hasFeature(.avx)) .{ .v_sd, .cvtsi2 } else .{ ._sd, .cvtsi2 }, | 10299 | 64 => if (self.hasFeature(.avx)) .{ .v_sd, .cvtsi2 } else .{ ._sd, .cvtsi2 }, |
| ... | @@ -10275,7 +10302,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10275,7 +10302,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 10275 | }, | 10302 | }, |
| 10276 | else => null, | 10303 | else => null, |
| 10277 | })) |tag| tag else return self.fail("TODO implement airIntToFloat from {} to {}", .{ | 10304 | })) |tag| tag else return self.fail("TODO implement airIntToFloat from {} to {}", .{ |
| 10278 | src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?), | 10305 | src_ty.fmt(mod), dst_ty.fmt(mod), |
| 10279 | }); | 10306 | }); |
| 10280 | const dst_alias = dst_reg.to128(); | 10307 | const dst_alias = dst_reg.to128(); |
| 10281 | const src_alias = registerAlias(src_reg, src_size); | 10308 | const src_alias = registerAlias(src_reg, src_size); |
| ... | @@ -10288,13 +10315,14 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10288,13 +10315,14 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 10288 | } | 10315 | } |
| 10289 | 10316 | ||
| 10290 | fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { | 10317 | fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 10318 | const mod = self.bin_file.options.module.?; | ||
| 10291 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 10319 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 10292 | 10320 | ||
| 10293 | const src_ty = self.air.typeOf(ty_op.operand); | 10321 | const src_ty = self.air.typeOf(ty_op.operand); |
| 10294 | const dst_ty = self.air.typeOfIndex(inst); | 10322 | const dst_ty = self.air.typeOfIndex(inst); |
| 10295 | const dst_bits = @intCast(u32, dst_ty.bitSize(self.target.*)); | 10323 | const dst_bits = @intCast(u32, dst_ty.bitSize(mod)); |
| 10296 | const dst_signedness = | 10324 | const dst_signedness = |
| 10297 | if (dst_ty.isAbiInt()) dst_ty.intInfo(self.target.*).signedness else .unsigned; | 10325 | if (dst_ty.isAbiInt(mod)) dst_ty.intInfo(mod).signedness else .unsigned; |
| 10298 | 10326 | ||
| 10299 | const dst_size = math.divCeil(u32, @max(switch (dst_signedness) { | 10327 | const dst_size = math.divCeil(u32, @max(switch (dst_signedness) { |
| 10300 | .signed => dst_bits, | 10328 | .signed => dst_bits, |
| ... | @@ -10312,13 +10340,13 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10312,13 +10340,13 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 10312 | const src_lock = self.register_manager.lockRegAssumeUnused(src_reg); | 10340 | const src_lock = self.register_manager.lockRegAssumeUnused(src_reg); |
| 10313 | defer self.register_manager.unlockReg(src_lock); | 10341 | defer self.register_manager.unlockReg(src_lock); |
| 10314 | 10342 | ||
| 10315 | const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty)); | 10343 | const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod)); |
| 10316 | const dst_mcv = MCValue{ .register = dst_reg }; | 10344 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 10317 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 10345 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 10318 | defer self.register_manager.unlockReg(dst_lock); | 10346 | defer self.register_manager.unlockReg(dst_lock); |
| 10319 | 10347 | ||
| 10320 | try self.asmRegisterRegister( | 10348 | try self.asmRegisterRegister( |
| 10321 | if (@as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag()) { | 10349 | if (@as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag(mod)) { |
| 10322 | .Float => switch (src_ty.floatBits(self.target.*)) { | 10350 | .Float => switch (src_ty.floatBits(self.target.*)) { |
| 10323 | 32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si }, | 10351 | 32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si }, |
| 10324 | 64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si }, | 10352 | 64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si }, |
| ... | @@ -10339,12 +10367,13 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10339,12 +10367,13 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 10339 | } | 10367 | } |
| 10340 | 10368 | ||
| 10341 | fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { | 10369 | fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { |
| 10370 | const mod = self.bin_file.options.module.?; | ||
| 10342 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 10371 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 10343 | const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | 10372 | const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| 10344 | 10373 | ||
| 10345 | const ptr_ty = self.air.typeOf(extra.ptr); | 10374 | const ptr_ty = self.air.typeOf(extra.ptr); |
| 10346 | const val_ty = self.air.typeOf(extra.expected_value); | 10375 | const val_ty = self.air.typeOf(extra.expected_value); |
| 10347 | const val_abi_size = @intCast(u32, val_ty.abiSize(self.target.*)); | 10376 | const val_abi_size = @intCast(u32, val_ty.abiSize(mod)); |
| 10348 | 10377 | ||
| 10349 | try self.spillRegisters(&.{ .rax, .rdx, .rbx, .rcx }); | 10378 | try self.spillRegisters(&.{ .rax, .rdx, .rbx, .rcx }); |
| 10350 | const regs_lock = self.register_manager.lockRegsAssumeUnused(4, .{ .rax, .rdx, .rbx, .rcx }); | 10379 | const regs_lock = self.register_manager.lockRegsAssumeUnused(4, .{ .rax, .rdx, .rbx, .rcx }); |
| ... | @@ -10433,6 +10462,7 @@ fn atomicOp( | ... | @@ -10433,6 +10462,7 @@ fn atomicOp( |
| 10433 | rmw_op: ?std.builtin.AtomicRmwOp, | 10462 | rmw_op: ?std.builtin.AtomicRmwOp, |
| 10434 | order: std.builtin.AtomicOrder, | 10463 | order: std.builtin.AtomicOrder, |
| 10435 | ) InnerError!MCValue { | 10464 | ) InnerError!MCValue { |
| 10465 | const mod = self.bin_file.options.module.?; | ||
| 10436 | const ptr_lock = switch (ptr_mcv) { | 10466 | const ptr_lock = switch (ptr_mcv) { |
| 10437 | .register => |reg| self.register_manager.lockReg(reg), | 10467 | .register => |reg| self.register_manager.lockReg(reg), |
| 10438 | else => null, | 10468 | else => null, |
| ... | @@ -10445,7 +10475,7 @@ fn atomicOp( | ... | @@ -10445,7 +10475,7 @@ fn atomicOp( |
| 10445 | }; | 10475 | }; |
| 10446 | defer if (val_lock) |lock| self.register_manager.unlockReg(lock); | 10476 | defer if (val_lock) |lock| self.register_manager.unlockReg(lock); |
| 10447 | 10477 | ||
| 10448 | const val_abi_size = @intCast(u32, val_ty.abiSize(self.target.*)); | 10478 | const val_abi_size = @intCast(u32, val_ty.abiSize(mod)); |
| 10449 | const ptr_size = Memory.PtrSize.fromSize(val_abi_size); | 10479 | const ptr_size = Memory.PtrSize.fromSize(val_abi_size); |
| 10450 | const ptr_mem = switch (ptr_mcv) { | 10480 | const ptr_mem = switch (ptr_mcv) { |
| 10451 | .immediate, .register, .register_offset, .lea_frame => ptr_mcv.deref().mem(ptr_size), | 10481 | .immediate, .register, .register_offset, .lea_frame => ptr_mcv.deref().mem(ptr_size), |
| ... | @@ -10539,8 +10569,8 @@ fn atomicOp( | ... | @@ -10539,8 +10569,8 @@ fn atomicOp( |
| 10539 | .Or => try self.genBinOpMir(.{ ._, .@"or" }, val_ty, tmp_mcv, val_mcv), | 10569 | .Or => try self.genBinOpMir(.{ ._, .@"or" }, val_ty, tmp_mcv, val_mcv), |
| 10540 | .Xor => try self.genBinOpMir(.{ ._, .xor }, val_ty, tmp_mcv, val_mcv), | 10570 | .Xor => try self.genBinOpMir(.{ ._, .xor }, val_ty, tmp_mcv, val_mcv), |
| 10541 | .Min, .Max => { | 10571 | .Min, .Max => { |
| 10542 | const cc: Condition = switch (if (val_ty.isAbiInt()) | 10572 | const cc: Condition = switch (if (val_ty.isAbiInt(mod)) |
| 10543 | val_ty.intInfo(self.target.*).signedness | 10573 | val_ty.intInfo(mod).signedness |
| 10544 | else | 10574 | else |
| 10545 | .unsigned) { | 10575 | .unsigned) { |
| 10546 | .unsigned => switch (op) { | 10576 | .unsigned => switch (op) { |
| ... | @@ -10728,6 +10758,7 @@ fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOr | ... | @@ -10728,6 +10758,7 @@ fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOr |
| 10728 | } | 10758 | } |
| 10729 | 10759 | ||
| 10730 | fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | 10760 | fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 10761 | const mod = self.bin_file.options.module.?; | ||
| 10731 | if (safety) { | 10762 | if (safety) { |
| 10732 | // TODO if the value is undef, write 0xaa bytes to dest | 10763 | // TODO if the value is undef, write 0xaa bytes to dest |
| 10733 | } else { | 10764 | } else { |
| ... | @@ -10752,7 +10783,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -10752,7 +10783,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 10752 | }; | 10783 | }; |
| 10753 | defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock); | 10784 | defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock); |
| 10754 | 10785 | ||
| 10755 | const elem_abi_size = @intCast(u31, elem_ty.abiSize(self.target.*)); | 10786 | const elem_abi_size = @intCast(u31, elem_ty.abiSize(mod)); |
| 10756 | 10787 | ||
| 10757 | if (elem_abi_size == 1) { | 10788 | if (elem_abi_size == 1) { |
| 10758 | const ptr: MCValue = switch (dst_ptr_ty.ptrSize()) { | 10789 | const ptr: MCValue = switch (dst_ptr_ty.ptrSize()) { |
| ... | @@ -10897,8 +10928,8 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10897,8 +10928,8 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 10897 | // We need a properly aligned and sized call frame to be able to call this function. | 10928 | // We need a properly aligned and sized call frame to be able to call this function. |
| 10898 | { | 10929 | { |
| 10899 | const needed_call_frame = FrameAlloc.init(.{ | 10930 | const needed_call_frame = FrameAlloc.init(.{ |
| 10900 | .size = inst_ty.abiSize(self.target.*), | 10931 | .size = inst_ty.abiSize(mod), |
| 10901 | .alignment = inst_ty.abiAlignment(self.target.*), | 10932 | .alignment = inst_ty.abiAlignment(mod), |
| 10902 | }); | 10933 | }); |
| 10903 | const frame_allocs_slice = self.frame_allocs.slice(); | 10934 | const frame_allocs_slice = self.frame_allocs.slice(); |
| 10904 | const stack_frame_size = | 10935 | const stack_frame_size = |
| ... | @@ -11013,14 +11044,15 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11013,14 +11044,15 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 11013 | } | 11044 | } |
| 11014 | 11045 | ||
| 11015 | fn airSplat(self: *Self, inst: Air.Inst.Index) !void { | 11046 | fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 11047 | const mod = self.bin_file.options.module.?; | ||
| 11016 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 11048 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 11017 | const vector_ty = self.air.typeOfIndex(inst); | 11049 | const vector_ty = self.air.typeOfIndex(inst); |
| 11018 | const dst_rc = regClassForType(vector_ty); | 11050 | const dst_rc = regClassForType(vector_ty, mod); |
| 11019 | const scalar_ty = vector_ty.scalarType(); | 11051 | const scalar_ty = vector_ty.scalarType(mod); |
| 11020 | 11052 | ||
| 11021 | const src_mcv = try self.resolveInst(ty_op.operand); | 11053 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 11022 | const result: MCValue = result: { | 11054 | const result: MCValue = result: { |
| 11023 | switch (scalar_ty.zigTypeTag()) { | 11055 | switch (scalar_ty.zigTypeTag(mod)) { |
| 11024 | else => {}, | 11056 | else => {}, |
| 11025 | .Float => switch (scalar_ty.floatBits(self.target.*)) { | 11057 | .Float => switch (scalar_ty.floatBits(self.target.*)) { |
| 11026 | 32 => switch (vector_ty.vectorLen()) { | 11058 | 32 => switch (vector_ty.vectorLen()) { |
| ... | @@ -11233,36 +11265,37 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11233,36 +11265,37 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { |
| 11233 | } | 11265 | } |
| 11234 | 11266 | ||
| 11235 | fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | 11267 | fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11268 | const mod = self.bin_file.options.module.?; | ||
| 11236 | const result_ty = self.air.typeOfIndex(inst); | 11269 | const result_ty = self.air.typeOfIndex(inst); |
| 11237 | const len = @intCast(usize, result_ty.arrayLen()); | 11270 | const len = @intCast(usize, result_ty.arrayLen()); |
| 11238 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 11271 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 11239 | const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); | 11272 | const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); |
| 11240 | const result: MCValue = result: { | 11273 | const result: MCValue = result: { |
| 11241 | switch (result_ty.zigTypeTag()) { | 11274 | switch (result_ty.zigTypeTag(mod)) { |
| 11242 | .Struct => { | 11275 | .Struct => { |
| 11243 | const frame_index = | 11276 | const frame_index = |
| 11244 | try self.allocFrameIndex(FrameAlloc.initType(result_ty, self.target.*)); | 11277 | try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod)); |
| 11245 | if (result_ty.containerLayout() == .Packed) { | 11278 | if (result_ty.containerLayout() == .Packed) { |
| 11246 | const struct_obj = result_ty.castTag(.@"struct").?.data; | 11279 | const struct_obj = result_ty.castTag(.@"struct").?.data; |
| 11247 | try self.genInlineMemset( | 11280 | try self.genInlineMemset( |
| 11248 | .{ .lea_frame = .{ .index = frame_index } }, | 11281 | .{ .lea_frame = .{ .index = frame_index } }, |
| 11249 | .{ .immediate = 0 }, | 11282 | .{ .immediate = 0 }, |
| 11250 | .{ .immediate = result_ty.abiSize(self.target.*) }, | 11283 | .{ .immediate = result_ty.abiSize(mod) }, |
| 11251 | ); | 11284 | ); |
| 11252 | for (elements, 0..) |elem, elem_i| { | 11285 | for (elements, 0..) |elem, elem_i| { |
| 11253 | if (result_ty.structFieldValueComptime(elem_i) != null) continue; | 11286 | if (result_ty.structFieldValueComptime(mod, elem_i) != null) continue; |
| 11254 | 11287 | ||
| 11255 | const elem_ty = result_ty.structFieldType(elem_i); | 11288 | const elem_ty = result_ty.structFieldType(elem_i); |
| 11256 | const elem_bit_size = @intCast(u32, elem_ty.bitSize(self.target.*)); | 11289 | const elem_bit_size = @intCast(u32, elem_ty.bitSize(mod)); |
| 11257 | if (elem_bit_size > 64) { | 11290 | if (elem_bit_size > 64) { |
| 11258 | return self.fail( | 11291 | return self.fail( |
| 11259 | "TODO airAggregateInit implement packed structs with large fields", | 11292 | "TODO airAggregateInit implement packed structs with large fields", |
| 11260 | .{}, | 11293 | .{}, |
| 11261 | ); | 11294 | ); |
| 11262 | } | 11295 | } |
| 11263 | const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | 11296 | const elem_abi_size = @intCast(u32, elem_ty.abiSize(mod)); |
| 11264 | const elem_abi_bits = elem_abi_size * 8; | 11297 | const elem_abi_bits = elem_abi_size * 8; |
| 11265 | const elem_off = struct_obj.packedFieldBitOffset(self.target.*, elem_i); | 11298 | const elem_off = struct_obj.packedFieldBitOffset(mod, elem_i); |
| 11266 | const elem_byte_off = @intCast(i32, elem_off / elem_abi_bits * elem_abi_size); | 11299 | const elem_byte_off = @intCast(i32, elem_off / elem_abi_bits * elem_abi_size); |
| 11267 | const elem_bit_off = elem_off % elem_abi_bits; | 11300 | const elem_bit_off = elem_off % elem_abi_bits; |
| 11268 | const elem_mcv = try self.resolveInst(elem); | 11301 | const elem_mcv = try self.resolveInst(elem); |
| ... | @@ -11322,10 +11355,10 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11322,10 +11355,10 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11322 | } | 11355 | } |
| 11323 | } | 11356 | } |
| 11324 | } else for (elements, 0..) |elem, elem_i| { | 11357 | } else for (elements, 0..) |elem, elem_i| { |
| 11325 | if (result_ty.structFieldValueComptime(elem_i) != null) continue; | 11358 | if (result_ty.structFieldValueComptime(mod, elem_i) != null) continue; |
| 11326 | 11359 | ||
| 11327 | const elem_ty = result_ty.structFieldType(elem_i); | 11360 | const elem_ty = result_ty.structFieldType(elem_i); |
| 11328 | const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, self.target.*)); | 11361 | const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, mod)); |
| 11329 | const elem_mcv = try self.resolveInst(elem); | 11362 | const elem_mcv = try self.resolveInst(elem); |
| 11330 | const mat_elem_mcv = switch (elem_mcv) { | 11363 | const mat_elem_mcv = switch (elem_mcv) { |
| 11331 | .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index }, | 11364 | .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index }, |
| ... | @@ -11337,9 +11370,9 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11337,9 +11370,9 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11337 | }, | 11370 | }, |
| 11338 | .Array => { | 11371 | .Array => { |
| 11339 | const frame_index = | 11372 | const frame_index = |
| 11340 | try self.allocFrameIndex(FrameAlloc.initType(result_ty, self.target.*)); | 11373 | try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod)); |
| 11341 | const elem_ty = result_ty.childType(); | 11374 | const elem_ty = result_ty.childType(); |
| 11342 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | 11375 | const elem_size = @intCast(u32, elem_ty.abiSize(mod)); |
| 11343 | 11376 | ||
| 11344 | for (elements, 0..) |elem, elem_i| { | 11377 | for (elements, 0..) |elem, elem_i| { |
| 11345 | const elem_mcv = try self.resolveInst(elem); | 11378 | const elem_mcv = try self.resolveInst(elem); |
| ... | @@ -11374,11 +11407,12 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11374,11 +11407,12 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11374 | } | 11407 | } |
| 11375 | 11408 | ||
| 11376 | fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { | 11409 | fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11410 | const mod = self.bin_file.options.module.?; | ||
| 11377 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 11411 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 11378 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; | 11412 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 11379 | const result: MCValue = result: { | 11413 | const result: MCValue = result: { |
| 11380 | const union_ty = self.air.typeOfIndex(inst); | 11414 | const union_ty = self.air.typeOfIndex(inst); |
| 11381 | const layout = union_ty.unionGetLayout(self.target.*); | 11415 | const layout = union_ty.unionGetLayout(mod); |
| 11382 | 11416 | ||
| 11383 | const src_ty = self.air.typeOf(extra.init); | 11417 | const src_ty = self.air.typeOf(extra.init); |
| 11384 | const src_mcv = try self.resolveInst(extra.init); | 11418 | const src_mcv = try self.resolveInst(extra.init); |
| ... | @@ -11400,7 +11434,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11400,7 +11434,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11400 | const tag_val = Value.initPayload(&tag_pl.base); | 11434 | const tag_val = Value.initPayload(&tag_pl.base); |
| 11401 | var tag_int_pl: Value.Payload.U64 = undefined; | 11435 | var tag_int_pl: Value.Payload.U64 = undefined; |
| 11402 | const tag_int_val = tag_val.enumToInt(tag_ty, &tag_int_pl); | 11436 | const tag_int_val = tag_val.enumToInt(tag_ty, &tag_int_pl); |
| 11403 | const tag_int = tag_int_val.toUnsignedInt(self.target.*); | 11437 | const tag_int = tag_int_val.toUnsignedInt(mod); |
| 11404 | const tag_off = if (layout.tag_align < layout.payload_align) | 11438 | const tag_off = if (layout.tag_align < layout.payload_align) |
| 11405 | @intCast(i32, layout.payload_size) | 11439 | @intCast(i32, layout.payload_size) |
| 11406 | else | 11440 | else |
| ... | @@ -11424,6 +11458,7 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11424,6 +11458,7 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { |
| 11424 | } | 11458 | } |
| 11425 | 11459 | ||
| 11426 | fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { | 11460 | fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 11461 | const mod = self.bin_file.options.module.?; | ||
| 11427 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 11462 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 11428 | const extra = self.air.extraData(Air.Bin, pl_op.payload).data; | 11463 | const extra = self.air.extraData(Air.Bin, pl_op.payload).data; |
| 11429 | const ty = self.air.typeOfIndex(inst); | 11464 | const ty = self.air.typeOfIndex(inst); |
| ... | @@ -11466,14 +11501,14 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11466,14 +11501,14 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 11466 | const mir_tag = if (@as( | 11501 | const mir_tag = if (@as( |
| 11467 | ?Mir.Inst.FixedTag, | 11502 | ?Mir.Inst.FixedTag, |
| 11468 | if (mem.eql(u2, &order, &.{ 1, 3, 2 }) or mem.eql(u2, &order, &.{ 3, 1, 2 })) | 11503 | if (mem.eql(u2, &order, &.{ 1, 3, 2 }) or mem.eql(u2, &order, &.{ 3, 1, 2 })) |
| 11469 | switch (ty.zigTypeTag()) { | 11504 | switch (ty.zigTypeTag(mod)) { |
| 11470 | .Float => switch (ty.floatBits(self.target.*)) { | 11505 | .Float => switch (ty.floatBits(self.target.*)) { |
| 11471 | 32 => .{ .v_ss, .fmadd132 }, | 11506 | 32 => .{ .v_ss, .fmadd132 }, |
| 11472 | 64 => .{ .v_sd, .fmadd132 }, | 11507 | 64 => .{ .v_sd, .fmadd132 }, |
| 11473 | 16, 80, 128 => null, | 11508 | 16, 80, 128 => null, |
| 11474 | else => unreachable, | 11509 | else => unreachable, |
| 11475 | }, | 11510 | }, |
| 11476 | .Vector => switch (ty.childType().zigTypeTag()) { | 11511 | .Vector => switch (ty.childType().zigTypeTag(mod)) { |
| 11477 | .Float => switch (ty.childType().floatBits(self.target.*)) { | 11512 | .Float => switch (ty.childType().floatBits(self.target.*)) { |
| 11478 | 32 => switch (ty.vectorLen()) { | 11513 | 32 => switch (ty.vectorLen()) { |
| 11479 | 1 => .{ .v_ss, .fmadd132 }, | 11514 | 1 => .{ .v_ss, .fmadd132 }, |
| ... | @@ -11493,14 +11528,14 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11493,14 +11528,14 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 11493 | else => unreachable, | 11528 | else => unreachable, |
| 11494 | } | 11529 | } |
| 11495 | else if (mem.eql(u2, &order, &.{ 2, 1, 3 }) or mem.eql(u2, &order, &.{ 1, 2, 3 })) | 11530 | else if (mem.eql(u2, &order, &.{ 2, 1, 3 }) or mem.eql(u2, &order, &.{ 1, 2, 3 })) |
| 11496 | switch (ty.zigTypeTag()) { | 11531 | switch (ty.zigTypeTag(mod)) { |
| 11497 | .Float => switch (ty.floatBits(self.target.*)) { | 11532 | .Float => switch (ty.floatBits(self.target.*)) { |
| 11498 | 32 => .{ .v_ss, .fmadd213 }, | 11533 | 32 => .{ .v_ss, .fmadd213 }, |
| 11499 | 64 => .{ .v_sd, .fmadd213 }, | 11534 | 64 => .{ .v_sd, .fmadd213 }, |
| 11500 | 16, 80, 128 => null, | 11535 | 16, 80, 128 => null, |
| 11501 | else => unreachable, | 11536 | else => unreachable, |
| 11502 | }, | 11537 | }, |
| 11503 | .Vector => switch (ty.childType().zigTypeTag()) { | 11538 | .Vector => switch (ty.childType().zigTypeTag(mod)) { |
| 11504 | .Float => switch (ty.childType().floatBits(self.target.*)) { | 11539 | .Float => switch (ty.childType().floatBits(self.target.*)) { |
| 11505 | 32 => switch (ty.vectorLen()) { | 11540 | 32 => switch (ty.vectorLen()) { |
| 11506 | 1 => .{ .v_ss, .fmadd213 }, | 11541 | 1 => .{ .v_ss, .fmadd213 }, |
| ... | @@ -11520,14 +11555,14 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11520,14 +11555,14 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 11520 | else => unreachable, | 11555 | else => unreachable, |
| 11521 | } | 11556 | } |
| 11522 | else if (mem.eql(u2, &order, &.{ 2, 3, 1 }) or mem.eql(u2, &order, &.{ 3, 2, 1 })) | 11557 | else if (mem.eql(u2, &order, &.{ 2, 3, 1 }) or mem.eql(u2, &order, &.{ 3, 2, 1 })) |
| 11523 | switch (ty.zigTypeTag()) { | 11558 | switch (ty.zigTypeTag(mod)) { |
| 11524 | .Float => switch (ty.floatBits(self.target.*)) { | 11559 | .Float => switch (ty.floatBits(self.target.*)) { |
| 11525 | 32 => .{ .v_ss, .fmadd231 }, | 11560 | 32 => .{ .v_ss, .fmadd231 }, |
| 11526 | 64 => .{ .v_sd, .fmadd231 }, | 11561 | 64 => .{ .v_sd, .fmadd231 }, |
| 11527 | 16, 80, 128 => null, | 11562 | 16, 80, 128 => null, |
| 11528 | else => unreachable, | 11563 | else => unreachable, |
| 11529 | }, | 11564 | }, |
| 11530 | .Vector => switch (ty.childType().zigTypeTag()) { | 11565 | .Vector => switch (ty.childType().zigTypeTag(mod)) { |
| 11531 | .Float => switch (ty.childType().floatBits(self.target.*)) { | 11566 | .Float => switch (ty.childType().floatBits(self.target.*)) { |
| 11532 | 32 => switch (ty.vectorLen()) { | 11567 | 32 => switch (ty.vectorLen()) { |
| 11533 | 1 => .{ .v_ss, .fmadd231 }, | 11568 | 1 => .{ .v_ss, .fmadd231 }, |
| ... | @@ -11555,7 +11590,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11555,7 +11590,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 11555 | var mops: [3]MCValue = undefined; | 11590 | var mops: [3]MCValue = undefined; |
| 11556 | for (order, mcvs) |mop_index, mcv| mops[mop_index - 1] = mcv; | 11591 | for (order, mcvs) |mop_index, mcv| mops[mop_index - 1] = mcv; |
| 11557 | 11592 | ||
| 11558 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 11593 | const abi_size = @intCast(u32, ty.abiSize(mod)); |
| 11559 | const mop1_reg = registerAlias(mops[0].getReg().?, abi_size); | 11594 | const mop1_reg = registerAlias(mops[0].getReg().?, abi_size); |
| 11560 | const mop2_reg = registerAlias(mops[1].getReg().?, abi_size); | 11595 | const mop2_reg = registerAlias(mops[1].getReg().?, abi_size); |
| 11561 | if (mops[2].isRegister()) try self.asmRegisterRegisterRegister( | 11596 | if (mops[2].isRegister()) try self.asmRegisterRegisterRegister( |
| ... | @@ -11573,10 +11608,11 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11573,10 +11608,11 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 11573 | } | 11608 | } |
| 11574 | 11609 | ||
| 11575 | fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { | 11610 | fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 11611 | const mod = self.bin_file.options.module.?; | ||
| 11576 | const ty = self.air.typeOf(ref); | 11612 | const ty = self.air.typeOf(ref); |
| 11577 | 11613 | ||
| 11578 | // If the type has no codegen bits, no need to store it. | 11614 | // If the type has no codegen bits, no need to store it. |
| 11579 | if (!ty.hasRuntimeBitsIgnoreComptime()) return .none; | 11615 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return .none; |
| 11580 | 11616 | ||
| 11581 | if (Air.refToIndex(ref)) |inst| { | 11617 | if (Air.refToIndex(ref)) |inst| { |
| 11582 | const mcv = switch (self.air.instructions.items(.tag)[inst]) { | 11618 | const mcv = switch (self.air.instructions.items(.tag)[inst]) { |
| ... | @@ -11584,7 +11620,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { | ... | @@ -11584,7 +11620,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 11584 | const gop = try self.const_tracking.getOrPut(self.gpa, inst); | 11620 | const gop = try self.const_tracking.getOrPut(self.gpa, inst); |
| 11585 | if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{ | 11621 | if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{ |
| 11586 | .ty = ty, | 11622 | .ty = ty, |
| 11587 | .val = self.air.value(ref).?, | 11623 | .val = self.air.value(ref, mod).?, |
| 11588 | })); | 11624 | })); |
| 11589 | break :tracking gop.value_ptr; | 11625 | break :tracking gop.value_ptr; |
| 11590 | }, | 11626 | }, |
| ... | @@ -11597,7 +11633,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { | ... | @@ -11597,7 +11633,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 11597 | } | 11633 | } |
| 11598 | } | 11634 | } |
| 11599 | 11635 | ||
| 11600 | return self.genTypedValue(.{ .ty = ty, .val = self.air.value(ref).? }); | 11636 | return self.genTypedValue(.{ .ty = ty, .val = self.air.value(ref, mod).? }); |
| 11601 | } | 11637 | } |
| 11602 | 11638 | ||
| 11603 | fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking { | 11639 | fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking { |
| ... | @@ -11670,6 +11706,7 @@ fn resolveCallingConventionValues( | ... | @@ -11670,6 +11706,7 @@ fn resolveCallingConventionValues( |
| 11670 | var_args: []const Air.Inst.Ref, | 11706 | var_args: []const Air.Inst.Ref, |
| 11671 | stack_frame_base: FrameIndex, | 11707 | stack_frame_base: FrameIndex, |
| 11672 | ) !CallMCValues { | 11708 | ) !CallMCValues { |
| 11709 | const mod = self.bin_file.options.module.?; | ||
| 11673 | const cc = fn_ty.fnCallingConvention(); | 11710 | const cc = fn_ty.fnCallingConvention(); |
| 11674 | const param_len = fn_ty.fnParamLen(); | 11711 | const param_len = fn_ty.fnParamLen(); |
| 11675 | const param_types = try self.gpa.alloc(Type, param_len + var_args.len); | 11712 | const param_types = try self.gpa.alloc(Type, param_len + var_args.len); |
| ... | @@ -11702,21 +11739,21 @@ fn resolveCallingConventionValues( | ... | @@ -11702,21 +11739,21 @@ fn resolveCallingConventionValues( |
| 11702 | switch (self.target.os.tag) { | 11739 | switch (self.target.os.tag) { |
| 11703 | .windows => { | 11740 | .windows => { |
| 11704 | // Align the stack to 16bytes before allocating shadow stack space (if any). | 11741 | // Align the stack to 16bytes before allocating shadow stack space (if any). |
| 11705 | result.stack_byte_count += @intCast(u31, 4 * Type.usize.abiSize(self.target.*)); | 11742 | result.stack_byte_count += @intCast(u31, 4 * Type.usize.abiSize(mod)); |
| 11706 | }, | 11743 | }, |
| 11707 | else => {}, | 11744 | else => {}, |
| 11708 | } | 11745 | } |
| 11709 | 11746 | ||
| 11710 | // Return values | 11747 | // Return values |
| 11711 | if (ret_ty.zigTypeTag() == .NoReturn) { | 11748 | if (ret_ty.zigTypeTag(mod) == .NoReturn) { |
| 11712 | result.return_value = InstTracking.init(.unreach); | 11749 | result.return_value = InstTracking.init(.unreach); |
| 11713 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime()) { | 11750 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 11714 | // TODO: is this even possible for C calling convention? | 11751 | // TODO: is this even possible for C calling convention? |
| 11715 | result.return_value = InstTracking.init(.none); | 11752 | result.return_value = InstTracking.init(.none); |
| 11716 | } else { | 11753 | } else { |
| 11717 | const classes = switch (self.target.os.tag) { | 11754 | const classes = switch (self.target.os.tag) { |
| 11718 | .windows => &[1]abi.Class{abi.classifyWindows(ret_ty, self.target.*)}, | 11755 | .windows => &[1]abi.Class{abi.classifyWindows(ret_ty, mod)}, |
| 11719 | else => mem.sliceTo(&abi.classifySystemV(ret_ty, self.target.*, .ret), .none), | 11756 | else => mem.sliceTo(&abi.classifySystemV(ret_ty, mod, .ret), .none), |
| 11720 | }; | 11757 | }; |
| 11721 | if (classes.len > 1) { | 11758 | if (classes.len > 1) { |
| 11722 | return self.fail("TODO handle multiple classes per type", .{}); | 11759 | return self.fail("TODO handle multiple classes per type", .{}); |
| ... | @@ -11725,7 +11762,7 @@ fn resolveCallingConventionValues( | ... | @@ -11725,7 +11762,7 @@ fn resolveCallingConventionValues( |
| 11725 | result.return_value = switch (classes[0]) { | 11762 | result.return_value = switch (classes[0]) { |
| 11726 | .integer => InstTracking.init(.{ .register = registerAlias( | 11763 | .integer => InstTracking.init(.{ .register = registerAlias( |
| 11727 | ret_reg, | 11764 | ret_reg, |
| 11728 | @intCast(u32, ret_ty.abiSize(self.target.*)), | 11765 | @intCast(u32, ret_ty.abiSize(mod)), |
| 11729 | ) }), | 11766 | ) }), |
| 11730 | .float, .sse => InstTracking.init(.{ .register = .xmm0 }), | 11767 | .float, .sse => InstTracking.init(.{ .register = .xmm0 }), |
| 11731 | .memory => ret: { | 11768 | .memory => ret: { |
| ... | @@ -11744,11 +11781,11 @@ fn resolveCallingConventionValues( | ... | @@ -11744,11 +11781,11 @@ fn resolveCallingConventionValues( |
| 11744 | 11781 | ||
| 11745 | // Input params | 11782 | // Input params |
| 11746 | for (param_types, result.args) |ty, *arg| { | 11783 | for (param_types, result.args) |ty, *arg| { |
| 11747 | assert(ty.hasRuntimeBitsIgnoreComptime()); | 11784 | assert(ty.hasRuntimeBitsIgnoreComptime(mod)); |
| 11748 | 11785 | ||
| 11749 | const classes = switch (self.target.os.tag) { | 11786 | const classes = switch (self.target.os.tag) { |
| 11750 | .windows => &[1]abi.Class{abi.classifyWindows(ty, self.target.*)}, | 11787 | .windows => &[1]abi.Class{abi.classifyWindows(ty, mod)}, |
| 11751 | else => mem.sliceTo(&abi.classifySystemV(ty, self.target.*, .arg), .none), | 11788 | else => mem.sliceTo(&abi.classifySystemV(ty, mod, .arg), .none), |
| 11752 | }; | 11789 | }; |
| 11753 | if (classes.len > 1) { | 11790 | if (classes.len > 1) { |
| 11754 | return self.fail("TODO handle multiple classes per type", .{}); | 11791 | return self.fail("TODO handle multiple classes per type", .{}); |
| ... | @@ -11783,8 +11820,8 @@ fn resolveCallingConventionValues( | ... | @@ -11783,8 +11820,8 @@ fn resolveCallingConventionValues( |
| 11783 | }), | 11820 | }), |
| 11784 | } | 11821 | } |
| 11785 | 11822 | ||
| 11786 | const param_size = @intCast(u31, ty.abiSize(self.target.*)); | 11823 | const param_size = @intCast(u31, ty.abiSize(mod)); |
| 11787 | const param_align = @intCast(u31, ty.abiAlignment(self.target.*)); | 11824 | const param_align = @intCast(u31, ty.abiAlignment(mod)); |
| 11788 | result.stack_byte_count = | 11825 | result.stack_byte_count = |
| 11789 | mem.alignForwardGeneric(u31, result.stack_byte_count, param_align); | 11826 | mem.alignForwardGeneric(u31, result.stack_byte_count, param_align); |
| 11790 | arg.* = .{ .load_frame = .{ | 11827 | arg.* = .{ .load_frame = .{ |
| ... | @@ -11798,13 +11835,13 @@ fn resolveCallingConventionValues( | ... | @@ -11798,13 +11835,13 @@ fn resolveCallingConventionValues( |
| 11798 | result.stack_align = 16; | 11835 | result.stack_align = 16; |
| 11799 | 11836 | ||
| 11800 | // Return values | 11837 | // Return values |
| 11801 | if (ret_ty.zigTypeTag() == .NoReturn) { | 11838 | if (ret_ty.zigTypeTag(mod) == .NoReturn) { |
| 11802 | result.return_value = InstTracking.init(.unreach); | 11839 | result.return_value = InstTracking.init(.unreach); |
| 11803 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime()) { | 11840 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 11804 | result.return_value = InstTracking.init(.none); | 11841 | result.return_value = InstTracking.init(.none); |
| 11805 | } else { | 11842 | } else { |
| 11806 | const ret_reg = abi.getCAbiIntReturnRegs(self.target.*)[0]; | 11843 | const ret_reg = abi.getCAbiIntReturnRegs(self.target.*)[0]; |
| 11807 | const ret_ty_size = @intCast(u31, ret_ty.abiSize(self.target.*)); | 11844 | const ret_ty_size = @intCast(u31, ret_ty.abiSize(mod)); |
| 11808 | if (ret_ty_size <= 8 and !ret_ty.isRuntimeFloat()) { | 11845 | if (ret_ty_size <= 8 and !ret_ty.isRuntimeFloat()) { |
| 11809 | const aliased_reg = registerAlias(ret_reg, ret_ty_size); | 11846 | const aliased_reg = registerAlias(ret_reg, ret_ty_size); |
| 11810 | result.return_value = .{ .short = .{ .register = aliased_reg }, .long = .none }; | 11847 | result.return_value = .{ .short = .{ .register = aliased_reg }, .long = .none }; |
| ... | @@ -11819,12 +11856,12 @@ fn resolveCallingConventionValues( | ... | @@ -11819,12 +11856,12 @@ fn resolveCallingConventionValues( |
| 11819 | 11856 | ||
| 11820 | // Input params | 11857 | // Input params |
| 11821 | for (param_types, result.args) |ty, *arg| { | 11858 | for (param_types, result.args) |ty, *arg| { |
| 11822 | if (!ty.hasRuntimeBitsIgnoreComptime()) { | 11859 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 11823 | arg.* = .none; | 11860 | arg.* = .none; |
| 11824 | continue; | 11861 | continue; |
| 11825 | } | 11862 | } |
| 11826 | const param_size = @intCast(u31, ty.abiSize(self.target.*)); | 11863 | const param_size = @intCast(u31, ty.abiSize(mod)); |
| 11827 | const param_align = @intCast(u31, ty.abiAlignment(self.target.*)); | 11864 | const param_align = @intCast(u31, ty.abiAlignment(mod)); |
| 11828 | result.stack_byte_count = | 11865 | result.stack_byte_count = |
| 11829 | mem.alignForwardGeneric(u31, result.stack_byte_count, param_align); | 11866 | mem.alignForwardGeneric(u31, result.stack_byte_count, param_align); |
| 11830 | arg.* = .{ .load_frame = .{ | 11867 | arg.* = .{ .load_frame = .{ |
| ... | @@ -11908,9 +11945,10 @@ fn registerAlias(reg: Register, size_bytes: u32) Register { | ... | @@ -11908,9 +11945,10 @@ fn registerAlias(reg: Register, size_bytes: u32) Register { |
| 11908 | /// Truncates the value in the register in place. | 11945 | /// Truncates the value in the register in place. |
| 11909 | /// Clobbers any remaining bits. | 11946 | /// Clobbers any remaining bits. |
| 11910 | fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { | 11947 | fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { |
| 11911 | const int_info = if (ty.isAbiInt()) ty.intInfo(self.target.*) else std.builtin.Type.Int{ | 11948 | const mod = self.bin_file.options.module.?; |
| 11949 | const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{ | ||
| 11912 | .signedness = .unsigned, | 11950 | .signedness = .unsigned, |
| 11913 | .bits = @intCast(u16, ty.bitSize(self.target.*)), | 11951 | .bits = @intCast(u16, ty.bitSize(mod)), |
| 11914 | }; | 11952 | }; |
| 11915 | const max_reg_bit_width = Register.rax.bitSize(); | 11953 | const max_reg_bit_width = Register.rax.bitSize(); |
| 11916 | switch (int_info.signedness) { | 11954 | switch (int_info.signedness) { |
| ... | @@ -11953,8 +11991,9 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { | ... | @@ -11953,8 +11991,9 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { |
| 11953 | } | 11991 | } |
| 11954 | 11992 | ||
| 11955 | fn regBitSize(self: *Self, ty: Type) u64 { | 11993 | fn regBitSize(self: *Self, ty: Type) u64 { |
| 11956 | const abi_size = ty.abiSize(self.target.*); | 11994 | const mod = self.bin_file.options.module.?; |
| 11957 | return switch (ty.zigTypeTag()) { | 11995 | const abi_size = ty.abiSize(mod); |
| 11996 | return switch (ty.zigTypeTag(mod)) { | ||
| 11958 | else => switch (abi_size) { | 11997 | else => switch (abi_size) { |
| 11959 | 1 => 8, | 11998 | 1 => 8, |
| 11960 | 2 => 16, | 11999 | 2 => 16, |
| ... | @@ -11971,7 +12010,8 @@ fn regBitSize(self: *Self, ty: Type) u64 { | ... | @@ -11971,7 +12010,8 @@ fn regBitSize(self: *Self, ty: Type) u64 { |
| 11971 | } | 12010 | } |
| 11972 | 12011 | ||
| 11973 | fn regExtraBits(self: *Self, ty: Type) u64 { | 12012 | fn regExtraBits(self: *Self, ty: Type) u64 { |
| 11974 | return self.regBitSize(ty) - ty.bitSize(self.target.*); | 12013 | const mod = self.bin_file.options.module.?; |
| 12014 | return self.regBitSize(ty) - ty.bitSize(mod); | ||
| 11975 | } | 12015 | } |
| 11976 | 12016 | ||
| 11977 | fn hasFeature(self: *Self, feature: Target.x86.Feature) bool { | 12017 | fn hasFeature(self: *Self, feature: Target.x86.Feature) bool { |
src/arch/x86_64/abi.zig+26-56| ... | @@ -1,10 +1,3 @@ | ... | @@ -1,10 +1,3 @@ |
| 1 | const std = @import("std"); | ||
| 2 | const Type = @import("../../type.zig").Type; | ||
| 3 | const Target = std.Target; | ||
| 4 | const assert = std.debug.assert; | ||
| 5 | const Register = @import("bits.zig").Register; | ||
| 6 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; | ||
| 7 | |||
| 8 | pub const Class = enum { | 1 | pub const Class = enum { |
| 9 | integer, | 2 | integer, |
| 10 | sse, | 3 | sse, |
| ... | @@ -19,7 +12,7 @@ pub const Class = enum { | ... | @@ -19,7 +12,7 @@ pub const Class = enum { |
| 19 | float_combine, | 12 | float_combine, |
| 20 | }; | 13 | }; |
| 21 | 14 | ||
| 22 | pub fn classifyWindows(ty: Type, target: Target) Class { | 15 | pub fn classifyWindows(ty: Type, mod: *const Module) Class { |
| 23 | // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017 | 16 | // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017 |
| 24 | // "There's a strict one-to-one correspondence between a function call's arguments | 17 | // "There's a strict one-to-one correspondence between a function call's arguments |
| 25 | // and the registers used for those arguments. Any argument that doesn't fit in 8 | 18 | // and the registers used for those arguments. Any argument that doesn't fit in 8 |
| ... | @@ -28,7 +21,7 @@ pub fn classifyWindows(ty: Type, target: Target) Class { | ... | @@ -28,7 +21,7 @@ pub fn classifyWindows(ty: Type, target: Target) Class { |
| 28 | // "All floating point operations are done using the 16 XMM registers." | 21 | // "All floating point operations are done using the 16 XMM registers." |
| 29 | // "Structs and unions of size 8, 16, 32, or 64 bits, and __m64 types, are passed | 22 | // "Structs and unions of size 8, 16, 32, or 64 bits, and __m64 types, are passed |
| 30 | // as if they were integers of the same size." | 23 | // as if they were integers of the same size." |
| 31 | switch (ty.zigTypeTag()) { | 24 | switch (ty.zigTypeTag(mod)) { |
| 32 | .Pointer, | 25 | .Pointer, |
| 33 | .Int, | 26 | .Int, |
| 34 | .Bool, | 27 | .Bool, |
| ... | @@ -43,10 +36,10 @@ pub fn classifyWindows(ty: Type, target: Target) Class { | ... | @@ -43,10 +36,10 @@ pub fn classifyWindows(ty: Type, target: Target) Class { |
| 43 | .ErrorUnion, | 36 | .ErrorUnion, |
| 44 | .AnyFrame, | 37 | .AnyFrame, |
| 45 | .Frame, | 38 | .Frame, |
| 46 | => switch (ty.abiSize(target)) { | 39 | => switch (ty.abiSize(mod)) { |
| 47 | 0 => unreachable, | 40 | 0 => unreachable, |
| 48 | 1, 2, 4, 8 => return .integer, | 41 | 1, 2, 4, 8 => return .integer, |
| 49 | else => switch (ty.zigTypeTag()) { | 42 | else => switch (ty.zigTypeTag(mod)) { |
| 50 | .Int => return .win_i128, | 43 | .Int => return .win_i128, |
| 51 | .Struct, .Union => if (ty.containerLayout() == .Packed) { | 44 | .Struct, .Union => if (ty.containerLayout() == .Packed) { |
| 52 | return .win_i128; | 45 | return .win_i128; |
| ... | @@ -75,13 +68,14 @@ pub const Context = enum { ret, arg, other }; | ... | @@ -75,13 +68,14 @@ pub const Context = enum { ret, arg, other }; |
| 75 | 68 | ||
| 76 | /// There are a maximum of 8 possible return slots. Returned values are in | 69 | /// There are a maximum of 8 possible return slots. Returned values are in |
| 77 | /// the beginning of the array; unused slots are filled with .none. | 70 | /// the beginning of the array; unused slots are filled with .none. |
| 78 | pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { | 71 | pub fn classifySystemV(ty: Type, mod: *const Module, ctx: Context) [8]Class { |
| 72 | const target = mod.getTarget(); | ||
| 79 | const memory_class = [_]Class{ | 73 | const memory_class = [_]Class{ |
| 80 | .memory, .none, .none, .none, | 74 | .memory, .none, .none, .none, |
| 81 | .none, .none, .none, .none, | 75 | .none, .none, .none, .none, |
| 82 | }; | 76 | }; |
| 83 | var result = [1]Class{.none} ** 8; | 77 | var result = [1]Class{.none} ** 8; |
| 84 | switch (ty.zigTypeTag()) { | 78 | switch (ty.zigTypeTag(mod)) { |
| 85 | .Pointer => switch (ty.ptrSize()) { | 79 | .Pointer => switch (ty.ptrSize()) { |
| 86 | .Slice => { | 80 | .Slice => { |
| 87 | result[0] = .integer; | 81 | result[0] = .integer; |
| ... | @@ -94,7 +88,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { | ... | @@ -94,7 +88,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { |
| 94 | }, | 88 | }, |
| 95 | }, | 89 | }, |
| 96 | .Int, .Enum, .ErrorSet => { | 90 | .Int, .Enum, .ErrorSet => { |
| 97 | const bits = ty.intInfo(target).bits; | 91 | const bits = ty.intInfo(mod).bits; |
| 98 | if (bits <= 64) { | 92 | if (bits <= 64) { |
| 99 | result[0] = .integer; | 93 | result[0] = .integer; |
| 100 | return result; | 94 | return result; |
| ... | @@ -165,7 +159,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { | ... | @@ -165,7 +159,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { |
| 165 | }, | 159 | }, |
| 166 | .Vector => { | 160 | .Vector => { |
| 167 | const elem_ty = ty.childType(); | 161 | const elem_ty = ty.childType(); |
| 168 | const bits = elem_ty.bitSize(target) * ty.arrayLen(); | 162 | const bits = elem_ty.bitSize(mod) * ty.arrayLen(); |
| 169 | if (bits <= 64) return .{ | 163 | if (bits <= 64) return .{ |
| 170 | .sse, .none, .none, .none, | 164 | .sse, .none, .none, .none, |
| 171 | .none, .none, .none, .none, | 165 | .none, .none, .none, .none, |
| ... | @@ -204,7 +198,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { | ... | @@ -204,7 +198,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { |
| 204 | return memory_class; | 198 | return memory_class; |
| 205 | }, | 199 | }, |
| 206 | .Optional => { | 200 | .Optional => { |
| 207 | if (ty.isPtrLikeOptional()) { | 201 | if (ty.isPtrLikeOptional(mod)) { |
| 208 | result[0] = .integer; | 202 | result[0] = .integer; |
| 209 | return result; | 203 | return result; |
| 210 | } | 204 | } |
| ... | @@ -215,7 +209,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { | ... | @@ -215,7 +209,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { |
| 215 | // it contains unaligned fields, it has class MEMORY" | 209 | // it contains unaligned fields, it has class MEMORY" |
| 216 | // "If the size of the aggregate exceeds a single eightbyte, each is classified | 210 | // "If the size of the aggregate exceeds a single eightbyte, each is classified |
| 217 | // separately.". | 211 | // separately.". |
| 218 | const ty_size = ty.abiSize(target); | 212 | const ty_size = ty.abiSize(mod); |
| 219 | if (ty.containerLayout() == .Packed) { | 213 | if (ty.containerLayout() == .Packed) { |
| 220 | assert(ty_size <= 128); | 214 | assert(ty_size <= 128); |
| 221 | result[0] = .integer; | 215 | result[0] = .integer; |
| ... | @@ -230,12 +224,12 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { | ... | @@ -230,12 +224,12 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { |
| 230 | const fields = ty.structFields(); | 224 | const fields = ty.structFields(); |
| 231 | for (fields.values()) |field| { | 225 | for (fields.values()) |field| { |
| 232 | if (field.abi_align != 0) { | 226 | if (field.abi_align != 0) { |
| 233 | if (field.abi_align < field.ty.abiAlignment(target)) { | 227 | if (field.abi_align < field.ty.abiAlignment(mod)) { |
| 234 | return memory_class; | 228 | return memory_class; |
| 235 | } | 229 | } |
| 236 | } | 230 | } |
| 237 | const field_size = field.ty.abiSize(target); | 231 | const field_size = field.ty.abiSize(mod); |
| 238 | const field_class_array = classifySystemV(field.ty, target, .other); | 232 | const field_class_array = classifySystemV(field.ty, mod, .other); |
| 239 | const field_class = std.mem.sliceTo(&field_class_array, .none); | 233 | const field_class = std.mem.sliceTo(&field_class_array, .none); |
| 240 | if (byte_i + field_size <= 8) { | 234 | if (byte_i + field_size <= 8) { |
| 241 | // Combine this field with the previous one. | 235 | // Combine this field with the previous one. |
| ... | @@ -334,7 +328,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { | ... | @@ -334,7 +328,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { |
| 334 | // it contains unaligned fields, it has class MEMORY" | 328 | // it contains unaligned fields, it has class MEMORY" |
| 335 | // "If the size of the aggregate exceeds a single eightbyte, each is classified | 329 | // "If the size of the aggregate exceeds a single eightbyte, each is classified |
| 336 | // separately.". | 330 | // separately.". |
| 337 | const ty_size = ty.abiSize(target); | 331 | const ty_size = ty.abiSize(mod); |
| 338 | if (ty.containerLayout() == .Packed) { | 332 | if (ty.containerLayout() == .Packed) { |
| 339 | assert(ty_size <= 128); | 333 | assert(ty_size <= 128); |
| 340 | result[0] = .integer; | 334 | result[0] = .integer; |
| ... | @@ -347,12 +341,12 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { | ... | @@ -347,12 +341,12 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { |
| 347 | const fields = ty.unionFields(); | 341 | const fields = ty.unionFields(); |
| 348 | for (fields.values()) |field| { | 342 | for (fields.values()) |field| { |
| 349 | if (field.abi_align != 0) { | 343 | if (field.abi_align != 0) { |
| 350 | if (field.abi_align < field.ty.abiAlignment(target)) { | 344 | if (field.abi_align < field.ty.abiAlignment(mod)) { |
| 351 | return memory_class; | 345 | return memory_class; |
| 352 | } | 346 | } |
| 353 | } | 347 | } |
| 354 | // Combine this field with the previous one. | 348 | // Combine this field with the previous one. |
| 355 | const field_class = classifySystemV(field.ty, target, .other); | 349 | const field_class = classifySystemV(field.ty, mod, .other); |
| 356 | for (&result, 0..) |*result_item, i| { | 350 | for (&result, 0..) |*result_item, i| { |
| 357 | const field_item = field_class[i]; | 351 | const field_item = field_class[i]; |
| 358 | // "If both classes are equal, this is the resulting class." | 352 | // "If both classes are equal, this is the resulting class." |
| ... | @@ -426,7 +420,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { | ... | @@ -426,7 +420,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { |
| 426 | return result; | 420 | return result; |
| 427 | }, | 421 | }, |
| 428 | .Array => { | 422 | .Array => { |
| 429 | const ty_size = ty.abiSize(target); | 423 | const ty_size = ty.abiSize(mod); |
| 430 | if (ty_size <= 64) { | 424 | if (ty_size <= 64) { |
| 431 | result[0] = .integer; | 425 | result[0] = .integer; |
| 432 | return result; | 426 | return result; |
| ... | @@ -527,10 +521,17 @@ pub const RegisterClass = struct { | ... | @@ -527,10 +521,17 @@ pub const RegisterClass = struct { |
| 527 | }; | 521 | }; |
| 528 | }; | 522 | }; |
| 529 | 523 | ||
| 524 | const builtin = @import("builtin"); | ||
| 525 | const std = @import("std"); | ||
| 526 | const Target = std.Target; | ||
| 527 | const assert = std.debug.assert; | ||
| 530 | const testing = std.testing; | 528 | const testing = std.testing; |
| 529 | |||
| 531 | const Module = @import("../../Module.zig"); | 530 | const Module = @import("../../Module.zig"); |
| 531 | const Register = @import("bits.zig").Register; | ||
| 532 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; | ||
| 533 | const Type = @import("../../type.zig").Type; | ||
| 532 | const Value = @import("../../value.zig").Value; | 534 | const Value = @import("../../value.zig").Value; |
| 533 | const builtin = @import("builtin"); | ||
| 534 | 535 | ||
| 535 | fn _field(comptime tag: Type.Tag, offset: u32) Module.Struct.Field { | 536 | fn _field(comptime tag: Type.Tag, offset: u32) Module.Struct.Field { |
| 536 | return .{ | 537 | return .{ |
| ... | @@ -541,34 +542,3 @@ fn _field(comptime tag: Type.Tag, offset: u32) Module.Struct.Field { | ... | @@ -541,34 +542,3 @@ fn _field(comptime tag: Type.Tag, offset: u32) Module.Struct.Field { |
| 541 | .is_comptime = false, | 542 | .is_comptime = false, |
| 542 | }; | 543 | }; |
| 543 | } | 544 | } |
| 544 | |||
| 545 | test "C_C_D" { | ||
| 546 | var fields = Module.Struct.Fields{}; | ||
| 547 | // const C_C_D = extern struct { v1: i8, v2: i8, v3: f64 }; | ||
| 548 | try fields.ensureTotalCapacity(testing.allocator, 3); | ||
| 549 | defer fields.deinit(testing.allocator); | ||
| 550 | fields.putAssumeCapacity("v1", _field(.i8, 0)); | ||
| 551 | fields.putAssumeCapacity("v2", _field(.i8, 1)); | ||
| 552 | fields.putAssumeCapacity("v3", _field(.f64, 4)); | ||
| 553 | |||
| 554 | var C_C_D_struct = Module.Struct{ | ||
| 555 | .fields = fields, | ||
| 556 | .namespace = undefined, | ||
| 557 | .owner_decl = undefined, | ||
| 558 | .zir_index = undefined, | ||
| 559 | .layout = .Extern, | ||
| 560 | .status = .fully_resolved, | ||
| 561 | .known_non_opv = true, | ||
| 562 | .is_tuple = false, | ||
| 563 | }; | ||
| 564 | var C_C_D = Type.Payload.Struct{ .data = &C_C_D_struct }; | ||
| 565 | |||
| 566 | try testing.expectEqual( | ||
| 567 | [_]Class{ .integer, .sse, .none, .none, .none, .none, .none, .none }, | ||
| 568 | classifySystemV(Type.initPayload(&C_C_D.base), builtin.target, .ret), | ||
| 569 | ); | ||
| 570 | try testing.expectEqual( | ||
| 571 | [_]Class{ .integer, .sse, .none, .none, .none, .none, .none, .none }, | ||
| 572 | classifySystemV(Type.initPayload(&C_C_D.base), builtin.target, .arg), | ||
| 573 | ); | ||
| 574 | } |
src/codegen.zig+101-103| ... | @@ -154,7 +154,7 @@ pub fn generateLazySymbol( | ... | @@ -154,7 +154,7 @@ pub fn generateLazySymbol( |
| 154 | } | 154 | } |
| 155 | mem.writeInt(u32, code.items[offset..][0..4], @intCast(u32, code.items.len), endian); | 155 | mem.writeInt(u32, code.items[offset..][0..4], @intCast(u32, code.items.len), endian); |
| 156 | return Result.ok; | 156 | return Result.ok; |
| 157 | } else if (lazy_sym.ty.zigTypeTag() == .Enum) { | 157 | } else if (lazy_sym.ty.zigTypeTag(mod) == .Enum) { |
| 158 | alignment.* = 1; | 158 | alignment.* = 1; |
| 159 | for (lazy_sym.ty.enumFields().keys()) |tag_name| { | 159 | for (lazy_sym.ty.enumFields().keys()) |tag_name| { |
| 160 | try code.ensureUnusedCapacity(tag_name.len + 1); | 160 | try code.ensureUnusedCapacity(tag_name.len + 1); |
| ... | @@ -186,22 +186,22 @@ pub fn generateSymbol( | ... | @@ -186,22 +186,22 @@ pub fn generateSymbol( |
| 186 | typed_value.val = rt.data; | 186 | typed_value.val = rt.data; |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | const target = bin_file.options.target; | 189 | const mod = bin_file.options.module.?; |
| 190 | const target = mod.getTarget(); | ||
| 190 | const endian = target.cpu.arch.endian(); | 191 | const endian = target.cpu.arch.endian(); |
| 191 | 192 | ||
| 192 | const mod = bin_file.options.module.?; | ||
| 193 | log.debug("generateSymbol: ty = {}, val = {}", .{ | 193 | log.debug("generateSymbol: ty = {}, val = {}", .{ |
| 194 | typed_value.ty.fmt(mod), | 194 | typed_value.ty.fmt(mod), |
| 195 | typed_value.val.fmtValue(typed_value.ty, mod), | 195 | typed_value.val.fmtValue(typed_value.ty, mod), |
| 196 | }); | 196 | }); |
| 197 | 197 | ||
| 198 | if (typed_value.val.isUndefDeep()) { | 198 | if (typed_value.val.isUndefDeep()) { |
| 199 | const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow; | 199 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; |
| 200 | try code.appendNTimes(0xaa, abi_size); | 200 | try code.appendNTimes(0xaa, abi_size); |
| 201 | return Result.ok; | 201 | return Result.ok; |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | switch (typed_value.ty.zigTypeTag()) { | 204 | switch (typed_value.ty.zigTypeTag(mod)) { |
| 205 | .Fn => { | 205 | .Fn => { |
| 206 | return Result{ | 206 | return Result{ |
| 207 | .fail = try ErrorMsg.create( | 207 | .fail = try ErrorMsg.create( |
| ... | @@ -219,7 +219,7 @@ pub fn generateSymbol( | ... | @@ -219,7 +219,7 @@ pub fn generateSymbol( |
| 219 | 64 => writeFloat(f64, typed_value.val.toFloat(f64), target, endian, try code.addManyAsArray(8)), | 219 | 64 => writeFloat(f64, typed_value.val.toFloat(f64), target, endian, try code.addManyAsArray(8)), |
| 220 | 80 => { | 220 | 80 => { |
| 221 | writeFloat(f80, typed_value.val.toFloat(f80), target, endian, try code.addManyAsArray(10)); | 221 | writeFloat(f80, typed_value.val.toFloat(f80), target, endian, try code.addManyAsArray(10)); |
| 222 | const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow; | 222 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; |
| 223 | try code.appendNTimes(0, abi_size - 10); | 223 | try code.appendNTimes(0, abi_size - 10); |
| 224 | }, | 224 | }, |
| 225 | 128 => writeFloat(f128, typed_value.val.toFloat(f128), target, endian, try code.addManyAsArray(16)), | 225 | 128 => writeFloat(f128, typed_value.val.toFloat(f128), target, endian, try code.addManyAsArray(16)), |
| ... | @@ -242,7 +242,7 @@ pub fn generateSymbol( | ... | @@ -242,7 +242,7 @@ pub fn generateSymbol( |
| 242 | try code.ensureUnusedCapacity(bytes.len + 1); | 242 | try code.ensureUnusedCapacity(bytes.len + 1); |
| 243 | code.appendSliceAssumeCapacity(bytes); | 243 | code.appendSliceAssumeCapacity(bytes); |
| 244 | if (typed_value.ty.sentinel()) |sent_val| { | 244 | if (typed_value.ty.sentinel()) |sent_val| { |
| 245 | const byte = @intCast(u8, sent_val.toUnsignedInt(target)); | 245 | const byte = @intCast(u8, sent_val.toUnsignedInt(mod)); |
| 246 | code.appendAssumeCapacity(byte); | 246 | code.appendAssumeCapacity(byte); |
| 247 | } | 247 | } |
| 248 | return Result.ok; | 248 | return Result.ok; |
| ... | @@ -330,11 +330,11 @@ pub fn generateSymbol( | ... | @@ -330,11 +330,11 @@ pub fn generateSymbol( |
| 330 | .zero, .one, .int_u64, .int_big_positive => { | 330 | .zero, .one, .int_u64, .int_big_positive => { |
| 331 | switch (target.ptrBitWidth()) { | 331 | switch (target.ptrBitWidth()) { |
| 332 | 32 => { | 332 | 32 => { |
| 333 | const x = typed_value.val.toUnsignedInt(target); | 333 | const x = typed_value.val.toUnsignedInt(mod); |
| 334 | mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, x), endian); | 334 | mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, x), endian); |
| 335 | }, | 335 | }, |
| 336 | 64 => { | 336 | 64 => { |
| 337 | const x = typed_value.val.toUnsignedInt(target); | 337 | const x = typed_value.val.toUnsignedInt(mod); |
| 338 | mem.writeInt(u64, try code.addManyAsArray(8), x, endian); | 338 | mem.writeInt(u64, try code.addManyAsArray(8), x, endian); |
| 339 | }, | 339 | }, |
| 340 | else => unreachable, | 340 | else => unreachable, |
| ... | @@ -399,19 +399,19 @@ pub fn generateSymbol( | ... | @@ -399,19 +399,19 @@ pub fn generateSymbol( |
| 399 | }, | 399 | }, |
| 400 | }, | 400 | }, |
| 401 | .Int => { | 401 | .Int => { |
| 402 | const info = typed_value.ty.intInfo(target); | 402 | const info = typed_value.ty.intInfo(mod); |
| 403 | if (info.bits <= 8) { | 403 | if (info.bits <= 8) { |
| 404 | const x: u8 = switch (info.signedness) { | 404 | const x: u8 = switch (info.signedness) { |
| 405 | .unsigned => @intCast(u8, typed_value.val.toUnsignedInt(target)), | 405 | .unsigned => @intCast(u8, typed_value.val.toUnsignedInt(mod)), |
| 406 | .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt(target))), | 406 | .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt(mod))), |
| 407 | }; | 407 | }; |
| 408 | try code.append(x); | 408 | try code.append(x); |
| 409 | return Result.ok; | 409 | return Result.ok; |
| 410 | } | 410 | } |
| 411 | if (info.bits > 64) { | 411 | if (info.bits > 64) { |
| 412 | var bigint_buffer: Value.BigIntSpace = undefined; | 412 | var bigint_buffer: Value.BigIntSpace = undefined; |
| 413 | const bigint = typed_value.val.toBigInt(&bigint_buffer, target); | 413 | const bigint = typed_value.val.toBigInt(&bigint_buffer, mod); |
| 414 | const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow; | 414 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; |
| 415 | const start = code.items.len; | 415 | const start = code.items.len; |
| 416 | try code.resize(start + abi_size); | 416 | try code.resize(start + abi_size); |
| 417 | bigint.writeTwosComplement(code.items[start..][0..abi_size], endian); | 417 | bigint.writeTwosComplement(code.items[start..][0..abi_size], endian); |
| ... | @@ -420,25 +420,25 @@ pub fn generateSymbol( | ... | @@ -420,25 +420,25 @@ pub fn generateSymbol( |
| 420 | switch (info.signedness) { | 420 | switch (info.signedness) { |
| 421 | .unsigned => { | 421 | .unsigned => { |
| 422 | if (info.bits <= 16) { | 422 | if (info.bits <= 16) { |
| 423 | const x = @intCast(u16, typed_value.val.toUnsignedInt(target)); | 423 | const x = @intCast(u16, typed_value.val.toUnsignedInt(mod)); |
| 424 | mem.writeInt(u16, try code.addManyAsArray(2), x, endian); | 424 | mem.writeInt(u16, try code.addManyAsArray(2), x, endian); |
| 425 | } else if (info.bits <= 32) { | 425 | } else if (info.bits <= 32) { |
| 426 | const x = @intCast(u32, typed_value.val.toUnsignedInt(target)); | 426 | const x = @intCast(u32, typed_value.val.toUnsignedInt(mod)); |
| 427 | mem.writeInt(u32, try code.addManyAsArray(4), x, endian); | 427 | mem.writeInt(u32, try code.addManyAsArray(4), x, endian); |
| 428 | } else { | 428 | } else { |
| 429 | const x = typed_value.val.toUnsignedInt(target); | 429 | const x = typed_value.val.toUnsignedInt(mod); |
| 430 | mem.writeInt(u64, try code.addManyAsArray(8), x, endian); | 430 | mem.writeInt(u64, try code.addManyAsArray(8), x, endian); |
| 431 | } | 431 | } |
| 432 | }, | 432 | }, |
| 433 | .signed => { | 433 | .signed => { |
| 434 | if (info.bits <= 16) { | 434 | if (info.bits <= 16) { |
| 435 | const x = @intCast(i16, typed_value.val.toSignedInt(target)); | 435 | const x = @intCast(i16, typed_value.val.toSignedInt(mod)); |
| 436 | mem.writeInt(i16, try code.addManyAsArray(2), x, endian); | 436 | mem.writeInt(i16, try code.addManyAsArray(2), x, endian); |
| 437 | } else if (info.bits <= 32) { | 437 | } else if (info.bits <= 32) { |
| 438 | const x = @intCast(i32, typed_value.val.toSignedInt(target)); | 438 | const x = @intCast(i32, typed_value.val.toSignedInt(mod)); |
| 439 | mem.writeInt(i32, try code.addManyAsArray(4), x, endian); | 439 | mem.writeInt(i32, try code.addManyAsArray(4), x, endian); |
| 440 | } else { | 440 | } else { |
| 441 | const x = typed_value.val.toSignedInt(target); | 441 | const x = typed_value.val.toSignedInt(mod); |
| 442 | mem.writeInt(i64, try code.addManyAsArray(8), x, endian); | 442 | mem.writeInt(i64, try code.addManyAsArray(8), x, endian); |
| 443 | } | 443 | } |
| 444 | }, | 444 | }, |
| ... | @@ -449,9 +449,9 @@ pub fn generateSymbol( | ... | @@ -449,9 +449,9 @@ pub fn generateSymbol( |
| 449 | var int_buffer: Value.Payload.U64 = undefined; | 449 | var int_buffer: Value.Payload.U64 = undefined; |
| 450 | const int_val = typed_value.enumToInt(&int_buffer); | 450 | const int_val = typed_value.enumToInt(&int_buffer); |
| 451 | 451 | ||
| 452 | const info = typed_value.ty.intInfo(target); | 452 | const info = typed_value.ty.intInfo(mod); |
| 453 | if (info.bits <= 8) { | 453 | if (info.bits <= 8) { |
| 454 | const x = @intCast(u8, int_val.toUnsignedInt(target)); | 454 | const x = @intCast(u8, int_val.toUnsignedInt(mod)); |
| 455 | try code.append(x); | 455 | try code.append(x); |
| 456 | return Result.ok; | 456 | return Result.ok; |
| 457 | } | 457 | } |
| ... | @@ -468,25 +468,25 @@ pub fn generateSymbol( | ... | @@ -468,25 +468,25 @@ pub fn generateSymbol( |
| 468 | switch (info.signedness) { | 468 | switch (info.signedness) { |
| 469 | .unsigned => { | 469 | .unsigned => { |
| 470 | if (info.bits <= 16) { | 470 | if (info.bits <= 16) { |
| 471 | const x = @intCast(u16, int_val.toUnsignedInt(target)); | 471 | const x = @intCast(u16, int_val.toUnsignedInt(mod)); |
| 472 | mem.writeInt(u16, try code.addManyAsArray(2), x, endian); | 472 | mem.writeInt(u16, try code.addManyAsArray(2), x, endian); |
| 473 | } else if (info.bits <= 32) { | 473 | } else if (info.bits <= 32) { |
| 474 | const x = @intCast(u32, int_val.toUnsignedInt(target)); | 474 | const x = @intCast(u32, int_val.toUnsignedInt(mod)); |
| 475 | mem.writeInt(u32, try code.addManyAsArray(4), x, endian); | 475 | mem.writeInt(u32, try code.addManyAsArray(4), x, endian); |
| 476 | } else { | 476 | } else { |
| 477 | const x = int_val.toUnsignedInt(target); | 477 | const x = int_val.toUnsignedInt(mod); |
| 478 | mem.writeInt(u64, try code.addManyAsArray(8), x, endian); | 478 | mem.writeInt(u64, try code.addManyAsArray(8), x, endian); |
| 479 | } | 479 | } |
| 480 | }, | 480 | }, |
| 481 | .signed => { | 481 | .signed => { |
| 482 | if (info.bits <= 16) { | 482 | if (info.bits <= 16) { |
| 483 | const x = @intCast(i16, int_val.toSignedInt(target)); | 483 | const x = @intCast(i16, int_val.toSignedInt(mod)); |
| 484 | mem.writeInt(i16, try code.addManyAsArray(2), x, endian); | 484 | mem.writeInt(i16, try code.addManyAsArray(2), x, endian); |
| 485 | } else if (info.bits <= 32) { | 485 | } else if (info.bits <= 32) { |
| 486 | const x = @intCast(i32, int_val.toSignedInt(target)); | 486 | const x = @intCast(i32, int_val.toSignedInt(mod)); |
| 487 | mem.writeInt(i32, try code.addManyAsArray(4), x, endian); | 487 | mem.writeInt(i32, try code.addManyAsArray(4), x, endian); |
| 488 | } else { | 488 | } else { |
| 489 | const x = int_val.toSignedInt(target); | 489 | const x = int_val.toSignedInt(mod); |
| 490 | mem.writeInt(i64, try code.addManyAsArray(8), x, endian); | 490 | mem.writeInt(i64, try code.addManyAsArray(8), x, endian); |
| 491 | } | 491 | } |
| 492 | }, | 492 | }, |
| ... | @@ -503,7 +503,7 @@ pub fn generateSymbol( | ... | @@ -503,7 +503,7 @@ pub fn generateSymbol( |
| 503 | const struct_obj = typed_value.ty.castTag(.@"struct").?.data; | 503 | const struct_obj = typed_value.ty.castTag(.@"struct").?.data; |
| 504 | const fields = struct_obj.fields.values(); | 504 | const fields = struct_obj.fields.values(); |
| 505 | const field_vals = typed_value.val.castTag(.aggregate).?.data; | 505 | const field_vals = typed_value.val.castTag(.aggregate).?.data; |
| 506 | const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow; | 506 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; |
| 507 | const current_pos = code.items.len; | 507 | const current_pos = code.items.len; |
| 508 | try code.resize(current_pos + abi_size); | 508 | try code.resize(current_pos + abi_size); |
| 509 | var bits: u16 = 0; | 509 | var bits: u16 = 0; |
| ... | @@ -512,8 +512,8 @@ pub fn generateSymbol( | ... | @@ -512,8 +512,8 @@ pub fn generateSymbol( |
| 512 | const field_ty = fields[index].ty; | 512 | const field_ty = fields[index].ty; |
| 513 | // pointer may point to a decl which must be marked used | 513 | // pointer may point to a decl which must be marked used |
| 514 | // but can also result in a relocation. Therefore we handle those seperately. | 514 | // but can also result in a relocation. Therefore we handle those seperately. |
| 515 | if (field_ty.zigTypeTag() == .Pointer) { | 515 | if (field_ty.zigTypeTag(mod) == .Pointer) { |
| 516 | const field_size = math.cast(usize, field_ty.abiSize(target)) orelse return error.Overflow; | 516 | const field_size = math.cast(usize, field_ty.abiSize(mod)) orelse return error.Overflow; |
| 517 | var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size); | 517 | var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size); |
| 518 | defer tmp_list.deinit(); | 518 | defer tmp_list.deinit(); |
| 519 | switch (try generateSymbol(bin_file, src_loc, .{ | 519 | switch (try generateSymbol(bin_file, src_loc, .{ |
| ... | @@ -526,7 +526,7 @@ pub fn generateSymbol( | ... | @@ -526,7 +526,7 @@ pub fn generateSymbol( |
| 526 | } else { | 526 | } else { |
| 527 | field_val.writeToPackedMemory(field_ty, mod, code.items[current_pos..], bits) catch unreachable; | 527 | field_val.writeToPackedMemory(field_ty, mod, code.items[current_pos..], bits) catch unreachable; |
| 528 | } | 528 | } |
| 529 | bits += @intCast(u16, field_ty.bitSize(target)); | 529 | bits += @intCast(u16, field_ty.bitSize(mod)); |
| 530 | } | 530 | } |
| 531 | 531 | ||
| 532 | return Result.ok; | 532 | return Result.ok; |
| ... | @@ -536,7 +536,7 @@ pub fn generateSymbol( | ... | @@ -536,7 +536,7 @@ pub fn generateSymbol( |
| 536 | const field_vals = typed_value.val.castTag(.aggregate).?.data; | 536 | const field_vals = typed_value.val.castTag(.aggregate).?.data; |
| 537 | for (field_vals, 0..) |field_val, index| { | 537 | for (field_vals, 0..) |field_val, index| { |
| 538 | const field_ty = typed_value.ty.structFieldType(index); | 538 | const field_ty = typed_value.ty.structFieldType(index); |
| 539 | if (!field_ty.hasRuntimeBits()) continue; | 539 | if (!field_ty.hasRuntimeBits(mod)) continue; |
| 540 | 540 | ||
| 541 | switch (try generateSymbol(bin_file, src_loc, .{ | 541 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 542 | .ty = field_ty, | 542 | .ty = field_ty, |
| ... | @@ -548,7 +548,7 @@ pub fn generateSymbol( | ... | @@ -548,7 +548,7 @@ pub fn generateSymbol( |
| 548 | const unpadded_field_end = code.items.len - struct_begin; | 548 | const unpadded_field_end = code.items.len - struct_begin; |
| 549 | 549 | ||
| 550 | // Pad struct members if required | 550 | // Pad struct members if required |
| 551 | const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target); | 551 | const padded_field_end = typed_value.ty.structFieldOffset(index + 1, mod); |
| 552 | const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse return error.Overflow; | 552 | const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse return error.Overflow; |
| 553 | 553 | ||
| 554 | if (padding > 0) { | 554 | if (padding > 0) { |
| ... | @@ -560,7 +560,7 @@ pub fn generateSymbol( | ... | @@ -560,7 +560,7 @@ pub fn generateSymbol( |
| 560 | }, | 560 | }, |
| 561 | .Union => { | 561 | .Union => { |
| 562 | const union_obj = typed_value.val.castTag(.@"union").?.data; | 562 | const union_obj = typed_value.val.castTag(.@"union").?.data; |
| 563 | const layout = typed_value.ty.unionGetLayout(target); | 563 | const layout = typed_value.ty.unionGetLayout(mod); |
| 564 | 564 | ||
| 565 | if (layout.payload_size == 0) { | 565 | if (layout.payload_size == 0) { |
| 566 | return generateSymbol(bin_file, src_loc, .{ | 566 | return generateSymbol(bin_file, src_loc, .{ |
| ... | @@ -584,7 +584,7 @@ pub fn generateSymbol( | ... | @@ -584,7 +584,7 @@ pub fn generateSymbol( |
| 584 | const field_index = typed_value.ty.unionTagFieldIndex(union_obj.tag, mod).?; | 584 | const field_index = typed_value.ty.unionTagFieldIndex(union_obj.tag, mod).?; |
| 585 | assert(union_ty.haveFieldTypes()); | 585 | assert(union_ty.haveFieldTypes()); |
| 586 | const field_ty = union_ty.fields.values()[field_index].ty; | 586 | const field_ty = union_ty.fields.values()[field_index].ty; |
| 587 | if (!field_ty.hasRuntimeBits()) { | 587 | if (!field_ty.hasRuntimeBits(mod)) { |
| 588 | try code.writer().writeByteNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow); | 588 | try code.writer().writeByteNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow); |
| 589 | } else { | 589 | } else { |
| 590 | switch (try generateSymbol(bin_file, src_loc, .{ | 590 | switch (try generateSymbol(bin_file, src_loc, .{ |
| ... | @@ -595,7 +595,7 @@ pub fn generateSymbol( | ... | @@ -595,7 +595,7 @@ pub fn generateSymbol( |
| 595 | .fail => |em| return Result{ .fail = em }, | 595 | .fail => |em| return Result{ .fail = em }, |
| 596 | } | 596 | } |
| 597 | 597 | ||
| 598 | const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(target)) orelse return error.Overflow; | 598 | const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(mod)) orelse return error.Overflow; |
| 599 | if (padding > 0) { | 599 | if (padding > 0) { |
| 600 | try code.writer().writeByteNTimes(0, padding); | 600 | try code.writer().writeByteNTimes(0, padding); |
| 601 | } | 601 | } |
| ... | @@ -620,15 +620,15 @@ pub fn generateSymbol( | ... | @@ -620,15 +620,15 @@ pub fn generateSymbol( |
| 620 | .Optional => { | 620 | .Optional => { |
| 621 | var opt_buf: Type.Payload.ElemType = undefined; | 621 | var opt_buf: Type.Payload.ElemType = undefined; |
| 622 | const payload_type = typed_value.ty.optionalChild(&opt_buf); | 622 | const payload_type = typed_value.ty.optionalChild(&opt_buf); |
| 623 | const is_pl = !typed_value.val.isNull(); | 623 | const is_pl = !typed_value.val.isNull(mod); |
| 624 | const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow; | 624 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; |
| 625 | 625 | ||
| 626 | if (!payload_type.hasRuntimeBits()) { | 626 | if (!payload_type.hasRuntimeBits(mod)) { |
| 627 | try code.writer().writeByteNTimes(@boolToInt(is_pl), abi_size); | 627 | try code.writer().writeByteNTimes(@boolToInt(is_pl), abi_size); |
| 628 | return Result.ok; | 628 | return Result.ok; |
| 629 | } | 629 | } |
| 630 | 630 | ||
| 631 | if (typed_value.ty.optionalReprIsPayload()) { | 631 | if (typed_value.ty.optionalReprIsPayload(mod)) { |
| 632 | if (typed_value.val.castTag(.opt_payload)) |payload| { | 632 | if (typed_value.val.castTag(.opt_payload)) |payload| { |
| 633 | switch (try generateSymbol(bin_file, src_loc, .{ | 633 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 634 | .ty = payload_type, | 634 | .ty = payload_type, |
| ... | @@ -637,7 +637,7 @@ pub fn generateSymbol( | ... | @@ -637,7 +637,7 @@ pub fn generateSymbol( |
| 637 | .ok => {}, | 637 | .ok => {}, |
| 638 | .fail => |em| return Result{ .fail = em }, | 638 | .fail => |em| return Result{ .fail = em }, |
| 639 | } | 639 | } |
| 640 | } else if (!typed_value.val.isNull()) { | 640 | } else if (!typed_value.val.isNull(mod)) { |
| 641 | switch (try generateSymbol(bin_file, src_loc, .{ | 641 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 642 | .ty = payload_type, | 642 | .ty = payload_type, |
| 643 | .val = typed_value.val, | 643 | .val = typed_value.val, |
| ... | @@ -652,7 +652,7 @@ pub fn generateSymbol( | ... | @@ -652,7 +652,7 @@ pub fn generateSymbol( |
| 652 | return Result.ok; | 652 | return Result.ok; |
| 653 | } | 653 | } |
| 654 | 654 | ||
| 655 | const padding = abi_size - (math.cast(usize, payload_type.abiSize(target)) orelse return error.Overflow) - 1; | 655 | const padding = abi_size - (math.cast(usize, payload_type.abiSize(mod)) orelse return error.Overflow) - 1; |
| 656 | const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.initTag(.undef); | 656 | const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.initTag(.undef); |
| 657 | switch (try generateSymbol(bin_file, src_loc, .{ | 657 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 658 | .ty = payload_type, | 658 | .ty = payload_type, |
| ... | @@ -671,7 +671,7 @@ pub fn generateSymbol( | ... | @@ -671,7 +671,7 @@ pub fn generateSymbol( |
| 671 | const payload_ty = typed_value.ty.errorUnionPayload(); | 671 | const payload_ty = typed_value.ty.errorUnionPayload(); |
| 672 | const is_payload = typed_value.val.errorUnionIsPayload(); | 672 | const is_payload = typed_value.val.errorUnionIsPayload(); |
| 673 | 673 | ||
| 674 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 674 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 675 | const err_val = if (is_payload) Value.initTag(.zero) else typed_value.val; | 675 | const err_val = if (is_payload) Value.initTag(.zero) else typed_value.val; |
| 676 | return generateSymbol(bin_file, src_loc, .{ | 676 | return generateSymbol(bin_file, src_loc, .{ |
| 677 | .ty = error_ty, | 677 | .ty = error_ty, |
| ... | @@ -679,9 +679,9 @@ pub fn generateSymbol( | ... | @@ -679,9 +679,9 @@ pub fn generateSymbol( |
| 679 | }, code, debug_output, reloc_info); | 679 | }, code, debug_output, reloc_info); |
| 680 | } | 680 | } |
| 681 | 681 | ||
| 682 | const payload_align = payload_ty.abiAlignment(target); | 682 | const payload_align = payload_ty.abiAlignment(mod); |
| 683 | const error_align = Type.anyerror.abiAlignment(target); | 683 | const error_align = Type.anyerror.abiAlignment(mod); |
| 684 | const abi_align = typed_value.ty.abiAlignment(target); | 684 | const abi_align = typed_value.ty.abiAlignment(mod); |
| 685 | 685 | ||
| 686 | // error value first when its type is larger than the error union's payload | 686 | // error value first when its type is larger than the error union's payload |
| 687 | if (error_align > payload_align) { | 687 | if (error_align > payload_align) { |
| ... | @@ -743,7 +743,7 @@ pub fn generateSymbol( | ... | @@ -743,7 +743,7 @@ pub fn generateSymbol( |
| 743 | try code.writer().writeInt(u32, kv.value, endian); | 743 | try code.writer().writeInt(u32, kv.value, endian); |
| 744 | }, | 744 | }, |
| 745 | else => { | 745 | else => { |
| 746 | try code.writer().writeByteNTimes(0, @intCast(usize, Type.anyerror.abiSize(target))); | 746 | try code.writer().writeByteNTimes(0, @intCast(usize, Type.anyerror.abiSize(mod))); |
| 747 | }, | 747 | }, |
| 748 | } | 748 | } |
| 749 | return Result.ok; | 749 | return Result.ok; |
| ... | @@ -752,7 +752,7 @@ pub fn generateSymbol( | ... | @@ -752,7 +752,7 @@ pub fn generateSymbol( |
| 752 | .bytes => { | 752 | .bytes => { |
| 753 | const bytes = typed_value.val.castTag(.bytes).?.data; | 753 | const bytes = typed_value.val.castTag(.bytes).?.data; |
| 754 | const len = math.cast(usize, typed_value.ty.arrayLen()) orelse return error.Overflow; | 754 | const len = math.cast(usize, typed_value.ty.arrayLen()) orelse return error.Overflow; |
| 755 | const padding = math.cast(usize, typed_value.ty.abiSize(target) - len) orelse | 755 | const padding = math.cast(usize, typed_value.ty.abiSize(mod) - len) orelse |
| 756 | return error.Overflow; | 756 | return error.Overflow; |
| 757 | try code.ensureUnusedCapacity(len + padding); | 757 | try code.ensureUnusedCapacity(len + padding); |
| 758 | code.appendSliceAssumeCapacity(bytes[0..len]); | 758 | code.appendSliceAssumeCapacity(bytes[0..len]); |
| ... | @@ -763,8 +763,8 @@ pub fn generateSymbol( | ... | @@ -763,8 +763,8 @@ pub fn generateSymbol( |
| 763 | const elem_vals = typed_value.val.castTag(.aggregate).?.data; | 763 | const elem_vals = typed_value.val.castTag(.aggregate).?.data; |
| 764 | const elem_ty = typed_value.ty.elemType(); | 764 | const elem_ty = typed_value.ty.elemType(); |
| 765 | const len = math.cast(usize, typed_value.ty.arrayLen()) orelse return error.Overflow; | 765 | const len = math.cast(usize, typed_value.ty.arrayLen()) orelse return error.Overflow; |
| 766 | const padding = math.cast(usize, typed_value.ty.abiSize(target) - | 766 | const padding = math.cast(usize, typed_value.ty.abiSize(mod) - |
| 767 | (math.divCeil(u64, elem_ty.bitSize(target) * len, 8) catch |err| switch (err) { | 767 | (math.divCeil(u64, elem_ty.bitSize(mod) * len, 8) catch |err| switch (err) { |
| 768 | error.DivisionByZero => unreachable, | 768 | error.DivisionByZero => unreachable, |
| 769 | else => |e| return e, | 769 | else => |e| return e, |
| 770 | })) orelse return error.Overflow; | 770 | })) orelse return error.Overflow; |
| ... | @@ -784,8 +784,8 @@ pub fn generateSymbol( | ... | @@ -784,8 +784,8 @@ pub fn generateSymbol( |
| 784 | const array = typed_value.val.castTag(.repeated).?.data; | 784 | const array = typed_value.val.castTag(.repeated).?.data; |
| 785 | const elem_ty = typed_value.ty.childType(); | 785 | const elem_ty = typed_value.ty.childType(); |
| 786 | const len = typed_value.ty.arrayLen(); | 786 | const len = typed_value.ty.arrayLen(); |
| 787 | const padding = math.cast(usize, typed_value.ty.abiSize(target) - | 787 | const padding = math.cast(usize, typed_value.ty.abiSize(mod) - |
| 788 | (math.divCeil(u64, elem_ty.bitSize(target) * len, 8) catch |err| switch (err) { | 788 | (math.divCeil(u64, elem_ty.bitSize(mod) * len, 8) catch |err| switch (err) { |
| 789 | error.DivisionByZero => unreachable, | 789 | error.DivisionByZero => unreachable, |
| 790 | else => |e| return e, | 790 | else => |e| return e, |
| 791 | })) orelse return error.Overflow; | 791 | })) orelse return error.Overflow; |
| ... | @@ -805,7 +805,7 @@ pub fn generateSymbol( | ... | @@ -805,7 +805,7 @@ pub fn generateSymbol( |
| 805 | .str_lit => { | 805 | .str_lit => { |
| 806 | const str_lit = typed_value.val.castTag(.str_lit).?.data; | 806 | const str_lit = typed_value.val.castTag(.str_lit).?.data; |
| 807 | const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | 807 | const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; |
| 808 | const padding = math.cast(usize, typed_value.ty.abiSize(target) - str_lit.len) orelse | 808 | const padding = math.cast(usize, typed_value.ty.abiSize(mod) - str_lit.len) orelse |
| 809 | return error.Overflow; | 809 | return error.Overflow; |
| 810 | try code.ensureUnusedCapacity(str_lit.len + padding); | 810 | try code.ensureUnusedCapacity(str_lit.len + padding); |
| 811 | code.appendSliceAssumeCapacity(bytes); | 811 | code.appendSliceAssumeCapacity(bytes); |
| ... | @@ -832,7 +832,7 @@ fn lowerParentPtr( | ... | @@ -832,7 +832,7 @@ fn lowerParentPtr( |
| 832 | debug_output: DebugInfoOutput, | 832 | debug_output: DebugInfoOutput, |
| 833 | reloc_info: RelocInfo, | 833 | reloc_info: RelocInfo, |
| 834 | ) CodeGenError!Result { | 834 | ) CodeGenError!Result { |
| 835 | const target = bin_file.options.target; | 835 | const mod = bin_file.options.module.?; |
| 836 | switch (parent_ptr.tag()) { | 836 | switch (parent_ptr.tag()) { |
| 837 | .field_ptr => { | 837 | .field_ptr => { |
| 838 | const field_ptr = parent_ptr.castTag(.field_ptr).?.data; | 838 | const field_ptr = parent_ptr.castTag(.field_ptr).?.data; |
| ... | @@ -843,19 +843,19 @@ fn lowerParentPtr( | ... | @@ -843,19 +843,19 @@ fn lowerParentPtr( |
| 843 | field_ptr.container_ptr, | 843 | field_ptr.container_ptr, |
| 844 | code, | 844 | code, |
| 845 | debug_output, | 845 | debug_output, |
| 846 | reloc_info.offset(@intCast(u32, switch (field_ptr.container_ty.zigTypeTag()) { | 846 | reloc_info.offset(@intCast(u32, switch (field_ptr.container_ty.zigTypeTag(mod)) { |
| 847 | .Pointer => offset: { | 847 | .Pointer => offset: { |
| 848 | assert(field_ptr.container_ty.isSlice()); | 848 | assert(field_ptr.container_ty.isSlice()); |
| 849 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 849 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 850 | break :offset switch (field_ptr.field_index) { | 850 | break :offset switch (field_ptr.field_index) { |
| 851 | 0 => 0, | 851 | 0 => 0, |
| 852 | 1 => field_ptr.container_ty.slicePtrFieldType(&buf).abiSize(target), | 852 | 1 => field_ptr.container_ty.slicePtrFieldType(&buf).abiSize(mod), |
| 853 | else => unreachable, | 853 | else => unreachable, |
| 854 | }; | 854 | }; |
| 855 | }, | 855 | }, |
| 856 | .Struct, .Union => field_ptr.container_ty.structFieldOffset( | 856 | .Struct, .Union => field_ptr.container_ty.structFieldOffset( |
| 857 | field_ptr.field_index, | 857 | field_ptr.field_index, |
| 858 | target, | 858 | mod, |
| 859 | ), | 859 | ), |
| 860 | else => return Result{ .fail = try ErrorMsg.create( | 860 | else => return Result{ .fail = try ErrorMsg.create( |
| 861 | bin_file.allocator, | 861 | bin_file.allocator, |
| ... | @@ -875,7 +875,7 @@ fn lowerParentPtr( | ... | @@ -875,7 +875,7 @@ fn lowerParentPtr( |
| 875 | elem_ptr.array_ptr, | 875 | elem_ptr.array_ptr, |
| 876 | code, | 876 | code, |
| 877 | debug_output, | 877 | debug_output, |
| 878 | reloc_info.offset(@intCast(u32, elem_ptr.index * elem_ptr.elem_ty.abiSize(target))), | 878 | reloc_info.offset(@intCast(u32, elem_ptr.index * elem_ptr.elem_ty.abiSize(mod))), |
| 879 | ); | 879 | ); |
| 880 | }, | 880 | }, |
| 881 | .opt_payload_ptr => { | 881 | .opt_payload_ptr => { |
| ... | @@ -900,7 +900,7 @@ fn lowerParentPtr( | ... | @@ -900,7 +900,7 @@ fn lowerParentPtr( |
| 900 | eu_payload_ptr.container_ptr, | 900 | eu_payload_ptr.container_ptr, |
| 901 | code, | 901 | code, |
| 902 | debug_output, | 902 | debug_output, |
| 903 | reloc_info.offset(@intCast(u32, errUnionPayloadOffset(pl_ty, target))), | 903 | reloc_info.offset(@intCast(u32, errUnionPayloadOffset(pl_ty, mod))), |
| 904 | ); | 904 | ); |
| 905 | }, | 905 | }, |
| 906 | .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef( | 906 | .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef( |
| ... | @@ -945,7 +945,7 @@ fn lowerDeclRef( | ... | @@ -945,7 +945,7 @@ fn lowerDeclRef( |
| 945 | reloc_info: RelocInfo, | 945 | reloc_info: RelocInfo, |
| 946 | ) CodeGenError!Result { | 946 | ) CodeGenError!Result { |
| 947 | const target = bin_file.options.target; | 947 | const target = bin_file.options.target; |
| 948 | const module = bin_file.options.module.?; | 948 | const mod = bin_file.options.module.?; |
| 949 | if (typed_value.ty.isSlice()) { | 949 | if (typed_value.ty.isSlice()) { |
| 950 | // generate ptr | 950 | // generate ptr |
| 951 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 951 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| ... | @@ -961,7 +961,7 @@ fn lowerDeclRef( | ... | @@ -961,7 +961,7 @@ fn lowerDeclRef( |
| 961 | // generate length | 961 | // generate length |
| 962 | var slice_len: Value.Payload.U64 = .{ | 962 | var slice_len: Value.Payload.U64 = .{ |
| 963 | .base = .{ .tag = .int_u64 }, | 963 | .base = .{ .tag = .int_u64 }, |
| 964 | .data = typed_value.val.sliceLen(module), | 964 | .data = typed_value.val.sliceLen(mod), |
| 965 | }; | 965 | }; |
| 966 | switch (try generateSymbol(bin_file, src_loc, .{ | 966 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 967 | .ty = Type.usize, | 967 | .ty = Type.usize, |
| ... | @@ -975,14 +975,14 @@ fn lowerDeclRef( | ... | @@ -975,14 +975,14 @@ fn lowerDeclRef( |
| 975 | } | 975 | } |
| 976 | 976 | ||
| 977 | const ptr_width = target.ptrBitWidth(); | 977 | const ptr_width = target.ptrBitWidth(); |
| 978 | const decl = module.declPtr(decl_index); | 978 | const decl = mod.declPtr(decl_index); |
| 979 | const is_fn_body = decl.ty.zigTypeTag() == .Fn; | 979 | const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn; |
| 980 | if (!is_fn_body and !decl.ty.hasRuntimeBits()) { | 980 | if (!is_fn_body and !decl.ty.hasRuntimeBits(mod)) { |
| 981 | try code.writer().writeByteNTimes(0xaa, @divExact(ptr_width, 8)); | 981 | try code.writer().writeByteNTimes(0xaa, @divExact(ptr_width, 8)); |
| 982 | return Result.ok; | 982 | return Result.ok; |
| 983 | } | 983 | } |
| 984 | 984 | ||
| 985 | module.markDeclAlive(decl); | 985 | mod.markDeclAlive(decl); |
| 986 | 986 | ||
| 987 | const vaddr = try bin_file.getDeclVAddr(decl_index, .{ | 987 | const vaddr = try bin_file.getDeclVAddr(decl_index, .{ |
| 988 | .parent_atom_index = reloc_info.parent_atom_index, | 988 | .parent_atom_index = reloc_info.parent_atom_index, |
| ... | @@ -1059,16 +1059,16 @@ fn genDeclRef( | ... | @@ -1059,16 +1059,16 @@ fn genDeclRef( |
| 1059 | tv: TypedValue, | 1059 | tv: TypedValue, |
| 1060 | decl_index: Module.Decl.Index, | 1060 | decl_index: Module.Decl.Index, |
| 1061 | ) CodeGenError!GenResult { | 1061 | ) CodeGenError!GenResult { |
| 1062 | const module = bin_file.options.module.?; | 1062 | const mod = bin_file.options.module.?; |
| 1063 | log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(module), tv.val.fmtValue(tv.ty, module) }); | 1063 | log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(mod), tv.val.fmtValue(tv.ty, mod) }); |
| 1064 | 1064 | ||
| 1065 | const target = bin_file.options.target; | 1065 | const target = bin_file.options.target; |
| 1066 | const ptr_bits = target.ptrBitWidth(); | 1066 | const ptr_bits = target.ptrBitWidth(); |
| 1067 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | 1067 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 1068 | 1068 | ||
| 1069 | const decl = module.declPtr(decl_index); | 1069 | const decl = mod.declPtr(decl_index); |
| 1070 | 1070 | ||
| 1071 | if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime()) { | 1071 | if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) { |
| 1072 | const imm: u64 = switch (ptr_bytes) { | 1072 | const imm: u64 = switch (ptr_bytes) { |
| 1073 | 1 => 0xaa, | 1073 | 1 => 0xaa, |
| 1074 | 2 => 0xaaaa, | 1074 | 2 => 0xaaaa, |
| ... | @@ -1080,20 +1080,20 @@ fn genDeclRef( | ... | @@ -1080,20 +1080,20 @@ fn genDeclRef( |
| 1080 | } | 1080 | } |
| 1081 | 1081 | ||
| 1082 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? | 1082 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? |
| 1083 | if (tv.ty.castPtrToFn()) |fn_ty| { | 1083 | if (tv.ty.castPtrToFn(mod)) |fn_ty| { |
| 1084 | if (fn_ty.fnInfo().is_generic) { | 1084 | if (fn_ty.fnInfo().is_generic) { |
| 1085 | return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(target) }); | 1085 | return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(mod) }); |
| 1086 | } | 1086 | } |
| 1087 | } else if (tv.ty.zigTypeTag() == .Pointer) { | 1087 | } else if (tv.ty.zigTypeTag(mod) == .Pointer) { |
| 1088 | const elem_ty = tv.ty.elemType2(); | 1088 | const elem_ty = tv.ty.elemType2(mod); |
| 1089 | if (!elem_ty.hasRuntimeBits()) { | 1089 | if (!elem_ty.hasRuntimeBits(mod)) { |
| 1090 | return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(target) }); | 1090 | return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(mod) }); |
| 1091 | } | 1091 | } |
| 1092 | } | 1092 | } |
| 1093 | 1093 | ||
| 1094 | module.markDeclAlive(decl); | 1094 | mod.markDeclAlive(decl); |
| 1095 | 1095 | ||
| 1096 | const is_threadlocal = tv.val.isPtrToThreadLocal(module) and !bin_file.options.single_threaded; | 1096 | const is_threadlocal = tv.val.isPtrToThreadLocal(mod) and !bin_file.options.single_threaded; |
| 1097 | 1097 | ||
| 1098 | if (bin_file.cast(link.File.Elf)) |elf_file| { | 1098 | if (bin_file.cast(link.File.Elf)) |elf_file| { |
| 1099 | const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index); | 1099 | const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index); |
| ... | @@ -1186,7 +1186,7 @@ pub fn genTypedValue( | ... | @@ -1186,7 +1186,7 @@ pub fn genTypedValue( |
| 1186 | } | 1186 | } |
| 1187 | } | 1187 | } |
| 1188 | 1188 | ||
| 1189 | switch (typed_value.ty.zigTypeTag()) { | 1189 | switch (typed_value.ty.zigTypeTag(mod)) { |
| 1190 | .Void => return GenResult.mcv(.none), | 1190 | .Void => return GenResult.mcv(.none), |
| 1191 | .Pointer => switch (typed_value.ty.ptrSize()) { | 1191 | .Pointer => switch (typed_value.ty.ptrSize()) { |
| 1192 | .Slice => {}, | 1192 | .Slice => {}, |
| ... | @@ -1196,18 +1196,18 @@ pub fn genTypedValue( | ... | @@ -1196,18 +1196,18 @@ pub fn genTypedValue( |
| 1196 | return GenResult.mcv(.{ .immediate = 0 }); | 1196 | return GenResult.mcv(.{ .immediate = 0 }); |
| 1197 | }, | 1197 | }, |
| 1198 | .int_u64 => { | 1198 | .int_u64 => { |
| 1199 | return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(target) }); | 1199 | return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(mod) }); |
| 1200 | }, | 1200 | }, |
| 1201 | else => {}, | 1201 | else => {}, |
| 1202 | } | 1202 | } |
| 1203 | }, | 1203 | }, |
| 1204 | }, | 1204 | }, |
| 1205 | .Int => { | 1205 | .Int => { |
| 1206 | const info = typed_value.ty.intInfo(target); | 1206 | const info = typed_value.ty.intInfo(mod); |
| 1207 | if (info.bits <= ptr_bits) { | 1207 | if (info.bits <= ptr_bits) { |
| 1208 | const unsigned = switch (info.signedness) { | 1208 | const unsigned = switch (info.signedness) { |
| 1209 | .signed => @bitCast(u64, typed_value.val.toSignedInt(target)), | 1209 | .signed => @bitCast(u64, typed_value.val.toSignedInt(mod)), |
| 1210 | .unsigned => typed_value.val.toUnsignedInt(target), | 1210 | .unsigned => typed_value.val.toUnsignedInt(mod), |
| 1211 | }; | 1211 | }; |
| 1212 | return GenResult.mcv(.{ .immediate = unsigned }); | 1212 | return GenResult.mcv(.{ .immediate = unsigned }); |
| 1213 | } | 1213 | } |
| ... | @@ -1216,7 +1216,7 @@ pub fn genTypedValue( | ... | @@ -1216,7 +1216,7 @@ pub fn genTypedValue( |
| 1216 | return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool()) }); | 1216 | return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool()) }); |
| 1217 | }, | 1217 | }, |
| 1218 | .Optional => { | 1218 | .Optional => { |
| 1219 | if (typed_value.ty.isPtrLikeOptional()) { | 1219 | if (typed_value.ty.isPtrLikeOptional(mod)) { |
| 1220 | if (typed_value.val.tag() == .null_value) return GenResult.mcv(.{ .immediate = 0 }); | 1220 | if (typed_value.val.tag() == .null_value) return GenResult.mcv(.{ .immediate = 0 }); |
| 1221 | 1221 | ||
| 1222 | var buf: Type.Payload.ElemType = undefined; | 1222 | var buf: Type.Payload.ElemType = undefined; |
| ... | @@ -1224,8 +1224,8 @@ pub fn genTypedValue( | ... | @@ -1224,8 +1224,8 @@ pub fn genTypedValue( |
| 1224 | .ty = typed_value.ty.optionalChild(&buf), | 1224 | .ty = typed_value.ty.optionalChild(&buf), |
| 1225 | .val = if (typed_value.val.castTag(.opt_payload)) |pl| pl.data else typed_value.val, | 1225 | .val = if (typed_value.val.castTag(.opt_payload)) |pl| pl.data else typed_value.val, |
| 1226 | }, owner_decl_index); | 1226 | }, owner_decl_index); |
| 1227 | } else if (typed_value.ty.abiSize(target) == 1) { | 1227 | } else if (typed_value.ty.abiSize(mod) == 1) { |
| 1228 | return GenResult.mcv(.{ .immediate = @boolToInt(!typed_value.val.isNull()) }); | 1228 | return GenResult.mcv(.{ .immediate = @boolToInt(!typed_value.val.isNull(mod)) }); |
| 1229 | } | 1229 | } |
| 1230 | }, | 1230 | }, |
| 1231 | .Enum => { | 1231 | .Enum => { |
| ... | @@ -1241,9 +1241,8 @@ pub fn genTypedValue( | ... | @@ -1241,9 +1241,8 @@ pub fn genTypedValue( |
| 1241 | typed_value.ty.cast(Type.Payload.EnumFull).?.data.values; | 1241 | typed_value.ty.cast(Type.Payload.EnumFull).?.data.values; |
| 1242 | if (enum_values.count() != 0) { | 1242 | if (enum_values.count() != 0) { |
| 1243 | const tag_val = enum_values.keys()[field_index.data]; | 1243 | const tag_val = enum_values.keys()[field_index.data]; |
| 1244 | var buf: Type.Payload.Bits = undefined; | ||
| 1245 | return genTypedValue(bin_file, src_loc, .{ | 1244 | return genTypedValue(bin_file, src_loc, .{ |
| 1246 | .ty = typed_value.ty.intTagType(&buf), | 1245 | .ty = typed_value.ty.intTagType(), |
| 1247 | .val = tag_val, | 1246 | .val = tag_val, |
| 1248 | }, owner_decl_index); | 1247 | }, owner_decl_index); |
| 1249 | } else { | 1248 | } else { |
| ... | @@ -1253,8 +1252,7 @@ pub fn genTypedValue( | ... | @@ -1253,8 +1252,7 @@ pub fn genTypedValue( |
| 1253 | else => unreachable, | 1252 | else => unreachable, |
| 1254 | } | 1253 | } |
| 1255 | } else { | 1254 | } else { |
| 1256 | var int_tag_buffer: Type.Payload.Bits = undefined; | 1255 | const int_tag_ty = typed_value.ty.intTagType(); |
| 1257 | const int_tag_ty = typed_value.ty.intTagType(&int_tag_buffer); | ||
| 1258 | return genTypedValue(bin_file, src_loc, .{ | 1256 | return genTypedValue(bin_file, src_loc, .{ |
| 1259 | .ty = int_tag_ty, | 1257 | .ty = int_tag_ty, |
| 1260 | .val = typed_value.val, | 1258 | .val = typed_value.val, |
| ... | @@ -1281,7 +1279,7 @@ pub fn genTypedValue( | ... | @@ -1281,7 +1279,7 @@ pub fn genTypedValue( |
| 1281 | const payload_type = typed_value.ty.errorUnionPayload(); | 1279 | const payload_type = typed_value.ty.errorUnionPayload(); |
| 1282 | const is_pl = typed_value.val.errorUnionIsPayload(); | 1280 | const is_pl = typed_value.val.errorUnionIsPayload(); |
| 1283 | 1281 | ||
| 1284 | if (!payload_type.hasRuntimeBitsIgnoreComptime()) { | 1282 | if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1285 | // We use the error type directly as the type. | 1283 | // We use the error type directly as the type. |
| 1286 | const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero); | 1284 | const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero); |
| 1287 | return genTypedValue(bin_file, src_loc, .{ | 1285 | return genTypedValue(bin_file, src_loc, .{ |
| ... | @@ -1306,23 +1304,23 @@ pub fn genTypedValue( | ... | @@ -1306,23 +1304,23 @@ pub fn genTypedValue( |
| 1306 | return genUnnamedConst(bin_file, src_loc, typed_value, owner_decl_index); | 1304 | return genUnnamedConst(bin_file, src_loc, typed_value, owner_decl_index); |
| 1307 | } | 1305 | } |
| 1308 | 1306 | ||
| 1309 | pub fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u64 { | 1307 | pub fn errUnionPayloadOffset(payload_ty: Type, mod: *const Module) u64 { |
| 1310 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return 0; | 1308 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return 0; |
| 1311 | const payload_align = payload_ty.abiAlignment(target); | 1309 | const payload_align = payload_ty.abiAlignment(mod); |
| 1312 | const error_align = Type.anyerror.abiAlignment(target); | 1310 | const error_align = Type.anyerror.abiAlignment(mod); |
| 1313 | if (payload_align >= error_align or !payload_ty.hasRuntimeBitsIgnoreComptime()) { | 1311 | if (payload_align >= error_align or !payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1314 | return 0; | 1312 | return 0; |
| 1315 | } else { | 1313 | } else { |
| 1316 | return mem.alignForwardGeneric(u64, Type.anyerror.abiSize(target), payload_align); | 1314 | return mem.alignForwardGeneric(u64, Type.anyerror.abiSize(mod), payload_align); |
| 1317 | } | 1315 | } |
| 1318 | } | 1316 | } |
| 1319 | 1317 | ||
| 1320 | pub fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u64 { | 1318 | pub fn errUnionErrorOffset(payload_ty: Type, mod: *const Module) u64 { |
| 1321 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return 0; | 1319 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return 0; |
| 1322 | const payload_align = payload_ty.abiAlignment(target); | 1320 | const payload_align = payload_ty.abiAlignment(mod); |
| 1323 | const error_align = Type.anyerror.abiAlignment(target); | 1321 | const error_align = Type.anyerror.abiAlignment(mod); |
| 1324 | if (payload_align >= error_align and payload_ty.hasRuntimeBitsIgnoreComptime()) { | 1322 | if (payload_align >= error_align and payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1325 | return mem.alignForwardGeneric(u64, payload_ty.abiSize(target), error_align); | 1323 | return mem.alignForwardGeneric(u64, payload_ty.abiSize(mod), error_align); |
| 1326 | } else { | 1324 | } else { |
| 1327 | return 0; | 1325 | return 0; |
| 1328 | } | 1326 | } |
src/codegen/c.zig+368-359| ... | @@ -16,6 +16,7 @@ const trace = @import("../tracy.zig").trace; | ... | @@ -16,6 +16,7 @@ const trace = @import("../tracy.zig").trace; |
| 16 | const LazySrcLoc = Module.LazySrcLoc; | 16 | const LazySrcLoc = Module.LazySrcLoc; |
| 17 | const Air = @import("../Air.zig"); | 17 | const Air = @import("../Air.zig"); |
| 18 | const Liveness = @import("../Liveness.zig"); | 18 | const Liveness = @import("../Liveness.zig"); |
| 19 | const InternPool = @import("../InternPool.zig"); | ||
| 19 | 20 | ||
| 20 | const BigIntLimb = std.math.big.Limb; | 21 | const BigIntLimb = std.math.big.Limb; |
| 21 | const BigInt = std.math.big.int; | 22 | const BigInt = std.math.big.int; |
| ... | @@ -285,10 +286,11 @@ pub const Function = struct { | ... | @@ -285,10 +286,11 @@ pub const Function = struct { |
| 285 | const gop = try f.value_map.getOrPut(inst); | 286 | const gop = try f.value_map.getOrPut(inst); |
| 286 | if (gop.found_existing) return gop.value_ptr.*; | 287 | if (gop.found_existing) return gop.value_ptr.*; |
| 287 | 288 | ||
| 288 | const val = f.air.value(ref).?; | 289 | const mod = f.object.dg.module; |
| 290 | const val = f.air.value(ref, mod).?; | ||
| 289 | const ty = f.air.typeOf(ref); | 291 | const ty = f.air.typeOf(ref); |
| 290 | 292 | ||
| 291 | const result: CValue = if (lowersToArray(ty, f.object.dg.module.getTarget())) result: { | 293 | const result: CValue = if (lowersToArray(ty, mod)) result: { |
| 292 | const writer = f.object.code_header.writer(); | 294 | const writer = f.object.code_header.writer(); |
| 293 | const alignment = 0; | 295 | const alignment = 0; |
| 294 | const decl_c_value = try f.allocLocalValue(ty, alignment); | 296 | const decl_c_value = try f.allocLocalValue(ty, alignment); |
| ... | @@ -318,11 +320,11 @@ pub const Function = struct { | ... | @@ -318,11 +320,11 @@ pub const Function = struct { |
| 318 | /// those which go into `allocs`. This function does not add the resulting local into `allocs`; | 320 | /// those which go into `allocs`. This function does not add the resulting local into `allocs`; |
| 319 | /// that responsibility lies with the caller. | 321 | /// that responsibility lies with the caller. |
| 320 | fn allocLocalValue(f: *Function, ty: Type, alignment: u32) !CValue { | 322 | fn allocLocalValue(f: *Function, ty: Type, alignment: u32) !CValue { |
| 323 | const mod = f.object.dg.module; | ||
| 321 | const gpa = f.object.dg.gpa; | 324 | const gpa = f.object.dg.gpa; |
| 322 | const target = f.object.dg.module.getTarget(); | ||
| 323 | try f.locals.append(gpa, .{ | 325 | try f.locals.append(gpa, .{ |
| 324 | .cty_idx = try f.typeToIndex(ty, .complete), | 326 | .cty_idx = try f.typeToIndex(ty, .complete), |
| 325 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target)), | 327 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)), |
| 326 | }); | 328 | }); |
| 327 | return .{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) }; | 329 | return .{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) }; |
| 328 | } | 330 | } |
| ... | @@ -336,10 +338,10 @@ pub const Function = struct { | ... | @@ -336,10 +338,10 @@ pub const Function = struct { |
| 336 | /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should | 338 | /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should |
| 337 | /// not be used for persistent locals (i.e. those in `allocs`). | 339 | /// not be used for persistent locals (i.e. those in `allocs`). |
| 338 | fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: u32) !CValue { | 340 | fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: u32) !CValue { |
| 339 | const target = f.object.dg.module.getTarget(); | 341 | const mod = f.object.dg.module; |
| 340 | if (f.free_locals_map.getPtr(.{ | 342 | if (f.free_locals_map.getPtr(.{ |
| 341 | .cty_idx = try f.typeToIndex(ty, .complete), | 343 | .cty_idx = try f.typeToIndex(ty, .complete), |
| 342 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target)), | 344 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)), |
| 343 | })) |locals_list| { | 345 | })) |locals_list| { |
| 344 | if (locals_list.popOrNull()) |local_entry| { | 346 | if (locals_list.popOrNull()) |local_entry| { |
| 345 | return .{ .new_local = local_entry.key }; | 347 | return .{ .new_local = local_entry.key }; |
| ... | @@ -352,8 +354,9 @@ pub const Function = struct { | ... | @@ -352,8 +354,9 @@ pub const Function = struct { |
| 352 | fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void { | 354 | fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void { |
| 353 | switch (c_value) { | 355 | switch (c_value) { |
| 354 | .constant => |inst| { | 356 | .constant => |inst| { |
| 357 | const mod = f.object.dg.module; | ||
| 355 | const ty = f.air.typeOf(inst); | 358 | const ty = f.air.typeOf(inst); |
| 356 | const val = f.air.value(inst).?; | 359 | const val = f.air.value(inst, mod).?; |
| 357 | return f.object.dg.renderValue(w, ty, val, location); | 360 | return f.object.dg.renderValue(w, ty, val, location); |
| 358 | }, | 361 | }, |
| 359 | .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location), | 362 | .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location), |
| ... | @@ -364,8 +367,9 @@ pub const Function = struct { | ... | @@ -364,8 +367,9 @@ pub const Function = struct { |
| 364 | fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void { | 367 | fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void { |
| 365 | switch (c_value) { | 368 | switch (c_value) { |
| 366 | .constant => |inst| { | 369 | .constant => |inst| { |
| 370 | const mod = f.object.dg.module; | ||
| 367 | const ty = f.air.typeOf(inst); | 371 | const ty = f.air.typeOf(inst); |
| 368 | const val = f.air.value(inst).?; | 372 | const val = f.air.value(inst, mod).?; |
| 369 | try w.writeAll("(*"); | 373 | try w.writeAll("(*"); |
| 370 | try f.object.dg.renderValue(w, ty, val, .Other); | 374 | try f.object.dg.renderValue(w, ty, val, .Other); |
| 371 | return w.writeByte(')'); | 375 | return w.writeByte(')'); |
| ... | @@ -377,8 +381,9 @@ pub const Function = struct { | ... | @@ -377,8 +381,9 @@ pub const Function = struct { |
| 377 | fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void { | 381 | fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void { |
| 378 | switch (c_value) { | 382 | switch (c_value) { |
| 379 | .constant => |inst| { | 383 | .constant => |inst| { |
| 384 | const mod = f.object.dg.module; | ||
| 380 | const ty = f.air.typeOf(inst); | 385 | const ty = f.air.typeOf(inst); |
| 381 | const val = f.air.value(inst).?; | 386 | const val = f.air.value(inst, mod).?; |
| 382 | try f.object.dg.renderValue(w, ty, val, .Other); | 387 | try f.object.dg.renderValue(w, ty, val, .Other); |
| 383 | try w.writeByte('.'); | 388 | try w.writeByte('.'); |
| 384 | return f.writeCValue(w, member, .Other); | 389 | return f.writeCValue(w, member, .Other); |
| ... | @@ -390,8 +395,9 @@ pub const Function = struct { | ... | @@ -390,8 +395,9 @@ pub const Function = struct { |
| 390 | fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void { | 395 | fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void { |
| 391 | switch (c_value) { | 396 | switch (c_value) { |
| 392 | .constant => |inst| { | 397 | .constant => |inst| { |
| 398 | const mod = f.object.dg.module; | ||
| 393 | const ty = f.air.typeOf(inst); | 399 | const ty = f.air.typeOf(inst); |
| 394 | const val = f.air.value(inst).?; | 400 | const val = f.air.value(inst, mod).?; |
| 395 | try w.writeByte('('); | 401 | try w.writeByte('('); |
| 396 | try f.object.dg.renderValue(w, ty, val, .Other); | 402 | try f.object.dg.renderValue(w, ty, val, .Other); |
| 397 | try w.writeAll(")->"); | 403 | try w.writeAll(")->"); |
| ... | @@ -522,11 +528,12 @@ pub const DeclGen = struct { | ... | @@ -522,11 +528,12 @@ pub const DeclGen = struct { |
| 522 | decl_index: Decl.Index, | 528 | decl_index: Decl.Index, |
| 523 | location: ValueRenderLocation, | 529 | location: ValueRenderLocation, |
| 524 | ) error{ OutOfMemory, AnalysisFail }!void { | 530 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 525 | const decl = dg.module.declPtr(decl_index); | 531 | const mod = dg.module; |
| 532 | const decl = mod.declPtr(decl_index); | ||
| 526 | assert(decl.has_tv); | 533 | assert(decl.has_tv); |
| 527 | 534 | ||
| 528 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. | 535 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| 529 | if (ty.isPtrAtRuntime() and !decl.ty.isFnOrHasRuntimeBits()) { | 536 | if (ty.isPtrAtRuntime(mod) and !decl.ty.isFnOrHasRuntimeBits(mod)) { |
| 530 | return dg.writeCValue(writer, .{ .undef = ty }); | 537 | return dg.writeCValue(writer, .{ .undef = ty }); |
| 531 | } | 538 | } |
| 532 | 539 | ||
| ... | @@ -553,7 +560,7 @@ pub const DeclGen = struct { | ... | @@ -553,7 +560,7 @@ pub const DeclGen = struct { |
| 553 | 560 | ||
| 554 | var len_pl: Value.Payload.U64 = .{ | 561 | var len_pl: Value.Payload.U64 = .{ |
| 555 | .base = .{ .tag = .int_u64 }, | 562 | .base = .{ .tag = .int_u64 }, |
| 556 | .data = val.sliceLen(dg.module), | 563 | .data = val.sliceLen(mod), |
| 557 | }; | 564 | }; |
| 558 | const len_val = Value.initPayload(&len_pl.base); | 565 | const len_val = Value.initPayload(&len_pl.base); |
| 559 | 566 | ||
| ... | @@ -568,7 +575,7 @@ pub const DeclGen = struct { | ... | @@ -568,7 +575,7 @@ pub const DeclGen = struct { |
| 568 | // them). The analysis until now should ensure that the C function | 575 | // them). The analysis until now should ensure that the C function |
| 569 | // pointers are compatible. If they are not, then there is a bug | 576 | // pointers are compatible. If they are not, then there is a bug |
| 570 | // somewhere and we should let the C compiler tell us about it. | 577 | // somewhere and we should let the C compiler tell us about it. |
| 571 | const need_typecast = if (ty.castPtrToFn()) |_| false else !ty.eql(decl.ty, dg.module); | 578 | const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.eql(decl.ty, mod); |
| 572 | if (need_typecast) { | 579 | if (need_typecast) { |
| 573 | try writer.writeAll("(("); | 580 | try writer.writeAll("(("); |
| 574 | try dg.renderType(writer, ty); | 581 | try dg.renderType(writer, ty); |
| ... | @@ -584,6 +591,8 @@ pub const DeclGen = struct { | ... | @@ -584,6 +591,8 @@ pub const DeclGen = struct { |
| 584 | // | 591 | // |
| 585 | // Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr | 592 | // Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr |
| 586 | fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type, location: ValueRenderLocation) error{ OutOfMemory, AnalysisFail }!void { | 593 | fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type, location: ValueRenderLocation) error{ OutOfMemory, AnalysisFail }!void { |
| 594 | const mod = dg.module; | ||
| 595 | |||
| 587 | if (!ptr_ty.isSlice()) { | 596 | if (!ptr_ty.isSlice()) { |
| 588 | try writer.writeByte('('); | 597 | try writer.writeByte('('); |
| 589 | try dg.renderType(writer, ptr_ty); | 598 | try dg.renderType(writer, ptr_ty); |
| ... | @@ -601,7 +610,6 @@ pub const DeclGen = struct { | ... | @@ -601,7 +610,6 @@ pub const DeclGen = struct { |
| 601 | try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index, location); | 610 | try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index, location); |
| 602 | }, | 611 | }, |
| 603 | .field_ptr => { | 612 | .field_ptr => { |
| 604 | const target = dg.module.getTarget(); | ||
| 605 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; | 613 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| 606 | 614 | ||
| 607 | // Ensure complete type definition is visible before accessing fields. | 615 | // Ensure complete type definition is visible before accessing fields. |
| ... | @@ -615,7 +623,7 @@ pub const DeclGen = struct { | ... | @@ -615,7 +623,7 @@ pub const DeclGen = struct { |
| 615 | field_ptr.container_ty, | 623 | field_ptr.container_ty, |
| 616 | ptr_ty, | 624 | ptr_ty, |
| 617 | @intCast(u32, field_ptr.field_index), | 625 | @intCast(u32, field_ptr.field_index), |
| 618 | target, | 626 | mod, |
| 619 | )) { | 627 | )) { |
| 620 | .begin => try dg.renderParentPtr( | 628 | .begin => try dg.renderParentPtr( |
| 621 | writer, | 629 | writer, |
| ... | @@ -714,19 +722,20 @@ pub const DeclGen = struct { | ... | @@ -714,19 +722,20 @@ pub const DeclGen = struct { |
| 714 | if (val.castTag(.runtime_value)) |rt| { | 722 | if (val.castTag(.runtime_value)) |rt| { |
| 715 | val = rt.data; | 723 | val = rt.data; |
| 716 | } | 724 | } |
| 717 | const target = dg.module.getTarget(); | 725 | const mod = dg.module; |
| 726 | const target = mod.getTarget(); | ||
| 718 | const initializer_type: ValueRenderLocation = switch (location) { | 727 | const initializer_type: ValueRenderLocation = switch (location) { |
| 719 | .StaticInitializer => .StaticInitializer, | 728 | .StaticInitializer => .StaticInitializer, |
| 720 | else => .Initializer, | 729 | else => .Initializer, |
| 721 | }; | 730 | }; |
| 722 | 731 | ||
| 723 | const safety_on = switch (dg.module.optimizeMode()) { | 732 | const safety_on = switch (mod.optimizeMode()) { |
| 724 | .Debug, .ReleaseSafe => true, | 733 | .Debug, .ReleaseSafe => true, |
| 725 | .ReleaseFast, .ReleaseSmall => false, | 734 | .ReleaseFast, .ReleaseSmall => false, |
| 726 | }; | 735 | }; |
| 727 | 736 | ||
| 728 | if (val.isUndefDeep()) { | 737 | if (val.isUndefDeep()) { |
| 729 | switch (ty.zigTypeTag()) { | 738 | switch (ty.zigTypeTag(mod)) { |
| 730 | .Bool => { | 739 | .Bool => { |
| 731 | if (safety_on) { | 740 | if (safety_on) { |
| 732 | return writer.writeAll("0xaa"); | 741 | return writer.writeAll("0xaa"); |
| ... | @@ -737,8 +746,8 @@ pub const DeclGen = struct { | ... | @@ -737,8 +746,8 @@ pub const DeclGen = struct { |
| 737 | .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}), | 746 | .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}), |
| 738 | .Float => { | 747 | .Float => { |
| 739 | const bits = ty.floatBits(target); | 748 | const bits = ty.floatBits(target); |
| 740 | var repr_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = bits }; | 749 | // All unsigned ints matching float types are pre-allocated. |
| 741 | const repr_ty = Type.initPayload(&repr_pl.base); | 750 | const repr_ty = mod.intType(.unsigned, bits) catch unreachable; |
| 742 | 751 | ||
| 743 | try writer.writeAll("zig_cast_"); | 752 | try writer.writeAll("zig_cast_"); |
| 744 | try dg.renderTypeForBuiltinFnName(writer, ty); | 753 | try dg.renderTypeForBuiltinFnName(writer, ty); |
| ... | @@ -778,11 +787,11 @@ pub const DeclGen = struct { | ... | @@ -778,11 +787,11 @@ pub const DeclGen = struct { |
| 778 | var opt_buf: Type.Payload.ElemType = undefined; | 787 | var opt_buf: Type.Payload.ElemType = undefined; |
| 779 | const payload_ty = ty.optionalChild(&opt_buf); | 788 | const payload_ty = ty.optionalChild(&opt_buf); |
| 780 | 789 | ||
| 781 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 790 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 782 | return dg.renderValue(writer, Type.bool, val, location); | 791 | return dg.renderValue(writer, Type.bool, val, location); |
| 783 | } | 792 | } |
| 784 | 793 | ||
| 785 | if (ty.optionalReprIsPayload()) { | 794 | if (ty.optionalReprIsPayload(mod)) { |
| 786 | return dg.renderValue(writer, payload_ty, val, location); | 795 | return dg.renderValue(writer, payload_ty, val, location); |
| 787 | } | 796 | } |
| 788 | 797 | ||
| ... | @@ -811,7 +820,7 @@ pub const DeclGen = struct { | ... | @@ -811,7 +820,7 @@ pub const DeclGen = struct { |
| 811 | for (0..ty.structFieldCount()) |field_i| { | 820 | for (0..ty.structFieldCount()) |field_i| { |
| 812 | if (ty.structFieldIsComptime(field_i)) continue; | 821 | if (ty.structFieldIsComptime(field_i)) continue; |
| 813 | const field_ty = ty.structFieldType(field_i); | 822 | const field_ty = ty.structFieldType(field_i); |
| 814 | if (!field_ty.hasRuntimeBits()) continue; | 823 | if (!field_ty.hasRuntimeBits(mod)) continue; |
| 815 | 824 | ||
| 816 | if (!empty) try writer.writeByte(','); | 825 | if (!empty) try writer.writeByte(','); |
| 817 | try dg.renderValue(writer, field_ty, val, initializer_type); | 826 | try dg.renderValue(writer, field_ty, val, initializer_type); |
| ... | @@ -832,17 +841,17 @@ pub const DeclGen = struct { | ... | @@ -832,17 +841,17 @@ pub const DeclGen = struct { |
| 832 | 841 | ||
| 833 | try writer.writeByte('{'); | 842 | try writer.writeByte('{'); |
| 834 | if (ty.unionTagTypeSafety()) |tag_ty| { | 843 | if (ty.unionTagTypeSafety()) |tag_ty| { |
| 835 | const layout = ty.unionGetLayout(target); | 844 | const layout = ty.unionGetLayout(mod); |
| 836 | if (layout.tag_size != 0) { | 845 | if (layout.tag_size != 0) { |
| 837 | try writer.writeAll(" .tag = "); | 846 | try writer.writeAll(" .tag = "); |
| 838 | try dg.renderValue(writer, tag_ty, val, initializer_type); | 847 | try dg.renderValue(writer, tag_ty, val, initializer_type); |
| 839 | } | 848 | } |
| 840 | if (ty.unionHasAllZeroBitFieldTypes()) return try writer.writeByte('}'); | 849 | if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}'); |
| 841 | if (layout.tag_size != 0) try writer.writeByte(','); | 850 | if (layout.tag_size != 0) try writer.writeByte(','); |
| 842 | try writer.writeAll(" .payload = {"); | 851 | try writer.writeAll(" .payload = {"); |
| 843 | } | 852 | } |
| 844 | for (ty.unionFields().values()) |field| { | 853 | for (ty.unionFields().values()) |field| { |
| 845 | if (!field.ty.hasRuntimeBits()) continue; | 854 | if (!field.ty.hasRuntimeBits(mod)) continue; |
| 846 | try dg.renderValue(writer, field.ty, val, initializer_type); | 855 | try dg.renderValue(writer, field.ty, val, initializer_type); |
| 847 | break; | 856 | break; |
| 848 | } | 857 | } |
| ... | @@ -853,7 +862,7 @@ pub const DeclGen = struct { | ... | @@ -853,7 +862,7 @@ pub const DeclGen = struct { |
| 853 | const payload_ty = ty.errorUnionPayload(); | 862 | const payload_ty = ty.errorUnionPayload(); |
| 854 | const error_ty = ty.errorUnionSet(); | 863 | const error_ty = ty.errorUnionSet(); |
| 855 | 864 | ||
| 856 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 865 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 857 | return dg.renderValue(writer, error_ty, val, location); | 866 | return dg.renderValue(writer, error_ty, val, location); |
| 858 | } | 867 | } |
| 859 | 868 | ||
| ... | @@ -916,7 +925,7 @@ pub const DeclGen = struct { | ... | @@ -916,7 +925,7 @@ pub const DeclGen = struct { |
| 916 | } | 925 | } |
| 917 | unreachable; | 926 | unreachable; |
| 918 | } | 927 | } |
| 919 | switch (ty.zigTypeTag()) { | 928 | switch (ty.zigTypeTag(mod)) { |
| 920 | .Int => switch (val.tag()) { | 929 | .Int => switch (val.tag()) { |
| 921 | .field_ptr, | 930 | .field_ptr, |
| 922 | .elem_ptr, | 931 | .elem_ptr, |
| ... | @@ -931,8 +940,8 @@ pub const DeclGen = struct { | ... | @@ -931,8 +940,8 @@ pub const DeclGen = struct { |
| 931 | const bits = ty.floatBits(target); | 940 | const bits = ty.floatBits(target); |
| 932 | const f128_val = val.toFloat(f128); | 941 | const f128_val = val.toFloat(f128); |
| 933 | 942 | ||
| 934 | var repr_ty_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = bits }; | 943 | // All unsigned ints matching float types are pre-allocated. |
| 935 | const repr_ty = Type.initPayload(&repr_ty_pl.base); | 944 | const repr_ty = mod.intType(.unsigned, bits) catch unreachable; |
| 936 | 945 | ||
| 937 | assert(bits <= 128); | 946 | assert(bits <= 128); |
| 938 | var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; | 947 | var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; |
| ... | @@ -1109,7 +1118,7 @@ pub const DeclGen = struct { | ... | @@ -1109,7 +1118,7 @@ pub const DeclGen = struct { |
| 1109 | }, | 1118 | }, |
| 1110 | else => unreachable, | 1119 | else => unreachable, |
| 1111 | }; | 1120 | }; |
| 1112 | const sentinel = if (ty.sentinel()) |sentinel| @intCast(u8, sentinel.toUnsignedInt(target)) else null; | 1121 | const sentinel = if (ty.sentinel()) |sentinel| @intCast(u8, sentinel.toUnsignedInt(mod)) else null; |
| 1113 | try writer.print("{s}", .{ | 1122 | try writer.print("{s}", .{ |
| 1114 | fmtStringLiteral(bytes[0..@intCast(usize, ty.arrayLen())], sentinel), | 1123 | fmtStringLiteral(bytes[0..@intCast(usize, ty.arrayLen())], sentinel), |
| 1115 | }); | 1124 | }); |
| ... | @@ -1131,11 +1140,11 @@ pub const DeclGen = struct { | ... | @@ -1131,11 +1140,11 @@ pub const DeclGen = struct { |
| 1131 | var index: usize = 0; | 1140 | var index: usize = 0; |
| 1132 | while (index < ai.len) : (index += 1) { | 1141 | while (index < ai.len) : (index += 1) { |
| 1133 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); | 1142 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); |
| 1134 | const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(target)); | 1143 | const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); |
| 1135 | try literal.writeChar(elem_val_u8); | 1144 | try literal.writeChar(elem_val_u8); |
| 1136 | } | 1145 | } |
| 1137 | if (ai.sentinel) |s| { | 1146 | if (ai.sentinel) |s| { |
| 1138 | const s_u8 = @intCast(u8, s.toUnsignedInt(target)); | 1147 | const s_u8 = @intCast(u8, s.toUnsignedInt(mod)); |
| 1139 | if (s_u8 != 0) try literal.writeChar(s_u8); | 1148 | if (s_u8 != 0) try literal.writeChar(s_u8); |
| 1140 | } | 1149 | } |
| 1141 | try literal.end(); | 1150 | try literal.end(); |
| ... | @@ -1145,7 +1154,7 @@ pub const DeclGen = struct { | ... | @@ -1145,7 +1154,7 @@ pub const DeclGen = struct { |
| 1145 | while (index < ai.len) : (index += 1) { | 1154 | while (index < ai.len) : (index += 1) { |
| 1146 | if (index != 0) try writer.writeByte(','); | 1155 | if (index != 0) try writer.writeByte(','); |
| 1147 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); | 1156 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); |
| 1148 | const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(target)); | 1157 | const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod)); |
| 1149 | try writer.print("'\\x{x}'", .{elem_val_u8}); | 1158 | try writer.print("'\\x{x}'", .{elem_val_u8}); |
| 1150 | } | 1159 | } |
| 1151 | if (ai.sentinel) |s| { | 1160 | if (ai.sentinel) |s| { |
| ... | @@ -1183,10 +1192,10 @@ pub const DeclGen = struct { | ... | @@ -1183,10 +1192,10 @@ pub const DeclGen = struct { |
| 1183 | const payload_ty = ty.optionalChild(&opt_buf); | 1192 | const payload_ty = ty.optionalChild(&opt_buf); |
| 1184 | 1193 | ||
| 1185 | const is_null_val = Value.makeBool(val.tag() == .null_value); | 1194 | const is_null_val = Value.makeBool(val.tag() == .null_value); |
| 1186 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) | 1195 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 1187 | return dg.renderValue(writer, Type.bool, is_null_val, location); | 1196 | return dg.renderValue(writer, Type.bool, is_null_val, location); |
| 1188 | 1197 | ||
| 1189 | if (ty.optionalReprIsPayload()) { | 1198 | if (ty.optionalReprIsPayload(mod)) { |
| 1190 | const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else val; | 1199 | const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else val; |
| 1191 | return dg.renderValue(writer, payload_ty, payload_val, location); | 1200 | return dg.renderValue(writer, payload_ty, payload_val, location); |
| 1192 | } | 1201 | } |
| ... | @@ -1218,7 +1227,7 @@ pub const DeclGen = struct { | ... | @@ -1218,7 +1227,7 @@ pub const DeclGen = struct { |
| 1218 | const error_ty = ty.errorUnionSet(); | 1227 | const error_ty = ty.errorUnionSet(); |
| 1219 | const error_val = if (val.errorUnionIsPayload()) Value.zero else val; | 1228 | const error_val = if (val.errorUnionIsPayload()) Value.zero else val; |
| 1220 | 1229 | ||
| 1221 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 1230 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1222 | return dg.renderValue(writer, error_ty, error_val, location); | 1231 | return dg.renderValue(writer, error_ty, error_val, location); |
| 1223 | } | 1232 | } |
| 1224 | 1233 | ||
| ... | @@ -1263,8 +1272,7 @@ pub const DeclGen = struct { | ... | @@ -1263,8 +1272,7 @@ pub const DeclGen = struct { |
| 1263 | } | 1272 | } |
| 1264 | }, | 1273 | }, |
| 1265 | else => { | 1274 | else => { |
| 1266 | var int_tag_ty_buffer: Type.Payload.Bits = undefined; | 1275 | const int_tag_ty = ty.intTagType(); |
| 1267 | const int_tag_ty = ty.intTagType(&int_tag_ty_buffer); | ||
| 1268 | return dg.renderValue(writer, int_tag_ty, val, location); | 1276 | return dg.renderValue(writer, int_tag_ty, val, location); |
| 1269 | }, | 1277 | }, |
| 1270 | } | 1278 | } |
| ... | @@ -1295,7 +1303,7 @@ pub const DeclGen = struct { | ... | @@ -1295,7 +1303,7 @@ pub const DeclGen = struct { |
| 1295 | for (field_vals, 0..) |field_val, field_i| { | 1303 | for (field_vals, 0..) |field_val, field_i| { |
| 1296 | if (ty.structFieldIsComptime(field_i)) continue; | 1304 | if (ty.structFieldIsComptime(field_i)) continue; |
| 1297 | const field_ty = ty.structFieldType(field_i); | 1305 | const field_ty = ty.structFieldType(field_i); |
| 1298 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 1306 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1299 | 1307 | ||
| 1300 | if (!empty) try writer.writeByte(','); | 1308 | if (!empty) try writer.writeByte(','); |
| 1301 | try dg.renderValue(writer, field_ty, field_val, initializer_type); | 1309 | try dg.renderValue(writer, field_ty, field_val, initializer_type); |
| ... | @@ -1306,13 +1314,10 @@ pub const DeclGen = struct { | ... | @@ -1306,13 +1314,10 @@ pub const DeclGen = struct { |
| 1306 | }, | 1314 | }, |
| 1307 | .Packed => { | 1315 | .Packed => { |
| 1308 | const field_vals = val.castTag(.aggregate).?.data; | 1316 | const field_vals = val.castTag(.aggregate).?.data; |
| 1309 | const int_info = ty.intInfo(target); | 1317 | const int_info = ty.intInfo(mod); |
| 1310 | 1318 | ||
| 1311 | var bit_offset_ty_pl = Type.Payload.Bits{ | 1319 | const bits = Type.smallestUnsignedBits(int_info.bits - 1); |
| 1312 | .base = .{ .tag = .int_unsigned }, | 1320 | const bit_offset_ty = try mod.intType(.unsigned, bits); |
| 1313 | .data = Type.smallestUnsignedBits(int_info.bits - 1), | ||
| 1314 | }; | ||
| 1315 | const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base); | ||
| 1316 | 1321 | ||
| 1317 | var bit_offset_val_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = 0 }; | 1322 | var bit_offset_val_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = 0 }; |
| 1318 | const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base); | 1323 | const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base); |
| ... | @@ -1321,7 +1326,7 @@ pub const DeclGen = struct { | ... | @@ -1321,7 +1326,7 @@ pub const DeclGen = struct { |
| 1321 | for (0..field_vals.len) |field_i| { | 1326 | for (0..field_vals.len) |field_i| { |
| 1322 | if (ty.structFieldIsComptime(field_i)) continue; | 1327 | if (ty.structFieldIsComptime(field_i)) continue; |
| 1323 | const field_ty = ty.structFieldType(field_i); | 1328 | const field_ty = ty.structFieldType(field_i); |
| 1324 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 1329 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1325 | 1330 | ||
| 1326 | eff_num_fields += 1; | 1331 | eff_num_fields += 1; |
| 1327 | } | 1332 | } |
| ... | @@ -1330,7 +1335,7 @@ pub const DeclGen = struct { | ... | @@ -1330,7 +1335,7 @@ pub const DeclGen = struct { |
| 1330 | try writer.writeByte('('); | 1335 | try writer.writeByte('('); |
| 1331 | try dg.renderValue(writer, ty, Value.undef, initializer_type); | 1336 | try dg.renderValue(writer, ty, Value.undef, initializer_type); |
| 1332 | try writer.writeByte(')'); | 1337 | try writer.writeByte(')'); |
| 1333 | } else if (ty.bitSize(target) > 64) { | 1338 | } else if (ty.bitSize(mod) > 64) { |
| 1334 | // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) | 1339 | // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) |
| 1335 | var num_or = eff_num_fields - 1; | 1340 | var num_or = eff_num_fields - 1; |
| 1336 | while (num_or > 0) : (num_or -= 1) { | 1341 | while (num_or > 0) : (num_or -= 1) { |
| ... | @@ -1344,7 +1349,7 @@ pub const DeclGen = struct { | ... | @@ -1344,7 +1349,7 @@ pub const DeclGen = struct { |
| 1344 | for (field_vals, 0..) |field_val, field_i| { | 1349 | for (field_vals, 0..) |field_val, field_i| { |
| 1345 | if (ty.structFieldIsComptime(field_i)) continue; | 1350 | if (ty.structFieldIsComptime(field_i)) continue; |
| 1346 | const field_ty = ty.structFieldType(field_i); | 1351 | const field_ty = ty.structFieldType(field_i); |
| 1347 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 1352 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1348 | 1353 | ||
| 1349 | const cast_context = IntCastContext{ .value = .{ .value = field_val } }; | 1354 | const cast_context = IntCastContext{ .value = .{ .value = field_val } }; |
| 1350 | if (bit_offset_val_pl.data != 0) { | 1355 | if (bit_offset_val_pl.data != 0) { |
| ... | @@ -1362,7 +1367,7 @@ pub const DeclGen = struct { | ... | @@ -1362,7 +1367,7 @@ pub const DeclGen = struct { |
| 1362 | if (needs_closing_paren) try writer.writeByte(')'); | 1367 | if (needs_closing_paren) try writer.writeByte(')'); |
| 1363 | if (eff_index != eff_num_fields - 1) try writer.writeAll(", "); | 1368 | if (eff_index != eff_num_fields - 1) try writer.writeAll(", "); |
| 1364 | 1369 | ||
| 1365 | bit_offset_val_pl.data += field_ty.bitSize(target); | 1370 | bit_offset_val_pl.data += field_ty.bitSize(mod); |
| 1366 | needs_closing_paren = true; | 1371 | needs_closing_paren = true; |
| 1367 | eff_index += 1; | 1372 | eff_index += 1; |
| 1368 | } | 1373 | } |
| ... | @@ -1373,7 +1378,7 @@ pub const DeclGen = struct { | ... | @@ -1373,7 +1378,7 @@ pub const DeclGen = struct { |
| 1373 | for (field_vals, 0..) |field_val, field_i| { | 1378 | for (field_vals, 0..) |field_val, field_i| { |
| 1374 | if (ty.structFieldIsComptime(field_i)) continue; | 1379 | if (ty.structFieldIsComptime(field_i)) continue; |
| 1375 | const field_ty = ty.structFieldType(field_i); | 1380 | const field_ty = ty.structFieldType(field_i); |
| 1376 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 1381 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1377 | 1382 | ||
| 1378 | if (!empty) try writer.writeAll(" | "); | 1383 | if (!empty) try writer.writeAll(" | "); |
| 1379 | try writer.writeByte('('); | 1384 | try writer.writeByte('('); |
| ... | @@ -1388,7 +1393,7 @@ pub const DeclGen = struct { | ... | @@ -1388,7 +1393,7 @@ pub const DeclGen = struct { |
| 1388 | try dg.renderValue(writer, field_ty, field_val, .Other); | 1393 | try dg.renderValue(writer, field_ty, field_val, .Other); |
| 1389 | } | 1394 | } |
| 1390 | 1395 | ||
| 1391 | bit_offset_val_pl.data += field_ty.bitSize(target); | 1396 | bit_offset_val_pl.data += field_ty.bitSize(mod); |
| 1392 | empty = false; | 1397 | empty = false; |
| 1393 | } | 1398 | } |
| 1394 | try writer.writeByte(')'); | 1399 | try writer.writeByte(')'); |
| ... | @@ -1408,12 +1413,12 @@ pub const DeclGen = struct { | ... | @@ -1408,12 +1413,12 @@ pub const DeclGen = struct { |
| 1408 | const field_ty = ty.unionFields().values()[field_i].ty; | 1413 | const field_ty = ty.unionFields().values()[field_i].ty; |
| 1409 | const field_name = ty.unionFields().keys()[field_i]; | 1414 | const field_name = ty.unionFields().keys()[field_i]; |
| 1410 | if (ty.containerLayout() == .Packed) { | 1415 | if (ty.containerLayout() == .Packed) { |
| 1411 | if (field_ty.hasRuntimeBits()) { | 1416 | if (field_ty.hasRuntimeBits(mod)) { |
| 1412 | if (field_ty.isPtrAtRuntime()) { | 1417 | if (field_ty.isPtrAtRuntime(mod)) { |
| 1413 | try writer.writeByte('('); | 1418 | try writer.writeByte('('); |
| 1414 | try dg.renderType(writer, ty); | 1419 | try dg.renderType(writer, ty); |
| 1415 | try writer.writeByte(')'); | 1420 | try writer.writeByte(')'); |
| 1416 | } else if (field_ty.zigTypeTag() == .Float) { | 1421 | } else if (field_ty.zigTypeTag(mod) == .Float) { |
| 1417 | try writer.writeByte('('); | 1422 | try writer.writeByte('('); |
| 1418 | try dg.renderType(writer, ty); | 1423 | try dg.renderType(writer, ty); |
| 1419 | try writer.writeByte(')'); | 1424 | try writer.writeByte(')'); |
| ... | @@ -1427,21 +1432,21 @@ pub const DeclGen = struct { | ... | @@ -1427,21 +1432,21 @@ pub const DeclGen = struct { |
| 1427 | 1432 | ||
| 1428 | try writer.writeByte('{'); | 1433 | try writer.writeByte('{'); |
| 1429 | if (ty.unionTagTypeSafety()) |tag_ty| { | 1434 | if (ty.unionTagTypeSafety()) |tag_ty| { |
| 1430 | const layout = ty.unionGetLayout(target); | 1435 | const layout = ty.unionGetLayout(mod); |
| 1431 | if (layout.tag_size != 0) { | 1436 | if (layout.tag_size != 0) { |
| 1432 | try writer.writeAll(" .tag = "); | 1437 | try writer.writeAll(" .tag = "); |
| 1433 | try dg.renderValue(writer, tag_ty, union_obj.tag, initializer_type); | 1438 | try dg.renderValue(writer, tag_ty, union_obj.tag, initializer_type); |
| 1434 | } | 1439 | } |
| 1435 | if (ty.unionHasAllZeroBitFieldTypes()) return try writer.writeByte('}'); | 1440 | if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}'); |
| 1436 | if (layout.tag_size != 0) try writer.writeByte(','); | 1441 | if (layout.tag_size != 0) try writer.writeByte(','); |
| 1437 | try writer.writeAll(" .payload = {"); | 1442 | try writer.writeAll(" .payload = {"); |
| 1438 | } | 1443 | } |
| 1439 | if (field_ty.hasRuntimeBits()) { | 1444 | if (field_ty.hasRuntimeBits(mod)) { |
| 1440 | try writer.print(" .{ } = ", .{fmtIdent(field_name)}); | 1445 | try writer.print(" .{ } = ", .{fmtIdent(field_name)}); |
| 1441 | try dg.renderValue(writer, field_ty, union_obj.val, initializer_type); | 1446 | try dg.renderValue(writer, field_ty, union_obj.val, initializer_type); |
| 1442 | try writer.writeByte(' '); | 1447 | try writer.writeByte(' '); |
| 1443 | } else for (ty.unionFields().values()) |field| { | 1448 | } else for (ty.unionFields().values()) |field| { |
| 1444 | if (!field.ty.hasRuntimeBits()) continue; | 1449 | if (!field.ty.hasRuntimeBits(mod)) continue; |
| 1445 | try dg.renderValue(writer, field.ty, Value.undef, initializer_type); | 1450 | try dg.renderValue(writer, field.ty, Value.undef, initializer_type); |
| 1446 | break; | 1451 | break; |
| 1447 | } | 1452 | } |
| ... | @@ -1478,9 +1483,9 @@ pub const DeclGen = struct { | ... | @@ -1478,9 +1483,9 @@ pub const DeclGen = struct { |
| 1478 | }, | 1483 | }, |
| 1479 | ) !void { | 1484 | ) !void { |
| 1480 | const store = &dg.ctypes.set; | 1485 | const store = &dg.ctypes.set; |
| 1481 | const module = dg.module; | 1486 | const mod = dg.module; |
| 1482 | 1487 | ||
| 1483 | const fn_decl = module.declPtr(fn_decl_index); | 1488 | const fn_decl = mod.declPtr(fn_decl_index); |
| 1484 | const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind); | 1489 | const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind); |
| 1485 | 1490 | ||
| 1486 | const fn_info = fn_decl.ty.fnInfo(); | 1491 | const fn_info = fn_decl.ty.fnInfo(); |
| ... | @@ -1498,7 +1503,7 @@ pub const DeclGen = struct { | ... | @@ -1498,7 +1503,7 @@ pub const DeclGen = struct { |
| 1498 | const trailing = try renderTypePrefix( | 1503 | const trailing = try renderTypePrefix( |
| 1499 | dg.decl_index, | 1504 | dg.decl_index, |
| 1500 | store.*, | 1505 | store.*, |
| 1501 | module, | 1506 | mod, |
| 1502 | w, | 1507 | w, |
| 1503 | fn_cty_idx, | 1508 | fn_cty_idx, |
| 1504 | .suffix, | 1509 | .suffix, |
| ... | @@ -1525,7 +1530,7 @@ pub const DeclGen = struct { | ... | @@ -1525,7 +1530,7 @@ pub const DeclGen = struct { |
| 1525 | try renderTypeSuffix( | 1530 | try renderTypeSuffix( |
| 1526 | dg.decl_index, | 1531 | dg.decl_index, |
| 1527 | store.*, | 1532 | store.*, |
| 1528 | module, | 1533 | mod, |
| 1529 | w, | 1534 | w, |
| 1530 | fn_cty_idx, | 1535 | fn_cty_idx, |
| 1531 | .suffix, | 1536 | .suffix, |
| ... | @@ -1577,9 +1582,9 @@ pub const DeclGen = struct { | ... | @@ -1577,9 +1582,9 @@ pub const DeclGen = struct { |
| 1577 | 1582 | ||
| 1578 | fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void { | 1583 | fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void { |
| 1579 | const store = &dg.ctypes.set; | 1584 | const store = &dg.ctypes.set; |
| 1580 | const module = dg.module; | 1585 | const mod = dg.module; |
| 1581 | _ = try renderTypePrefix(dg.decl_index, store.*, module, w, idx, .suffix, .{}); | 1586 | _ = try renderTypePrefix(dg.decl_index, store.*, mod, w, idx, .suffix, .{}); |
| 1582 | try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix, .{}); | 1587 | try renderTypeSuffix(dg.decl_index, store.*, mod, w, idx, .suffix, .{}); |
| 1583 | } | 1588 | } |
| 1584 | 1589 | ||
| 1585 | const IntCastContext = union(enum) { | 1590 | const IntCastContext = union(enum) { |
| ... | @@ -1619,18 +1624,18 @@ pub const DeclGen = struct { | ... | @@ -1619,18 +1624,18 @@ pub const DeclGen = struct { |
| 1619 | /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src) | 1624 | /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src) |
| 1620 | /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src)) | 1625 | /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src)) |
| 1621 | fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void { | 1626 | fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void { |
| 1622 | const target = dg.module.getTarget(); | 1627 | const mod = dg.module; |
| 1623 | const dest_bits = dest_ty.bitSize(target); | 1628 | const dest_bits = dest_ty.bitSize(mod); |
| 1624 | const dest_int_info = dest_ty.intInfo(target); | 1629 | const dest_int_info = dest_ty.intInfo(mod); |
| 1625 | 1630 | ||
| 1626 | const src_is_ptr = src_ty.isPtrAtRuntime(); | 1631 | const src_is_ptr = src_ty.isPtrAtRuntime(mod); |
| 1627 | const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { | 1632 | const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { |
| 1628 | .unsigned => Type.usize, | 1633 | .unsigned => Type.usize, |
| 1629 | .signed => Type.isize, | 1634 | .signed => Type.isize, |
| 1630 | } else src_ty; | 1635 | } else src_ty; |
| 1631 | 1636 | ||
| 1632 | const src_bits = src_eff_ty.bitSize(target); | 1637 | const src_bits = src_eff_ty.bitSize(mod); |
| 1633 | const src_int_info = if (src_eff_ty.isAbiInt()) src_eff_ty.intInfo(target) else null; | 1638 | const src_int_info = if (src_eff_ty.isAbiInt(mod)) src_eff_ty.intInfo(mod) else null; |
| 1634 | if (dest_bits <= 64 and src_bits <= 64) { | 1639 | if (dest_bits <= 64 and src_bits <= 64) { |
| 1635 | const needs_cast = src_int_info == null or | 1640 | const needs_cast = src_int_info == null or |
| 1636 | (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or | 1641 | (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or |
| ... | @@ -1703,8 +1708,8 @@ pub const DeclGen = struct { | ... | @@ -1703,8 +1708,8 @@ pub const DeclGen = struct { |
| 1703 | alignment: u32, | 1708 | alignment: u32, |
| 1704 | kind: CType.Kind, | 1709 | kind: CType.Kind, |
| 1705 | ) error{ OutOfMemory, AnalysisFail }!void { | 1710 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1706 | const target = dg.module.getTarget(); | 1711 | const mod = dg.module; |
| 1707 | const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target)); | 1712 | const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)); |
| 1708 | try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas); | 1713 | try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas); |
| 1709 | } | 1714 | } |
| 1710 | 1715 | ||
| ... | @@ -1717,7 +1722,7 @@ pub const DeclGen = struct { | ... | @@ -1717,7 +1722,7 @@ pub const DeclGen = struct { |
| 1717 | alignas: CType.AlignAs, | 1722 | alignas: CType.AlignAs, |
| 1718 | ) error{ OutOfMemory, AnalysisFail }!void { | 1723 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1719 | const store = &dg.ctypes.set; | 1724 | const store = &dg.ctypes.set; |
| 1720 | const module = dg.module; | 1725 | const mod = dg.module; |
| 1721 | 1726 | ||
| 1722 | switch (std.math.order(alignas.@"align", alignas.abi)) { | 1727 | switch (std.math.order(alignas.@"align", alignas.abi)) { |
| 1723 | .lt => try w.print("zig_under_align({}) ", .{alignas.getAlign()}), | 1728 | .lt => try w.print("zig_under_align({}) ", .{alignas.getAlign()}), |
| ... | @@ -1726,22 +1731,23 @@ pub const DeclGen = struct { | ... | @@ -1726,22 +1731,23 @@ pub const DeclGen = struct { |
| 1726 | } | 1731 | } |
| 1727 | 1732 | ||
| 1728 | const trailing = | 1733 | const trailing = |
| 1729 | try renderTypePrefix(dg.decl_index, store.*, module, w, cty_idx, .suffix, qualifiers); | 1734 | try renderTypePrefix(dg.decl_index, store.*, mod, w, cty_idx, .suffix, qualifiers); |
| 1730 | try w.print("{}", .{trailing}); | 1735 | try w.print("{}", .{trailing}); |
| 1731 | try dg.writeCValue(w, name); | 1736 | try dg.writeCValue(w, name); |
| 1732 | try renderTypeSuffix(dg.decl_index, store.*, module, w, cty_idx, .suffix, .{}); | 1737 | try renderTypeSuffix(dg.decl_index, store.*, mod, w, cty_idx, .suffix, .{}); |
| 1733 | } | 1738 | } |
| 1734 | 1739 | ||
| 1735 | fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool { | 1740 | fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool { |
| 1741 | const mod = dg.module; | ||
| 1736 | switch (tv.val.tag()) { | 1742 | switch (tv.val.tag()) { |
| 1737 | .extern_fn => return true, | 1743 | .extern_fn => return true, |
| 1738 | .function => { | 1744 | .function => { |
| 1739 | const func = tv.val.castTag(.function).?.data; | 1745 | const func = tv.val.castTag(.function).?.data; |
| 1740 | return dg.module.decl_exports.contains(func.owner_decl); | 1746 | return mod.decl_exports.contains(func.owner_decl); |
| 1741 | }, | 1747 | }, |
| 1742 | .variable => { | 1748 | .variable => { |
| 1743 | const variable = tv.val.castTag(.variable).?.data; | 1749 | const variable = tv.val.castTag(.variable).?.data; |
| 1744 | return dg.module.decl_exports.contains(variable.owner_decl); | 1750 | return mod.decl_exports.contains(variable.owner_decl); |
| 1745 | }, | 1751 | }, |
| 1746 | else => unreachable, | 1752 | else => unreachable, |
| 1747 | } | 1753 | } |
| ... | @@ -1838,10 +1844,11 @@ pub const DeclGen = struct { | ... | @@ -1838,10 +1844,11 @@ pub const DeclGen = struct { |
| 1838 | } | 1844 | } |
| 1839 | 1845 | ||
| 1840 | fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void { | 1846 | fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void { |
| 1841 | const decl = dg.module.declPtr(decl_index); | 1847 | const mod = dg.module; |
| 1842 | dg.module.markDeclAlive(decl); | 1848 | const decl = mod.declPtr(decl_index); |
| 1849 | mod.markDeclAlive(decl); | ||
| 1843 | 1850 | ||
| 1844 | if (dg.module.decl_exports.get(decl_index)) |exports| { | 1851 | if (mod.decl_exports.get(decl_index)) |exports| { |
| 1845 | try writer.writeAll(exports.items[export_index].options.name); | 1852 | try writer.writeAll(exports.items[export_index].options.name); |
| 1846 | } else if (decl.isExtern()) { | 1853 | } else if (decl.isExtern()) { |
| 1847 | try writer.writeAll(mem.span(decl.name)); | 1854 | try writer.writeAll(mem.span(decl.name)); |
| ... | @@ -1850,7 +1857,7 @@ pub const DeclGen = struct { | ... | @@ -1850,7 +1857,7 @@ pub const DeclGen = struct { |
| 1850 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. | 1857 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. |
| 1851 | var name: [100]u8 = undefined; | 1858 | var name: [100]u8 = undefined; |
| 1852 | var name_stream = std.io.fixedBufferStream(&name); | 1859 | var name_stream = std.io.fixedBufferStream(&name); |
| 1853 | decl.renderFullyQualifiedName(dg.module, name_stream.writer()) catch |err| switch (err) { | 1860 | decl.renderFullyQualifiedName(mod, name_stream.writer()) catch |err| switch (err) { |
| 1854 | error.NoSpaceLeft => {}, | 1861 | error.NoSpaceLeft => {}, |
| 1855 | }; | 1862 | }; |
| 1856 | try writer.print("{}__{d}", .{ | 1863 | try writer.print("{}__{d}", .{ |
| ... | @@ -1894,10 +1901,10 @@ pub const DeclGen = struct { | ... | @@ -1894,10 +1901,10 @@ pub const DeclGen = struct { |
| 1894 | .bits => {}, | 1901 | .bits => {}, |
| 1895 | } | 1902 | } |
| 1896 | 1903 | ||
| 1897 | const target = dg.module.getTarget(); | 1904 | const mod = dg.module; |
| 1898 | const int_info = if (ty.isAbiInt()) ty.intInfo(target) else std.builtin.Type.Int{ | 1905 | const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{ |
| 1899 | .signedness = .unsigned, | 1906 | .signedness = .unsigned, |
| 1900 | .bits = @intCast(u16, ty.bitSize(target)), | 1907 | .bits = @intCast(u16, ty.bitSize(mod)), |
| 1901 | }; | 1908 | }; |
| 1902 | 1909 | ||
| 1903 | if (is_big) try writer.print(", {}", .{int_info.signedness == .signed}); | 1910 | if (is_big) try writer.print(", {}", .{int_info.signedness == .signed}); |
| ... | @@ -1916,6 +1923,7 @@ pub const DeclGen = struct { | ... | @@ -1916,6 +1923,7 @@ pub const DeclGen = struct { |
| 1916 | val: Value, | 1923 | val: Value, |
| 1917 | loc: ValueRenderLocation, | 1924 | loc: ValueRenderLocation, |
| 1918 | ) !std.fmt.Formatter(formatIntLiteral) { | 1925 | ) !std.fmt.Formatter(formatIntLiteral) { |
| 1926 | const mod = dg.module; | ||
| 1919 | const kind: CType.Kind = switch (loc) { | 1927 | const kind: CType.Kind = switch (loc) { |
| 1920 | .FunctionArgument => .parameter, | 1928 | .FunctionArgument => .parameter, |
| 1921 | .Initializer, .Other => .complete, | 1929 | .Initializer, .Other => .complete, |
| ... | @@ -1923,7 +1931,7 @@ pub const DeclGen = struct { | ... | @@ -1923,7 +1931,7 @@ pub const DeclGen = struct { |
| 1923 | }; | 1931 | }; |
| 1924 | return std.fmt.Formatter(formatIntLiteral){ .data = .{ | 1932 | return std.fmt.Formatter(formatIntLiteral){ .data = .{ |
| 1925 | .dg = dg, | 1933 | .dg = dg, |
| 1926 | .int_info = ty.intInfo(dg.module.getTarget()), | 1934 | .int_info = ty.intInfo(mod), |
| 1927 | .kind = kind, | 1935 | .kind = kind, |
| 1928 | .cty = try dg.typeToCType(ty, kind), | 1936 | .cty = try dg.typeToCType(ty, kind), |
| 1929 | .val = val, | 1937 | .val = val, |
| ... | @@ -2646,11 +2654,12 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2646,11 +2654,12 @@ pub fn genDecl(o: *Object) !void { |
| 2646 | const tracy = trace(@src()); | 2654 | const tracy = trace(@src()); |
| 2647 | defer tracy.end(); | 2655 | defer tracy.end(); |
| 2648 | 2656 | ||
| 2657 | const mod = o.dg.module; | ||
| 2649 | const decl = o.dg.decl.?; | 2658 | const decl = o.dg.decl.?; |
| 2650 | const decl_c_value = .{ .decl = o.dg.decl_index.unwrap().? }; | 2659 | const decl_c_value = .{ .decl = o.dg.decl_index.unwrap().? }; |
| 2651 | const tv: TypedValue = .{ .ty = decl.ty, .val = decl.val }; | 2660 | const tv: TypedValue = .{ .ty = decl.ty, .val = decl.val }; |
| 2652 | 2661 | ||
| 2653 | if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime()) return; | 2662 | if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; |
| 2654 | if (tv.val.tag() == .extern_fn) { | 2663 | if (tv.val.tag() == .extern_fn) { |
| 2655 | const fwd_decl_writer = o.dg.fwd_decl.writer(); | 2664 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2656 | try fwd_decl_writer.writeAll("zig_extern "); | 2665 | try fwd_decl_writer.writeAll("zig_extern "); |
| ... | @@ -2704,8 +2713,9 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { | ... | @@ -2704,8 +2713,9 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 2704 | .val = dg.decl.?.val, | 2713 | .val = dg.decl.?.val, |
| 2705 | }; | 2714 | }; |
| 2706 | const writer = dg.fwd_decl.writer(); | 2715 | const writer = dg.fwd_decl.writer(); |
| 2716 | const mod = dg.module; | ||
| 2707 | 2717 | ||
| 2708 | switch (tv.ty.zigTypeTag()) { | 2718 | switch (tv.ty.zigTypeTag(mod)) { |
| 2709 | .Fn => { | 2719 | .Fn => { |
| 2710 | const is_global = dg.declIsGlobal(tv); | 2720 | const is_global = dg.declIsGlobal(tv); |
| 2711 | if (is_global) { | 2721 | if (is_global) { |
| ... | @@ -2791,6 +2801,7 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con | ... | @@ -2791,6 +2801,7 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con |
| 2791 | } | 2801 | } |
| 2792 | 2802 | ||
| 2793 | fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { | 2803 | fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { |
| 2804 | const mod = f.object.dg.module; | ||
| 2794 | const air_tags = f.air.instructions.items(.tag); | 2805 | const air_tags = f.air.instructions.items(.tag); |
| 2795 | 2806 | ||
| 2796 | for (body) |inst| { | 2807 | for (body) |inst| { |
| ... | @@ -2826,10 +2837,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -2826,10 +2837,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 2826 | .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none), | 2837 | .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none), |
| 2827 | .rem => blk: { | 2838 | .rem => blk: { |
| 2828 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 2839 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 2829 | const lhs_scalar_ty = f.air.typeOf(bin_op.lhs).scalarType(); | 2840 | const lhs_scalar_ty = f.air.typeOf(bin_op.lhs).scalarType(mod); |
| 2830 | // For binary operations @TypeOf(lhs)==@TypeOf(rhs), | 2841 | // For binary operations @TypeOf(lhs)==@TypeOf(rhs), |
| 2831 | // so we only check one. | 2842 | // so we only check one. |
| 2832 | break :blk if (lhs_scalar_ty.isInt()) | 2843 | break :blk if (lhs_scalar_ty.isInt(mod)) |
| 2833 | try airBinOp(f, inst, "%", "rem", .none) | 2844 | try airBinOp(f, inst, "%", "rem", .none) |
| 2834 | else | 2845 | else |
| 2835 | try airBinFloatOp(f, inst, "fmod"); | 2846 | try airBinFloatOp(f, inst, "fmod"); |
| ... | @@ -3095,9 +3106,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ | ... | @@ -3095,9 +3106,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ |
| 3095 | } | 3106 | } |
| 3096 | 3107 | ||
| 3097 | fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | 3108 | fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3109 | const mod = f.object.dg.module; | ||
| 3098 | const inst_ty = f.air.typeOfIndex(inst); | 3110 | const inst_ty = f.air.typeOfIndex(inst); |
| 3099 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3111 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3100 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { | 3112 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3101 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3113 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3102 | return .none; | 3114 | return .none; |
| 3103 | } | 3115 | } |
| ... | @@ -3120,13 +3132,14 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3120,13 +3132,14 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3120 | } | 3132 | } |
| 3121 | 3133 | ||
| 3122 | fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 3134 | fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3135 | const mod = f.object.dg.module; | ||
| 3123 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 3136 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 3124 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 3137 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3125 | 3138 | ||
| 3126 | const inst_ty = f.air.typeOfIndex(inst); | 3139 | const inst_ty = f.air.typeOfIndex(inst); |
| 3127 | const ptr_ty = f.air.typeOf(bin_op.lhs); | 3140 | const ptr_ty = f.air.typeOf(bin_op.lhs); |
| 3128 | const elem_ty = ptr_ty.childType(); | 3141 | const elem_ty = ptr_ty.childType(); |
| 3129 | const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(); | 3142 | const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod); |
| 3130 | 3143 | ||
| 3131 | const ptr = try f.resolveInst(bin_op.lhs); | 3144 | const ptr = try f.resolveInst(bin_op.lhs); |
| 3132 | const index = try f.resolveInst(bin_op.rhs); | 3145 | const index = try f.resolveInst(bin_op.rhs); |
| ... | @@ -3155,9 +3168,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3155,9 +3168,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3155 | } | 3168 | } |
| 3156 | 3169 | ||
| 3157 | fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | 3170 | fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3171 | const mod = f.object.dg.module; | ||
| 3158 | const inst_ty = f.air.typeOfIndex(inst); | 3172 | const inst_ty = f.air.typeOfIndex(inst); |
| 3159 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3173 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3160 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { | 3174 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3161 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3175 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3162 | return .none; | 3176 | return .none; |
| 3163 | } | 3177 | } |
| ... | @@ -3180,13 +3194,14 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3180,13 +3194,14 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3180 | } | 3194 | } |
| 3181 | 3195 | ||
| 3182 | fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 3196 | fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3197 | const mod = f.object.dg.module; | ||
| 3183 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 3198 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 3184 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 3199 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3185 | 3200 | ||
| 3186 | const inst_ty = f.air.typeOfIndex(inst); | 3201 | const inst_ty = f.air.typeOfIndex(inst); |
| 3187 | const slice_ty = f.air.typeOf(bin_op.lhs); | 3202 | const slice_ty = f.air.typeOf(bin_op.lhs); |
| 3188 | const elem_ty = slice_ty.elemType2(); | 3203 | const elem_ty = slice_ty.elemType2(mod); |
| 3189 | const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(); | 3204 | const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod); |
| 3190 | 3205 | ||
| 3191 | const slice = try f.resolveInst(bin_op.lhs); | 3206 | const slice = try f.resolveInst(bin_op.lhs); |
| 3192 | const index = try f.resolveInst(bin_op.rhs); | 3207 | const index = try f.resolveInst(bin_op.rhs); |
| ... | @@ -3209,9 +3224,10 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3209,9 +3224,10 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3209 | } | 3224 | } |
| 3210 | 3225 | ||
| 3211 | fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | 3226 | fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3227 | const mod = f.object.dg.module; | ||
| 3212 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3228 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3213 | const inst_ty = f.air.typeOfIndex(inst); | 3229 | const inst_ty = f.air.typeOfIndex(inst); |
| 3214 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { | 3230 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3215 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3231 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3216 | return .none; | 3232 | return .none; |
| 3217 | } | 3233 | } |
| ... | @@ -3234,14 +3250,14 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3234,14 +3250,14 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3234 | } | 3250 | } |
| 3235 | 3251 | ||
| 3236 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { | 3252 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3253 | const mod = f.object.dg.module; | ||
| 3237 | const inst_ty = f.air.typeOfIndex(inst); | 3254 | const inst_ty = f.air.typeOfIndex(inst); |
| 3238 | const elem_type = inst_ty.elemType(); | 3255 | const elem_type = inst_ty.elemType(); |
| 3239 | if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty }; | 3256 | if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty }; |
| 3240 | 3257 | ||
| 3241 | const target = f.object.dg.module.getTarget(); | ||
| 3242 | const local = try f.allocLocalValue( | 3258 | const local = try f.allocLocalValue( |
| 3243 | elem_type, | 3259 | elem_type, |
| 3244 | inst_ty.ptrAlignment(target), | 3260 | inst_ty.ptrAlignment(mod), |
| 3245 | ); | 3261 | ); |
| 3246 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); | 3262 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3247 | const gpa = f.object.dg.module.gpa; | 3263 | const gpa = f.object.dg.module.gpa; |
| ... | @@ -3250,14 +3266,14 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3250,14 +3266,14 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3250 | } | 3266 | } |
| 3251 | 3267 | ||
| 3252 | fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 3268 | fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3269 | const mod = f.object.dg.module; | ||
| 3253 | const inst_ty = f.air.typeOfIndex(inst); | 3270 | const inst_ty = f.air.typeOfIndex(inst); |
| 3254 | const elem_ty = inst_ty.elemType(); | 3271 | const elem_ty = inst_ty.elemType(); |
| 3255 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty }; | 3272 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty }; |
| 3256 | 3273 | ||
| 3257 | const target = f.object.dg.module.getTarget(); | ||
| 3258 | const local = try f.allocLocalValue( | 3274 | const local = try f.allocLocalValue( |
| 3259 | elem_ty, | 3275 | elem_ty, |
| 3260 | inst_ty.ptrAlignment(target), | 3276 | inst_ty.ptrAlignment(mod), |
| 3261 | ); | 3277 | ); |
| 3262 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); | 3278 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3263 | const gpa = f.object.dg.module.gpa; | 3279 | const gpa = f.object.dg.module.gpa; |
| ... | @@ -3290,14 +3306,15 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3290,14 +3306,15 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3290 | } | 3306 | } |
| 3291 | 3307 | ||
| 3292 | fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | 3308 | fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3309 | const mod = f.object.dg.module; | ||
| 3293 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 3310 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 3294 | 3311 | ||
| 3295 | const ptr_ty = f.air.typeOf(ty_op.operand); | 3312 | const ptr_ty = f.air.typeOf(ty_op.operand); |
| 3296 | const ptr_scalar_ty = ptr_ty.scalarType(); | 3313 | const ptr_scalar_ty = ptr_ty.scalarType(mod); |
| 3297 | const ptr_info = ptr_scalar_ty.ptrInfo().data; | 3314 | const ptr_info = ptr_scalar_ty.ptrInfo().data; |
| 3298 | const src_ty = ptr_info.pointee_type; | 3315 | const src_ty = ptr_info.pointee_type; |
| 3299 | 3316 | ||
| 3300 | if (!src_ty.hasRuntimeBitsIgnoreComptime()) { | 3317 | if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3301 | try reap(f, inst, &.{ty_op.operand}); | 3318 | try reap(f, inst, &.{ty_op.operand}); |
| 3302 | return .none; | 3319 | return .none; |
| 3303 | } | 3320 | } |
| ... | @@ -3306,9 +3323,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3306,9 +3323,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3306 | 3323 | ||
| 3307 | try reap(f, inst, &.{ty_op.operand}); | 3324 | try reap(f, inst, &.{ty_op.operand}); |
| 3308 | 3325 | ||
| 3309 | const target = f.object.dg.module.getTarget(); | 3326 | const is_aligned = ptr_info.@"align" == 0 or ptr_info.@"align" >= src_ty.abiAlignment(mod); |
| 3310 | const is_aligned = ptr_info.@"align" == 0 or ptr_info.@"align" >= src_ty.abiAlignment(target); | 3327 | const is_array = lowersToArray(src_ty, mod); |
| 3311 | const is_array = lowersToArray(src_ty, target); | ||
| 3312 | const need_memcpy = !is_aligned or is_array; | 3328 | const need_memcpy = !is_aligned or is_array; |
| 3313 | 3329 | ||
| 3314 | const writer = f.object.writer(); | 3330 | const writer = f.object.writer(); |
| ... | @@ -3327,17 +3343,10 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3327,17 +3343,10 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3327 | try f.renderType(writer, src_ty); | 3343 | try f.renderType(writer, src_ty); |
| 3328 | try writer.writeAll("))"); | 3344 | try writer.writeAll("))"); |
| 3329 | } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) { | 3345 | } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) { |
| 3330 | var host_pl = Type.Payload.Bits{ | 3346 | const host_bits: u16 = ptr_info.host_size * 8; |
| 3331 | .base = .{ .tag = .int_unsigned }, | 3347 | const host_ty = try mod.intType(.unsigned, host_bits); |
| 3332 | .data = ptr_info.host_size * 8, | ||
| 3333 | }; | ||
| 3334 | const host_ty = Type.initPayload(&host_pl.base); | ||
| 3335 | 3348 | ||
| 3336 | var bit_offset_ty_pl = Type.Payload.Bits{ | 3349 | const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1)); |
| 3337 | .base = .{ .tag = .int_unsigned }, | ||
| 3338 | .data = Type.smallestUnsignedBits(host_pl.data - 1), | ||
| 3339 | }; | ||
| 3340 | const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base); | ||
| 3341 | 3350 | ||
| 3342 | var bit_offset_val_pl: Value.Payload.U64 = .{ | 3351 | var bit_offset_val_pl: Value.Payload.U64 = .{ |
| 3343 | .base = .{ .tag = .int_u64 }, | 3352 | .base = .{ .tag = .int_u64 }, |
| ... | @@ -3345,11 +3354,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3345,11 +3354,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3345 | }; | 3354 | }; |
| 3346 | const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base); | 3355 | const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base); |
| 3347 | 3356 | ||
| 3348 | var field_pl = Type.Payload.Bits{ | 3357 | const field_ty = try mod.intType(.unsigned, @intCast(u16, src_ty.bitSize(mod))); |
| 3349 | .base = .{ .tag = .int_unsigned }, | ||
| 3350 | .data = @intCast(u16, src_ty.bitSize(target)), | ||
| 3351 | }; | ||
| 3352 | const field_ty = Type.initPayload(&field_pl.base); | ||
| 3353 | 3358 | ||
| 3354 | try f.writeCValue(writer, local, .Other); | 3359 | try f.writeCValue(writer, local, .Other); |
| 3355 | try v.elem(f, writer); | 3360 | try v.elem(f, writer); |
| ... | @@ -3360,9 +3365,9 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3360,9 +3365,9 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3360 | try writer.writeAll("(("); | 3365 | try writer.writeAll("(("); |
| 3361 | try f.renderType(writer, field_ty); | 3366 | try f.renderType(writer, field_ty); |
| 3362 | try writer.writeByte(')'); | 3367 | try writer.writeByte(')'); |
| 3363 | const cant_cast = host_ty.isInt() and host_ty.bitSize(target) > 64; | 3368 | const cant_cast = host_ty.isInt(mod) and host_ty.bitSize(mod) > 64; |
| 3364 | if (cant_cast) { | 3369 | if (cant_cast) { |
| 3365 | if (field_ty.bitSize(target) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); | 3370 | if (field_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); |
| 3366 | try writer.writeAll("zig_lo_"); | 3371 | try writer.writeAll("zig_lo_"); |
| 3367 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | 3372 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); |
| 3368 | try writer.writeByte('('); | 3373 | try writer.writeByte('('); |
| ... | @@ -3390,23 +3395,23 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3390,23 +3395,23 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3390 | } | 3395 | } |
| 3391 | 3396 | ||
| 3392 | fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { | 3397 | fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 3398 | const mod = f.object.dg.module; | ||
| 3393 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 3399 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 3394 | const writer = f.object.writer(); | 3400 | const writer = f.object.writer(); |
| 3395 | const target = f.object.dg.module.getTarget(); | ||
| 3396 | const op_inst = Air.refToIndex(un_op); | 3401 | const op_inst = Air.refToIndex(un_op); |
| 3397 | const op_ty = f.air.typeOf(un_op); | 3402 | const op_ty = f.air.typeOf(un_op); |
| 3398 | const ret_ty = if (is_ptr) op_ty.childType() else op_ty; | 3403 | const ret_ty = if (is_ptr) op_ty.childType() else op_ty; |
| 3399 | var lowered_ret_buf: LowerFnRetTyBuffer = undefined; | 3404 | var lowered_ret_buf: LowerFnRetTyBuffer = undefined; |
| 3400 | const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target); | 3405 | const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, mod); |
| 3401 | 3406 | ||
| 3402 | if (op_inst != null and f.air.instructions.items(.tag)[op_inst.?] == .call_always_tail) { | 3407 | if (op_inst != null and f.air.instructions.items(.tag)[op_inst.?] == .call_always_tail) { |
| 3403 | try reap(f, inst, &.{un_op}); | 3408 | try reap(f, inst, &.{un_op}); |
| 3404 | _ = try airCall(f, op_inst.?, .always_tail); | 3409 | _ = try airCall(f, op_inst.?, .always_tail); |
| 3405 | } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) { | 3410 | } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3406 | const operand = try f.resolveInst(un_op); | 3411 | const operand = try f.resolveInst(un_op); |
| 3407 | try reap(f, inst, &.{un_op}); | 3412 | try reap(f, inst, &.{un_op}); |
| 3408 | var deref = is_ptr; | 3413 | var deref = is_ptr; |
| 3409 | const is_array = lowersToArray(ret_ty, target); | 3414 | const is_array = lowersToArray(ret_ty, mod); |
| 3410 | const ret_val = if (is_array) ret_val: { | 3415 | const ret_val = if (is_array) ret_val: { |
| 3411 | const array_local = try f.allocLocal(inst, lowered_ret_ty); | 3416 | const array_local = try f.allocLocal(inst, lowered_ret_ty); |
| 3412 | try writer.writeAll("memcpy("); | 3417 | try writer.writeAll("memcpy("); |
| ... | @@ -3442,15 +3447,16 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { | ... | @@ -3442,15 +3447,16 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 3442 | } | 3447 | } |
| 3443 | 3448 | ||
| 3444 | fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { | 3449 | fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3450 | const mod = f.object.dg.module; | ||
| 3445 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 3451 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 3446 | 3452 | ||
| 3447 | const operand = try f.resolveInst(ty_op.operand); | 3453 | const operand = try f.resolveInst(ty_op.operand); |
| 3448 | try reap(f, inst, &.{ty_op.operand}); | 3454 | try reap(f, inst, &.{ty_op.operand}); |
| 3449 | 3455 | ||
| 3450 | const inst_ty = f.air.typeOfIndex(inst); | 3456 | const inst_ty = f.air.typeOfIndex(inst); |
| 3451 | const inst_scalar_ty = inst_ty.scalarType(); | 3457 | const inst_scalar_ty = inst_ty.scalarType(mod); |
| 3452 | const operand_ty = f.air.typeOf(ty_op.operand); | 3458 | const operand_ty = f.air.typeOf(ty_op.operand); |
| 3453 | const scalar_ty = operand_ty.scalarType(); | 3459 | const scalar_ty = operand_ty.scalarType(mod); |
| 3454 | 3460 | ||
| 3455 | const writer = f.object.writer(); | 3461 | const writer = f.object.writer(); |
| 3456 | const local = try f.allocLocal(inst, inst_ty); | 3462 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -3467,20 +3473,20 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3467,20 +3473,20 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3467 | } | 3473 | } |
| 3468 | 3474 | ||
| 3469 | fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | 3475 | fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3476 | const mod = f.object.dg.module; | ||
| 3470 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 3477 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 3471 | 3478 | ||
| 3472 | const operand = try f.resolveInst(ty_op.operand); | 3479 | const operand = try f.resolveInst(ty_op.operand); |
| 3473 | try reap(f, inst, &.{ty_op.operand}); | 3480 | try reap(f, inst, &.{ty_op.operand}); |
| 3474 | const inst_ty = f.air.typeOfIndex(inst); | 3481 | const inst_ty = f.air.typeOfIndex(inst); |
| 3475 | const inst_scalar_ty = inst_ty.scalarType(); | 3482 | const inst_scalar_ty = inst_ty.scalarType(mod); |
| 3476 | const target = f.object.dg.module.getTarget(); | 3483 | const dest_int_info = inst_scalar_ty.intInfo(mod); |
| 3477 | const dest_int_info = inst_scalar_ty.intInfo(target); | ||
| 3478 | const dest_bits = dest_int_info.bits; | 3484 | const dest_bits = dest_int_info.bits; |
| 3479 | const dest_c_bits = toCIntBits(dest_int_info.bits) orelse | 3485 | const dest_c_bits = toCIntBits(dest_int_info.bits) orelse |
| 3480 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); | 3486 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); |
| 3481 | const operand_ty = f.air.typeOf(ty_op.operand); | 3487 | const operand_ty = f.air.typeOf(ty_op.operand); |
| 3482 | const scalar_ty = operand_ty.scalarType(); | 3488 | const scalar_ty = operand_ty.scalarType(mod); |
| 3483 | const scalar_int_info = scalar_ty.intInfo(target); | 3489 | const scalar_int_info = scalar_ty.intInfo(mod); |
| 3484 | 3490 | ||
| 3485 | const writer = f.object.writer(); | 3491 | const writer = f.object.writer(); |
| 3486 | const local = try f.allocLocal(inst, inst_ty); | 3492 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -3515,7 +3521,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3515,7 +3521,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3515 | var stack align(@alignOf(ExpectedContents)) = | 3521 | var stack align(@alignOf(ExpectedContents)) = |
| 3516 | std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator()); | 3522 | std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator()); |
| 3517 | 3523 | ||
| 3518 | const mask_val = try inst_scalar_ty.maxInt(stack.get(), target); | 3524 | const mask_val = try inst_scalar_ty.maxInt(stack.get(), mod); |
| 3519 | try writer.writeAll("zig_and_"); | 3525 | try writer.writeAll("zig_and_"); |
| 3520 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | 3526 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); |
| 3521 | try writer.writeByte('('); | 3527 | try writer.writeByte('('); |
| ... | @@ -3577,17 +3583,18 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3577,17 +3583,18 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3577 | } | 3583 | } |
| 3578 | 3584 | ||
| 3579 | fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | 3585 | fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3586 | const mod = f.object.dg.module; | ||
| 3580 | // *a = b; | 3587 | // *a = b; |
| 3581 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3588 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3582 | 3589 | ||
| 3583 | const ptr_ty = f.air.typeOf(bin_op.lhs); | 3590 | const ptr_ty = f.air.typeOf(bin_op.lhs); |
| 3584 | const ptr_scalar_ty = ptr_ty.scalarType(); | 3591 | const ptr_scalar_ty = ptr_ty.scalarType(mod); |
| 3585 | const ptr_info = ptr_scalar_ty.ptrInfo().data; | 3592 | const ptr_info = ptr_scalar_ty.ptrInfo().data; |
| 3586 | 3593 | ||
| 3587 | const ptr_val = try f.resolveInst(bin_op.lhs); | 3594 | const ptr_val = try f.resolveInst(bin_op.lhs); |
| 3588 | const src_ty = f.air.typeOf(bin_op.rhs); | 3595 | const src_ty = f.air.typeOf(bin_op.rhs); |
| 3589 | 3596 | ||
| 3590 | const val_is_undef = if (f.air.value(bin_op.rhs)) |v| v.isUndefDeep() else false; | 3597 | const val_is_undef = if (f.air.value(bin_op.rhs, mod)) |v| v.isUndefDeep() else false; |
| 3591 | 3598 | ||
| 3592 | if (val_is_undef) { | 3599 | if (val_is_undef) { |
| 3593 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3600 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| ... | @@ -3602,10 +3609,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3602,10 +3609,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3602 | return .none; | 3609 | return .none; |
| 3603 | } | 3610 | } |
| 3604 | 3611 | ||
| 3605 | const target = f.object.dg.module.getTarget(); | ||
| 3606 | const is_aligned = ptr_info.@"align" == 0 or | 3612 | const is_aligned = ptr_info.@"align" == 0 or |
| 3607 | ptr_info.@"align" >= ptr_info.pointee_type.abiAlignment(target); | 3613 | ptr_info.@"align" >= ptr_info.pointee_type.abiAlignment(mod); |
| 3608 | const is_array = lowersToArray(ptr_info.pointee_type, target); | 3614 | const is_array = lowersToArray(ptr_info.pointee_type, mod); |
| 3609 | const need_memcpy = !is_aligned or is_array; | 3615 | const need_memcpy = !is_aligned or is_array; |
| 3610 | 3616 | ||
| 3611 | const src_val = try f.resolveInst(bin_op.rhs); | 3617 | const src_val = try f.resolveInst(bin_op.rhs); |
| ... | @@ -3647,14 +3653,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3647,14 +3653,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3647 | } | 3653 | } |
| 3648 | } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) { | 3654 | } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) { |
| 3649 | const host_bits = ptr_info.host_size * 8; | 3655 | const host_bits = ptr_info.host_size * 8; |
| 3650 | var host_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = host_bits }; | 3656 | const host_ty = try mod.intType(.unsigned, host_bits); |
| 3651 | const host_ty = Type.initPayload(&host_pl.base); | ||
| 3652 | 3657 | ||
| 3653 | var bit_offset_ty_pl = Type.Payload.Bits{ | 3658 | const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1)); |
| 3654 | .base = .{ .tag = .int_unsigned }, | ||
| 3655 | .data = Type.smallestUnsignedBits(host_bits - 1), | ||
| 3656 | }; | ||
| 3657 | const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base); | ||
| 3658 | 3659 | ||
| 3659 | var bit_offset_val_pl: Value.Payload.U64 = .{ | 3660 | var bit_offset_val_pl: Value.Payload.U64 = .{ |
| 3660 | .base = .{ .tag = .int_u64 }, | 3661 | .base = .{ .tag = .int_u64 }, |
| ... | @@ -3662,7 +3663,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3662,7 +3663,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3662 | }; | 3663 | }; |
| 3663 | const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base); | 3664 | const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base); |
| 3664 | 3665 | ||
| 3665 | const src_bits = src_ty.bitSize(target); | 3666 | const src_bits = src_ty.bitSize(mod); |
| 3666 | 3667 | ||
| 3667 | const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb; | 3668 | const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb; |
| 3668 | var stack align(@alignOf(ExpectedContents)) = | 3669 | var stack align(@alignOf(ExpectedContents)) = |
| ... | @@ -3693,9 +3694,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3693,9 +3694,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3693 | try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)}); | 3694 | try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)}); |
| 3694 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | 3695 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); |
| 3695 | try writer.writeByte('('); | 3696 | try writer.writeByte('('); |
| 3696 | const cant_cast = host_ty.isInt() and host_ty.bitSize(target) > 64; | 3697 | const cant_cast = host_ty.isInt(mod) and host_ty.bitSize(mod) > 64; |
| 3697 | if (cant_cast) { | 3698 | if (cant_cast) { |
| 3698 | if (src_ty.bitSize(target) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); | 3699 | if (src_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); |
| 3699 | try writer.writeAll("zig_make_"); | 3700 | try writer.writeAll("zig_make_"); |
| 3700 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | 3701 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); |
| 3701 | try writer.writeAll("(0, "); | 3702 | try writer.writeAll("(0, "); |
| ... | @@ -3705,7 +3706,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3705,7 +3706,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3705 | try writer.writeByte(')'); | 3706 | try writer.writeByte(')'); |
| 3706 | } | 3707 | } |
| 3707 | 3708 | ||
| 3708 | if (src_ty.isPtrAtRuntime()) { | 3709 | if (src_ty.isPtrAtRuntime(mod)) { |
| 3709 | try writer.writeByte('('); | 3710 | try writer.writeByte('('); |
| 3710 | try f.renderType(writer, Type.usize); | 3711 | try f.renderType(writer, Type.usize); |
| 3711 | try writer.writeByte(')'); | 3712 | try writer.writeByte(')'); |
| ... | @@ -3728,6 +3729,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3728,6 +3729,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3728 | } | 3729 | } |
| 3729 | 3730 | ||
| 3730 | fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue { | 3731 | fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue { |
| 3732 | const mod = f.object.dg.module; | ||
| 3731 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 3733 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 3732 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 3734 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3733 | 3735 | ||
| ... | @@ -3737,7 +3739,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: | ... | @@ -3737,7 +3739,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 3737 | 3739 | ||
| 3738 | const inst_ty = f.air.typeOfIndex(inst); | 3740 | const inst_ty = f.air.typeOfIndex(inst); |
| 3739 | const operand_ty = f.air.typeOf(bin_op.lhs); | 3741 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 3740 | const scalar_ty = operand_ty.scalarType(); | 3742 | const scalar_ty = operand_ty.scalarType(mod); |
| 3741 | 3743 | ||
| 3742 | const w = f.object.writer(); | 3744 | const w = f.object.writer(); |
| 3743 | const local = try f.allocLocal(inst, inst_ty); | 3745 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -3765,9 +3767,10 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: | ... | @@ -3765,9 +3767,10 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 3765 | } | 3767 | } |
| 3766 | 3768 | ||
| 3767 | fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { | 3769 | fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3770 | const mod = f.object.dg.module; | ||
| 3768 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 3771 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 3769 | const operand_ty = f.air.typeOf(ty_op.operand); | 3772 | const operand_ty = f.air.typeOf(ty_op.operand); |
| 3770 | const scalar_ty = operand_ty.scalarType(); | 3773 | const scalar_ty = operand_ty.scalarType(mod); |
| 3771 | if (scalar_ty.tag() != .bool) return try airUnBuiltinCall(f, inst, "not", .bits); | 3774 | if (scalar_ty.tag() != .bool) return try airUnBuiltinCall(f, inst, "not", .bits); |
| 3772 | 3775 | ||
| 3773 | const op = try f.resolveInst(ty_op.operand); | 3776 | const op = try f.resolveInst(ty_op.operand); |
| ... | @@ -3797,11 +3800,11 @@ fn airBinOp( | ... | @@ -3797,11 +3800,11 @@ fn airBinOp( |
| 3797 | operation: []const u8, | 3800 | operation: []const u8, |
| 3798 | info: BuiltinInfo, | 3801 | info: BuiltinInfo, |
| 3799 | ) !CValue { | 3802 | ) !CValue { |
| 3803 | const mod = f.object.dg.module; | ||
| 3800 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3804 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3801 | const operand_ty = f.air.typeOf(bin_op.lhs); | 3805 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 3802 | const scalar_ty = operand_ty.scalarType(); | 3806 | const scalar_ty = operand_ty.scalarType(mod); |
| 3803 | const target = f.object.dg.module.getTarget(); | 3807 | if ((scalar_ty.isInt(mod) and scalar_ty.bitSize(mod) > 64) or scalar_ty.isRuntimeFloat()) |
| 3804 | if ((scalar_ty.isInt() and scalar_ty.bitSize(target) > 64) or scalar_ty.isRuntimeFloat()) | ||
| 3805 | return try airBinBuiltinCall(f, inst, operation, info); | 3808 | return try airBinBuiltinCall(f, inst, operation, info); |
| 3806 | 3809 | ||
| 3807 | const lhs = try f.resolveInst(bin_op.lhs); | 3810 | const lhs = try f.resolveInst(bin_op.lhs); |
| ... | @@ -3835,12 +3838,12 @@ fn airCmpOp( | ... | @@ -3835,12 +3838,12 @@ fn airCmpOp( |
| 3835 | data: anytype, | 3838 | data: anytype, |
| 3836 | operator: std.math.CompareOperator, | 3839 | operator: std.math.CompareOperator, |
| 3837 | ) !CValue { | 3840 | ) !CValue { |
| 3841 | const mod = f.object.dg.module; | ||
| 3838 | const lhs_ty = f.air.typeOf(data.lhs); | 3842 | const lhs_ty = f.air.typeOf(data.lhs); |
| 3839 | const scalar_ty = lhs_ty.scalarType(); | 3843 | const scalar_ty = lhs_ty.scalarType(mod); |
| 3840 | 3844 | ||
| 3841 | const target = f.object.dg.module.getTarget(); | 3845 | const scalar_bits = scalar_ty.bitSize(mod); |
| 3842 | const scalar_bits = scalar_ty.bitSize(target); | 3846 | if (scalar_ty.isInt(mod) and scalar_bits > 64) |
| 3843 | if (scalar_ty.isInt() and scalar_bits > 64) | ||
| 3844 | return airCmpBuiltinCall( | 3847 | return airCmpBuiltinCall( |
| 3845 | f, | 3848 | f, |
| 3846 | inst, | 3849 | inst, |
| ... | @@ -3885,12 +3888,12 @@ fn airEquality( | ... | @@ -3885,12 +3888,12 @@ fn airEquality( |
| 3885 | inst: Air.Inst.Index, | 3888 | inst: Air.Inst.Index, |
| 3886 | operator: std.math.CompareOperator, | 3889 | operator: std.math.CompareOperator, |
| 3887 | ) !CValue { | 3890 | ) !CValue { |
| 3891 | const mod = f.object.dg.module; | ||
| 3888 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3892 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3889 | 3893 | ||
| 3890 | const operand_ty = f.air.typeOf(bin_op.lhs); | 3894 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 3891 | const target = f.object.dg.module.getTarget(); | 3895 | const operand_bits = operand_ty.bitSize(mod); |
| 3892 | const operand_bits = operand_ty.bitSize(target); | 3896 | if (operand_ty.isInt(mod) and operand_bits > 64) |
| 3893 | if (operand_ty.isInt() and operand_bits > 64) | ||
| 3894 | return airCmpBuiltinCall( | 3897 | return airCmpBuiltinCall( |
| 3895 | f, | 3898 | f, |
| 3896 | inst, | 3899 | inst, |
| ... | @@ -3912,7 +3915,7 @@ fn airEquality( | ... | @@ -3912,7 +3915,7 @@ fn airEquality( |
| 3912 | try f.writeCValue(writer, local, .Other); | 3915 | try f.writeCValue(writer, local, .Other); |
| 3913 | try writer.writeAll(" = "); | 3916 | try writer.writeAll(" = "); |
| 3914 | 3917 | ||
| 3915 | if (operand_ty.zigTypeTag() == .Optional and !operand_ty.optionalReprIsPayload()) { | 3918 | if (operand_ty.zigTypeTag(mod) == .Optional and !operand_ty.optionalReprIsPayload(mod)) { |
| 3916 | // (A && B) || (C && (A == B)) | 3919 | // (A && B) || (C && (A == B)) |
| 3917 | // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload | 3920 | // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload |
| 3918 | 3921 | ||
| ... | @@ -3965,6 +3968,7 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3965,6 +3968,7 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3965 | } | 3968 | } |
| 3966 | 3969 | ||
| 3967 | fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | 3970 | fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 3971 | const mod = f.object.dg.module; | ||
| 3968 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 3972 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 3969 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 3973 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3970 | 3974 | ||
| ... | @@ -3973,8 +3977,8 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | ... | @@ -3973,8 +3977,8 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 3973 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3977 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3974 | 3978 | ||
| 3975 | const inst_ty = f.air.typeOfIndex(inst); | 3979 | const inst_ty = f.air.typeOfIndex(inst); |
| 3976 | const inst_scalar_ty = inst_ty.scalarType(); | 3980 | const inst_scalar_ty = inst_ty.scalarType(mod); |
| 3977 | const elem_ty = inst_scalar_ty.elemType2(); | 3981 | const elem_ty = inst_scalar_ty.elemType2(mod); |
| 3978 | 3982 | ||
| 3979 | const local = try f.allocLocal(inst, inst_ty); | 3983 | const local = try f.allocLocal(inst, inst_ty); |
| 3980 | const writer = f.object.writer(); | 3984 | const writer = f.object.writer(); |
| ... | @@ -3983,7 +3987,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | ... | @@ -3983,7 +3987,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 3983 | try v.elem(f, writer); | 3987 | try v.elem(f, writer); |
| 3984 | try writer.writeAll(" = "); | 3988 | try writer.writeAll(" = "); |
| 3985 | 3989 | ||
| 3986 | if (elem_ty.hasRuntimeBitsIgnoreComptime()) { | 3990 | if (elem_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3987 | // We must convert to and from integer types to prevent UB if the operation | 3991 | // We must convert to and from integer types to prevent UB if the operation |
| 3988 | // results in a NULL pointer, or if LHS is NULL. The operation is only UB | 3992 | // results in a NULL pointer, or if LHS is NULL. The operation is only UB |
| 3989 | // if the result is NULL and then dereferenced. | 3993 | // if the result is NULL and then dereferenced. |
| ... | @@ -4012,13 +4016,13 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | ... | @@ -4012,13 +4016,13 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4012 | } | 4016 | } |
| 4013 | 4017 | ||
| 4014 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { | 4018 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { |
| 4019 | const mod = f.object.dg.module; | ||
| 4015 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 4020 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 4016 | 4021 | ||
| 4017 | const inst_ty = f.air.typeOfIndex(inst); | 4022 | const inst_ty = f.air.typeOfIndex(inst); |
| 4018 | const inst_scalar_ty = inst_ty.scalarType(); | 4023 | const inst_scalar_ty = inst_ty.scalarType(mod); |
| 4019 | 4024 | ||
| 4020 | const target = f.object.dg.module.getTarget(); | 4025 | if (inst_scalar_ty.isInt(mod) and inst_scalar_ty.bitSize(mod) > 64) |
| 4021 | if (inst_scalar_ty.isInt() and inst_scalar_ty.bitSize(target) > 64) | ||
| 4022 | return try airBinBuiltinCall(f, inst, operation[1..], .none); | 4026 | return try airBinBuiltinCall(f, inst, operation[1..], .none); |
| 4023 | if (inst_scalar_ty.isRuntimeFloat()) | 4027 | if (inst_scalar_ty.isRuntimeFloat()) |
| 4024 | return try airBinFloatOp(f, inst, operation); | 4028 | return try airBinFloatOp(f, inst, operation); |
| ... | @@ -4092,12 +4096,11 @@ fn airCall( | ... | @@ -4092,12 +4096,11 @@ fn airCall( |
| 4092 | inst: Air.Inst.Index, | 4096 | inst: Air.Inst.Index, |
| 4093 | modifier: std.builtin.CallModifier, | 4097 | modifier: std.builtin.CallModifier, |
| 4094 | ) !CValue { | 4098 | ) !CValue { |
| 4099 | const mod = f.object.dg.module; | ||
| 4095 | // Not even allowed to call panic in a naked function. | 4100 | // Not even allowed to call panic in a naked function. |
| 4096 | if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention() == .Naked) return .none; | 4101 | if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention() == .Naked) return .none; |
| 4097 | 4102 | ||
| 4098 | const gpa = f.object.dg.gpa; | 4103 | const gpa = f.object.dg.gpa; |
| 4099 | const module = f.object.dg.module; | ||
| 4100 | const target = module.getTarget(); | ||
| 4101 | const writer = f.object.writer(); | 4104 | const writer = f.object.writer(); |
| 4102 | 4105 | ||
| 4103 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; | 4106 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| ... | @@ -4116,7 +4119,7 @@ fn airCall( | ... | @@ -4116,7 +4119,7 @@ fn airCall( |
| 4116 | resolved_arg.* = try f.resolveInst(arg); | 4119 | resolved_arg.* = try f.resolveInst(arg); |
| 4117 | if (arg_cty != try f.typeToIndex(arg_ty, .complete)) { | 4120 | if (arg_cty != try f.typeToIndex(arg_ty, .complete)) { |
| 4118 | var lowered_arg_buf: LowerFnRetTyBuffer = undefined; | 4121 | var lowered_arg_buf: LowerFnRetTyBuffer = undefined; |
| 4119 | const lowered_arg_ty = lowerFnRetTy(arg_ty, &lowered_arg_buf, target); | 4122 | const lowered_arg_ty = lowerFnRetTy(arg_ty, &lowered_arg_buf, mod); |
| 4120 | 4123 | ||
| 4121 | const array_local = try f.allocLocal(inst, lowered_arg_ty); | 4124 | const array_local = try f.allocLocal(inst, lowered_arg_ty); |
| 4122 | try writer.writeAll("memcpy("); | 4125 | try writer.writeAll("memcpy("); |
| ... | @@ -4139,7 +4142,7 @@ fn airCall( | ... | @@ -4139,7 +4142,7 @@ fn airCall( |
| 4139 | } | 4142 | } |
| 4140 | 4143 | ||
| 4141 | const callee_ty = f.air.typeOf(pl_op.operand); | 4144 | const callee_ty = f.air.typeOf(pl_op.operand); |
| 4142 | const fn_ty = switch (callee_ty.zigTypeTag()) { | 4145 | const fn_ty = switch (callee_ty.zigTypeTag(mod)) { |
| 4143 | .Fn => callee_ty, | 4146 | .Fn => callee_ty, |
| 4144 | .Pointer => callee_ty.childType(), | 4147 | .Pointer => callee_ty.childType(), |
| 4145 | else => unreachable, | 4148 | else => unreachable, |
| ... | @@ -4147,13 +4150,13 @@ fn airCall( | ... | @@ -4147,13 +4150,13 @@ fn airCall( |
| 4147 | 4150 | ||
| 4148 | const ret_ty = fn_ty.fnReturnType(); | 4151 | const ret_ty = fn_ty.fnReturnType(); |
| 4149 | var lowered_ret_buf: LowerFnRetTyBuffer = undefined; | 4152 | var lowered_ret_buf: LowerFnRetTyBuffer = undefined; |
| 4150 | const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target); | 4153 | const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, mod); |
| 4151 | 4154 | ||
| 4152 | const result_local = result: { | 4155 | const result_local = result: { |
| 4153 | if (modifier == .always_tail) { | 4156 | if (modifier == .always_tail) { |
| 4154 | try writer.writeAll("zig_always_tail return "); | 4157 | try writer.writeAll("zig_always_tail return "); |
| 4155 | break :result .none; | 4158 | break :result .none; |
| 4156 | } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) { | 4159 | } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4157 | break :result .none; | 4160 | break :result .none; |
| 4158 | } else if (f.liveness.isUnused(inst)) { | 4161 | } else if (f.liveness.isUnused(inst)) { |
| 4159 | try writer.writeByte('('); | 4162 | try writer.writeByte('('); |
| ... | @@ -4171,7 +4174,7 @@ fn airCall( | ... | @@ -4171,7 +4174,7 @@ fn airCall( |
| 4171 | callee: { | 4174 | callee: { |
| 4172 | known: { | 4175 | known: { |
| 4173 | const fn_decl = fn_decl: { | 4176 | const fn_decl = fn_decl: { |
| 4174 | const callee_val = f.air.value(pl_op.operand) orelse break :known; | 4177 | const callee_val = f.air.value(pl_op.operand, mod) orelse break :known; |
| 4175 | break :fn_decl switch (callee_val.tag()) { | 4178 | break :fn_decl switch (callee_val.tag()) { |
| 4176 | .extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl, | 4179 | .extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl, |
| 4177 | .function => callee_val.castTag(.function).?.data.owner_decl, | 4180 | .function => callee_val.castTag(.function).?.data.owner_decl, |
| ... | @@ -4181,9 +4184,9 @@ fn airCall( | ... | @@ -4181,9 +4184,9 @@ fn airCall( |
| 4181 | }; | 4184 | }; |
| 4182 | switch (modifier) { | 4185 | switch (modifier) { |
| 4183 | .auto, .always_tail => try f.object.dg.renderDeclName(writer, fn_decl, 0), | 4186 | .auto, .always_tail => try f.object.dg.renderDeclName(writer, fn_decl, 0), |
| 4184 | inline .never_tail, .never_inline => |mod| try writer.writeAll(try f.getLazyFnName( | 4187 | inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName( |
| 4185 | @unionInit(LazyFnKey, @tagName(mod), fn_decl), | 4188 | @unionInit(LazyFnKey, @tagName(m), fn_decl), |
| 4186 | @unionInit(LazyFnValue.Data, @tagName(mod), {}), | 4189 | @unionInit(LazyFnValue.Data, @tagName(m), {}), |
| 4187 | )), | 4190 | )), |
| 4188 | else => unreachable, | 4191 | else => unreachable, |
| 4189 | } | 4192 | } |
| ... | @@ -4211,7 +4214,7 @@ fn airCall( | ... | @@ -4211,7 +4214,7 @@ fn airCall( |
| 4211 | try writer.writeAll(");\n"); | 4214 | try writer.writeAll(");\n"); |
| 4212 | 4215 | ||
| 4213 | const result = result: { | 4216 | const result = result: { |
| 4214 | if (result_local == .none or !lowersToArray(ret_ty, target)) | 4217 | if (result_local == .none or !lowersToArray(ret_ty, mod)) |
| 4215 | break :result result_local; | 4218 | break :result result_local; |
| 4216 | 4219 | ||
| 4217 | const array_local = try f.allocLocal(inst, ret_ty); | 4220 | const array_local = try f.allocLocal(inst, ret_ty); |
| ... | @@ -4254,9 +4257,10 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4254,9 +4257,10 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4254 | } | 4257 | } |
| 4255 | 4258 | ||
| 4256 | fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { | 4259 | fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4260 | const mod = f.object.dg.module; | ||
| 4257 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; | 4261 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| 4258 | const name = f.air.nullTerminatedString(pl_op.payload); | 4262 | const name = f.air.nullTerminatedString(pl_op.payload); |
| 4259 | const operand_is_undef = if (f.air.value(pl_op.operand)) |v| v.isUndefDeep() else false; | 4263 | const operand_is_undef = if (f.air.value(pl_op.operand, mod)) |v| v.isUndefDeep() else false; |
| 4260 | if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand); | 4264 | if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand); |
| 4261 | 4265 | ||
| 4262 | try reap(f, inst, &.{pl_op.operand}); | 4266 | try reap(f, inst, &.{pl_op.operand}); |
| ... | @@ -4330,12 +4334,13 @@ fn lowerTry( | ... | @@ -4330,12 +4334,13 @@ fn lowerTry( |
| 4330 | err_union_ty: Type, | 4334 | err_union_ty: Type, |
| 4331 | is_ptr: bool, | 4335 | is_ptr: bool, |
| 4332 | ) !CValue { | 4336 | ) !CValue { |
| 4337 | const mod = f.object.dg.module; | ||
| 4333 | const err_union = try f.resolveInst(operand); | 4338 | const err_union = try f.resolveInst(operand); |
| 4334 | const inst_ty = f.air.typeOfIndex(inst); | 4339 | const inst_ty = f.air.typeOfIndex(inst); |
| 4335 | const liveness_condbr = f.liveness.getCondBr(inst); | 4340 | const liveness_condbr = f.liveness.getCondBr(inst); |
| 4336 | const writer = f.object.writer(); | 4341 | const writer = f.object.writer(); |
| 4337 | const payload_ty = err_union_ty.errorUnionPayload(); | 4342 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 4338 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); | 4343 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod); |
| 4339 | 4344 | ||
| 4340 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { | 4345 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { |
| 4341 | try writer.writeAll("if ("); | 4346 | try writer.writeAll("if ("); |
| ... | @@ -4431,6 +4436,8 @@ const LocalResult = struct { | ... | @@ -4431,6 +4436,8 @@ const LocalResult = struct { |
| 4431 | need_free: bool, | 4436 | need_free: bool, |
| 4432 | 4437 | ||
| 4433 | fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue { | 4438 | fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue { |
| 4439 | const mod = f.object.dg.module; | ||
| 4440 | |||
| 4434 | if (lr.need_free) { | 4441 | if (lr.need_free) { |
| 4435 | // Move the freshly allocated local to be owned by this instruction, | 4442 | // Move the freshly allocated local to be owned by this instruction, |
| 4436 | // by returning it here instead of freeing it. | 4443 | // by returning it here instead of freeing it. |
| ... | @@ -4441,7 +4448,7 @@ const LocalResult = struct { | ... | @@ -4441,7 +4448,7 @@ const LocalResult = struct { |
| 4441 | try lr.free(f); | 4448 | try lr.free(f); |
| 4442 | const writer = f.object.writer(); | 4449 | const writer = f.object.writer(); |
| 4443 | try f.writeCValue(writer, local, .Other); | 4450 | try f.writeCValue(writer, local, .Other); |
| 4444 | if (dest_ty.isAbiInt()) { | 4451 | if (dest_ty.isAbiInt(mod)) { |
| 4445 | try writer.writeAll(" = "); | 4452 | try writer.writeAll(" = "); |
| 4446 | } else { | 4453 | } else { |
| 4447 | try writer.writeAll(" = ("); | 4454 | try writer.writeAll(" = ("); |
| ... | @@ -4461,12 +4468,13 @@ const LocalResult = struct { | ... | @@ -4461,12 +4468,13 @@ const LocalResult = struct { |
| 4461 | }; | 4468 | }; |
| 4462 | 4469 | ||
| 4463 | fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult { | 4470 | fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult { |
| 4464 | const target = f.object.dg.module.getTarget(); | 4471 | const mod = f.object.dg.module; |
| 4472 | const target = mod.getTarget(); | ||
| 4465 | const writer = f.object.writer(); | 4473 | const writer = f.object.writer(); |
| 4466 | 4474 | ||
| 4467 | if (operand_ty.isAbiInt() and dest_ty.isAbiInt()) { | 4475 | if (operand_ty.isAbiInt(mod) and dest_ty.isAbiInt(mod)) { |
| 4468 | const src_info = dest_ty.intInfo(target); | 4476 | const src_info = dest_ty.intInfo(mod); |
| 4469 | const dest_info = operand_ty.intInfo(target); | 4477 | const dest_info = operand_ty.intInfo(mod); |
| 4470 | if (src_info.signedness == dest_info.signedness and | 4478 | if (src_info.signedness == dest_info.signedness and |
| 4471 | src_info.bits == dest_info.bits) | 4479 | src_info.bits == dest_info.bits) |
| 4472 | { | 4480 | { |
| ... | @@ -4477,7 +4485,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4477,7 +4485,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4477 | } | 4485 | } |
| 4478 | } | 4486 | } |
| 4479 | 4487 | ||
| 4480 | if (dest_ty.isPtrAtRuntime() and operand_ty.isPtrAtRuntime()) { | 4488 | if (dest_ty.isPtrAtRuntime(mod) and operand_ty.isPtrAtRuntime(mod)) { |
| 4481 | const local = try f.allocLocal(0, dest_ty); | 4489 | const local = try f.allocLocal(0, dest_ty); |
| 4482 | try f.writeCValue(writer, local, .Other); | 4490 | try f.writeCValue(writer, local, .Other); |
| 4483 | try writer.writeAll(" = ("); | 4491 | try writer.writeAll(" = ("); |
| ... | @@ -4494,7 +4502,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4494,7 +4502,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4494 | const operand_lval = if (operand == .constant) blk: { | 4502 | const operand_lval = if (operand == .constant) blk: { |
| 4495 | const operand_local = try f.allocLocal(0, operand_ty); | 4503 | const operand_local = try f.allocLocal(0, operand_ty); |
| 4496 | try f.writeCValue(writer, operand_local, .Other); | 4504 | try f.writeCValue(writer, operand_local, .Other); |
| 4497 | if (operand_ty.isAbiInt()) { | 4505 | if (operand_ty.isAbiInt(mod)) { |
| 4498 | try writer.writeAll(" = "); | 4506 | try writer.writeAll(" = "); |
| 4499 | } else { | 4507 | } else { |
| 4500 | try writer.writeAll(" = ("); | 4508 | try writer.writeAll(" = ("); |
| ... | @@ -4516,13 +4524,10 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4516,13 +4524,10 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4516 | try writer.writeAll("));\n"); | 4524 | try writer.writeAll("));\n"); |
| 4517 | 4525 | ||
| 4518 | // Ensure padding bits have the expected value. | 4526 | // Ensure padding bits have the expected value. |
| 4519 | if (dest_ty.isAbiInt()) { | 4527 | if (dest_ty.isAbiInt(mod)) { |
| 4520 | const dest_cty = try f.typeToCType(dest_ty, .complete); | 4528 | const dest_cty = try f.typeToCType(dest_ty, .complete); |
| 4521 | const dest_info = dest_ty.intInfo(target); | 4529 | const dest_info = dest_ty.intInfo(mod); |
| 4522 | var info_ty_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dest_info.signedness) { | 4530 | var bits: u16 = dest_info.bits; |
| 4523 | .unsigned => .int_unsigned, | ||
| 4524 | .signed => .int_signed, | ||
| 4525 | } }, .data = dest_info.bits }; | ||
| 4526 | var wrap_cty: ?CType = null; | 4531 | var wrap_cty: ?CType = null; |
| 4527 | var need_bitcasts = false; | 4532 | var need_bitcasts = false; |
| 4528 | 4533 | ||
| ... | @@ -4535,9 +4540,9 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4535,9 +4540,9 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4535 | const elem_cty = f.indexToCType(pl.data.elem_type); | 4540 | const elem_cty = f.indexToCType(pl.data.elem_type); |
| 4536 | wrap_cty = elem_cty.toSignedness(dest_info.signedness); | 4541 | wrap_cty = elem_cty.toSignedness(dest_info.signedness); |
| 4537 | need_bitcasts = wrap_cty.?.tag() == .zig_i128; | 4542 | need_bitcasts = wrap_cty.?.tag() == .zig_i128; |
| 4538 | info_ty_pl.data -= 1; | 4543 | bits -= 1; |
| 4539 | info_ty_pl.data %= @intCast(u16, f.byteSize(elem_cty) * 8); | 4544 | bits %= @intCast(u16, f.byteSize(elem_cty) * 8); |
| 4540 | info_ty_pl.data += 1; | 4545 | bits += 1; |
| 4541 | } | 4546 | } |
| 4542 | try writer.writeAll(" = "); | 4547 | try writer.writeAll(" = "); |
| 4543 | if (need_bitcasts) { | 4548 | if (need_bitcasts) { |
| ... | @@ -4546,7 +4551,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4546,7 +4551,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4546 | try writer.writeByte('('); | 4551 | try writer.writeByte('('); |
| 4547 | } | 4552 | } |
| 4548 | try writer.writeAll("zig_wrap_"); | 4553 | try writer.writeAll("zig_wrap_"); |
| 4549 | const info_ty = Type.initPayload(&info_ty_pl.base); | 4554 | const info_ty = try mod.intType(dest_info.signedness, bits); |
| 4550 | if (wrap_cty) |cty| | 4555 | if (wrap_cty) |cty| |
| 4551 | try f.object.dg.renderCTypeForBuiltinFnName(writer, cty) | 4556 | try f.object.dg.renderCTypeForBuiltinFnName(writer, cty) |
| 4552 | else | 4557 | else |
| ... | @@ -4675,6 +4680,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4675,6 +4680,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4675 | } | 4680 | } |
| 4676 | 4681 | ||
| 4677 | fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | 4682 | fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4683 | const mod = f.object.dg.module; | ||
| 4678 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; | 4684 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| 4679 | const condition = try f.resolveInst(pl_op.operand); | 4685 | const condition = try f.resolveInst(pl_op.operand); |
| 4680 | try reap(f, inst, &.{pl_op.operand}); | 4686 | try reap(f, inst, &.{pl_op.operand}); |
| ... | @@ -4683,11 +4689,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4683,11 +4689,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4683 | const writer = f.object.writer(); | 4689 | const writer = f.object.writer(); |
| 4684 | 4690 | ||
| 4685 | try writer.writeAll("switch ("); | 4691 | try writer.writeAll("switch ("); |
| 4686 | if (condition_ty.zigTypeTag() == .Bool) { | 4692 | if (condition_ty.zigTypeTag(mod) == .Bool) { |
| 4687 | try writer.writeByte('('); | 4693 | try writer.writeByte('('); |
| 4688 | try f.renderType(writer, Type.u1); | 4694 | try f.renderType(writer, Type.u1); |
| 4689 | try writer.writeByte(')'); | 4695 | try writer.writeByte(')'); |
| 4690 | } else if (condition_ty.isPtrAtRuntime()) { | 4696 | } else if (condition_ty.isPtrAtRuntime(mod)) { |
| 4691 | try writer.writeByte('('); | 4697 | try writer.writeByte('('); |
| 4692 | try f.renderType(writer, Type.usize); | 4698 | try f.renderType(writer, Type.usize); |
| 4693 | try writer.writeByte(')'); | 4699 | try writer.writeByte(')'); |
| ... | @@ -4714,12 +4720,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4714,12 +4720,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4714 | for (items) |item| { | 4720 | for (items) |item| { |
| 4715 | try f.object.indent_writer.insertNewline(); | 4721 | try f.object.indent_writer.insertNewline(); |
| 4716 | try writer.writeAll("case "); | 4722 | try writer.writeAll("case "); |
| 4717 | if (condition_ty.isPtrAtRuntime()) { | 4723 | if (condition_ty.isPtrAtRuntime(mod)) { |
| 4718 | try writer.writeByte('('); | 4724 | try writer.writeByte('('); |
| 4719 | try f.renderType(writer, Type.usize); | 4725 | try f.renderType(writer, Type.usize); |
| 4720 | try writer.writeByte(')'); | 4726 | try writer.writeByte(')'); |
| 4721 | } | 4727 | } |
| 4722 | try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other); | 4728 | try f.object.dg.renderValue(writer, condition_ty, f.air.value(item, mod).?, .Other); |
| 4723 | try writer.writeByte(':'); | 4729 | try writer.writeByte(':'); |
| 4724 | } | 4730 | } |
| 4725 | try writer.writeByte(' '); | 4731 | try writer.writeByte(' '); |
| ... | @@ -4764,6 +4770,7 @@ fn asmInputNeedsLocal(constraint: []const u8, value: CValue) bool { | ... | @@ -4764,6 +4770,7 @@ fn asmInputNeedsLocal(constraint: []const u8, value: CValue) bool { |
| 4764 | } | 4770 | } |
| 4765 | 4771 | ||
| 4766 | fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | 4772 | fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4773 | const mod = f.object.dg.module; | ||
| 4767 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 4774 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 4768 | const extra = f.air.extraData(Air.Asm, ty_pl.payload); | 4775 | const extra = f.air.extraData(Air.Asm, ty_pl.payload); |
| 4769 | const is_volatile = @truncate(u1, extra.data.flags >> 31) != 0; | 4776 | const is_volatile = @truncate(u1, extra.data.flags >> 31) != 0; |
| ... | @@ -4778,7 +4785,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4778,7 +4785,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4778 | const result = result: { | 4785 | const result = result: { |
| 4779 | const writer = f.object.writer(); | 4786 | const writer = f.object.writer(); |
| 4780 | const inst_ty = f.air.typeOfIndex(inst); | 4787 | const inst_ty = f.air.typeOfIndex(inst); |
| 4781 | const local = if (inst_ty.hasRuntimeBitsIgnoreComptime()) local: { | 4788 | const local = if (inst_ty.hasRuntimeBitsIgnoreComptime(mod)) local: { |
| 4782 | const local = try f.allocLocal(inst, inst_ty); | 4789 | const local = try f.allocLocal(inst, inst_ty); |
| 4783 | if (f.wantSafety()) { | 4790 | if (f.wantSafety()) { |
| 4784 | try f.writeCValue(writer, local, .Other); | 4791 | try f.writeCValue(writer, local, .Other); |
| ... | @@ -5025,6 +5032,7 @@ fn airIsNull( | ... | @@ -5025,6 +5032,7 @@ fn airIsNull( |
| 5025 | operator: []const u8, | 5032 | operator: []const u8, |
| 5026 | is_ptr: bool, | 5033 | is_ptr: bool, |
| 5027 | ) !CValue { | 5034 | ) !CValue { |
| 5035 | const mod = f.object.dg.module; | ||
| 5028 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 5036 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 5029 | 5037 | ||
| 5030 | const writer = f.object.writer(); | 5038 | const writer = f.object.writer(); |
| ... | @@ -5046,14 +5054,14 @@ fn airIsNull( | ... | @@ -5046,14 +5054,14 @@ fn airIsNull( |
| 5046 | const payload_ty = optional_ty.optionalChild(&payload_buf); | 5054 | const payload_ty = optional_ty.optionalChild(&payload_buf); |
| 5047 | var slice_ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; | 5055 | var slice_ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 5048 | 5056 | ||
| 5049 | const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime()) | 5057 | const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 5050 | TypedValue{ .ty = Type.bool, .val = Value.true } | 5058 | TypedValue{ .ty = Type.bool, .val = Value.true } |
| 5051 | else if (optional_ty.isPtrLikeOptional()) | 5059 | else if (optional_ty.isPtrLikeOptional(mod)) |
| 5052 | // operand is a regular pointer, test `operand !=/== NULL` | 5060 | // operand is a regular pointer, test `operand !=/== NULL` |
| 5053 | TypedValue{ .ty = optional_ty, .val = Value.null } | 5061 | TypedValue{ .ty = optional_ty, .val = Value.null } |
| 5054 | else if (payload_ty.zigTypeTag() == .ErrorSet) | 5062 | else if (payload_ty.zigTypeTag(mod) == .ErrorSet) |
| 5055 | TypedValue{ .ty = payload_ty, .val = Value.zero } | 5063 | TypedValue{ .ty = payload_ty, .val = Value.zero } |
| 5056 | else if (payload_ty.isSlice() and optional_ty.optionalReprIsPayload()) rhs: { | 5064 | else if (payload_ty.isSlice() and optional_ty.optionalReprIsPayload(mod)) rhs: { |
| 5057 | try writer.writeAll(".ptr"); | 5065 | try writer.writeAll(".ptr"); |
| 5058 | const slice_ptr_ty = payload_ty.slicePtrFieldType(&slice_ptr_buf); | 5066 | const slice_ptr_ty = payload_ty.slicePtrFieldType(&slice_ptr_buf); |
| 5059 | break :rhs TypedValue{ .ty = slice_ptr_ty, .val = Value.null }; | 5067 | break :rhs TypedValue{ .ty = slice_ptr_ty, .val = Value.null }; |
| ... | @@ -5070,6 +5078,7 @@ fn airIsNull( | ... | @@ -5070,6 +5078,7 @@ fn airIsNull( |
| 5070 | } | 5078 | } |
| 5071 | 5079 | ||
| 5072 | fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { | 5080 | fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5081 | const mod = f.object.dg.module; | ||
| 5073 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5082 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5074 | 5083 | ||
| 5075 | const operand = try f.resolveInst(ty_op.operand); | 5084 | const operand = try f.resolveInst(ty_op.operand); |
| ... | @@ -5079,7 +5088,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5079,7 +5088,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5079 | var buf: Type.Payload.ElemType = undefined; | 5088 | var buf: Type.Payload.ElemType = undefined; |
| 5080 | const payload_ty = opt_ty.optionalChild(&buf); | 5089 | const payload_ty = opt_ty.optionalChild(&buf); |
| 5081 | 5090 | ||
| 5082 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 5091 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5083 | return .none; | 5092 | return .none; |
| 5084 | } | 5093 | } |
| 5085 | 5094 | ||
| ... | @@ -5087,7 +5096,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5087,7 +5096,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5087 | const writer = f.object.writer(); | 5096 | const writer = f.object.writer(); |
| 5088 | const local = try f.allocLocal(inst, inst_ty); | 5097 | const local = try f.allocLocal(inst, inst_ty); |
| 5089 | 5098 | ||
| 5090 | if (opt_ty.optionalReprIsPayload()) { | 5099 | if (opt_ty.optionalReprIsPayload(mod)) { |
| 5091 | try f.writeCValue(writer, local, .Other); | 5100 | try f.writeCValue(writer, local, .Other); |
| 5092 | try writer.writeAll(" = "); | 5101 | try writer.writeAll(" = "); |
| 5093 | try f.writeCValue(writer, operand, .Other); | 5102 | try f.writeCValue(writer, operand, .Other); |
| ... | @@ -5104,6 +5113,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5104,6 +5113,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5104 | } | 5113 | } |
| 5105 | 5114 | ||
| 5106 | fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 5115 | fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5116 | const mod = f.object.dg.module; | ||
| 5107 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5117 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5108 | 5118 | ||
| 5109 | const writer = f.object.writer(); | 5119 | const writer = f.object.writer(); |
| ... | @@ -5113,14 +5123,14 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5113,14 +5123,14 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5113 | const opt_ty = ptr_ty.childType(); | 5123 | const opt_ty = ptr_ty.childType(); |
| 5114 | const inst_ty = f.air.typeOfIndex(inst); | 5124 | const inst_ty = f.air.typeOfIndex(inst); |
| 5115 | 5125 | ||
| 5116 | if (!inst_ty.childType().hasRuntimeBitsIgnoreComptime()) { | 5126 | if (!inst_ty.childType().hasRuntimeBitsIgnoreComptime(mod)) { |
| 5117 | return .{ .undef = inst_ty }; | 5127 | return .{ .undef = inst_ty }; |
| 5118 | } | 5128 | } |
| 5119 | 5129 | ||
| 5120 | const local = try f.allocLocal(inst, inst_ty); | 5130 | const local = try f.allocLocal(inst, inst_ty); |
| 5121 | try f.writeCValue(writer, local, .Other); | 5131 | try f.writeCValue(writer, local, .Other); |
| 5122 | 5132 | ||
| 5123 | if (opt_ty.optionalReprIsPayload()) { | 5133 | if (opt_ty.optionalReprIsPayload(mod)) { |
| 5124 | // the operand is just a regular pointer, no need to do anything special. | 5134 | // the operand is just a regular pointer, no need to do anything special. |
| 5125 | // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C | 5135 | // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C |
| 5126 | try writer.writeAll(" = "); | 5136 | try writer.writeAll(" = "); |
| ... | @@ -5134,6 +5144,7 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5134,6 +5144,7 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5134 | } | 5144 | } |
| 5135 | 5145 | ||
| 5136 | fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | 5146 | fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5147 | const mod = f.object.dg.module; | ||
| 5137 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5148 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5138 | const writer = f.object.writer(); | 5149 | const writer = f.object.writer(); |
| 5139 | const operand = try f.resolveInst(ty_op.operand); | 5150 | const operand = try f.resolveInst(ty_op.operand); |
| ... | @@ -5144,7 +5155,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5144,7 +5155,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5144 | 5155 | ||
| 5145 | const inst_ty = f.air.typeOfIndex(inst); | 5156 | const inst_ty = f.air.typeOfIndex(inst); |
| 5146 | 5157 | ||
| 5147 | if (opt_ty.optionalReprIsPayload()) { | 5158 | if (opt_ty.optionalReprIsPayload(mod)) { |
| 5148 | if (f.liveness.isUnused(inst)) { | 5159 | if (f.liveness.isUnused(inst)) { |
| 5149 | return .none; | 5160 | return .none; |
| 5150 | } | 5161 | } |
| ... | @@ -5179,36 +5190,36 @@ fn fieldLocation( | ... | @@ -5179,36 +5190,36 @@ fn fieldLocation( |
| 5179 | container_ty: Type, | 5190 | container_ty: Type, |
| 5180 | field_ptr_ty: Type, | 5191 | field_ptr_ty: Type, |
| 5181 | field_index: u32, | 5192 | field_index: u32, |
| 5182 | target: std.Target, | 5193 | mod: *const Module, |
| 5183 | ) union(enum) { | 5194 | ) union(enum) { |
| 5184 | begin: void, | 5195 | begin: void, |
| 5185 | field: CValue, | 5196 | field: CValue, |
| 5186 | byte_offset: u32, | 5197 | byte_offset: u32, |
| 5187 | end: void, | 5198 | end: void, |
| 5188 | } { | 5199 | } { |
| 5189 | return switch (container_ty.zigTypeTag()) { | 5200 | return switch (container_ty.zigTypeTag(mod)) { |
| 5190 | .Struct => switch (container_ty.containerLayout()) { | 5201 | .Struct => switch (container_ty.containerLayout()) { |
| 5191 | .Auto, .Extern => for (field_index..container_ty.structFieldCount()) |next_field_index| { | 5202 | .Auto, .Extern => for (field_index..container_ty.structFieldCount()) |next_field_index| { |
| 5192 | if (container_ty.structFieldIsComptime(next_field_index)) continue; | 5203 | if (container_ty.structFieldIsComptime(next_field_index)) continue; |
| 5193 | const field_ty = container_ty.structFieldType(next_field_index); | 5204 | const field_ty = container_ty.structFieldType(next_field_index); |
| 5194 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 5205 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 5195 | 5206 | ||
| 5196 | break .{ .field = if (container_ty.isSimpleTuple()) | 5207 | break .{ .field = if (container_ty.isSimpleTuple()) |
| 5197 | .{ .field = next_field_index } | 5208 | .{ .field = next_field_index } |
| 5198 | else | 5209 | else |
| 5199 | .{ .identifier = container_ty.structFieldName(next_field_index) } }; | 5210 | .{ .identifier = container_ty.structFieldName(next_field_index) } }; |
| 5200 | } else if (container_ty.hasRuntimeBitsIgnoreComptime()) .end else .begin, | 5211 | } else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin, |
| 5201 | .Packed => if (field_ptr_ty.ptrInfo().data.host_size == 0) | 5212 | .Packed => if (field_ptr_ty.ptrInfo().data.host_size == 0) |
| 5202 | .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, target) } | 5213 | .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) } |
| 5203 | else | 5214 | else |
| 5204 | .begin, | 5215 | .begin, |
| 5205 | }, | 5216 | }, |
| 5206 | .Union => switch (container_ty.containerLayout()) { | 5217 | .Union => switch (container_ty.containerLayout()) { |
| 5207 | .Auto, .Extern => { | 5218 | .Auto, .Extern => { |
| 5208 | const field_ty = container_ty.structFieldType(field_index); | 5219 | const field_ty = container_ty.structFieldType(field_index); |
| 5209 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) | 5220 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 5210 | return if (container_ty.unionTagTypeSafety() != null and | 5221 | return if (container_ty.unionTagTypeSafety() != null and |
| 5211 | !container_ty.unionHasAllZeroBitFieldTypes()) | 5222 | !container_ty.unionHasAllZeroBitFieldTypes(mod)) |
| 5212 | .{ .field = .{ .identifier = "payload" } } | 5223 | .{ .field = .{ .identifier = "payload" } } |
| 5213 | else | 5224 | else |
| 5214 | .begin; | 5225 | .begin; |
| ... | @@ -5252,10 +5263,10 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue | ... | @@ -5252,10 +5263,10 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue |
| 5252 | } | 5263 | } |
| 5253 | 5264 | ||
| 5254 | fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 5265 | fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5266 | const mod = f.object.dg.module; | ||
| 5255 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 5267 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 5256 | const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | 5268 | const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 5257 | 5269 | ||
| 5258 | const target = f.object.dg.module.getTarget(); | ||
| 5259 | const container_ptr_ty = f.air.typeOfIndex(inst); | 5270 | const container_ptr_ty = f.air.typeOfIndex(inst); |
| 5260 | const container_ty = container_ptr_ty.childType(); | 5271 | const container_ty = container_ptr_ty.childType(); |
| 5261 | 5272 | ||
| ... | @@ -5270,7 +5281,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5270,7 +5281,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5270 | try f.renderType(writer, container_ptr_ty); | 5281 | try f.renderType(writer, container_ptr_ty); |
| 5271 | try writer.writeByte(')'); | 5282 | try writer.writeByte(')'); |
| 5272 | 5283 | ||
| 5273 | switch (fieldLocation(container_ty, field_ptr_ty, extra.field_index, target)) { | 5284 | switch (fieldLocation(container_ty, field_ptr_ty, extra.field_index, mod)) { |
| 5274 | .begin => try f.writeCValue(writer, field_ptr_val, .Initializer), | 5285 | .begin => try f.writeCValue(writer, field_ptr_val, .Initializer), |
| 5275 | .field => |field| { | 5286 | .field => |field| { |
| 5276 | var u8_ptr_pl = field_ptr_ty.ptrInfo(); | 5287 | var u8_ptr_pl = field_ptr_ty.ptrInfo(); |
| ... | @@ -5321,7 +5332,7 @@ fn fieldPtr( | ... | @@ -5321,7 +5332,7 @@ fn fieldPtr( |
| 5321 | container_ptr_val: CValue, | 5332 | container_ptr_val: CValue, |
| 5322 | field_index: u32, | 5333 | field_index: u32, |
| 5323 | ) !CValue { | 5334 | ) !CValue { |
| 5324 | const target = f.object.dg.module.getTarget(); | 5335 | const mod = f.object.dg.module; |
| 5325 | const container_ty = container_ptr_ty.elemType(); | 5336 | const container_ty = container_ptr_ty.elemType(); |
| 5326 | const field_ptr_ty = f.air.typeOfIndex(inst); | 5337 | const field_ptr_ty = f.air.typeOfIndex(inst); |
| 5327 | 5338 | ||
| ... | @@ -5335,7 +5346,7 @@ fn fieldPtr( | ... | @@ -5335,7 +5346,7 @@ fn fieldPtr( |
| 5335 | try f.renderType(writer, field_ptr_ty); | 5346 | try f.renderType(writer, field_ptr_ty); |
| 5336 | try writer.writeByte(')'); | 5347 | try writer.writeByte(')'); |
| 5337 | 5348 | ||
| 5338 | switch (fieldLocation(container_ty, field_ptr_ty, field_index, target)) { | 5349 | switch (fieldLocation(container_ty, field_ptr_ty, field_index, mod)) { |
| 5339 | .begin => try f.writeCValue(writer, container_ptr_val, .Initializer), | 5350 | .begin => try f.writeCValue(writer, container_ptr_val, .Initializer), |
| 5340 | .field => |field| { | 5351 | .field => |field| { |
| 5341 | try writer.writeByte('&'); | 5352 | try writer.writeByte('&'); |
| ... | @@ -5370,16 +5381,16 @@ fn fieldPtr( | ... | @@ -5370,16 +5381,16 @@ fn fieldPtr( |
| 5370 | } | 5381 | } |
| 5371 | 5382 | ||
| 5372 | fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | 5383 | fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5384 | const mod = f.object.dg.module; | ||
| 5373 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 5385 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 5374 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; | 5386 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; |
| 5375 | 5387 | ||
| 5376 | const inst_ty = f.air.typeOfIndex(inst); | 5388 | const inst_ty = f.air.typeOfIndex(inst); |
| 5377 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { | 5389 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5378 | try reap(f, inst, &.{extra.struct_operand}); | 5390 | try reap(f, inst, &.{extra.struct_operand}); |
| 5379 | return .none; | 5391 | return .none; |
| 5380 | } | 5392 | } |
| 5381 | 5393 | ||
| 5382 | const target = f.object.dg.module.getTarget(); | ||
| 5383 | const struct_byval = try f.resolveInst(extra.struct_operand); | 5394 | const struct_byval = try f.resolveInst(extra.struct_operand); |
| 5384 | try reap(f, inst, &.{extra.struct_operand}); | 5395 | try reap(f, inst, &.{extra.struct_operand}); |
| 5385 | const struct_ty = f.air.typeOf(extra.struct_operand); | 5396 | const struct_ty = f.air.typeOf(extra.struct_operand); |
| ... | @@ -5396,32 +5407,21 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5396,32 +5407,21 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5396 | .{ .identifier = struct_ty.structFieldName(extra.field_index) }, | 5407 | .{ .identifier = struct_ty.structFieldName(extra.field_index) }, |
| 5397 | .Packed => { | 5408 | .Packed => { |
| 5398 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 5409 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 5399 | const int_info = struct_ty.intInfo(target); | 5410 | const int_info = struct_ty.intInfo(mod); |
| 5400 | 5411 | ||
| 5401 | var bit_offset_ty_pl = Type.Payload.Bits{ | 5412 | const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); |
| 5402 | .base = .{ .tag = .int_unsigned }, | ||
| 5403 | .data = Type.smallestUnsignedBits(int_info.bits - 1), | ||
| 5404 | }; | ||
| 5405 | const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base); | ||
| 5406 | 5413 | ||
| 5407 | var bit_offset_val_pl: Value.Payload.U64 = .{ | 5414 | var bit_offset_val_pl: Value.Payload.U64 = .{ |
| 5408 | .base = .{ .tag = .int_u64 }, | 5415 | .base = .{ .tag = .int_u64 }, |
| 5409 | .data = struct_obj.packedFieldBitOffset(target, extra.field_index), | 5416 | .data = struct_obj.packedFieldBitOffset(mod, extra.field_index), |
| 5410 | }; | 5417 | }; |
| 5411 | const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base); | 5418 | const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base); |
| 5412 | 5419 | ||
| 5413 | const field_int_signedness = if (inst_ty.isAbiInt()) | 5420 | const field_int_signedness = if (inst_ty.isAbiInt(mod)) |
| 5414 | inst_ty.intInfo(target).signedness | 5421 | inst_ty.intInfo(mod).signedness |
| 5415 | else | 5422 | else |
| 5416 | .unsigned; | 5423 | .unsigned; |
| 5417 | var field_int_pl = Type.Payload.Bits{ | 5424 | const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod))); |
| 5418 | .base = .{ .tag = switch (field_int_signedness) { | ||
| 5419 | .unsigned => .int_unsigned, | ||
| 5420 | .signed => .int_signed, | ||
| 5421 | } }, | ||
| 5422 | .data = @intCast(u16, inst_ty.bitSize(target)), | ||
| 5423 | }; | ||
| 5424 | const field_int_ty = Type.initPayload(&field_int_pl.base); | ||
| 5425 | 5425 | ||
| 5426 | const temp_local = try f.allocLocal(inst, field_int_ty); | 5426 | const temp_local = try f.allocLocal(inst, field_int_ty); |
| 5427 | try f.writeCValue(writer, temp_local, .Other); | 5427 | try f.writeCValue(writer, temp_local, .Other); |
| ... | @@ -5432,7 +5432,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5432,7 +5432,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5432 | try writer.writeByte(')'); | 5432 | try writer.writeByte(')'); |
| 5433 | const cant_cast = int_info.bits > 64; | 5433 | const cant_cast = int_info.bits > 64; |
| 5434 | if (cant_cast) { | 5434 | if (cant_cast) { |
| 5435 | if (field_int_ty.bitSize(target) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); | 5435 | if (field_int_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); |
| 5436 | try writer.writeAll("zig_lo_"); | 5436 | try writer.writeAll("zig_lo_"); |
| 5437 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | 5437 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); |
| 5438 | try writer.writeByte('('); | 5438 | try writer.writeByte('('); |
| ... | @@ -5511,6 +5511,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5511,6 +5511,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5511 | /// *(E!T) -> E | 5511 | /// *(E!T) -> E |
| 5512 | /// Note that the result is never a pointer. | 5512 | /// Note that the result is never a pointer. |
| 5513 | fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | 5513 | fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5514 | const mod = f.object.dg.module; | ||
| 5514 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5515 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5515 | 5516 | ||
| 5516 | const inst_ty = f.air.typeOfIndex(inst); | 5517 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -5518,13 +5519,13 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5518,13 +5519,13 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5518 | const operand_ty = f.air.typeOf(ty_op.operand); | 5519 | const operand_ty = f.air.typeOf(ty_op.operand); |
| 5519 | try reap(f, inst, &.{ty_op.operand}); | 5520 | try reap(f, inst, &.{ty_op.operand}); |
| 5520 | 5521 | ||
| 5521 | const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer; | 5522 | const operand_is_ptr = operand_ty.zigTypeTag(mod) == .Pointer; |
| 5522 | const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; | 5523 | const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; |
| 5523 | const error_ty = error_union_ty.errorUnionSet(); | 5524 | const error_ty = error_union_ty.errorUnionSet(); |
| 5524 | const payload_ty = error_union_ty.errorUnionPayload(); | 5525 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 5525 | const local = try f.allocLocal(inst, inst_ty); | 5526 | const local = try f.allocLocal(inst, inst_ty); |
| 5526 | 5527 | ||
| 5527 | if (!payload_ty.hasRuntimeBits() and operand == .local and operand.local == local.new_local) { | 5528 | if (!payload_ty.hasRuntimeBits(mod) and operand == .local and operand.local == local.new_local) { |
| 5528 | // The store will be 'x = x'; elide it. | 5529 | // The store will be 'x = x'; elide it. |
| 5529 | return local; | 5530 | return local; |
| 5530 | } | 5531 | } |
| ... | @@ -5533,7 +5534,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5533,7 +5534,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5533 | try f.writeCValue(writer, local, .Other); | 5534 | try f.writeCValue(writer, local, .Other); |
| 5534 | try writer.writeAll(" = "); | 5535 | try writer.writeAll(" = "); |
| 5535 | 5536 | ||
| 5536 | if (!payload_ty.hasRuntimeBits()) { | 5537 | if (!payload_ty.hasRuntimeBits(mod)) { |
| 5537 | try f.writeCValue(writer, operand, .Other); | 5538 | try f.writeCValue(writer, operand, .Other); |
| 5538 | } else { | 5539 | } else { |
| 5539 | if (!error_ty.errorSetIsEmpty()) | 5540 | if (!error_ty.errorSetIsEmpty()) |
| ... | @@ -5549,6 +5550,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5549,6 +5550,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5549 | } | 5550 | } |
| 5550 | 5551 | ||
| 5551 | fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { | 5552 | fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 5553 | const mod = f.object.dg.module; | ||
| 5552 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5554 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5553 | 5555 | ||
| 5554 | const inst_ty = f.air.typeOfIndex(inst); | 5556 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -5558,7 +5560,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu | ... | @@ -5558,7 +5560,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu |
| 5558 | const error_union_ty = if (is_ptr) operand_ty.childType() else operand_ty; | 5560 | const error_union_ty = if (is_ptr) operand_ty.childType() else operand_ty; |
| 5559 | 5561 | ||
| 5560 | const writer = f.object.writer(); | 5562 | const writer = f.object.writer(); |
| 5561 | if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) { | 5563 | if (!error_union_ty.errorUnionPayload().hasRuntimeBits(mod)) { |
| 5562 | if (!is_ptr) return .none; | 5564 | if (!is_ptr) return .none; |
| 5563 | 5565 | ||
| 5564 | const local = try f.allocLocal(inst, inst_ty); | 5566 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -5584,10 +5586,11 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu | ... | @@ -5584,10 +5586,11 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu |
| 5584 | } | 5586 | } |
| 5585 | 5587 | ||
| 5586 | fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { | 5588 | fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5589 | const mod = f.object.dg.module; | ||
| 5587 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5590 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5588 | 5591 | ||
| 5589 | const inst_ty = f.air.typeOfIndex(inst); | 5592 | const inst_ty = f.air.typeOfIndex(inst); |
| 5590 | const repr_is_payload = inst_ty.optionalReprIsPayload(); | 5593 | const repr_is_payload = inst_ty.optionalReprIsPayload(mod); |
| 5591 | const payload_ty = f.air.typeOf(ty_op.operand); | 5594 | const payload_ty = f.air.typeOf(ty_op.operand); |
| 5592 | const payload = try f.resolveInst(ty_op.operand); | 5595 | const payload = try f.resolveInst(ty_op.operand); |
| 5593 | try reap(f, inst, &.{ty_op.operand}); | 5596 | try reap(f, inst, &.{ty_op.operand}); |
| ... | @@ -5615,11 +5618,12 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5615,11 +5618,12 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5615 | } | 5618 | } |
| 5616 | 5619 | ||
| 5617 | fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | 5620 | fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5621 | const mod = f.object.dg.module; | ||
| 5618 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5622 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5619 | 5623 | ||
| 5620 | const inst_ty = f.air.typeOfIndex(inst); | 5624 | const inst_ty = f.air.typeOfIndex(inst); |
| 5621 | const payload_ty = inst_ty.errorUnionPayload(); | 5625 | const payload_ty = inst_ty.errorUnionPayload(); |
| 5622 | const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(); | 5626 | const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod); |
| 5623 | const err_ty = inst_ty.errorUnionSet(); | 5627 | const err_ty = inst_ty.errorUnionSet(); |
| 5624 | const err = try f.resolveInst(ty_op.operand); | 5628 | const err = try f.resolveInst(ty_op.operand); |
| 5625 | try reap(f, inst, &.{ty_op.operand}); | 5629 | try reap(f, inst, &.{ty_op.operand}); |
| ... | @@ -5653,6 +5657,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5653,6 +5657,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5653 | } | 5657 | } |
| 5654 | 5658 | ||
| 5655 | fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | 5659 | fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5660 | const mod = f.object.dg.module; | ||
| 5656 | const writer = f.object.writer(); | 5661 | const writer = f.object.writer(); |
| 5657 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5662 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5658 | const operand = try f.resolveInst(ty_op.operand); | 5663 | const operand = try f.resolveInst(ty_op.operand); |
| ... | @@ -5662,7 +5667,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5662,7 +5667,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5662 | const payload_ty = error_union_ty.errorUnionPayload(); | 5667 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 5663 | 5668 | ||
| 5664 | // First, set the non-error value. | 5669 | // First, set the non-error value. |
| 5665 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 5670 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5666 | try f.writeCValueDeref(writer, operand); | 5671 | try f.writeCValueDeref(writer, operand); |
| 5667 | try writer.writeAll(" = "); | 5672 | try writer.writeAll(" = "); |
| 5668 | try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other); | 5673 | try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other); |
| ... | @@ -5703,12 +5708,13 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5703,12 +5708,13 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5703 | } | 5708 | } |
| 5704 | 5709 | ||
| 5705 | fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { | 5710 | fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5711 | const mod = f.object.dg.module; | ||
| 5706 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5712 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5707 | 5713 | ||
| 5708 | const inst_ty = f.air.typeOfIndex(inst); | 5714 | const inst_ty = f.air.typeOfIndex(inst); |
| 5709 | const payload_ty = inst_ty.errorUnionPayload(); | 5715 | const payload_ty = inst_ty.errorUnionPayload(); |
| 5710 | const payload = try f.resolveInst(ty_op.operand); | 5716 | const payload = try f.resolveInst(ty_op.operand); |
| 5711 | const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(); | 5717 | const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod); |
| 5712 | const err_ty = inst_ty.errorUnionSet(); | 5718 | const err_ty = inst_ty.errorUnionSet(); |
| 5713 | try reap(f, inst, &.{ty_op.operand}); | 5719 | try reap(f, inst, &.{ty_op.operand}); |
| 5714 | 5720 | ||
| ... | @@ -5735,6 +5741,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5735,6 +5741,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5735 | } | 5741 | } |
| 5736 | 5742 | ||
| 5737 | fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue { | 5743 | fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue { |
| 5744 | const mod = f.object.dg.module; | ||
| 5738 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 5745 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 5739 | 5746 | ||
| 5740 | const writer = f.object.writer(); | 5747 | const writer = f.object.writer(); |
| ... | @@ -5750,7 +5757,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const | ... | @@ -5750,7 +5757,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const |
| 5750 | try writer.writeAll(" = "); | 5757 | try writer.writeAll(" = "); |
| 5751 | 5758 | ||
| 5752 | if (!error_ty.errorSetIsEmpty()) | 5759 | if (!error_ty.errorSetIsEmpty()) |
| 5753 | if (payload_ty.hasRuntimeBits()) | 5760 | if (payload_ty.hasRuntimeBits(mod)) |
| 5754 | if (is_ptr) | 5761 | if (is_ptr) |
| 5755 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }) | 5762 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }) |
| 5756 | else | 5763 | else |
| ... | @@ -5768,6 +5775,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const | ... | @@ -5768,6 +5775,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const |
| 5768 | } | 5775 | } |
| 5769 | 5776 | ||
| 5770 | fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | 5777 | fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5778 | const mod = f.object.dg.module; | ||
| 5771 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5779 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5772 | 5780 | ||
| 5773 | const operand = try f.resolveInst(ty_op.operand); | 5781 | const operand = try f.resolveInst(ty_op.operand); |
| ... | @@ -5784,7 +5792,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5784,7 +5792,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5784 | if (operand == .undef) { | 5792 | if (operand == .undef) { |
| 5785 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 5793 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 5786 | try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(&buf) }, .Initializer); | 5794 | try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(&buf) }, .Initializer); |
| 5787 | } else if (array_ty.hasRuntimeBitsIgnoreComptime()) { | 5795 | } else if (array_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5788 | try writer.writeAll("&("); | 5796 | try writer.writeAll("&("); |
| 5789 | try f.writeCValueDeref(writer, operand); | 5797 | try f.writeCValueDeref(writer, operand); |
| 5790 | try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, Value.zero)}); | 5798 | try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, Value.zero)}); |
| ... | @@ -5801,6 +5809,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5801,6 +5809,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5801 | } | 5809 | } |
| 5802 | 5810 | ||
| 5803 | fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { | 5811 | fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5812 | const mod = f.object.dg.module; | ||
| 5804 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5813 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5805 | 5814 | ||
| 5806 | const inst_ty = f.air.typeOfIndex(inst); | 5815 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -5810,10 +5819,10 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5810,10 +5819,10 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5810 | const target = f.object.dg.module.getTarget(); | 5819 | const target = f.object.dg.module.getTarget(); |
| 5811 | const operation = if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat()) | 5820 | const operation = if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat()) |
| 5812 | if (inst_ty.floatBits(target) < operand_ty.floatBits(target)) "trunc" else "extend" | 5821 | if (inst_ty.floatBits(target) < operand_ty.floatBits(target)) "trunc" else "extend" |
| 5813 | else if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) | 5822 | else if (inst_ty.isInt(mod) and operand_ty.isRuntimeFloat()) |
| 5814 | if (inst_ty.isSignedInt()) "fix" else "fixuns" | 5823 | if (inst_ty.isSignedInt(mod)) "fix" else "fixuns" |
| 5815 | else if (inst_ty.isRuntimeFloat() and operand_ty.isInt()) | 5824 | else if (inst_ty.isRuntimeFloat() and operand_ty.isInt(mod)) |
| 5816 | if (operand_ty.isSignedInt()) "float" else "floatun" | 5825 | if (operand_ty.isSignedInt(mod)) "float" else "floatun" |
| 5817 | else | 5826 | else |
| 5818 | unreachable; | 5827 | unreachable; |
| 5819 | 5828 | ||
| ... | @@ -5822,19 +5831,19 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5822,19 +5831,19 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5822 | try f.writeCValue(writer, local, .Other); | 5831 | try f.writeCValue(writer, local, .Other); |
| 5823 | 5832 | ||
| 5824 | try writer.writeAll(" = "); | 5833 | try writer.writeAll(" = "); |
| 5825 | if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) { | 5834 | if (inst_ty.isInt(mod) and operand_ty.isRuntimeFloat()) { |
| 5826 | try writer.writeAll("zig_wrap_"); | 5835 | try writer.writeAll("zig_wrap_"); |
| 5827 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | 5836 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 5828 | try writer.writeByte('('); | 5837 | try writer.writeByte('('); |
| 5829 | } | 5838 | } |
| 5830 | try writer.writeAll("zig_"); | 5839 | try writer.writeAll("zig_"); |
| 5831 | try writer.writeAll(operation); | 5840 | try writer.writeAll(operation); |
| 5832 | try writer.writeAll(compilerRtAbbrev(operand_ty, target)); | 5841 | try writer.writeAll(compilerRtAbbrev(operand_ty, mod)); |
| 5833 | try writer.writeAll(compilerRtAbbrev(inst_ty, target)); | 5842 | try writer.writeAll(compilerRtAbbrev(inst_ty, mod)); |
| 5834 | try writer.writeByte('('); | 5843 | try writer.writeByte('('); |
| 5835 | try f.writeCValue(writer, operand, .FunctionArgument); | 5844 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 5836 | try writer.writeByte(')'); | 5845 | try writer.writeByte(')'); |
| 5837 | if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) { | 5846 | if (inst_ty.isInt(mod) and operand_ty.isRuntimeFloat()) { |
| 5838 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); | 5847 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); |
| 5839 | try writer.writeByte(')'); | 5848 | try writer.writeByte(')'); |
| 5840 | } | 5849 | } |
| ... | @@ -5871,14 +5880,15 @@ fn airUnBuiltinCall( | ... | @@ -5871,14 +5880,15 @@ fn airUnBuiltinCall( |
| 5871 | operation: []const u8, | 5880 | operation: []const u8, |
| 5872 | info: BuiltinInfo, | 5881 | info: BuiltinInfo, |
| 5873 | ) !CValue { | 5882 | ) !CValue { |
| 5883 | const mod = f.object.dg.module; | ||
| 5874 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5884 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5875 | 5885 | ||
| 5876 | const operand = try f.resolveInst(ty_op.operand); | 5886 | const operand = try f.resolveInst(ty_op.operand); |
| 5877 | try reap(f, inst, &.{ty_op.operand}); | 5887 | try reap(f, inst, &.{ty_op.operand}); |
| 5878 | const inst_ty = f.air.typeOfIndex(inst); | 5888 | const inst_ty = f.air.typeOfIndex(inst); |
| 5879 | const inst_scalar_ty = inst_ty.scalarType(); | 5889 | const inst_scalar_ty = inst_ty.scalarType(mod); |
| 5880 | const operand_ty = f.air.typeOf(ty_op.operand); | 5890 | const operand_ty = f.air.typeOf(ty_op.operand); |
| 5881 | const scalar_ty = operand_ty.scalarType(); | 5891 | const scalar_ty = operand_ty.scalarType(mod); |
| 5882 | 5892 | ||
| 5883 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | 5893 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); |
| 5884 | const ref_ret = inst_scalar_cty.tag() == .array; | 5894 | const ref_ret = inst_scalar_cty.tag() == .array; |
| ... | @@ -5914,6 +5924,7 @@ fn airBinBuiltinCall( | ... | @@ -5914,6 +5924,7 @@ fn airBinBuiltinCall( |
| 5914 | operation: []const u8, | 5924 | operation: []const u8, |
| 5915 | info: BuiltinInfo, | 5925 | info: BuiltinInfo, |
| 5916 | ) !CValue { | 5926 | ) !CValue { |
| 5927 | const mod = f.object.dg.module; | ||
| 5917 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 5928 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 5918 | 5929 | ||
| 5919 | const operand_ty = f.air.typeOf(bin_op.lhs); | 5930 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| ... | @@ -5925,8 +5936,8 @@ fn airBinBuiltinCall( | ... | @@ -5925,8 +5936,8 @@ fn airBinBuiltinCall( |
| 5925 | if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 5936 | if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 5926 | 5937 | ||
| 5927 | const inst_ty = f.air.typeOfIndex(inst); | 5938 | const inst_ty = f.air.typeOfIndex(inst); |
| 5928 | const inst_scalar_ty = inst_ty.scalarType(); | 5939 | const inst_scalar_ty = inst_ty.scalarType(mod); |
| 5929 | const scalar_ty = operand_ty.scalarType(); | 5940 | const scalar_ty = operand_ty.scalarType(mod); |
| 5930 | 5941 | ||
| 5931 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | 5942 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); |
| 5932 | const ref_ret = inst_scalar_cty.tag() == .array; | 5943 | const ref_ret = inst_scalar_cty.tag() == .array; |
| ... | @@ -5968,14 +5979,15 @@ fn airCmpBuiltinCall( | ... | @@ -5968,14 +5979,15 @@ fn airCmpBuiltinCall( |
| 5968 | operation: enum { cmp, operator }, | 5979 | operation: enum { cmp, operator }, |
| 5969 | info: BuiltinInfo, | 5980 | info: BuiltinInfo, |
| 5970 | ) !CValue { | 5981 | ) !CValue { |
| 5982 | const mod = f.object.dg.module; | ||
| 5971 | const lhs = try f.resolveInst(data.lhs); | 5983 | const lhs = try f.resolveInst(data.lhs); |
| 5972 | const rhs = try f.resolveInst(data.rhs); | 5984 | const rhs = try f.resolveInst(data.rhs); |
| 5973 | try reap(f, inst, &.{ data.lhs, data.rhs }); | 5985 | try reap(f, inst, &.{ data.lhs, data.rhs }); |
| 5974 | 5986 | ||
| 5975 | const inst_ty = f.air.typeOfIndex(inst); | 5987 | const inst_ty = f.air.typeOfIndex(inst); |
| 5976 | const inst_scalar_ty = inst_ty.scalarType(); | 5988 | const inst_scalar_ty = inst_ty.scalarType(mod); |
| 5977 | const operand_ty = f.air.typeOf(data.lhs); | 5989 | const operand_ty = f.air.typeOf(data.lhs); |
| 5978 | const scalar_ty = operand_ty.scalarType(); | 5990 | const scalar_ty = operand_ty.scalarType(mod); |
| 5979 | 5991 | ||
| 5980 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | 5992 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); |
| 5981 | const ref_ret = inst_scalar_cty.tag() == .array; | 5993 | const ref_ret = inst_scalar_cty.tag() == .array; |
| ... | @@ -6017,6 +6029,7 @@ fn airCmpBuiltinCall( | ... | @@ -6017,6 +6029,7 @@ fn airCmpBuiltinCall( |
| 6017 | } | 6029 | } |
| 6018 | 6030 | ||
| 6019 | fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue { | 6031 | fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue { |
| 6032 | const mod = f.object.dg.module; | ||
| 6020 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 6033 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 6021 | const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | 6034 | const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| 6022 | const inst_ty = f.air.typeOfIndex(inst); | 6035 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -6030,15 +6043,13 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6030,15 +6043,13 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6030 | const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value); | 6043 | const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value); |
| 6031 | try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value }); | 6044 | try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value }); |
| 6032 | 6045 | ||
| 6033 | const target = f.object.dg.module.getTarget(); | 6046 | const repr_ty = if (ty.isRuntimeFloat()) |
| 6034 | var repr_pl = Type.Payload.Bits{ | 6047 | mod.intType(.unsigned, @intCast(u16, ty.abiSize(mod) * 8)) catch unreachable |
| 6035 | .base = .{ .tag = .int_unsigned }, | 6048 | else |
| 6036 | .data = @intCast(u16, ty.abiSize(target) * 8), | 6049 | ty; |
| 6037 | }; | ||
| 6038 | const repr_ty = if (ty.isRuntimeFloat()) Type.initPayload(&repr_pl.base) else ty; | ||
| 6039 | 6050 | ||
| 6040 | const local = try f.allocLocal(inst, inst_ty); | 6051 | const local = try f.allocLocal(inst, inst_ty); |
| 6041 | if (inst_ty.isPtrLikeOptional()) { | 6052 | if (inst_ty.isPtrLikeOptional(mod)) { |
| 6042 | { | 6053 | { |
| 6043 | const a = try Assignment.start(f, writer, ty); | 6054 | const a = try Assignment.start(f, writer, ty); |
| 6044 | try f.writeCValue(writer, local, .Other); | 6055 | try f.writeCValue(writer, local, .Other); |
| ... | @@ -6123,6 +6134,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6123,6 +6134,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6123 | } | 6134 | } |
| 6124 | 6135 | ||
| 6125 | fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { | 6136 | fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6137 | const mod = f.object.dg.module; | ||
| 6126 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; | 6138 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| 6127 | const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data; | 6139 | const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data; |
| 6128 | const inst_ty = f.air.typeOfIndex(inst); | 6140 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -6135,14 +6147,10 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6135,14 +6147,10 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6135 | const operand_mat = try Materialize.start(f, inst, writer, ty, operand); | 6147 | const operand_mat = try Materialize.start(f, inst, writer, ty, operand); |
| 6136 | try reap(f, inst, &.{ pl_op.operand, extra.operand }); | 6148 | try reap(f, inst, &.{ pl_op.operand, extra.operand }); |
| 6137 | 6149 | ||
| 6138 | const target = f.object.dg.module.getTarget(); | 6150 | const repr_bits = @intCast(u16, ty.abiSize(mod) * 8); |
| 6139 | var repr_pl = Type.Payload.Bits{ | ||
| 6140 | .base = .{ .tag = .int_unsigned }, | ||
| 6141 | .data = @intCast(u16, ty.abiSize(target) * 8), | ||
| 6142 | }; | ||
| 6143 | const is_float = ty.isRuntimeFloat(); | 6151 | const is_float = ty.isRuntimeFloat(); |
| 6144 | const is_128 = repr_pl.data == 128; | 6152 | const is_128 = repr_bits == 128; |
| 6145 | const repr_ty = if (is_float) Type.initPayload(&repr_pl.base) else ty; | 6153 | const repr_ty = if (is_float) mod.intType(.unsigned, repr_bits) catch unreachable else ty; |
| 6146 | 6154 | ||
| 6147 | const local = try f.allocLocal(inst, inst_ty); | 6155 | const local = try f.allocLocal(inst, inst_ty); |
| 6148 | try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())}); | 6156 | try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())}); |
| ... | @@ -6181,18 +6189,17 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6181,18 +6189,17 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6181 | } | 6189 | } |
| 6182 | 6190 | ||
| 6183 | fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { | 6191 | fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6192 | const mod = f.object.dg.module; | ||
| 6184 | const atomic_load = f.air.instructions.items(.data)[inst].atomic_load; | 6193 | const atomic_load = f.air.instructions.items(.data)[inst].atomic_load; |
| 6185 | const ptr = try f.resolveInst(atomic_load.ptr); | 6194 | const ptr = try f.resolveInst(atomic_load.ptr); |
| 6186 | try reap(f, inst, &.{atomic_load.ptr}); | 6195 | try reap(f, inst, &.{atomic_load.ptr}); |
| 6187 | const ptr_ty = f.air.typeOf(atomic_load.ptr); | 6196 | const ptr_ty = f.air.typeOf(atomic_load.ptr); |
| 6188 | const ty = ptr_ty.childType(); | 6197 | const ty = ptr_ty.childType(); |
| 6189 | 6198 | ||
| 6190 | const target = f.object.dg.module.getTarget(); | 6199 | const repr_ty = if (ty.isRuntimeFloat()) |
| 6191 | var repr_pl = Type.Payload.Bits{ | 6200 | mod.intType(.unsigned, @intCast(u16, ty.abiSize(mod) * 8)) catch unreachable |
| 6192 | .base = .{ .tag = .int_unsigned }, | 6201 | else |
| 6193 | .data = @intCast(u16, ty.abiSize(target) * 8), | 6202 | ty; |
| 6194 | }; | ||
| 6195 | const repr_ty = if (ty.isRuntimeFloat()) Type.initPayload(&repr_pl.base) else ty; | ||
| 6196 | 6203 | ||
| 6197 | const inst_ty = f.air.typeOfIndex(inst); | 6204 | const inst_ty = f.air.typeOfIndex(inst); |
| 6198 | const writer = f.object.writer(); | 6205 | const writer = f.object.writer(); |
| ... | @@ -6218,6 +6225,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6218,6 +6225,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6218 | } | 6225 | } |
| 6219 | 6226 | ||
| 6220 | fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue { | 6227 | fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue { |
| 6228 | const mod = f.object.dg.module; | ||
| 6221 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 6229 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 6222 | const ptr_ty = f.air.typeOf(bin_op.lhs); | 6230 | const ptr_ty = f.air.typeOf(bin_op.lhs); |
| 6223 | const ty = ptr_ty.childType(); | 6231 | const ty = ptr_ty.childType(); |
| ... | @@ -6228,12 +6236,10 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa | ... | @@ -6228,12 +6236,10 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa |
| 6228 | const element_mat = try Materialize.start(f, inst, writer, ty, element); | 6236 | const element_mat = try Materialize.start(f, inst, writer, ty, element); |
| 6229 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 6237 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6230 | 6238 | ||
| 6231 | const target = f.object.dg.module.getTarget(); | 6239 | const repr_ty = if (ty.isRuntimeFloat()) |
| 6232 | var repr_pl = Type.Payload.Bits{ | 6240 | mod.intType(.unsigned, @intCast(u16, ty.abiSize(mod) * 8)) catch unreachable |
| 6233 | .base = .{ .tag = .int_unsigned }, | 6241 | else |
| 6234 | .data = @intCast(u16, ty.abiSize(target) * 8), | 6242 | ty; |
| 6235 | }; | ||
| 6236 | const repr_ty = if (ty.isRuntimeFloat()) Type.initPayload(&repr_pl.base) else ty; | ||
| 6237 | 6243 | ||
| 6238 | try writer.writeAll("zig_atomic_store((zig_atomic("); | 6244 | try writer.writeAll("zig_atomic_store((zig_atomic("); |
| 6239 | try f.renderType(writer, ty); | 6245 | try f.renderType(writer, ty); |
| ... | @@ -6262,14 +6268,14 @@ fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !vo | ... | @@ -6262,14 +6268,14 @@ fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !vo |
| 6262 | } | 6268 | } |
| 6263 | 6269 | ||
| 6264 | fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | 6270 | fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6271 | const mod = f.object.dg.module; | ||
| 6265 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 6272 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 6266 | const dest_ty = f.air.typeOf(bin_op.lhs); | 6273 | const dest_ty = f.air.typeOf(bin_op.lhs); |
| 6267 | const dest_slice = try f.resolveInst(bin_op.lhs); | 6274 | const dest_slice = try f.resolveInst(bin_op.lhs); |
| 6268 | const value = try f.resolveInst(bin_op.rhs); | 6275 | const value = try f.resolveInst(bin_op.rhs); |
| 6269 | const elem_ty = f.air.typeOf(bin_op.rhs); | 6276 | const elem_ty = f.air.typeOf(bin_op.rhs); |
| 6270 | const target = f.object.dg.module.getTarget(); | 6277 | const elem_abi_size = elem_ty.abiSize(mod); |
| 6271 | const elem_abi_size = elem_ty.abiSize(target); | 6278 | const val_is_undef = if (f.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep() else false; |
| 6272 | const val_is_undef = if (f.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false; | ||
| 6273 | const writer = f.object.writer(); | 6279 | const writer = f.object.writer(); |
| 6274 | 6280 | ||
| 6275 | if (val_is_undef) { | 6281 | if (val_is_undef) { |
| ... | @@ -6383,12 +6389,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -6383,12 +6389,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6383 | } | 6389 | } |
| 6384 | 6390 | ||
| 6385 | fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { | 6391 | fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6392 | const mod = f.object.dg.module; | ||
| 6386 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 6393 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 6387 | const dest_ptr = try f.resolveInst(bin_op.lhs); | 6394 | const dest_ptr = try f.resolveInst(bin_op.lhs); |
| 6388 | const src_ptr = try f.resolveInst(bin_op.rhs); | 6395 | const src_ptr = try f.resolveInst(bin_op.rhs); |
| 6389 | const dest_ty = f.air.typeOf(bin_op.lhs); | 6396 | const dest_ty = f.air.typeOf(bin_op.lhs); |
| 6390 | const src_ty = f.air.typeOf(bin_op.rhs); | 6397 | const src_ty = f.air.typeOf(bin_op.rhs); |
| 6391 | const target = f.object.dg.module.getTarget(); | ||
| 6392 | const writer = f.object.writer(); | 6398 | const writer = f.object.writer(); |
| 6393 | 6399 | ||
| 6394 | try writer.writeAll("memcpy("); | 6400 | try writer.writeAll("memcpy("); |
| ... | @@ -6399,7 +6405,7 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6399,7 +6405,7 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6399 | switch (dest_ty.ptrSize()) { | 6405 | switch (dest_ty.ptrSize()) { |
| 6400 | .Slice => { | 6406 | .Slice => { |
| 6401 | const elem_ty = dest_ty.childType(); | 6407 | const elem_ty = dest_ty.childType(); |
| 6402 | const elem_abi_size = elem_ty.abiSize(target); | 6408 | const elem_abi_size = elem_ty.abiSize(mod); |
| 6403 | try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" }); | 6409 | try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" }); |
| 6404 | if (elem_abi_size > 1) { | 6410 | if (elem_abi_size > 1) { |
| 6405 | try writer.print(" * {d});\n", .{elem_abi_size}); | 6411 | try writer.print(" * {d});\n", .{elem_abi_size}); |
| ... | @@ -6410,7 +6416,7 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6410,7 +6416,7 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6410 | .One => { | 6416 | .One => { |
| 6411 | const array_ty = dest_ty.childType(); | 6417 | const array_ty = dest_ty.childType(); |
| 6412 | const elem_ty = array_ty.childType(); | 6418 | const elem_ty = array_ty.childType(); |
| 6413 | const elem_abi_size = elem_ty.abiSize(target); | 6419 | const elem_abi_size = elem_ty.abiSize(mod); |
| 6414 | const len = array_ty.arrayLen() * elem_abi_size; | 6420 | const len = array_ty.arrayLen() * elem_abi_size; |
| 6415 | try writer.print("{d});\n", .{len}); | 6421 | try writer.print("{d});\n", .{len}); |
| 6416 | }, | 6422 | }, |
| ... | @@ -6422,14 +6428,14 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6422,14 +6428,14 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6422 | } | 6428 | } |
| 6423 | 6429 | ||
| 6424 | fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | 6430 | fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6431 | const mod = f.object.dg.module; | ||
| 6425 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 6432 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 6426 | const union_ptr = try f.resolveInst(bin_op.lhs); | 6433 | const union_ptr = try f.resolveInst(bin_op.lhs); |
| 6427 | const new_tag = try f.resolveInst(bin_op.rhs); | 6434 | const new_tag = try f.resolveInst(bin_op.rhs); |
| 6428 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 6435 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6429 | 6436 | ||
| 6430 | const target = f.object.dg.module.getTarget(); | ||
| 6431 | const union_ty = f.air.typeOf(bin_op.lhs).childType(); | 6437 | const union_ty = f.air.typeOf(bin_op.lhs).childType(); |
| 6432 | const layout = union_ty.unionGetLayout(target); | 6438 | const layout = union_ty.unionGetLayout(mod); |
| 6433 | if (layout.tag_size == 0) return .none; | 6439 | if (layout.tag_size == 0) return .none; |
| 6434 | const tag_ty = union_ty.unionTagTypeSafety().?; | 6440 | const tag_ty = union_ty.unionTagTypeSafety().?; |
| 6435 | 6441 | ||
| ... | @@ -6443,14 +6449,14 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6443,14 +6449,14 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6443 | } | 6449 | } |
| 6444 | 6450 | ||
| 6445 | fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | 6451 | fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6452 | const mod = f.object.dg.module; | ||
| 6446 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 6453 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 6447 | 6454 | ||
| 6448 | const operand = try f.resolveInst(ty_op.operand); | 6455 | const operand = try f.resolveInst(ty_op.operand); |
| 6449 | try reap(f, inst, &.{ty_op.operand}); | 6456 | try reap(f, inst, &.{ty_op.operand}); |
| 6450 | 6457 | ||
| 6451 | const union_ty = f.air.typeOf(ty_op.operand); | 6458 | const union_ty = f.air.typeOf(ty_op.operand); |
| 6452 | const target = f.object.dg.module.getTarget(); | 6459 | const layout = union_ty.unionGetLayout(mod); |
| 6453 | const layout = union_ty.unionGetLayout(target); | ||
| 6454 | if (layout.tag_size == 0) return .none; | 6460 | if (layout.tag_size == 0) return .none; |
| 6455 | 6461 | ||
| 6456 | const inst_ty = f.air.typeOfIndex(inst); | 6462 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -6501,13 +6507,14 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6501,13 +6507,14 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6501 | } | 6507 | } |
| 6502 | 6508 | ||
| 6503 | fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { | 6509 | fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6510 | const mod = f.object.dg.module; | ||
| 6504 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 6511 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 6505 | 6512 | ||
| 6506 | const operand = try f.resolveInst(ty_op.operand); | 6513 | const operand = try f.resolveInst(ty_op.operand); |
| 6507 | try reap(f, inst, &.{ty_op.operand}); | 6514 | try reap(f, inst, &.{ty_op.operand}); |
| 6508 | 6515 | ||
| 6509 | const inst_ty = f.air.typeOfIndex(inst); | 6516 | const inst_ty = f.air.typeOfIndex(inst); |
| 6510 | const inst_scalar_ty = inst_ty.scalarType(); | 6517 | const inst_scalar_ty = inst_ty.scalarType(mod); |
| 6511 | 6518 | ||
| 6512 | const writer = f.object.writer(); | 6519 | const writer = f.object.writer(); |
| 6513 | const local = try f.allocLocal(inst, inst_ty); | 6520 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -6555,6 +6562,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6555,6 +6562,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6555 | } | 6562 | } |
| 6556 | 6563 | ||
| 6557 | fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { | 6564 | fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6565 | const mod = f.object.dg.module; | ||
| 6558 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 6566 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 6559 | const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data; | 6567 | const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data; |
| 6560 | 6568 | ||
| ... | @@ -6562,8 +6570,6 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6562,8 +6570,6 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6562 | const lhs = try f.resolveInst(extra.a); | 6570 | const lhs = try f.resolveInst(extra.a); |
| 6563 | const rhs = try f.resolveInst(extra.b); | 6571 | const rhs = try f.resolveInst(extra.b); |
| 6564 | 6572 | ||
| 6565 | const module = f.object.dg.module; | ||
| 6566 | const target = module.getTarget(); | ||
| 6567 | const inst_ty = f.air.typeOfIndex(inst); | 6573 | const inst_ty = f.air.typeOfIndex(inst); |
| 6568 | 6574 | ||
| 6569 | const writer = f.object.writer(); | 6575 | const writer = f.object.writer(); |
| ... | @@ -6581,7 +6587,7 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6581,7 +6587,7 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6581 | try writer.writeAll("] = "); | 6587 | try writer.writeAll("] = "); |
| 6582 | 6588 | ||
| 6583 | var buf: Value.ElemValueBuffer = undefined; | 6589 | var buf: Value.ElemValueBuffer = undefined; |
| 6584 | const mask_elem = mask.elemValueBuffer(module, index, &buf).toSignedInt(target); | 6590 | const mask_elem = mask.elemValueBuffer(mod, index, &buf).toSignedInt(mod); |
| 6585 | var src_pl = Value.Payload.U64{ | 6591 | var src_pl = Value.Payload.U64{ |
| 6586 | .base = .{ .tag = .int_u64 }, | 6592 | .base = .{ .tag = .int_u64 }, |
| 6587 | .data = @intCast(u64, mask_elem ^ mask_elem >> 63), | 6593 | .data = @intCast(u64, mask_elem ^ mask_elem >> 63), |
| ... | @@ -6597,16 +6603,17 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6597,16 +6603,17 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6597 | } | 6603 | } |
| 6598 | 6604 | ||
| 6599 | fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | 6605 | fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6606 | const mod = f.object.dg.module; | ||
| 6600 | const reduce = f.air.instructions.items(.data)[inst].reduce; | 6607 | const reduce = f.air.instructions.items(.data)[inst].reduce; |
| 6601 | 6608 | ||
| 6602 | const target = f.object.dg.module.getTarget(); | 6609 | const target = mod.getTarget(); |
| 6603 | const scalar_ty = f.air.typeOfIndex(inst); | 6610 | const scalar_ty = f.air.typeOfIndex(inst); |
| 6604 | const operand = try f.resolveInst(reduce.operand); | 6611 | const operand = try f.resolveInst(reduce.operand); |
| 6605 | try reap(f, inst, &.{reduce.operand}); | 6612 | try reap(f, inst, &.{reduce.operand}); |
| 6606 | const operand_ty = f.air.typeOf(reduce.operand); | 6613 | const operand_ty = f.air.typeOf(reduce.operand); |
| 6607 | const writer = f.object.writer(); | 6614 | const writer = f.object.writer(); |
| 6608 | 6615 | ||
| 6609 | const use_operator = scalar_ty.bitSize(target) <= 64; | 6616 | const use_operator = scalar_ty.bitSize(mod) <= 64; |
| 6610 | const op: union(enum) { | 6617 | const op: union(enum) { |
| 6611 | const Func = struct { operation: []const u8, info: BuiltinInfo = .none }; | 6618 | const Func = struct { operation: []const u8, info: BuiltinInfo = .none }; |
| 6612 | float_op: Func, | 6619 | float_op: Func, |
| ... | @@ -6617,28 +6624,28 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6617,28 +6624,28 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6617 | .And => if (use_operator) .{ .infix = " &= " } else .{ .builtin = .{ .operation = "and" } }, | 6624 | .And => if (use_operator) .{ .infix = " &= " } else .{ .builtin = .{ .operation = "and" } }, |
| 6618 | .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } }, | 6625 | .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } }, |
| 6619 | .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } }, | 6626 | .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } }, |
| 6620 | .Min => switch (scalar_ty.zigTypeTag()) { | 6627 | .Min => switch (scalar_ty.zigTypeTag(mod)) { |
| 6621 | .Int => if (use_operator) .{ .ternary = " < " } else .{ | 6628 | .Int => if (use_operator) .{ .ternary = " < " } else .{ |
| 6622 | .builtin = .{ .operation = "min" }, | 6629 | .builtin = .{ .operation = "min" }, |
| 6623 | }, | 6630 | }, |
| 6624 | .Float => .{ .float_op = .{ .operation = "fmin" } }, | 6631 | .Float => .{ .float_op = .{ .operation = "fmin" } }, |
| 6625 | else => unreachable, | 6632 | else => unreachable, |
| 6626 | }, | 6633 | }, |
| 6627 | .Max => switch (scalar_ty.zigTypeTag()) { | 6634 | .Max => switch (scalar_ty.zigTypeTag(mod)) { |
| 6628 | .Int => if (use_operator) .{ .ternary = " > " } else .{ | 6635 | .Int => if (use_operator) .{ .ternary = " > " } else .{ |
| 6629 | .builtin = .{ .operation = "max" }, | 6636 | .builtin = .{ .operation = "max" }, |
| 6630 | }, | 6637 | }, |
| 6631 | .Float => .{ .float_op = .{ .operation = "fmax" } }, | 6638 | .Float => .{ .float_op = .{ .operation = "fmax" } }, |
| 6632 | else => unreachable, | 6639 | else => unreachable, |
| 6633 | }, | 6640 | }, |
| 6634 | .Add => switch (scalar_ty.zigTypeTag()) { | 6641 | .Add => switch (scalar_ty.zigTypeTag(mod)) { |
| 6635 | .Int => if (use_operator) .{ .infix = " += " } else .{ | 6642 | .Int => if (use_operator) .{ .infix = " += " } else .{ |
| 6636 | .builtin = .{ .operation = "addw", .info = .bits }, | 6643 | .builtin = .{ .operation = "addw", .info = .bits }, |
| 6637 | }, | 6644 | }, |
| 6638 | .Float => .{ .builtin = .{ .operation = "add" } }, | 6645 | .Float => .{ .builtin = .{ .operation = "add" } }, |
| 6639 | else => unreachable, | 6646 | else => unreachable, |
| 6640 | }, | 6647 | }, |
| 6641 | .Mul => switch (scalar_ty.zigTypeTag()) { | 6648 | .Mul => switch (scalar_ty.zigTypeTag(mod)) { |
| 6642 | .Int => if (use_operator) .{ .infix = " *= " } else .{ | 6649 | .Int => if (use_operator) .{ .infix = " *= " } else .{ |
| 6643 | .builtin = .{ .operation = "mulw", .info = .bits }, | 6650 | .builtin = .{ .operation = "mulw", .info = .bits }, |
| 6644 | }, | 6651 | }, |
| ... | @@ -6680,22 +6687,22 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6680,22 +6687,22 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6680 | 6687 | ||
| 6681 | try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) { | 6688 | try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) { |
| 6682 | .Or, .Xor, .Add => Value.zero, | 6689 | .Or, .Xor, .Add => Value.zero, |
| 6683 | .And => switch (scalar_ty.zigTypeTag()) { | 6690 | .And => switch (scalar_ty.zigTypeTag(mod)) { |
| 6684 | .Bool => Value.one, | 6691 | .Bool => Value.one, |
| 6685 | else => switch (scalar_ty.intInfo(target).signedness) { | 6692 | else => switch (scalar_ty.intInfo(mod).signedness) { |
| 6686 | .unsigned => try scalar_ty.maxInt(stack.get(), target), | 6693 | .unsigned => try scalar_ty.maxInt(stack.get(), mod), |
| 6687 | .signed => Value.negative_one, | 6694 | .signed => Value.negative_one, |
| 6688 | }, | 6695 | }, |
| 6689 | }, | 6696 | }, |
| 6690 | .Min => switch (scalar_ty.zigTypeTag()) { | 6697 | .Min => switch (scalar_ty.zigTypeTag(mod)) { |
| 6691 | .Bool => Value.one, | 6698 | .Bool => Value.one, |
| 6692 | .Int => try scalar_ty.maxInt(stack.get(), target), | 6699 | .Int => try scalar_ty.maxInt(stack.get(), mod), |
| 6693 | .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target), | 6700 | .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target), |
| 6694 | else => unreachable, | 6701 | else => unreachable, |
| 6695 | }, | 6702 | }, |
| 6696 | .Max => switch (scalar_ty.zigTypeTag()) { | 6703 | .Max => switch (scalar_ty.zigTypeTag(mod)) { |
| 6697 | .Bool => Value.zero, | 6704 | .Bool => Value.zero, |
| 6698 | .Int => try scalar_ty.minInt(stack.get(), target), | 6705 | .Int => try scalar_ty.minInt(stack.get(), mod), |
| 6699 | .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target), | 6706 | .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target), |
| 6700 | else => unreachable, | 6707 | else => unreachable, |
| 6701 | }, | 6708 | }, |
| ... | @@ -6753,6 +6760,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6753,6 +6760,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6753 | } | 6760 | } |
| 6754 | 6761 | ||
| 6755 | fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | 6762 | fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6763 | const mod = f.object.dg.module; | ||
| 6756 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 6764 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 6757 | const inst_ty = f.air.typeOfIndex(inst); | 6765 | const inst_ty = f.air.typeOfIndex(inst); |
| 6758 | const len = @intCast(usize, inst_ty.arrayLen()); | 6766 | const len = @intCast(usize, inst_ty.arrayLen()); |
| ... | @@ -6770,11 +6778,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6770,11 +6778,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6770 | } | 6778 | } |
| 6771 | } | 6779 | } |
| 6772 | 6780 | ||
| 6773 | const target = f.object.dg.module.getTarget(); | ||
| 6774 | |||
| 6775 | const writer = f.object.writer(); | 6781 | const writer = f.object.writer(); |
| 6776 | const local = try f.allocLocal(inst, inst_ty); | 6782 | const local = try f.allocLocal(inst, inst_ty); |
| 6777 | switch (inst_ty.zigTypeTag()) { | 6783 | switch (inst_ty.zigTypeTag(mod)) { |
| 6778 | .Array, .Vector => { | 6784 | .Array, .Vector => { |
| 6779 | const elem_ty = inst_ty.childType(); | 6785 | const elem_ty = inst_ty.childType(); |
| 6780 | const a = try Assignment.init(f, elem_ty); | 6786 | const a = try Assignment.init(f, elem_ty); |
| ... | @@ -6799,7 +6805,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6799,7 +6805,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6799 | .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| { | 6805 | .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| { |
| 6800 | if (inst_ty.structFieldIsComptime(field_i)) continue; | 6806 | if (inst_ty.structFieldIsComptime(field_i)) continue; |
| 6801 | const field_ty = inst_ty.structFieldType(field_i); | 6807 | const field_ty = inst_ty.structFieldType(field_i); |
| 6802 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 6808 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 6803 | 6809 | ||
| 6804 | const a = try Assignment.start(f, writer, field_ty); | 6810 | const a = try Assignment.start(f, writer, field_ty); |
| 6805 | try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple()) | 6811 | try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple()) |
| ... | @@ -6813,13 +6819,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6813,13 +6819,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6813 | .Packed => { | 6819 | .Packed => { |
| 6814 | try f.writeCValue(writer, local, .Other); | 6820 | try f.writeCValue(writer, local, .Other); |
| 6815 | try writer.writeAll(" = "); | 6821 | try writer.writeAll(" = "); |
| 6816 | const int_info = inst_ty.intInfo(target); | 6822 | const int_info = inst_ty.intInfo(mod); |
| 6817 | 6823 | ||
| 6818 | var bit_offset_ty_pl = Type.Payload.Bits{ | 6824 | const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); |
| 6819 | .base = .{ .tag = .int_unsigned }, | ||
| 6820 | .data = Type.smallestUnsignedBits(int_info.bits - 1), | ||
| 6821 | }; | ||
| 6822 | const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base); | ||
| 6823 | 6825 | ||
| 6824 | var bit_offset_val_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = 0 }; | 6826 | var bit_offset_val_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = 0 }; |
| 6825 | const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base); | 6827 | const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base); |
| ... | @@ -6828,7 +6830,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6828,7 +6830,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6828 | for (0..elements.len) |field_i| { | 6830 | for (0..elements.len) |field_i| { |
| 6829 | if (inst_ty.structFieldIsComptime(field_i)) continue; | 6831 | if (inst_ty.structFieldIsComptime(field_i)) continue; |
| 6830 | const field_ty = inst_ty.structFieldType(field_i); | 6832 | const field_ty = inst_ty.structFieldType(field_i); |
| 6831 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 6833 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 6832 | 6834 | ||
| 6833 | if (!empty) { | 6835 | if (!empty) { |
| 6834 | try writer.writeAll("zig_or_"); | 6836 | try writer.writeAll("zig_or_"); |
| ... | @@ -6841,7 +6843,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6841,7 +6843,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6841 | for (resolved_elements, 0..) |element, field_i| { | 6843 | for (resolved_elements, 0..) |element, field_i| { |
| 6842 | if (inst_ty.structFieldIsComptime(field_i)) continue; | 6844 | if (inst_ty.structFieldIsComptime(field_i)) continue; |
| 6843 | const field_ty = inst_ty.structFieldType(field_i); | 6845 | const field_ty = inst_ty.structFieldType(field_i); |
| 6844 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 6846 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 6845 | 6847 | ||
| 6846 | if (!empty) try writer.writeAll(", "); | 6848 | if (!empty) try writer.writeAll(", "); |
| 6847 | // TODO: Skip this entire shift if val is 0? | 6849 | // TODO: Skip this entire shift if val is 0? |
| ... | @@ -6849,13 +6851,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6849,13 +6851,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6849 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | 6851 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 6850 | try writer.writeByte('('); | 6852 | try writer.writeByte('('); |
| 6851 | 6853 | ||
| 6852 | if (inst_ty.isAbiInt() and (field_ty.isAbiInt() or field_ty.isPtrAtRuntime())) { | 6854 | if (inst_ty.isAbiInt(mod) and (field_ty.isAbiInt(mod) or field_ty.isPtrAtRuntime(mod))) { |
| 6853 | try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument); | 6855 | try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument); |
| 6854 | } else { | 6856 | } else { |
| 6855 | try writer.writeByte('('); | 6857 | try writer.writeByte('('); |
| 6856 | try f.renderType(writer, inst_ty); | 6858 | try f.renderType(writer, inst_ty); |
| 6857 | try writer.writeByte(')'); | 6859 | try writer.writeByte(')'); |
| 6858 | if (field_ty.isPtrAtRuntime()) { | 6860 | if (field_ty.isPtrAtRuntime(mod)) { |
| 6859 | try writer.writeByte('('); | 6861 | try writer.writeByte('('); |
| 6860 | try f.renderType(writer, switch (int_info.signedness) { | 6862 | try f.renderType(writer, switch (int_info.signedness) { |
| 6861 | .unsigned => Type.usize, | 6863 | .unsigned => Type.usize, |
| ... | @@ -6872,7 +6874,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6872,7 +6874,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6872 | try writer.writeByte(')'); | 6874 | try writer.writeByte(')'); |
| 6873 | if (!empty) try writer.writeByte(')'); | 6875 | if (!empty) try writer.writeByte(')'); |
| 6874 | 6876 | ||
| 6875 | bit_offset_val_pl.data += field_ty.bitSize(target); | 6877 | bit_offset_val_pl.data += field_ty.bitSize(mod); |
| 6876 | empty = false; | 6878 | empty = false; |
| 6877 | } | 6879 | } |
| 6878 | 6880 | ||
| ... | @@ -6886,11 +6888,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6886,11 +6888,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6886 | } | 6888 | } |
| 6887 | 6889 | ||
| 6888 | fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | 6890 | fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6891 | const mod = f.object.dg.module; | ||
| 6889 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 6892 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 6890 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; | 6893 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 6891 | 6894 | ||
| 6892 | const union_ty = f.air.typeOfIndex(inst); | 6895 | const union_ty = f.air.typeOfIndex(inst); |
| 6893 | const target = f.object.dg.module.getTarget(); | ||
| 6894 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | 6896 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 6895 | const field_name = union_obj.fields.keys()[extra.field_index]; | 6897 | const field_name = union_obj.fields.keys()[extra.field_index]; |
| 6896 | const payload_ty = f.air.typeOf(extra.init); | 6898 | const payload_ty = f.air.typeOf(extra.init); |
| ... | @@ -6908,7 +6910,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6908,7 +6910,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6908 | } | 6910 | } |
| 6909 | 6911 | ||
| 6910 | const field: CValue = if (union_ty.unionTagTypeSafety()) |tag_ty| field: { | 6912 | const field: CValue = if (union_ty.unionTagTypeSafety()) |tag_ty| field: { |
| 6911 | const layout = union_ty.unionGetLayout(target); | 6913 | const layout = union_ty.unionGetLayout(mod); |
| 6912 | if (layout.tag_size != 0) { | 6914 | if (layout.tag_size != 0) { |
| 6913 | const field_index = tag_ty.enumFieldIndex(field_name).?; | 6915 | const field_index = tag_ty.enumFieldIndex(field_name).?; |
| 6914 | 6916 | ||
| ... | @@ -6991,13 +6993,14 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6991,13 +6993,14 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6991 | } | 6993 | } |
| 6992 | 6994 | ||
| 6993 | fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { | 6995 | fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6996 | const mod = f.object.dg.module; | ||
| 6994 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 6997 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 6995 | 6998 | ||
| 6996 | const operand = try f.resolveInst(un_op); | 6999 | const operand = try f.resolveInst(un_op); |
| 6997 | try reap(f, inst, &.{un_op}); | 7000 | try reap(f, inst, &.{un_op}); |
| 6998 | 7001 | ||
| 6999 | const operand_ty = f.air.typeOf(un_op); | 7002 | const operand_ty = f.air.typeOf(un_op); |
| 7000 | const scalar_ty = operand_ty.scalarType(); | 7003 | const scalar_ty = operand_ty.scalarType(mod); |
| 7001 | 7004 | ||
| 7002 | const writer = f.object.writer(); | 7005 | const writer = f.object.writer(); |
| 7003 | const local = try f.allocLocal(inst, operand_ty); | 7006 | const local = try f.allocLocal(inst, operand_ty); |
| ... | @@ -7016,13 +7019,14 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7016,13 +7019,14 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7016 | } | 7019 | } |
| 7017 | 7020 | ||
| 7018 | fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { | 7021 | fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { |
| 7022 | const mod = f.object.dg.module; | ||
| 7019 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 7023 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 7020 | 7024 | ||
| 7021 | const operand = try f.resolveInst(un_op); | 7025 | const operand = try f.resolveInst(un_op); |
| 7022 | try reap(f, inst, &.{un_op}); | 7026 | try reap(f, inst, &.{un_op}); |
| 7023 | 7027 | ||
| 7024 | const inst_ty = f.air.typeOfIndex(inst); | 7028 | const inst_ty = f.air.typeOfIndex(inst); |
| 7025 | const inst_scalar_ty = inst_ty.scalarType(); | 7029 | const inst_scalar_ty = inst_ty.scalarType(mod); |
| 7026 | 7030 | ||
| 7027 | const writer = f.object.writer(); | 7031 | const writer = f.object.writer(); |
| 7028 | const local = try f.allocLocal(inst, inst_ty); | 7032 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -7043,6 +7047,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal | ... | @@ -7043,6 +7047,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal |
| 7043 | } | 7047 | } |
| 7044 | 7048 | ||
| 7045 | fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { | 7049 | fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { |
| 7050 | const mod = f.object.dg.module; | ||
| 7046 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 7051 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 7047 | 7052 | ||
| 7048 | const lhs = try f.resolveInst(bin_op.lhs); | 7053 | const lhs = try f.resolveInst(bin_op.lhs); |
| ... | @@ -7050,7 +7055,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa | ... | @@ -7050,7 +7055,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa |
| 7050 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 7055 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 7051 | 7056 | ||
| 7052 | const inst_ty = f.air.typeOfIndex(inst); | 7057 | const inst_ty = f.air.typeOfIndex(inst); |
| 7053 | const inst_scalar_ty = inst_ty.scalarType(); | 7058 | const inst_scalar_ty = inst_ty.scalarType(mod); |
| 7054 | 7059 | ||
| 7055 | const writer = f.object.writer(); | 7060 | const writer = f.object.writer(); |
| 7056 | const local = try f.allocLocal(inst, inst_ty); | 7061 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -7074,6 +7079,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa | ... | @@ -7074,6 +7079,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa |
| 7074 | } | 7079 | } |
| 7075 | 7080 | ||
| 7076 | fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { | 7081 | fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7082 | const mod = f.object.dg.module; | ||
| 7077 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; | 7083 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| 7078 | const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data; | 7084 | const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data; |
| 7079 | 7085 | ||
| ... | @@ -7083,7 +7089,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7083,7 +7089,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7083 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand }); | 7089 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand }); |
| 7084 | 7090 | ||
| 7085 | const inst_ty = f.air.typeOfIndex(inst); | 7091 | const inst_ty = f.air.typeOfIndex(inst); |
| 7086 | const inst_scalar_ty = inst_ty.scalarType(); | 7092 | const inst_scalar_ty = inst_ty.scalarType(mod); |
| 7087 | 7093 | ||
| 7088 | const writer = f.object.writer(); | 7094 | const writer = f.object.writer(); |
| 7089 | const local = try f.allocLocal(inst, inst_ty); | 7095 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -7279,8 +7285,9 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 { | ... | @@ -7279,8 +7285,9 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 { |
| 7279 | }; | 7285 | }; |
| 7280 | } | 7286 | } |
| 7281 | 7287 | ||
| 7282 | fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 { | 7288 | fn compilerRtAbbrev(ty: Type, mod: *Module) []const u8 { |
| 7283 | return if (ty.isInt()) switch (ty.intInfo(target).bits) { | 7289 | const target = mod.getTarget(); |
| 7290 | return if (ty.isInt(mod)) switch (ty.intInfo(mod).bits) { | ||
| 7284 | 1...32 => "si", | 7291 | 1...32 => "si", |
| 7285 | 33...64 => "di", | 7292 | 33...64 => "di", |
| 7286 | 65...128 => "ti", | 7293 | 65...128 => "ti", |
| ... | @@ -7407,7 +7414,7 @@ fn undefPattern(comptime IntType: type) IntType { | ... | @@ -7407,7 +7414,7 @@ fn undefPattern(comptime IntType: type) IntType { |
| 7407 | 7414 | ||
| 7408 | const FormatIntLiteralContext = struct { | 7415 | const FormatIntLiteralContext = struct { |
| 7409 | dg: *DeclGen, | 7416 | dg: *DeclGen, |
| 7410 | int_info: std.builtin.Type.Int, | 7417 | int_info: InternPool.Key.IntType, |
| 7411 | kind: CType.Kind, | 7418 | kind: CType.Kind, |
| 7412 | cty: CType, | 7419 | cty: CType, |
| 7413 | val: Value, | 7420 | val: Value, |
| ... | @@ -7418,7 +7425,8 @@ fn formatIntLiteral( | ... | @@ -7418,7 +7425,8 @@ fn formatIntLiteral( |
| 7418 | options: std.fmt.FormatOptions, | 7425 | options: std.fmt.FormatOptions, |
| 7419 | writer: anytype, | 7426 | writer: anytype, |
| 7420 | ) @TypeOf(writer).Error!void { | 7427 | ) @TypeOf(writer).Error!void { |
| 7421 | const target = data.dg.module.getTarget(); | 7428 | const mod = data.dg.module; |
| 7429 | const target = mod.getTarget(); | ||
| 7422 | 7430 | ||
| 7423 | const ExpectedContents = struct { | 7431 | const ExpectedContents = struct { |
| 7424 | const base = 10; | 7432 | const base = 10; |
| ... | @@ -7449,7 +7457,7 @@ fn formatIntLiteral( | ... | @@ -7449,7 +7457,7 @@ fn formatIntLiteral( |
| 7449 | }; | 7457 | }; |
| 7450 | undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits); | 7458 | undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits); |
| 7451 | break :blk undef_int.toConst(); | 7459 | break :blk undef_int.toConst(); |
| 7452 | } else data.val.toBigInt(&int_buf, target); | 7460 | } else data.val.toBigInt(&int_buf, mod); |
| 7453 | assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits)); | 7461 | assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits)); |
| 7454 | 7462 | ||
| 7455 | const c_bits = @intCast(usize, data.cty.byteSize(data.dg.ctypes.set, target) * 8); | 7463 | const c_bits = @intCast(usize, data.cty.byteSize(data.dg.ctypes.set, target) * 8); |
| ... | @@ -7684,7 +7692,8 @@ const Vectorize = struct { | ... | @@ -7684,7 +7692,8 @@ const Vectorize = struct { |
| 7684 | index: CValue = .none, | 7692 | index: CValue = .none, |
| 7685 | 7693 | ||
| 7686 | pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize { | 7694 | pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize { |
| 7687 | return if (ty.zigTypeTag() == .Vector) index: { | 7695 | const mod = f.object.dg.module; |
| 7696 | return if (ty.zigTypeTag(mod) == .Vector) index: { | ||
| 7688 | var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = ty.vectorLen() }; | 7697 | var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = ty.vectorLen() }; |
| 7689 | 7698 | ||
| 7690 | const local = try f.allocLocal(inst, Type.usize); | 7699 | const local = try f.allocLocal(inst, Type.usize); |
| ... | @@ -7727,10 +7736,10 @@ const LowerFnRetTyBuffer = struct { | ... | @@ -7727,10 +7736,10 @@ const LowerFnRetTyBuffer = struct { |
| 7727 | values: [1]Value, | 7736 | values: [1]Value, |
| 7728 | payload: Type.Payload.AnonStruct, | 7737 | payload: Type.Payload.AnonStruct, |
| 7729 | }; | 7738 | }; |
| 7730 | fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) Type { | 7739 | fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, mod: *const Module) Type { |
| 7731 | if (ret_ty.zigTypeTag() == .NoReturn) return Type.initTag(.noreturn); | 7740 | if (ret_ty.zigTypeTag(mod) == .NoReturn) return Type.initTag(.noreturn); |
| 7732 | 7741 | ||
| 7733 | if (lowersToArray(ret_ty, target)) { | 7742 | if (lowersToArray(ret_ty, mod)) { |
| 7734 | buffer.names = [1][]const u8{"array"}; | 7743 | buffer.names = [1][]const u8{"array"}; |
| 7735 | buffer.types = [1]Type{ret_ty}; | 7744 | buffer.types = [1]Type{ret_ty}; |
| 7736 | buffer.values = [1]Value{Value.initTag(.unreachable_value)}; | 7745 | buffer.values = [1]Value{Value.initTag(.unreachable_value)}; |
| ... | @@ -7742,13 +7751,13 @@ fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) T | ... | @@ -7742,13 +7751,13 @@ fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) T |
| 7742 | return Type.initPayload(&buffer.payload.base); | 7751 | return Type.initPayload(&buffer.payload.base); |
| 7743 | } | 7752 | } |
| 7744 | 7753 | ||
| 7745 | return if (ret_ty.hasRuntimeBitsIgnoreComptime()) ret_ty else Type.void; | 7754 | return if (ret_ty.hasRuntimeBitsIgnoreComptime(mod)) ret_ty else Type.void; |
| 7746 | } | 7755 | } |
| 7747 | 7756 | ||
| 7748 | fn lowersToArray(ty: Type, target: std.Target) bool { | 7757 | fn lowersToArray(ty: Type, mod: *const Module) bool { |
| 7749 | return switch (ty.zigTypeTag()) { | 7758 | return switch (ty.zigTypeTag(mod)) { |
| 7750 | .Array, .Vector => return true, | 7759 | .Array, .Vector => return true, |
| 7751 | else => return ty.isAbiInt() and toCIntBits(@intCast(u32, ty.bitSize(target))) == null, | 7760 | else => return ty.isAbiInt(mod) and toCIntBits(@intCast(u32, ty.bitSize(mod))) == null, |
| 7752 | }; | 7761 | }; |
| 7753 | } | 7762 | } |
| 7754 | 7763 |
src/codegen/c/type.zig+74-76| ... | @@ -292,19 +292,19 @@ pub const CType = extern union { | ... | @@ -292,19 +292,19 @@ pub const CType = extern union { |
| 292 | .abi = std.math.log2_int(u32, abi_alignment), | 292 | .abi = std.math.log2_int(u32, abi_alignment), |
| 293 | }; | 293 | }; |
| 294 | } | 294 | } |
| 295 | pub fn abiAlign(ty: Type, target: Target) AlignAs { | 295 | pub fn abiAlign(ty: Type, mod: *const Module) AlignAs { |
| 296 | const abi_align = ty.abiAlignment(target); | 296 | const abi_align = ty.abiAlignment(mod); |
| 297 | return init(abi_align, abi_align); | 297 | return init(abi_align, abi_align); |
| 298 | } | 298 | } |
| 299 | pub fn fieldAlign(struct_ty: Type, field_i: usize, target: Target) AlignAs { | 299 | pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *const Module) AlignAs { |
| 300 | return init( | 300 | return init( |
| 301 | struct_ty.structFieldAlign(field_i, target), | 301 | struct_ty.structFieldAlign(field_i, mod), |
| 302 | struct_ty.structFieldType(field_i).abiAlignment(target), | 302 | struct_ty.structFieldType(field_i).abiAlignment(mod), |
| 303 | ); | 303 | ); |
| 304 | } | 304 | } |
| 305 | pub fn unionPayloadAlign(union_ty: Type, target: Target) AlignAs { | 305 | pub fn unionPayloadAlign(union_ty: Type, mod: *const Module) AlignAs { |
| 306 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | 306 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 307 | const union_payload_align = union_obj.abiAlignment(target, false); | 307 | const union_payload_align = union_obj.abiAlignment(mod, false); |
| 308 | return init(union_payload_align, union_payload_align); | 308 | return init(union_payload_align, union_payload_align); |
| 309 | } | 309 | } |
| 310 | 310 | ||
| ... | @@ -344,8 +344,8 @@ pub const CType = extern union { | ... | @@ -344,8 +344,8 @@ pub const CType = extern union { |
| 344 | return self.map.entries.items(.hash)[index - Tag.no_payload_count]; | 344 | return self.map.entries.items(.hash)[index - Tag.no_payload_count]; |
| 345 | } | 345 | } |
| 346 | 346 | ||
| 347 | pub fn typeToIndex(self: Set, ty: Type, target: Target, kind: Kind) ?Index { | 347 | pub fn typeToIndex(self: Set, ty: Type, mod: *Module, kind: Kind) ?Index { |
| 348 | const lookup = Convert.Lookup{ .imm = .{ .set = &self, .target = target } }; | 348 | const lookup = Convert.Lookup{ .imm = .{ .set = &self, .mod = mod } }; |
| 349 | 349 | ||
| 350 | var convert: Convert = undefined; | 350 | var convert: Convert = undefined; |
| 351 | convert.initType(ty, kind, lookup) catch unreachable; | 351 | convert.initType(ty, kind, lookup) catch unreachable; |
| ... | @@ -405,7 +405,7 @@ pub const CType = extern union { | ... | @@ -405,7 +405,7 @@ pub const CType = extern union { |
| 405 | ); | 405 | ); |
| 406 | if (!gop.found_existing) { | 406 | if (!gop.found_existing) { |
| 407 | errdefer _ = self.set.map.pop(); | 407 | errdefer _ = self.set.map.pop(); |
| 408 | gop.key_ptr.* = try createFromConvert(self, ty, lookup.getTarget(), kind, convert); | 408 | gop.key_ptr.* = try createFromConvert(self, ty, lookup.getModule(), kind, convert); |
| 409 | } | 409 | } |
| 410 | if (std.debug.runtime_safety) { | 410 | if (std.debug.runtime_safety) { |
| 411 | const adapter = TypeAdapter64{ | 411 | const adapter = TypeAdapter64{ |
| ... | @@ -1236,10 +1236,10 @@ pub const CType = extern union { | ... | @@ -1236,10 +1236,10 @@ pub const CType = extern union { |
| 1236 | } | 1236 | } |
| 1237 | 1237 | ||
| 1238 | pub const Lookup = union(enum) { | 1238 | pub const Lookup = union(enum) { |
| 1239 | fail: Target, | 1239 | fail: *Module, |
| 1240 | imm: struct { | 1240 | imm: struct { |
| 1241 | set: *const Store.Set, | 1241 | set: *const Store.Set, |
| 1242 | target: Target, | 1242 | mod: *Module, |
| 1243 | }, | 1243 | }, |
| 1244 | mut: struct { | 1244 | mut: struct { |
| 1245 | promoted: *Store.Promoted, | 1245 | promoted: *Store.Promoted, |
| ... | @@ -1254,10 +1254,14 @@ pub const CType = extern union { | ... | @@ -1254,10 +1254,14 @@ pub const CType = extern union { |
| 1254 | } | 1254 | } |
| 1255 | 1255 | ||
| 1256 | pub fn getTarget(self: @This()) Target { | 1256 | pub fn getTarget(self: @This()) Target { |
| 1257 | return self.getModule().getTarget(); | ||
| 1258 | } | ||
| 1259 | |||
| 1260 | pub fn getModule(self: @This()) *Module { | ||
| 1257 | return switch (self) { | 1261 | return switch (self) { |
| 1258 | .fail => |target| target, | 1262 | .fail => |mod| mod, |
| 1259 | .imm => |imm| imm.target, | 1263 | .imm => |imm| imm.mod, |
| 1260 | .mut => |mut| mut.mod.getTarget(), | 1264 | .mut => |mut| mut.mod, |
| 1261 | }; | 1265 | }; |
| 1262 | } | 1266 | } |
| 1263 | 1267 | ||
| ... | @@ -1272,7 +1276,7 @@ pub const CType = extern union { | ... | @@ -1272,7 +1276,7 @@ pub const CType = extern union { |
| 1272 | pub fn typeToIndex(self: @This(), ty: Type, kind: Kind) !?Index { | 1276 | pub fn typeToIndex(self: @This(), ty: Type, kind: Kind) !?Index { |
| 1273 | return switch (self) { | 1277 | return switch (self) { |
| 1274 | .fail => null, | 1278 | .fail => null, |
| 1275 | .imm => |imm| imm.set.typeToIndex(ty, imm.target, kind), | 1279 | .imm => |imm| imm.set.typeToIndex(ty, imm.mod, kind), |
| 1276 | .mut => |mut| try mut.promoted.typeToIndex(ty, mut.mod, kind), | 1280 | .mut => |mut| try mut.promoted.typeToIndex(ty, mut.mod, kind), |
| 1277 | }; | 1281 | }; |
| 1278 | } | 1282 | } |
| ... | @@ -1284,7 +1288,7 @@ pub const CType = extern union { | ... | @@ -1284,7 +1288,7 @@ pub const CType = extern union { |
| 1284 | pub fn freeze(self: @This()) @This() { | 1288 | pub fn freeze(self: @This()) @This() { |
| 1285 | return switch (self) { | 1289 | return switch (self) { |
| 1286 | .fail, .imm => self, | 1290 | .fail, .imm => self, |
| 1287 | .mut => |mut| .{ .imm = .{ .set = &mut.promoted.set, .target = self.getTarget() } }, | 1291 | .mut => |mut| .{ .imm = .{ .set = &mut.promoted.set, .mod = mut.mod } }, |
| 1288 | }; | 1292 | }; |
| 1289 | } | 1293 | } |
| 1290 | }; | 1294 | }; |
| ... | @@ -1338,7 +1342,7 @@ pub const CType = extern union { | ... | @@ -1338,7 +1342,7 @@ pub const CType = extern union { |
| 1338 | self.storage.anon.fields[0] = .{ | 1342 | self.storage.anon.fields[0] = .{ |
| 1339 | .name = "array", | 1343 | .name = "array", |
| 1340 | .type = array_idx, | 1344 | .type = array_idx, |
| 1341 | .alignas = AlignAs.abiAlign(ty, lookup.getTarget()), | 1345 | .alignas = AlignAs.abiAlign(ty, lookup.getModule()), |
| 1342 | }; | 1346 | }; |
| 1343 | self.initAnon(kind, fwd_idx, 1); | 1347 | self.initAnon(kind, fwd_idx, 1); |
| 1344 | } else self.init(switch (kind) { | 1348 | } else self.init(switch (kind) { |
| ... | @@ -1350,12 +1354,12 @@ pub const CType = extern union { | ... | @@ -1350,12 +1354,12 @@ pub const CType = extern union { |
| 1350 | } | 1354 | } |
| 1351 | 1355 | ||
| 1352 | pub fn initType(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void { | 1356 | pub fn initType(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void { |
| 1353 | const target = lookup.getTarget(); | 1357 | const mod = lookup.getModule(); |
| 1354 | 1358 | ||
| 1355 | self.* = undefined; | 1359 | self.* = undefined; |
| 1356 | if (!ty.isFnOrHasRuntimeBitsIgnoreComptime()) | 1360 | if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) |
| 1357 | self.init(.void) | 1361 | self.init(.void) |
| 1358 | else if (ty.isAbiInt()) switch (ty.tag()) { | 1362 | else if (ty.isAbiInt(mod)) switch (ty.tag()) { |
| 1359 | .usize => self.init(.uintptr_t), | 1363 | .usize => self.init(.uintptr_t), |
| 1360 | .isize => self.init(.intptr_t), | 1364 | .isize => self.init(.intptr_t), |
| 1361 | .c_char => self.init(.char), | 1365 | .c_char => self.init(.char), |
| ... | @@ -1367,13 +1371,13 @@ pub const CType = extern union { | ... | @@ -1367,13 +1371,13 @@ pub const CType = extern union { |
| 1367 | .c_ulong => self.init(.@"unsigned long"), | 1371 | .c_ulong => self.init(.@"unsigned long"), |
| 1368 | .c_longlong => self.init(.@"long long"), | 1372 | .c_longlong => self.init(.@"long long"), |
| 1369 | .c_ulonglong => self.init(.@"unsigned long long"), | 1373 | .c_ulonglong => self.init(.@"unsigned long long"), |
| 1370 | else => switch (tagFromIntInfo(ty.intInfo(target))) { | 1374 | else => switch (tagFromIntInfo(ty.intInfo(mod))) { |
| 1371 | .void => unreachable, | 1375 | .void => unreachable, |
| 1372 | else => |t| self.init(t), | 1376 | else => |t| self.init(t), |
| 1373 | .array => switch (kind) { | 1377 | .array => switch (kind) { |
| 1374 | .forward, .complete, .global => { | 1378 | .forward, .complete, .global => { |
| 1375 | const abi_size = ty.abiSize(target); | 1379 | const abi_size = ty.abiSize(mod); |
| 1376 | const abi_align = ty.abiAlignment(target); | 1380 | const abi_align = ty.abiAlignment(mod); |
| 1377 | self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{ | 1381 | self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{ |
| 1378 | .len = @divExact(abi_size, abi_align), | 1382 | .len = @divExact(abi_size, abi_align), |
| 1379 | .elem_type = tagFromIntInfo(.{ | 1383 | .elem_type = tagFromIntInfo(.{ |
| ... | @@ -1389,7 +1393,7 @@ pub const CType = extern union { | ... | @@ -1389,7 +1393,7 @@ pub const CType = extern union { |
| 1389 | .payload => unreachable, | 1393 | .payload => unreachable, |
| 1390 | }, | 1394 | }, |
| 1391 | }, | 1395 | }, |
| 1392 | } else switch (ty.zigTypeTag()) { | 1396 | } else switch (ty.zigTypeTag(mod)) { |
| 1393 | .Frame => unreachable, | 1397 | .Frame => unreachable, |
| 1394 | .AnyFrame => unreachable, | 1398 | .AnyFrame => unreachable, |
| 1395 | 1399 | ||
| ... | @@ -1434,12 +1438,12 @@ pub const CType = extern union { | ... | @@ -1434,12 +1438,12 @@ pub const CType = extern union { |
| 1434 | self.storage.anon.fields[0] = .{ | 1438 | self.storage.anon.fields[0] = .{ |
| 1435 | .name = "ptr", | 1439 | .name = "ptr", |
| 1436 | .type = ptr_idx, | 1440 | .type = ptr_idx, |
| 1437 | .alignas = AlignAs.abiAlign(ptr_ty, target), | 1441 | .alignas = AlignAs.abiAlign(ptr_ty, mod), |
| 1438 | }; | 1442 | }; |
| 1439 | self.storage.anon.fields[1] = .{ | 1443 | self.storage.anon.fields[1] = .{ |
| 1440 | .name = "len", | 1444 | .name = "len", |
| 1441 | .type = Tag.uintptr_t.toIndex(), | 1445 | .type = Tag.uintptr_t.toIndex(), |
| 1442 | .alignas = AlignAs.abiAlign(Type.usize, target), | 1446 | .alignas = AlignAs.abiAlign(Type.usize, mod), |
| 1443 | }; | 1447 | }; |
| 1444 | self.initAnon(kind, fwd_idx, 2); | 1448 | self.initAnon(kind, fwd_idx, 2); |
| 1445 | } else self.init(switch (kind) { | 1449 | } else self.init(switch (kind) { |
| ... | @@ -1462,12 +1466,8 @@ pub const CType = extern union { | ... | @@ -1462,12 +1466,8 @@ pub const CType = extern union { |
| 1462 | }, | 1466 | }, |
| 1463 | }; | 1467 | }; |
| 1464 | 1468 | ||
| 1465 | var host_int_pl = Type.Payload.Bits{ | ||
| 1466 | .base = .{ .tag = .int_unsigned }, | ||
| 1467 | .data = info.host_size * 8, | ||
| 1468 | }; | ||
| 1469 | const pointee_ty = if (info.host_size > 0 and info.vector_index == .none) | 1469 | const pointee_ty = if (info.host_size > 0 and info.vector_index == .none) |
| 1470 | Type.initPayload(&host_int_pl.base) | 1470 | try mod.intType(.unsigned, info.host_size * 8) |
| 1471 | else | 1471 | else |
| 1472 | info.pointee_type; | 1472 | info.pointee_type; |
| 1473 | 1473 | ||
| ... | @@ -1490,11 +1490,9 @@ pub const CType = extern union { | ... | @@ -1490,11 +1490,9 @@ pub const CType = extern union { |
| 1490 | if (ty.castTag(.@"struct")) |struct_obj| { | 1490 | if (ty.castTag(.@"struct")) |struct_obj| { |
| 1491 | try self.initType(struct_obj.data.backing_int_ty, kind, lookup); | 1491 | try self.initType(struct_obj.data.backing_int_ty, kind, lookup); |
| 1492 | } else { | 1492 | } else { |
| 1493 | var buf: Type.Payload.Bits = .{ | 1493 | const bits = @intCast(u16, ty.bitSize(mod)); |
| 1494 | .base = .{ .tag = .int_unsigned }, | 1494 | const int_ty = try mod.intType(.unsigned, bits); |
| 1495 | .data = @intCast(u16, ty.bitSize(target)), | 1495 | try self.initType(int_ty, kind, lookup); |
| 1496 | }; | ||
| 1497 | try self.initType(Type.initPayload(&buf.base), kind, lookup); | ||
| 1498 | } | 1496 | } |
| 1499 | } else if (ty.isTupleOrAnonStruct()) { | 1497 | } else if (ty.isTupleOrAnonStruct()) { |
| 1500 | if (lookup.isMutable()) { | 1498 | if (lookup.isMutable()) { |
| ... | @@ -1505,7 +1503,7 @@ pub const CType = extern union { | ... | @@ -1505,7 +1503,7 @@ pub const CType = extern union { |
| 1505 | }) |field_i| { | 1503 | }) |field_i| { |
| 1506 | const field_ty = ty.structFieldType(field_i); | 1504 | const field_ty = ty.structFieldType(field_i); |
| 1507 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | 1505 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or |
| 1508 | !field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 1506 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1509 | _ = try lookup.typeToIndex(field_ty, switch (kind) { | 1507 | _ = try lookup.typeToIndex(field_ty, switch (kind) { |
| 1510 | .forward, .forward_parameter => .forward, | 1508 | .forward, .forward_parameter => .forward, |
| 1511 | .complete, .parameter => .complete, | 1509 | .complete, .parameter => .complete, |
| ... | @@ -1555,7 +1553,7 @@ pub const CType = extern union { | ... | @@ -1555,7 +1553,7 @@ pub const CType = extern union { |
| 1555 | self.storage.anon.fields[field_count] = .{ | 1553 | self.storage.anon.fields[field_count] = .{ |
| 1556 | .name = "payload", | 1554 | .name = "payload", |
| 1557 | .type = payload_idx.?, | 1555 | .type = payload_idx.?, |
| 1558 | .alignas = AlignAs.unionPayloadAlign(ty, target), | 1556 | .alignas = AlignAs.unionPayloadAlign(ty, mod), |
| 1559 | }; | 1557 | }; |
| 1560 | field_count += 1; | 1558 | field_count += 1; |
| 1561 | } | 1559 | } |
| ... | @@ -1563,7 +1561,7 @@ pub const CType = extern union { | ... | @@ -1563,7 +1561,7 @@ pub const CType = extern union { |
| 1563 | self.storage.anon.fields[field_count] = .{ | 1561 | self.storage.anon.fields[field_count] = .{ |
| 1564 | .name = "tag", | 1562 | .name = "tag", |
| 1565 | .type = tag_idx.?, | 1563 | .type = tag_idx.?, |
| 1566 | .alignas = AlignAs.abiAlign(tag_ty.?, target), | 1564 | .alignas = AlignAs.abiAlign(tag_ty.?, mod), |
| 1567 | }; | 1565 | }; |
| 1568 | field_count += 1; | 1566 | field_count += 1; |
| 1569 | } | 1567 | } |
| ... | @@ -1576,7 +1574,7 @@ pub const CType = extern union { | ... | @@ -1576,7 +1574,7 @@ pub const CType = extern union { |
| 1576 | } }; | 1574 | } }; |
| 1577 | self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) }; | 1575 | self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) }; |
| 1578 | } else self.init(.@"struct"); | 1576 | } else self.init(.@"struct"); |
| 1579 | } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes()) { | 1577 | } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes(mod)) { |
| 1580 | self.init(.void); | 1578 | self.init(.void); |
| 1581 | } else { | 1579 | } else { |
| 1582 | var is_packed = false; | 1580 | var is_packed = false; |
| ... | @@ -1586,9 +1584,9 @@ pub const CType = extern union { | ... | @@ -1586,9 +1584,9 @@ pub const CType = extern union { |
| 1586 | else => unreachable, | 1584 | else => unreachable, |
| 1587 | }) |field_i| { | 1585 | }) |field_i| { |
| 1588 | const field_ty = ty.structFieldType(field_i); | 1586 | const field_ty = ty.structFieldType(field_i); |
| 1589 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 1587 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1590 | 1588 | ||
| 1591 | const field_align = AlignAs.fieldAlign(ty, field_i, target); | 1589 | const field_align = AlignAs.fieldAlign(ty, field_i, mod); |
| 1592 | if (field_align.@"align" < field_align.abi) { | 1590 | if (field_align.@"align" < field_align.abi) { |
| 1593 | is_packed = true; | 1591 | is_packed = true; |
| 1594 | if (!lookup.isMutable()) break; | 1592 | if (!lookup.isMutable()) break; |
| ... | @@ -1643,8 +1641,8 @@ pub const CType = extern union { | ... | @@ -1643,8 +1641,8 @@ pub const CType = extern union { |
| 1643 | .Optional => { | 1641 | .Optional => { |
| 1644 | var buf: Type.Payload.ElemType = undefined; | 1642 | var buf: Type.Payload.ElemType = undefined; |
| 1645 | const payload_ty = ty.optionalChild(&buf); | 1643 | const payload_ty = ty.optionalChild(&buf); |
| 1646 | if (payload_ty.hasRuntimeBitsIgnoreComptime()) { | 1644 | if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1647 | if (ty.optionalReprIsPayload()) { | 1645 | if (ty.optionalReprIsPayload(mod)) { |
| 1648 | try self.initType(payload_ty, kind, lookup); | 1646 | try self.initType(payload_ty, kind, lookup); |
| 1649 | } else if (switch (kind) { | 1647 | } else if (switch (kind) { |
| 1650 | .forward, .forward_parameter => @as(Index, undefined), | 1648 | .forward, .forward_parameter => @as(Index, undefined), |
| ... | @@ -1661,12 +1659,12 @@ pub const CType = extern union { | ... | @@ -1661,12 +1659,12 @@ pub const CType = extern union { |
| 1661 | self.storage.anon.fields[0] = .{ | 1659 | self.storage.anon.fields[0] = .{ |
| 1662 | .name = "payload", | 1660 | .name = "payload", |
| 1663 | .type = payload_idx, | 1661 | .type = payload_idx, |
| 1664 | .alignas = AlignAs.abiAlign(payload_ty, target), | 1662 | .alignas = AlignAs.abiAlign(payload_ty, mod), |
| 1665 | }; | 1663 | }; |
| 1666 | self.storage.anon.fields[1] = .{ | 1664 | self.storage.anon.fields[1] = .{ |
| 1667 | .name = "is_null", | 1665 | .name = "is_null", |
| 1668 | .type = Tag.bool.toIndex(), | 1666 | .type = Tag.bool.toIndex(), |
| 1669 | .alignas = AlignAs.abiAlign(Type.bool, target), | 1667 | .alignas = AlignAs.abiAlign(Type.bool, mod), |
| 1670 | }; | 1668 | }; |
| 1671 | self.initAnon(kind, fwd_idx, 2); | 1669 | self.initAnon(kind, fwd_idx, 2); |
| 1672 | } else self.init(switch (kind) { | 1670 | } else self.init(switch (kind) { |
| ... | @@ -1699,12 +1697,12 @@ pub const CType = extern union { | ... | @@ -1699,12 +1697,12 @@ pub const CType = extern union { |
| 1699 | self.storage.anon.fields[0] = .{ | 1697 | self.storage.anon.fields[0] = .{ |
| 1700 | .name = "payload", | 1698 | .name = "payload", |
| 1701 | .type = payload_idx, | 1699 | .type = payload_idx, |
| 1702 | .alignas = AlignAs.abiAlign(payload_ty, target), | 1700 | .alignas = AlignAs.abiAlign(payload_ty, mod), |
| 1703 | }; | 1701 | }; |
| 1704 | self.storage.anon.fields[1] = .{ | 1702 | self.storage.anon.fields[1] = .{ |
| 1705 | .name = "error", | 1703 | .name = "error", |
| 1706 | .type = error_idx, | 1704 | .type = error_idx, |
| 1707 | .alignas = AlignAs.abiAlign(error_ty, target), | 1705 | .alignas = AlignAs.abiAlign(error_ty, mod), |
| 1708 | }; | 1706 | }; |
| 1709 | self.initAnon(kind, fwd_idx, 2); | 1707 | self.initAnon(kind, fwd_idx, 2); |
| 1710 | } else self.init(switch (kind) { | 1708 | } else self.init(switch (kind) { |
| ... | @@ -1733,7 +1731,7 @@ pub const CType = extern union { | ... | @@ -1733,7 +1731,7 @@ pub const CType = extern union { |
| 1733 | }; | 1731 | }; |
| 1734 | _ = try lookup.typeToIndex(info.return_type, param_kind); | 1732 | _ = try lookup.typeToIndex(info.return_type, param_kind); |
| 1735 | for (info.param_types) |param_type| { | 1733 | for (info.param_types) |param_type| { |
| 1736 | if (!param_type.hasRuntimeBitsIgnoreComptime()) continue; | 1734 | if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1737 | _ = try lookup.typeToIndex(param_type, param_kind); | 1735 | _ = try lookup.typeToIndex(param_type, param_kind); |
| 1738 | } | 1736 | } |
| 1739 | } | 1737 | } |
| ... | @@ -1900,16 +1898,16 @@ pub const CType = extern union { | ... | @@ -1900,16 +1898,16 @@ pub const CType = extern union { |
| 1900 | } | 1898 | } |
| 1901 | } | 1899 | } |
| 1902 | 1900 | ||
| 1903 | fn createFromType(store: *Store.Promoted, ty: Type, target: Target, kind: Kind) !CType { | 1901 | fn createFromType(store: *Store.Promoted, ty: Type, mod: *const Module, kind: Kind) !CType { |
| 1904 | var convert: Convert = undefined; | 1902 | var convert: Convert = undefined; |
| 1905 | try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .target = target } }); | 1903 | try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .mod = mod } }); |
| 1906 | return createFromConvert(store, ty, target, kind, &convert); | 1904 | return createFromConvert(store, ty, mod, kind, &convert); |
| 1907 | } | 1905 | } |
| 1908 | 1906 | ||
| 1909 | fn createFromConvert( | 1907 | fn createFromConvert( |
| 1910 | store: *Store.Promoted, | 1908 | store: *Store.Promoted, |
| 1911 | ty: Type, | 1909 | ty: Type, |
| 1912 | target: Target, | 1910 | mod: *Module, |
| 1913 | kind: Kind, | 1911 | kind: Kind, |
| 1914 | convert: Convert, | 1912 | convert: Convert, |
| 1915 | ) !CType { | 1913 | ) !CType { |
| ... | @@ -1930,7 +1928,7 @@ pub const CType = extern union { | ... | @@ -1930,7 +1928,7 @@ pub const CType = extern union { |
| 1930 | .packed_struct, | 1928 | .packed_struct, |
| 1931 | .packed_union, | 1929 | .packed_union, |
| 1932 | => { | 1930 | => { |
| 1933 | const zig_ty_tag = ty.zigTypeTag(); | 1931 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 1934 | const fields_len = switch (zig_ty_tag) { | 1932 | const fields_len = switch (zig_ty_tag) { |
| 1935 | .Struct => ty.structFieldCount(), | 1933 | .Struct => ty.structFieldCount(), |
| 1936 | .Union => ty.unionFields().count(), | 1934 | .Union => ty.unionFields().count(), |
| ... | @@ -1941,7 +1939,7 @@ pub const CType = extern union { | ... | @@ -1941,7 +1939,7 @@ pub const CType = extern union { |
| 1941 | for (0..fields_len) |field_i| { | 1939 | for (0..fields_len) |field_i| { |
| 1942 | const field_ty = ty.structFieldType(field_i); | 1940 | const field_ty = ty.structFieldType(field_i); |
| 1943 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | 1941 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or |
| 1944 | !field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 1942 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1945 | c_fields_len += 1; | 1943 | c_fields_len += 1; |
| 1946 | } | 1944 | } |
| 1947 | 1945 | ||
| ... | @@ -1950,7 +1948,7 @@ pub const CType = extern union { | ... | @@ -1950,7 +1948,7 @@ pub const CType = extern union { |
| 1950 | for (0..fields_len) |field_i| { | 1948 | for (0..fields_len) |field_i| { |
| 1951 | const field_ty = ty.structFieldType(field_i); | 1949 | const field_ty = ty.structFieldType(field_i); |
| 1952 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | 1950 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or |
| 1953 | !field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 1951 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 1954 | 1952 | ||
| 1955 | defer c_field_i += 1; | 1953 | defer c_field_i += 1; |
| 1956 | fields_pl[c_field_i] = .{ | 1954 | fields_pl[c_field_i] = .{ |
| ... | @@ -1962,12 +1960,12 @@ pub const CType = extern union { | ... | @@ -1962,12 +1960,12 @@ pub const CType = extern union { |
| 1962 | .Union => ty.unionFields().keys()[field_i], | 1960 | .Union => ty.unionFields().keys()[field_i], |
| 1963 | else => unreachable, | 1961 | else => unreachable, |
| 1964 | }), | 1962 | }), |
| 1965 | .type = store.set.typeToIndex(field_ty, target, switch (kind) { | 1963 | .type = store.set.typeToIndex(field_ty, mod, switch (kind) { |
| 1966 | .forward, .forward_parameter => .forward, | 1964 | .forward, .forward_parameter => .forward, |
| 1967 | .complete, .parameter, .payload => .complete, | 1965 | .complete, .parameter, .payload => .complete, |
| 1968 | .global => .global, | 1966 | .global => .global, |
| 1969 | }).?, | 1967 | }).?, |
| 1970 | .alignas = AlignAs.fieldAlign(ty, field_i, target), | 1968 | .alignas = AlignAs.fieldAlign(ty, field_i, mod), |
| 1971 | }; | 1969 | }; |
| 1972 | } | 1970 | } |
| 1973 | 1971 | ||
| ... | @@ -2004,7 +2002,7 @@ pub const CType = extern union { | ... | @@ -2004,7 +2002,7 @@ pub const CType = extern union { |
| 2004 | const struct_pl = try arena.create(Payload.Aggregate); | 2002 | const struct_pl = try arena.create(Payload.Aggregate); |
| 2005 | struct_pl.* = .{ .base = .{ .tag = t }, .data = .{ | 2003 | struct_pl.* = .{ .base = .{ .tag = t }, .data = .{ |
| 2006 | .fields = fields_pl, | 2004 | .fields = fields_pl, |
| 2007 | .fwd_decl = store.set.typeToIndex(ty, target, .forward).?, | 2005 | .fwd_decl = store.set.typeToIndex(ty, mod, .forward).?, |
| 2008 | } }; | 2006 | } }; |
| 2009 | return initPayload(struct_pl); | 2007 | return initPayload(struct_pl); |
| 2010 | }, | 2008 | }, |
| ... | @@ -2026,21 +2024,21 @@ pub const CType = extern union { | ... | @@ -2026,21 +2024,21 @@ pub const CType = extern union { |
| 2026 | 2024 | ||
| 2027 | var c_params_len: usize = 0; | 2025 | var c_params_len: usize = 0; |
| 2028 | for (info.param_types) |param_type| { | 2026 | for (info.param_types) |param_type| { |
| 2029 | if (!param_type.hasRuntimeBitsIgnoreComptime()) continue; | 2027 | if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2030 | c_params_len += 1; | 2028 | c_params_len += 1; |
| 2031 | } | 2029 | } |
| 2032 | 2030 | ||
| 2033 | const params_pl = try arena.alloc(Index, c_params_len); | 2031 | const params_pl = try arena.alloc(Index, c_params_len); |
| 2034 | var c_param_i: usize = 0; | 2032 | var c_param_i: usize = 0; |
| 2035 | for (info.param_types) |param_type| { | 2033 | for (info.param_types) |param_type| { |
| 2036 | if (!param_type.hasRuntimeBitsIgnoreComptime()) continue; | 2034 | if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2037 | params_pl[c_param_i] = store.set.typeToIndex(param_type, target, param_kind).?; | 2035 | params_pl[c_param_i] = store.set.typeToIndex(param_type, mod, param_kind).?; |
| 2038 | c_param_i += 1; | 2036 | c_param_i += 1; |
| 2039 | } | 2037 | } |
| 2040 | 2038 | ||
| 2041 | const fn_pl = try arena.create(Payload.Function); | 2039 | const fn_pl = try arena.create(Payload.Function); |
| 2042 | fn_pl.* = .{ .base = .{ .tag = t }, .data = .{ | 2040 | fn_pl.* = .{ .base = .{ .tag = t }, .data = .{ |
| 2043 | .return_type = store.set.typeToIndex(info.return_type, target, param_kind).?, | 2041 | .return_type = store.set.typeToIndex(info.return_type, mod, param_kind).?, |
| 2044 | .param_types = params_pl, | 2042 | .param_types = params_pl, |
| 2045 | } }; | 2043 | } }; |
| 2046 | return initPayload(fn_pl); | 2044 | return initPayload(fn_pl); |
| ... | @@ -2067,12 +2065,12 @@ pub const CType = extern union { | ... | @@ -2067,12 +2065,12 @@ pub const CType = extern union { |
| 2067 | } | 2065 | } |
| 2068 | 2066 | ||
| 2069 | pub fn eql(self: @This(), ty: Type, cty: CType) bool { | 2067 | pub fn eql(self: @This(), ty: Type, cty: CType) bool { |
| 2068 | const mod = self.lookup.getModule(); | ||
| 2070 | switch (self.convert.value) { | 2069 | switch (self.convert.value) { |
| 2071 | .cty => |c| return c.eql(cty), | 2070 | .cty => |c| return c.eql(cty), |
| 2072 | .tag => |t| { | 2071 | .tag => |t| { |
| 2073 | if (t != cty.tag()) return false; | 2072 | if (t != cty.tag()) return false; |
| 2074 | 2073 | ||
| 2075 | const target = self.lookup.getTarget(); | ||
| 2076 | switch (t) { | 2074 | switch (t) { |
| 2077 | .fwd_anon_struct, | 2075 | .fwd_anon_struct, |
| 2078 | .fwd_anon_union, | 2076 | .fwd_anon_union, |
| ... | @@ -2084,7 +2082,7 @@ pub const CType = extern union { | ... | @@ -2084,7 +2082,7 @@ pub const CType = extern union { |
| 2084 | ]u8 = undefined; | 2082 | ]u8 = undefined; |
| 2085 | const c_fields = cty.cast(Payload.Fields).?.data; | 2083 | const c_fields = cty.cast(Payload.Fields).?.data; |
| 2086 | 2084 | ||
| 2087 | const zig_ty_tag = ty.zigTypeTag(); | 2085 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 2088 | var c_field_i: usize = 0; | 2086 | var c_field_i: usize = 0; |
| 2089 | for (0..switch (zig_ty_tag) { | 2087 | for (0..switch (zig_ty_tag) { |
| 2090 | .Struct => ty.structFieldCount(), | 2088 | .Struct => ty.structFieldCount(), |
| ... | @@ -2093,7 +2091,7 @@ pub const CType = extern union { | ... | @@ -2093,7 +2091,7 @@ pub const CType = extern union { |
| 2093 | }) |field_i| { | 2091 | }) |field_i| { |
| 2094 | const field_ty = ty.structFieldType(field_i); | 2092 | const field_ty = ty.structFieldType(field_i); |
| 2095 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | 2093 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or |
| 2096 | !field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 2094 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2097 | 2095 | ||
| 2098 | defer c_field_i += 1; | 2096 | defer c_field_i += 1; |
| 2099 | const c_field = &c_fields[c_field_i]; | 2097 | const c_field = &c_fields[c_field_i]; |
| ... | @@ -2113,7 +2111,7 @@ pub const CType = extern union { | ... | @@ -2113,7 +2111,7 @@ pub const CType = extern union { |
| 2113 | else => unreachable, | 2111 | else => unreachable, |
| 2114 | }, | 2112 | }, |
| 2115 | mem.span(c_field.name), | 2113 | mem.span(c_field.name), |
| 2116 | ) or AlignAs.fieldAlign(ty, field_i, target).@"align" != | 2114 | ) or AlignAs.fieldAlign(ty, field_i, mod).@"align" != |
| 2117 | c_field.alignas.@"align") return false; | 2115 | c_field.alignas.@"align") return false; |
| 2118 | } | 2116 | } |
| 2119 | return true; | 2117 | return true; |
| ... | @@ -2146,7 +2144,7 @@ pub const CType = extern union { | ... | @@ -2146,7 +2144,7 @@ pub const CType = extern union { |
| 2146 | .function, | 2144 | .function, |
| 2147 | .varargs_function, | 2145 | .varargs_function, |
| 2148 | => { | 2146 | => { |
| 2149 | if (ty.zigTypeTag() != .Fn) return false; | 2147 | if (ty.zigTypeTag(mod) != .Fn) return false; |
| 2150 | 2148 | ||
| 2151 | const info = ty.fnInfo(); | 2149 | const info = ty.fnInfo(); |
| 2152 | assert(!info.is_generic); | 2150 | assert(!info.is_generic); |
| ... | @@ -2162,7 +2160,7 @@ pub const CType = extern union { | ... | @@ -2162,7 +2160,7 @@ pub const CType = extern union { |
| 2162 | 2160 | ||
| 2163 | var c_param_i: usize = 0; | 2161 | var c_param_i: usize = 0; |
| 2164 | for (info.param_types) |param_type| { | 2162 | for (info.param_types) |param_type| { |
| 2165 | if (!param_type.hasRuntimeBitsIgnoreComptime()) continue; | 2163 | if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2166 | 2164 | ||
| 2167 | if (c_param_i >= data.param_types.len) return false; | 2165 | if (c_param_i >= data.param_types.len) return false; |
| 2168 | const param_cty = data.param_types[c_param_i]; | 2166 | const param_cty = data.param_types[c_param_i]; |
| ... | @@ -2202,7 +2200,7 @@ pub const CType = extern union { | ... | @@ -2202,7 +2200,7 @@ pub const CType = extern union { |
| 2202 | .tag => |t| { | 2200 | .tag => |t| { |
| 2203 | autoHash(hasher, t); | 2201 | autoHash(hasher, t); |
| 2204 | 2202 | ||
| 2205 | const target = self.lookup.getTarget(); | 2203 | const mod = self.lookup.getModule(); |
| 2206 | switch (t) { | 2204 | switch (t) { |
| 2207 | .fwd_anon_struct, | 2205 | .fwd_anon_struct, |
| 2208 | .fwd_anon_union, | 2206 | .fwd_anon_union, |
| ... | @@ -2211,15 +2209,15 @@ pub const CType = extern union { | ... | @@ -2211,15 +2209,15 @@ pub const CType = extern union { |
| 2211 | std.fmt.count("f{}", .{std.math.maxInt(usize)}) | 2209 | std.fmt.count("f{}", .{std.math.maxInt(usize)}) |
| 2212 | ]u8 = undefined; | 2210 | ]u8 = undefined; |
| 2213 | 2211 | ||
| 2214 | const zig_ty_tag = ty.zigTypeTag(); | 2212 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 2215 | for (0..switch (ty.zigTypeTag()) { | 2213 | for (0..switch (ty.zigTypeTag(mod)) { |
| 2216 | .Struct => ty.structFieldCount(), | 2214 | .Struct => ty.structFieldCount(), |
| 2217 | .Union => ty.unionFields().count(), | 2215 | .Union => ty.unionFields().count(), |
| 2218 | else => unreachable, | 2216 | else => unreachable, |
| 2219 | }) |field_i| { | 2217 | }) |field_i| { |
| 2220 | const field_ty = ty.structFieldType(field_i); | 2218 | const field_ty = ty.structFieldType(field_i); |
| 2221 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or | 2219 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or |
| 2222 | !field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 2220 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2223 | 2221 | ||
| 2224 | self.updateHasherRecurse(hasher, field_ty, switch (self.kind) { | 2222 | self.updateHasherRecurse(hasher, field_ty, switch (self.kind) { |
| 2225 | .forward, .forward_parameter => .forward, | 2223 | .forward, .forward_parameter => .forward, |
| ... | @@ -2234,7 +2232,7 @@ pub const CType = extern union { | ... | @@ -2234,7 +2232,7 @@ pub const CType = extern union { |
| 2234 | .Union => ty.unionFields().keys()[field_i], | 2232 | .Union => ty.unionFields().keys()[field_i], |
| 2235 | else => unreachable, | 2233 | else => unreachable, |
| 2236 | }); | 2234 | }); |
| 2237 | autoHash(hasher, AlignAs.fieldAlign(ty, field_i, target).@"align"); | 2235 | autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align"); |
| 2238 | } | 2236 | } |
| 2239 | }, | 2237 | }, |
| 2240 | 2238 | ||
| ... | @@ -2271,7 +2269,7 @@ pub const CType = extern union { | ... | @@ -2271,7 +2269,7 @@ pub const CType = extern union { |
| 2271 | 2269 | ||
| 2272 | self.updateHasherRecurse(hasher, info.return_type, param_kind); | 2270 | self.updateHasherRecurse(hasher, info.return_type, param_kind); |
| 2273 | for (info.param_types) |param_type| { | 2271 | for (info.param_types) |param_type| { |
| 2274 | if (!param_type.hasRuntimeBitsIgnoreComptime()) continue; | 2272 | if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2275 | self.updateHasherRecurse(hasher, param_type, param_kind); | 2273 | self.updateHasherRecurse(hasher, param_type, param_kind); |
| 2276 | } | 2274 | } |
| 2277 | }, | 2275 | }, |
src/codegen/llvm.zig+812-745| ... | @@ -598,7 +598,7 @@ pub const Object = struct { | ... | @@ -598,7 +598,7 @@ pub const Object = struct { |
| 598 | }; | 598 | }; |
| 599 | const llvm_slice_ty = self.context.structType(&type_fields, type_fields.len, .False); | 599 | const llvm_slice_ty = self.context.structType(&type_fields, type_fields.len, .False); |
| 600 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); | 600 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 601 | const slice_alignment = slice_ty.abiAlignment(target); | 601 | const slice_alignment = slice_ty.abiAlignment(mod); |
| 602 | 602 | ||
| 603 | const error_name_list = mod.error_name_list.items; | 603 | const error_name_list = mod.error_name_list.items; |
| 604 | const llvm_errors = try mod.gpa.alloc(*llvm.Value, error_name_list.len); | 604 | const llvm_errors = try mod.gpa.alloc(*llvm.Value, error_name_list.len); |
| ... | @@ -880,28 +880,28 @@ pub const Object = struct { | ... | @@ -880,28 +880,28 @@ pub const Object = struct { |
| 880 | 880 | ||
| 881 | pub fn updateFunc( | 881 | pub fn updateFunc( |
| 882 | o: *Object, | 882 | o: *Object, |
| 883 | module: *Module, | 883 | mod: *Module, |
| 884 | func: *Module.Fn, | 884 | func: *Module.Fn, |
| 885 | air: Air, | 885 | air: Air, |
| 886 | liveness: Liveness, | 886 | liveness: Liveness, |
| 887 | ) !void { | 887 | ) !void { |
| 888 | const decl_index = func.owner_decl; | 888 | const decl_index = func.owner_decl; |
| 889 | const decl = module.declPtr(decl_index); | 889 | const decl = mod.declPtr(decl_index); |
| 890 | const target = module.getTarget(); | 890 | const target = mod.getTarget(); |
| 891 | 891 | ||
| 892 | var dg: DeclGen = .{ | 892 | var dg: DeclGen = .{ |
| 893 | .context = o.context, | 893 | .context = o.context, |
| 894 | .object = o, | 894 | .object = o, |
| 895 | .module = module, | 895 | .module = mod, |
| 896 | .decl_index = decl_index, | 896 | .decl_index = decl_index, |
| 897 | .decl = decl, | 897 | .decl = decl, |
| 898 | .err_msg = null, | 898 | .err_msg = null, |
| 899 | .gpa = module.gpa, | 899 | .gpa = mod.gpa, |
| 900 | }; | 900 | }; |
| 901 | 901 | ||
| 902 | const llvm_func = try dg.resolveLlvmFunction(decl_index); | 902 | const llvm_func = try dg.resolveLlvmFunction(decl_index); |
| 903 | 903 | ||
| 904 | if (module.align_stack_fns.get(func)) |align_info| { | 904 | if (mod.align_stack_fns.get(func)) |align_info| { |
| 905 | dg.addFnAttrInt(llvm_func, "alignstack", align_info.alignment); | 905 | dg.addFnAttrInt(llvm_func, "alignstack", align_info.alignment); |
| 906 | dg.addFnAttr(llvm_func, "noinline"); | 906 | dg.addFnAttr(llvm_func, "noinline"); |
| 907 | } else { | 907 | } else { |
| ... | @@ -922,7 +922,7 @@ pub const Object = struct { | ... | @@ -922,7 +922,7 @@ pub const Object = struct { |
| 922 | } | 922 | } |
| 923 | 923 | ||
| 924 | // TODO: disable this if safety is off for the function scope | 924 | // TODO: disable this if safety is off for the function scope |
| 925 | const ssp_buf_size = module.comp.bin_file.options.stack_protector; | 925 | const ssp_buf_size = mod.comp.bin_file.options.stack_protector; |
| 926 | if (ssp_buf_size != 0) { | 926 | if (ssp_buf_size != 0) { |
| 927 | var buf: [12]u8 = undefined; | 927 | var buf: [12]u8 = undefined; |
| 928 | const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable; | 928 | const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable; |
| ... | @@ -931,7 +931,7 @@ pub const Object = struct { | ... | @@ -931,7 +931,7 @@ pub const Object = struct { |
| 931 | } | 931 | } |
| 932 | 932 | ||
| 933 | // TODO: disable this if safety is off for the function scope | 933 | // TODO: disable this if safety is off for the function scope |
| 934 | if (module.comp.bin_file.options.stack_check) { | 934 | if (mod.comp.bin_file.options.stack_check) { |
| 935 | dg.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack"); | 935 | dg.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack"); |
| 936 | } else if (target.os.tag == .uefi) { | 936 | } else if (target.os.tag == .uefi) { |
| 937 | dg.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); | 937 | dg.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); |
| ... | @@ -954,17 +954,17 @@ pub const Object = struct { | ... | @@ -954,17 +954,17 @@ pub const Object = struct { |
| 954 | 954 | ||
| 955 | // This gets the LLVM values from the function and stores them in `dg.args`. | 955 | // This gets the LLVM values from the function and stores them in `dg.args`. |
| 956 | const fn_info = decl.ty.fnInfo(); | 956 | const fn_info = decl.ty.fnInfo(); |
| 957 | const sret = firstParamSRet(fn_info, target); | 957 | const sret = firstParamSRet(fn_info, mod); |
| 958 | const ret_ptr = if (sret) llvm_func.getParam(0) else null; | 958 | const ret_ptr = if (sret) llvm_func.getParam(0) else null; |
| 959 | const gpa = dg.gpa; | 959 | const gpa = dg.gpa; |
| 960 | 960 | ||
| 961 | if (ccAbiPromoteInt(fn_info.cc, target, fn_info.return_type)) |s| switch (s) { | 961 | if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type)) |s| switch (s) { |
| 962 | .signed => dg.addAttr(llvm_func, 0, "signext"), | 962 | .signed => dg.addAttr(llvm_func, 0, "signext"), |
| 963 | .unsigned => dg.addAttr(llvm_func, 0, "zeroext"), | 963 | .unsigned => dg.addAttr(llvm_func, 0, "zeroext"), |
| 964 | }; | 964 | }; |
| 965 | 965 | ||
| 966 | const err_return_tracing = fn_info.return_type.isError() and | 966 | const err_return_tracing = fn_info.return_type.isError(mod) and |
| 967 | module.comp.bin_file.options.error_return_tracing; | 967 | mod.comp.bin_file.options.error_return_tracing; |
| 968 | 968 | ||
| 969 | const err_ret_trace = if (err_return_tracing) | 969 | const err_ret_trace = if (err_return_tracing) |
| 970 | llvm_func.getParam(@boolToInt(ret_ptr != null)) | 970 | llvm_func.getParam(@boolToInt(ret_ptr != null)) |
| ... | @@ -989,8 +989,8 @@ pub const Object = struct { | ... | @@ -989,8 +989,8 @@ pub const Object = struct { |
| 989 | const param = llvm_func.getParam(llvm_arg_i); | 989 | const param = llvm_func.getParam(llvm_arg_i); |
| 990 | try args.ensureUnusedCapacity(1); | 990 | try args.ensureUnusedCapacity(1); |
| 991 | 991 | ||
| 992 | if (isByRef(param_ty)) { | 992 | if (isByRef(param_ty, mod)) { |
| 993 | const alignment = param_ty.abiAlignment(target); | 993 | const alignment = param_ty.abiAlignment(mod); |
| 994 | const param_llvm_ty = param.typeOf(); | 994 | const param_llvm_ty = param.typeOf(); |
| 995 | const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); | 995 | const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 996 | const store_inst = builder.buildStore(param, arg_ptr); | 996 | const store_inst = builder.buildStore(param, arg_ptr); |
| ... | @@ -1007,14 +1007,14 @@ pub const Object = struct { | ... | @@ -1007,14 +1007,14 @@ pub const Object = struct { |
| 1007 | const param_ty = fn_info.param_types[it.zig_index - 1]; | 1007 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 1008 | const param_llvm_ty = try dg.lowerType(param_ty); | 1008 | const param_llvm_ty = try dg.lowerType(param_ty); |
| 1009 | const param = llvm_func.getParam(llvm_arg_i); | 1009 | const param = llvm_func.getParam(llvm_arg_i); |
| 1010 | const alignment = param_ty.abiAlignment(target); | 1010 | const alignment = param_ty.abiAlignment(mod); |
| 1011 | 1011 | ||
| 1012 | dg.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); | 1012 | dg.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); |
| 1013 | llvm_arg_i += 1; | 1013 | llvm_arg_i += 1; |
| 1014 | 1014 | ||
| 1015 | try args.ensureUnusedCapacity(1); | 1015 | try args.ensureUnusedCapacity(1); |
| 1016 | 1016 | ||
| 1017 | if (isByRef(param_ty)) { | 1017 | if (isByRef(param_ty, mod)) { |
| 1018 | args.appendAssumeCapacity(param); | 1018 | args.appendAssumeCapacity(param); |
| 1019 | } else { | 1019 | } else { |
| 1020 | const load_inst = builder.buildLoad(param_llvm_ty, param, ""); | 1020 | const load_inst = builder.buildLoad(param_llvm_ty, param, ""); |
| ... | @@ -1026,14 +1026,14 @@ pub const Object = struct { | ... | @@ -1026,14 +1026,14 @@ pub const Object = struct { |
| 1026 | const param_ty = fn_info.param_types[it.zig_index - 1]; | 1026 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 1027 | const param_llvm_ty = try dg.lowerType(param_ty); | 1027 | const param_llvm_ty = try dg.lowerType(param_ty); |
| 1028 | const param = llvm_func.getParam(llvm_arg_i); | 1028 | const param = llvm_func.getParam(llvm_arg_i); |
| 1029 | const alignment = param_ty.abiAlignment(target); | 1029 | const alignment = param_ty.abiAlignment(mod); |
| 1030 | 1030 | ||
| 1031 | dg.addArgAttr(llvm_func, llvm_arg_i, "noundef"); | 1031 | dg.addArgAttr(llvm_func, llvm_arg_i, "noundef"); |
| 1032 | llvm_arg_i += 1; | 1032 | llvm_arg_i += 1; |
| 1033 | 1033 | ||
| 1034 | try args.ensureUnusedCapacity(1); | 1034 | try args.ensureUnusedCapacity(1); |
| 1035 | 1035 | ||
| 1036 | if (isByRef(param_ty)) { | 1036 | if (isByRef(param_ty, mod)) { |
| 1037 | args.appendAssumeCapacity(param); | 1037 | args.appendAssumeCapacity(param); |
| 1038 | } else { | 1038 | } else { |
| 1039 | const load_inst = builder.buildLoad(param_llvm_ty, param, ""); | 1039 | const load_inst = builder.buildLoad(param_llvm_ty, param, ""); |
| ... | @@ -1048,10 +1048,10 @@ pub const Object = struct { | ... | @@ -1048,10 +1048,10 @@ pub const Object = struct { |
| 1048 | llvm_arg_i += 1; | 1048 | llvm_arg_i += 1; |
| 1049 | 1049 | ||
| 1050 | const param_llvm_ty = try dg.lowerType(param_ty); | 1050 | const param_llvm_ty = try dg.lowerType(param_ty); |
| 1051 | const abi_size = @intCast(c_uint, param_ty.abiSize(target)); | 1051 | const abi_size = @intCast(c_uint, param_ty.abiSize(mod)); |
| 1052 | const int_llvm_ty = dg.context.intType(abi_size * 8); | 1052 | const int_llvm_ty = dg.context.intType(abi_size * 8); |
| 1053 | const alignment = @max( | 1053 | const alignment = @max( |
| 1054 | param_ty.abiAlignment(target), | 1054 | param_ty.abiAlignment(mod), |
| 1055 | dg.object.target_data.abiAlignmentOfType(int_llvm_ty), | 1055 | dg.object.target_data.abiAlignmentOfType(int_llvm_ty), |
| 1056 | ); | 1056 | ); |
| 1057 | const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); | 1057 | const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); |
| ... | @@ -1060,7 +1060,7 @@ pub const Object = struct { | ... | @@ -1060,7 +1060,7 @@ pub const Object = struct { |
| 1060 | 1060 | ||
| 1061 | try args.ensureUnusedCapacity(1); | 1061 | try args.ensureUnusedCapacity(1); |
| 1062 | 1062 | ||
| 1063 | if (isByRef(param_ty)) { | 1063 | if (isByRef(param_ty, mod)) { |
| 1064 | args.appendAssumeCapacity(arg_ptr); | 1064 | args.appendAssumeCapacity(arg_ptr); |
| 1065 | } else { | 1065 | } else { |
| 1066 | const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); | 1066 | const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); |
| ... | @@ -1078,7 +1078,7 @@ pub const Object = struct { | ... | @@ -1078,7 +1078,7 @@ pub const Object = struct { |
| 1078 | dg.addArgAttr(llvm_func, llvm_arg_i, "noalias"); | 1078 | dg.addArgAttr(llvm_func, llvm_arg_i, "noalias"); |
| 1079 | } | 1079 | } |
| 1080 | } | 1080 | } |
| 1081 | if (param_ty.zigTypeTag() != .Optional) { | 1081 | if (param_ty.zigTypeTag(mod) != .Optional) { |
| 1082 | dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); | 1082 | dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); |
| 1083 | } | 1083 | } |
| 1084 | if (!ptr_info.mutable) { | 1084 | if (!ptr_info.mutable) { |
| ... | @@ -1087,7 +1087,7 @@ pub const Object = struct { | ... | @@ -1087,7 +1087,7 @@ pub const Object = struct { |
| 1087 | if (ptr_info.@"align" != 0) { | 1087 | if (ptr_info.@"align" != 0) { |
| 1088 | dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align"); | 1088 | dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align"); |
| 1089 | } else { | 1089 | } else { |
| 1090 | const elem_align = @max(ptr_info.pointee_type.abiAlignment(target), 1); | 1090 | const elem_align = @max(ptr_info.pointee_type.abiAlignment(mod), 1); |
| 1091 | dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align); | 1091 | dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align); |
| 1092 | } | 1092 | } |
| 1093 | const ptr_param = llvm_func.getParam(llvm_arg_i); | 1093 | const ptr_param = llvm_func.getParam(llvm_arg_i); |
| ... | @@ -1105,7 +1105,7 @@ pub const Object = struct { | ... | @@ -1105,7 +1105,7 @@ pub const Object = struct { |
| 1105 | const field_types = it.llvm_types_buffer[0..it.llvm_types_len]; | 1105 | const field_types = it.llvm_types_buffer[0..it.llvm_types_len]; |
| 1106 | const param_ty = fn_info.param_types[it.zig_index - 1]; | 1106 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 1107 | const param_llvm_ty = try dg.lowerType(param_ty); | 1107 | const param_llvm_ty = try dg.lowerType(param_ty); |
| 1108 | const param_alignment = param_ty.abiAlignment(target); | 1108 | const param_alignment = param_ty.abiAlignment(mod); |
| 1109 | const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target); | 1109 | const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target); |
| 1110 | const llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); | 1110 | const llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); |
| 1111 | for (field_types, 0..) |_, field_i_usize| { | 1111 | for (field_types, 0..) |_, field_i_usize| { |
| ... | @@ -1117,7 +1117,7 @@ pub const Object = struct { | ... | @@ -1117,7 +1117,7 @@ pub const Object = struct { |
| 1117 | store_inst.setAlignment(target.ptrBitWidth() / 8); | 1117 | store_inst.setAlignment(target.ptrBitWidth() / 8); |
| 1118 | } | 1118 | } |
| 1119 | 1119 | ||
| 1120 | const is_by_ref = isByRef(param_ty); | 1120 | const is_by_ref = isByRef(param_ty, mod); |
| 1121 | const loaded = if (is_by_ref) arg_ptr else l: { | 1121 | const loaded = if (is_by_ref) arg_ptr else l: { |
| 1122 | const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); | 1122 | const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); |
| 1123 | load_inst.setAlignment(param_alignment); | 1123 | load_inst.setAlignment(param_alignment); |
| ... | @@ -1139,11 +1139,11 @@ pub const Object = struct { | ... | @@ -1139,11 +1139,11 @@ pub const Object = struct { |
| 1139 | const param = llvm_func.getParam(llvm_arg_i); | 1139 | const param = llvm_func.getParam(llvm_arg_i); |
| 1140 | llvm_arg_i += 1; | 1140 | llvm_arg_i += 1; |
| 1141 | 1141 | ||
| 1142 | const alignment = param_ty.abiAlignment(target); | 1142 | const alignment = param_ty.abiAlignment(mod); |
| 1143 | const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); | 1143 | const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 1144 | _ = builder.buildStore(param, arg_ptr); | 1144 | _ = builder.buildStore(param, arg_ptr); |
| 1145 | 1145 | ||
| 1146 | if (isByRef(param_ty)) { | 1146 | if (isByRef(param_ty, mod)) { |
| 1147 | try args.append(arg_ptr); | 1147 | try args.append(arg_ptr); |
| 1148 | } else { | 1148 | } else { |
| 1149 | const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); | 1149 | const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); |
| ... | @@ -1157,11 +1157,11 @@ pub const Object = struct { | ... | @@ -1157,11 +1157,11 @@ pub const Object = struct { |
| 1157 | const param = llvm_func.getParam(llvm_arg_i); | 1157 | const param = llvm_func.getParam(llvm_arg_i); |
| 1158 | llvm_arg_i += 1; | 1158 | llvm_arg_i += 1; |
| 1159 | 1159 | ||
| 1160 | const alignment = param_ty.abiAlignment(target); | 1160 | const alignment = param_ty.abiAlignment(mod); |
| 1161 | const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); | 1161 | const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 1162 | _ = builder.buildStore(param, arg_ptr); | 1162 | _ = builder.buildStore(param, arg_ptr); |
| 1163 | 1163 | ||
| 1164 | if (isByRef(param_ty)) { | 1164 | if (isByRef(param_ty, mod)) { |
| 1165 | try args.append(arg_ptr); | 1165 | try args.append(arg_ptr); |
| 1166 | } else { | 1166 | } else { |
| 1167 | const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); | 1167 | const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); |
| ... | @@ -1180,7 +1180,7 @@ pub const Object = struct { | ... | @@ -1180,7 +1180,7 @@ pub const Object = struct { |
| 1180 | 1180 | ||
| 1181 | const line_number = decl.src_line + 1; | 1181 | const line_number = decl.src_line + 1; |
| 1182 | const is_internal_linkage = decl.val.tag() != .extern_fn and | 1182 | const is_internal_linkage = decl.val.tag() != .extern_fn and |
| 1183 | !module.decl_exports.contains(decl_index); | 1183 | !mod.decl_exports.contains(decl_index); |
| 1184 | const noret_bit: c_uint = if (fn_info.return_type.isNoReturn()) | 1184 | const noret_bit: c_uint = if (fn_info.return_type.isNoReturn()) |
| 1185 | llvm.DIFlags.NoReturn | 1185 | llvm.DIFlags.NoReturn |
| 1186 | else | 1186 | else |
| ... | @@ -1196,7 +1196,7 @@ pub const Object = struct { | ... | @@ -1196,7 +1196,7 @@ pub const Object = struct { |
| 1196 | true, // is definition | 1196 | true, // is definition |
| 1197 | line_number + func.lbrace_line, // scope line | 1197 | line_number + func.lbrace_line, // scope line |
| 1198 | llvm.DIFlags.StaticMember | noret_bit, | 1198 | llvm.DIFlags.StaticMember | noret_bit, |
| 1199 | module.comp.bin_file.options.optimize_mode != .Debug, | 1199 | mod.comp.bin_file.options.optimize_mode != .Debug, |
| 1200 | null, // decl_subprogram | 1200 | null, // decl_subprogram |
| 1201 | ); | 1201 | ); |
| 1202 | try dg.object.di_map.put(gpa, decl, subprogram.toNode()); | 1202 | try dg.object.di_map.put(gpa, decl, subprogram.toNode()); |
| ... | @@ -1219,7 +1219,7 @@ pub const Object = struct { | ... | @@ -1219,7 +1219,7 @@ pub const Object = struct { |
| 1219 | .func_inst_table = .{}, | 1219 | .func_inst_table = .{}, |
| 1220 | .llvm_func = llvm_func, | 1220 | .llvm_func = llvm_func, |
| 1221 | .blocks = .{}, | 1221 | .blocks = .{}, |
| 1222 | .single_threaded = module.comp.bin_file.options.single_threaded, | 1222 | .single_threaded = mod.comp.bin_file.options.single_threaded, |
| 1223 | .di_scope = di_scope, | 1223 | .di_scope = di_scope, |
| 1224 | .di_file = di_file, | 1224 | .di_file = di_file, |
| 1225 | .base_line = dg.decl.src_line, | 1225 | .base_line = dg.decl.src_line, |
| ... | @@ -1232,14 +1232,14 @@ pub const Object = struct { | ... | @@ -1232,14 +1232,14 @@ pub const Object = struct { |
| 1232 | fg.genBody(air.getMainBody()) catch |err| switch (err) { | 1232 | fg.genBody(air.getMainBody()) catch |err| switch (err) { |
| 1233 | error.CodegenFail => { | 1233 | error.CodegenFail => { |
| 1234 | decl.analysis = .codegen_failure; | 1234 | decl.analysis = .codegen_failure; |
| 1235 | try module.failed_decls.put(module.gpa, decl_index, dg.err_msg.?); | 1235 | try mod.failed_decls.put(mod.gpa, decl_index, dg.err_msg.?); |
| 1236 | dg.err_msg = null; | 1236 | dg.err_msg = null; |
| 1237 | return; | 1237 | return; |
| 1238 | }, | 1238 | }, |
| 1239 | else => |e| return e, | 1239 | else => |e| return e, |
| 1240 | }; | 1240 | }; |
| 1241 | 1241 | ||
| 1242 | try o.updateDeclExports(module, decl_index, module.getDeclExports(decl_index)); | 1242 | try o.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index)); |
| 1243 | } | 1243 | } |
| 1244 | 1244 | ||
| 1245 | pub fn updateDecl(self: *Object, module: *Module, decl_index: Module.Decl.Index) !void { | 1245 | pub fn updateDecl(self: *Object, module: *Module, decl_index: Module.Decl.Index) !void { |
| ... | @@ -1275,37 +1275,40 @@ pub const Object = struct { | ... | @@ -1275,37 +1275,40 @@ pub const Object = struct { |
| 1275 | 1275 | ||
| 1276 | pub fn updateDeclExports( | 1276 | pub fn updateDeclExports( |
| 1277 | self: *Object, | 1277 | self: *Object, |
| 1278 | module: *Module, | 1278 | mod: *Module, |
| 1279 | decl_index: Module.Decl.Index, | 1279 | decl_index: Module.Decl.Index, |
| 1280 | exports: []const *Module.Export, | 1280 | exports: []const *Module.Export, |
| 1281 | ) !void { | 1281 | ) !void { |
| 1282 | const gpa = mod.gpa; | ||
| 1282 | // If the module does not already have the function, we ignore this function call | 1283 | // If the module does not already have the function, we ignore this function call |
| 1283 | // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`. | 1284 | // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`. |
| 1284 | const llvm_global = self.decl_map.get(decl_index) orelse return; | 1285 | const llvm_global = self.decl_map.get(decl_index) orelse return; |
| 1285 | const decl = module.declPtr(decl_index); | 1286 | const decl = mod.declPtr(decl_index); |
| 1286 | if (decl.isExtern()) { | 1287 | if (decl.isExtern()) { |
| 1287 | const is_wasm_fn = module.getTarget().isWasm() and try decl.isFunction(); | 1288 | const is_wasm_fn = mod.getTarget().isWasm() and try decl.isFunction(mod); |
| 1288 | const mangle_name = is_wasm_fn and | 1289 | const mangle_name = is_wasm_fn and |
| 1289 | decl.getExternFn().?.lib_name != null and | 1290 | decl.getExternFn().?.lib_name != null and |
| 1290 | !std.mem.eql(u8, std.mem.sliceTo(decl.getExternFn().?.lib_name.?, 0), "c"); | 1291 | !std.mem.eql(u8, std.mem.sliceTo(decl.getExternFn().?.lib_name.?, 0), "c"); |
| 1291 | const decl_name = if (mangle_name) name: { | 1292 | const decl_name = if (mangle_name) name: { |
| 1292 | const tmp = try std.fmt.allocPrintZ(module.gpa, "{s}|{s}", .{ decl.name, decl.getExternFn().?.lib_name.? }); | 1293 | const tmp = try std.fmt.allocPrintZ(gpa, "{s}|{s}", .{ |
| 1294 | decl.name, decl.getExternFn().?.lib_name.?, | ||
| 1295 | }); | ||
| 1293 | break :name tmp.ptr; | 1296 | break :name tmp.ptr; |
| 1294 | } else decl.name; | 1297 | } else decl.name; |
| 1295 | defer if (mangle_name) module.gpa.free(std.mem.sliceTo(decl_name, 0)); | 1298 | defer if (mangle_name) gpa.free(std.mem.sliceTo(decl_name, 0)); |
| 1296 | 1299 | ||
| 1297 | llvm_global.setValueName(decl_name); | 1300 | llvm_global.setValueName(decl_name); |
| 1298 | if (self.getLlvmGlobal(decl_name)) |other_global| { | 1301 | if (self.getLlvmGlobal(decl_name)) |other_global| { |
| 1299 | if (other_global != llvm_global) { | 1302 | if (other_global != llvm_global) { |
| 1300 | log.debug("updateDeclExports isExtern()=true setValueName({s}) conflict", .{decl.name}); | 1303 | log.debug("updateDeclExports isExtern()=true setValueName({s}) conflict", .{decl.name}); |
| 1301 | try self.extern_collisions.put(module.gpa, decl_index, {}); | 1304 | try self.extern_collisions.put(gpa, decl_index, {}); |
| 1302 | } | 1305 | } |
| 1303 | } | 1306 | } |
| 1304 | llvm_global.setUnnamedAddr(.False); | 1307 | llvm_global.setUnnamedAddr(.False); |
| 1305 | llvm_global.setLinkage(.External); | 1308 | llvm_global.setLinkage(.External); |
| 1306 | if (module.wantDllExports()) llvm_global.setDLLStorageClass(.Default); | 1309 | if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.Default); |
| 1307 | if (self.di_map.get(decl)) |di_node| { | 1310 | if (self.di_map.get(decl)) |di_node| { |
| 1308 | if (try decl.isFunction()) { | 1311 | if (try decl.isFunction(mod)) { |
| 1309 | const di_func = @ptrCast(*llvm.DISubprogram, di_node); | 1312 | const di_func = @ptrCast(*llvm.DISubprogram, di_node); |
| 1310 | const linkage_name = llvm.MDString.get(self.context, decl.name, std.mem.len(decl.name)); | 1313 | const linkage_name = llvm.MDString.get(self.context, decl.name, std.mem.len(decl.name)); |
| 1311 | di_func.replaceLinkageName(linkage_name); | 1314 | di_func.replaceLinkageName(linkage_name); |
| ... | @@ -1329,9 +1332,9 @@ pub const Object = struct { | ... | @@ -1329,9 +1332,9 @@ pub const Object = struct { |
| 1329 | const exp_name = exports[0].options.name; | 1332 | const exp_name = exports[0].options.name; |
| 1330 | llvm_global.setValueName2(exp_name.ptr, exp_name.len); | 1333 | llvm_global.setValueName2(exp_name.ptr, exp_name.len); |
| 1331 | llvm_global.setUnnamedAddr(.False); | 1334 | llvm_global.setUnnamedAddr(.False); |
| 1332 | if (module.wantDllExports()) llvm_global.setDLLStorageClass(.DLLExport); | 1335 | if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.DLLExport); |
| 1333 | if (self.di_map.get(decl)) |di_node| { | 1336 | if (self.di_map.get(decl)) |di_node| { |
| 1334 | if (try decl.isFunction()) { | 1337 | if (try decl.isFunction(mod)) { |
| 1335 | const di_func = @ptrCast(*llvm.DISubprogram, di_node); | 1338 | const di_func = @ptrCast(*llvm.DISubprogram, di_node); |
| 1336 | const linkage_name = llvm.MDString.get(self.context, exp_name.ptr, exp_name.len); | 1339 | const linkage_name = llvm.MDString.get(self.context, exp_name.ptr, exp_name.len); |
| 1337 | di_func.replaceLinkageName(linkage_name); | 1340 | di_func.replaceLinkageName(linkage_name); |
| ... | @@ -1353,8 +1356,8 @@ pub const Object = struct { | ... | @@ -1353,8 +1356,8 @@ pub const Object = struct { |
| 1353 | .protected => llvm_global.setVisibility(.Protected), | 1356 | .protected => llvm_global.setVisibility(.Protected), |
| 1354 | } | 1357 | } |
| 1355 | if (exports[0].options.section) |section| { | 1358 | if (exports[0].options.section) |section| { |
| 1356 | const section_z = try module.gpa.dupeZ(u8, section); | 1359 | const section_z = try gpa.dupeZ(u8, section); |
| 1357 | defer module.gpa.free(section_z); | 1360 | defer gpa.free(section_z); |
| 1358 | llvm_global.setSection(section_z); | 1361 | llvm_global.setSection(section_z); |
| 1359 | } | 1362 | } |
| 1360 | if (decl.val.castTag(.variable)) |variable| { | 1363 | if (decl.val.castTag(.variable)) |variable| { |
| ... | @@ -1370,8 +1373,8 @@ pub const Object = struct { | ... | @@ -1370,8 +1373,8 @@ pub const Object = struct { |
| 1370 | // Until then we iterate over existing aliases and make them point | 1373 | // Until then we iterate over existing aliases and make them point |
| 1371 | // to the correct decl, or otherwise add a new alias. Old aliases are leaked. | 1374 | // to the correct decl, or otherwise add a new alias. Old aliases are leaked. |
| 1372 | for (exports[1..]) |exp| { | 1375 | for (exports[1..]) |exp| { |
| 1373 | const exp_name_z = try module.gpa.dupeZ(u8, exp.options.name); | 1376 | const exp_name_z = try gpa.dupeZ(u8, exp.options.name); |
| 1374 | defer module.gpa.free(exp_name_z); | 1377 | defer gpa.free(exp_name_z); |
| 1375 | 1378 | ||
| 1376 | if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| { | 1379 | if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| { |
| 1377 | alias.setAliasee(llvm_global); | 1380 | alias.setAliasee(llvm_global); |
| ... | @@ -1385,14 +1388,14 @@ pub const Object = struct { | ... | @@ -1385,14 +1388,14 @@ pub const Object = struct { |
| 1385 | } | 1388 | } |
| 1386 | } | 1389 | } |
| 1387 | } else { | 1390 | } else { |
| 1388 | const fqn = try decl.getFullyQualifiedName(module); | 1391 | const fqn = try decl.getFullyQualifiedName(mod); |
| 1389 | defer module.gpa.free(fqn); | 1392 | defer gpa.free(fqn); |
| 1390 | llvm_global.setValueName2(fqn.ptr, fqn.len); | 1393 | llvm_global.setValueName2(fqn.ptr, fqn.len); |
| 1391 | llvm_global.setLinkage(.Internal); | 1394 | llvm_global.setLinkage(.Internal); |
| 1392 | if (module.wantDllExports()) llvm_global.setDLLStorageClass(.Default); | 1395 | if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.Default); |
| 1393 | llvm_global.setUnnamedAddr(.True); | 1396 | llvm_global.setUnnamedAddr(.True); |
| 1394 | if (decl.val.castTag(.variable)) |variable| { | 1397 | if (decl.val.castTag(.variable)) |variable| { |
| 1395 | const single_threaded = module.comp.bin_file.options.single_threaded; | 1398 | const single_threaded = mod.comp.bin_file.options.single_threaded; |
| 1396 | if (variable.data.is_threadlocal and !single_threaded) { | 1399 | if (variable.data.is_threadlocal and !single_threaded) { |
| 1397 | llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel); | 1400 | llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel); |
| 1398 | } else { | 1401 | } else { |
| ... | @@ -1479,14 +1482,15 @@ pub const Object = struct { | ... | @@ -1479,14 +1482,15 @@ pub const Object = struct { |
| 1479 | const gpa = o.gpa; | 1482 | const gpa = o.gpa; |
| 1480 | const target = o.target; | 1483 | const target = o.target; |
| 1481 | const dib = o.di_builder.?; | 1484 | const dib = o.di_builder.?; |
| 1482 | switch (ty.zigTypeTag()) { | 1485 | const mod = o.module; |
| 1486 | switch (ty.zigTypeTag(mod)) { | ||
| 1483 | .Void, .NoReturn => { | 1487 | .Void, .NoReturn => { |
| 1484 | const di_type = dib.createBasicType("void", 0, DW.ATE.signed); | 1488 | const di_type = dib.createBasicType("void", 0, DW.ATE.signed); |
| 1485 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type); | 1489 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type); |
| 1486 | return di_type; | 1490 | return di_type; |
| 1487 | }, | 1491 | }, |
| 1488 | .Int => { | 1492 | .Int => { |
| 1489 | const info = ty.intInfo(target); | 1493 | const info = ty.intInfo(mod); |
| 1490 | assert(info.bits != 0); | 1494 | assert(info.bits != 0); |
| 1491 | const name = try ty.nameAlloc(gpa, o.module); | 1495 | const name = try ty.nameAlloc(gpa, o.module); |
| 1492 | defer gpa.free(name); | 1496 | defer gpa.free(name); |
| ... | @@ -1494,7 +1498,7 @@ pub const Object = struct { | ... | @@ -1494,7 +1498,7 @@ pub const Object = struct { |
| 1494 | .signed => DW.ATE.signed, | 1498 | .signed => DW.ATE.signed, |
| 1495 | .unsigned => DW.ATE.unsigned, | 1499 | .unsigned => DW.ATE.unsigned, |
| 1496 | }; | 1500 | }; |
| 1497 | const di_bits = ty.abiSize(target) * 8; // lldb cannot handle non-byte sized types | 1501 | const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types |
| 1498 | const di_type = dib.createBasicType(name, di_bits, dwarf_encoding); | 1502 | const di_type = dib.createBasicType(name, di_bits, dwarf_encoding); |
| 1499 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type); | 1503 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type); |
| 1500 | return di_type; | 1504 | return di_type; |
| ... | @@ -1503,7 +1507,7 @@ pub const Object = struct { | ... | @@ -1503,7 +1507,7 @@ pub const Object = struct { |
| 1503 | const owner_decl_index = ty.getOwnerDecl(); | 1507 | const owner_decl_index = ty.getOwnerDecl(); |
| 1504 | const owner_decl = o.module.declPtr(owner_decl_index); | 1508 | const owner_decl = o.module.declPtr(owner_decl_index); |
| 1505 | 1509 | ||
| 1506 | if (!ty.hasRuntimeBitsIgnoreComptime()) { | 1510 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1507 | const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); | 1511 | const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); |
| 1508 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` | 1512 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 1509 | // means we can't use `gop` anymore. | 1513 | // means we can't use `gop` anymore. |
| ... | @@ -1522,9 +1526,8 @@ pub const Object = struct { | ... | @@ -1522,9 +1526,8 @@ pub const Object = struct { |
| 1522 | }; | 1526 | }; |
| 1523 | const field_index_val = Value.initPayload(&buf_field_index.base); | 1527 | const field_index_val = Value.initPayload(&buf_field_index.base); |
| 1524 | 1528 | ||
| 1525 | var buffer: Type.Payload.Bits = undefined; | 1529 | const int_ty = ty.intTagType(); |
| 1526 | const int_ty = ty.intTagType(&buffer); | 1530 | const int_info = ty.intInfo(mod); |
| 1527 | const int_info = ty.intInfo(target); | ||
| 1528 | assert(int_info.bits != 0); | 1531 | assert(int_info.bits != 0); |
| 1529 | 1532 | ||
| 1530 | for (field_names, 0..) |field_name, i| { | 1533 | for (field_names, 0..) |field_name, i| { |
| ... | @@ -1536,7 +1539,7 @@ pub const Object = struct { | ... | @@ -1536,7 +1539,7 @@ pub const Object = struct { |
| 1536 | const field_int_val = field_index_val.enumToInt(ty, &buf_u64); | 1539 | const field_int_val = field_index_val.enumToInt(ty, &buf_u64); |
| 1537 | 1540 | ||
| 1538 | var bigint_space: Value.BigIntSpace = undefined; | 1541 | var bigint_space: Value.BigIntSpace = undefined; |
| 1539 | const bigint = field_int_val.toBigInt(&bigint_space, target); | 1542 | const bigint = field_int_val.toBigInt(&bigint_space, mod); |
| 1540 | 1543 | ||
| 1541 | if (bigint.limbs.len == 1) { | 1544 | if (bigint.limbs.len == 1) { |
| 1542 | enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned); | 1545 | enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned); |
| ... | @@ -1566,8 +1569,8 @@ pub const Object = struct { | ... | @@ -1566,8 +1569,8 @@ pub const Object = struct { |
| 1566 | name, | 1569 | name, |
| 1567 | di_file, | 1570 | di_file, |
| 1568 | owner_decl.src_node + 1, | 1571 | owner_decl.src_node + 1, |
| 1569 | ty.abiSize(target) * 8, | 1572 | ty.abiSize(mod) * 8, |
| 1570 | ty.abiAlignment(target) * 8, | 1573 | ty.abiAlignment(mod) * 8, |
| 1571 | enumerators.ptr, | 1574 | enumerators.ptr, |
| 1572 | @intCast(c_int, enumerators.len), | 1575 | @intCast(c_int, enumerators.len), |
| 1573 | try o.lowerDebugType(int_ty, .full), | 1576 | try o.lowerDebugType(int_ty, .full), |
| ... | @@ -1604,7 +1607,7 @@ pub const Object = struct { | ... | @@ -1604,7 +1607,7 @@ pub const Object = struct { |
| 1604 | !ptr_info.mutable or | 1607 | !ptr_info.mutable or |
| 1605 | ptr_info.@"volatile" or | 1608 | ptr_info.@"volatile" or |
| 1606 | ptr_info.size == .Many or ptr_info.size == .C or | 1609 | ptr_info.size == .Many or ptr_info.size == .C or |
| 1607 | !ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime()) | 1610 | !ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime(mod)) |
| 1608 | { | 1611 | { |
| 1609 | var payload: Type.Payload.Pointer = .{ | 1612 | var payload: Type.Payload.Pointer = .{ |
| 1610 | .data = .{ | 1613 | .data = .{ |
| ... | @@ -1623,7 +1626,7 @@ pub const Object = struct { | ... | @@ -1623,7 +1626,7 @@ pub const Object = struct { |
| 1623 | }, | 1626 | }, |
| 1624 | }, | 1627 | }, |
| 1625 | }; | 1628 | }; |
| 1626 | if (!ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime()) { | 1629 | if (!ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1627 | payload.data.pointee_type = Type.anyopaque; | 1630 | payload.data.pointee_type = Type.anyopaque; |
| 1628 | } | 1631 | } |
| 1629 | const bland_ptr_ty = Type.initPayload(&payload.base); | 1632 | const bland_ptr_ty = Type.initPayload(&payload.base); |
| ... | @@ -1657,10 +1660,10 @@ pub const Object = struct { | ... | @@ -1657,10 +1660,10 @@ pub const Object = struct { |
| 1657 | break :blk fwd_decl; | 1660 | break :blk fwd_decl; |
| 1658 | }; | 1661 | }; |
| 1659 | 1662 | ||
| 1660 | const ptr_size = ptr_ty.abiSize(target); | 1663 | const ptr_size = ptr_ty.abiSize(mod); |
| 1661 | const ptr_align = ptr_ty.abiAlignment(target); | 1664 | const ptr_align = ptr_ty.abiAlignment(mod); |
| 1662 | const len_size = len_ty.abiSize(target); | 1665 | const len_size = len_ty.abiSize(mod); |
| 1663 | const len_align = len_ty.abiAlignment(target); | 1666 | const len_align = len_ty.abiAlignment(mod); |
| 1664 | 1667 | ||
| 1665 | var offset: u64 = 0; | 1668 | var offset: u64 = 0; |
| 1666 | offset += ptr_size; | 1669 | offset += ptr_size; |
| ... | @@ -1697,8 +1700,8 @@ pub const Object = struct { | ... | @@ -1697,8 +1700,8 @@ pub const Object = struct { |
| 1697 | name.ptr, | 1700 | name.ptr, |
| 1698 | di_file, | 1701 | di_file, |
| 1699 | line, | 1702 | line, |
| 1700 | ty.abiSize(target) * 8, // size in bits | 1703 | ty.abiSize(mod) * 8, // size in bits |
| 1701 | ty.abiAlignment(target) * 8, // align in bits | 1704 | ty.abiAlignment(mod) * 8, // align in bits |
| 1702 | 0, // flags | 1705 | 0, // flags |
| 1703 | null, // derived from | 1706 | null, // derived from |
| 1704 | &fields, | 1707 | &fields, |
| ... | @@ -1719,7 +1722,7 @@ pub const Object = struct { | ... | @@ -1719,7 +1722,7 @@ pub const Object = struct { |
| 1719 | const ptr_di_ty = dib.createPointerType( | 1722 | const ptr_di_ty = dib.createPointerType( |
| 1720 | elem_di_ty, | 1723 | elem_di_ty, |
| 1721 | target.ptrBitWidth(), | 1724 | target.ptrBitWidth(), |
| 1722 | ty.ptrAlignment(target) * 8, | 1725 | ty.ptrAlignment(mod) * 8, |
| 1723 | name, | 1726 | name, |
| 1724 | ); | 1727 | ); |
| 1725 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. | 1728 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| ... | @@ -1750,8 +1753,8 @@ pub const Object = struct { | ... | @@ -1750,8 +1753,8 @@ pub const Object = struct { |
| 1750 | }, | 1753 | }, |
| 1751 | .Array => { | 1754 | .Array => { |
| 1752 | const array_di_ty = dib.createArrayType( | 1755 | const array_di_ty = dib.createArrayType( |
| 1753 | ty.abiSize(target) * 8, | 1756 | ty.abiSize(mod) * 8, |
| 1754 | ty.abiAlignment(target) * 8, | 1757 | ty.abiAlignment(mod) * 8, |
| 1755 | try o.lowerDebugType(ty.childType(), .full), | 1758 | try o.lowerDebugType(ty.childType(), .full), |
| 1756 | @intCast(c_int, ty.arrayLen()), | 1759 | @intCast(c_int, ty.arrayLen()), |
| 1757 | ); | 1760 | ); |
| ... | @@ -1760,14 +1763,14 @@ pub const Object = struct { | ... | @@ -1760,14 +1763,14 @@ pub const Object = struct { |
| 1760 | return array_di_ty; | 1763 | return array_di_ty; |
| 1761 | }, | 1764 | }, |
| 1762 | .Vector => { | 1765 | .Vector => { |
| 1763 | const elem_ty = ty.elemType2(); | 1766 | const elem_ty = ty.elemType2(mod); |
| 1764 | // Vector elements cannot be padded since that would make | 1767 | // Vector elements cannot be padded since that would make |
| 1765 | // @bitSizOf(elem) * len > @bitSizOf(vec). | 1768 | // @bitSizOf(elem) * len > @bitSizOf(vec). |
| 1766 | // Neither gdb nor lldb seem to be able to display non-byte sized | 1769 | // Neither gdb nor lldb seem to be able to display non-byte sized |
| 1767 | // vectors properly. | 1770 | // vectors properly. |
| 1768 | const elem_di_type = switch (elem_ty.zigTypeTag()) { | 1771 | const elem_di_type = switch (elem_ty.zigTypeTag(mod)) { |
| 1769 | .Int => blk: { | 1772 | .Int => blk: { |
| 1770 | const info = elem_ty.intInfo(target); | 1773 | const info = elem_ty.intInfo(mod); |
| 1771 | assert(info.bits != 0); | 1774 | assert(info.bits != 0); |
| 1772 | const name = try ty.nameAlloc(gpa, o.module); | 1775 | const name = try ty.nameAlloc(gpa, o.module); |
| 1773 | defer gpa.free(name); | 1776 | defer gpa.free(name); |
| ... | @@ -1782,8 +1785,8 @@ pub const Object = struct { | ... | @@ -1782,8 +1785,8 @@ pub const Object = struct { |
| 1782 | }; | 1785 | }; |
| 1783 | 1786 | ||
| 1784 | const vector_di_ty = dib.createVectorType( | 1787 | const vector_di_ty = dib.createVectorType( |
| 1785 | ty.abiSize(target) * 8, | 1788 | ty.abiSize(mod) * 8, |
| 1786 | ty.abiAlignment(target) * 8, | 1789 | ty.abiAlignment(mod) * 8, |
| 1787 | elem_di_type, | 1790 | elem_di_type, |
| 1788 | ty.vectorLen(), | 1791 | ty.vectorLen(), |
| 1789 | ); | 1792 | ); |
| ... | @@ -1796,13 +1799,13 @@ pub const Object = struct { | ... | @@ -1796,13 +1799,13 @@ pub const Object = struct { |
| 1796 | defer gpa.free(name); | 1799 | defer gpa.free(name); |
| 1797 | var buf: Type.Payload.ElemType = undefined; | 1800 | var buf: Type.Payload.ElemType = undefined; |
| 1798 | const child_ty = ty.optionalChild(&buf); | 1801 | const child_ty = ty.optionalChild(&buf); |
| 1799 | if (!child_ty.hasRuntimeBitsIgnoreComptime()) { | 1802 | if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1800 | const di_bits = 8; // lldb cannot handle non-byte sized types | 1803 | const di_bits = 8; // lldb cannot handle non-byte sized types |
| 1801 | const di_ty = dib.createBasicType(name, di_bits, DW.ATE.boolean); | 1804 | const di_ty = dib.createBasicType(name, di_bits, DW.ATE.boolean); |
| 1802 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty); | 1805 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty); |
| 1803 | return di_ty; | 1806 | return di_ty; |
| 1804 | } | 1807 | } |
| 1805 | if (ty.optionalReprIsPayload()) { | 1808 | if (ty.optionalReprIsPayload(mod)) { |
| 1806 | const ptr_di_ty = try o.lowerDebugType(child_ty, resolve); | 1809 | const ptr_di_ty = try o.lowerDebugType(child_ty, resolve); |
| 1807 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. | 1810 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1808 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.init(ptr_di_ty, resolve), .{ .mod = o.module }); | 1811 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.init(ptr_di_ty, resolve), .{ .mod = o.module }); |
| ... | @@ -1826,10 +1829,10 @@ pub const Object = struct { | ... | @@ -1826,10 +1829,10 @@ pub const Object = struct { |
| 1826 | }; | 1829 | }; |
| 1827 | 1830 | ||
| 1828 | const non_null_ty = Type.u8; | 1831 | const non_null_ty = Type.u8; |
| 1829 | const payload_size = child_ty.abiSize(target); | 1832 | const payload_size = child_ty.abiSize(mod); |
| 1830 | const payload_align = child_ty.abiAlignment(target); | 1833 | const payload_align = child_ty.abiAlignment(mod); |
| 1831 | const non_null_size = non_null_ty.abiSize(target); | 1834 | const non_null_size = non_null_ty.abiSize(mod); |
| 1832 | const non_null_align = non_null_ty.abiAlignment(target); | 1835 | const non_null_align = non_null_ty.abiAlignment(mod); |
| 1833 | 1836 | ||
| 1834 | var offset: u64 = 0; | 1837 | var offset: u64 = 0; |
| 1835 | offset += payload_size; | 1838 | offset += payload_size; |
| ... | @@ -1866,8 +1869,8 @@ pub const Object = struct { | ... | @@ -1866,8 +1869,8 @@ pub const Object = struct { |
| 1866 | name.ptr, | 1869 | name.ptr, |
| 1867 | di_file, | 1870 | di_file, |
| 1868 | line, | 1871 | line, |
| 1869 | ty.abiSize(target) * 8, // size in bits | 1872 | ty.abiSize(mod) * 8, // size in bits |
| 1870 | ty.abiAlignment(target) * 8, // align in bits | 1873 | ty.abiAlignment(mod) * 8, // align in bits |
| 1871 | 0, // flags | 1874 | 0, // flags |
| 1872 | null, // derived from | 1875 | null, // derived from |
| 1873 | &fields, | 1876 | &fields, |
| ... | @@ -1883,7 +1886,7 @@ pub const Object = struct { | ... | @@ -1883,7 +1886,7 @@ pub const Object = struct { |
| 1883 | }, | 1886 | }, |
| 1884 | .ErrorUnion => { | 1887 | .ErrorUnion => { |
| 1885 | const payload_ty = ty.errorUnionPayload(); | 1888 | const payload_ty = ty.errorUnionPayload(); |
| 1886 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 1889 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1887 | const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full); | 1890 | const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full); |
| 1888 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. | 1891 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1889 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(err_set_di_ty), .{ .mod = o.module }); | 1892 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(err_set_di_ty), .{ .mod = o.module }); |
| ... | @@ -1907,10 +1910,10 @@ pub const Object = struct { | ... | @@ -1907,10 +1910,10 @@ pub const Object = struct { |
| 1907 | break :blk fwd_decl; | 1910 | break :blk fwd_decl; |
| 1908 | }; | 1911 | }; |
| 1909 | 1912 | ||
| 1910 | const error_size = Type.anyerror.abiSize(target); | 1913 | const error_size = Type.anyerror.abiSize(mod); |
| 1911 | const error_align = Type.anyerror.abiAlignment(target); | 1914 | const error_align = Type.anyerror.abiAlignment(mod); |
| 1912 | const payload_size = payload_ty.abiSize(target); | 1915 | const payload_size = payload_ty.abiSize(mod); |
| 1913 | const payload_align = payload_ty.abiAlignment(target); | 1916 | const payload_align = payload_ty.abiAlignment(mod); |
| 1914 | 1917 | ||
| 1915 | var error_index: u32 = undefined; | 1918 | var error_index: u32 = undefined; |
| 1916 | var payload_index: u32 = undefined; | 1919 | var payload_index: u32 = undefined; |
| ... | @@ -1957,8 +1960,8 @@ pub const Object = struct { | ... | @@ -1957,8 +1960,8 @@ pub const Object = struct { |
| 1957 | name.ptr, | 1960 | name.ptr, |
| 1958 | di_file, | 1961 | di_file, |
| 1959 | line, | 1962 | line, |
| 1960 | ty.abiSize(target) * 8, // size in bits | 1963 | ty.abiSize(mod) * 8, // size in bits |
| 1961 | ty.abiAlignment(target) * 8, // align in bits | 1964 | ty.abiAlignment(mod) * 8, // align in bits |
| 1962 | 0, // flags | 1965 | 0, // flags |
| 1963 | null, // derived from | 1966 | null, // derived from |
| 1964 | &fields, | 1967 | &fields, |
| ... | @@ -1988,12 +1991,12 @@ pub const Object = struct { | ... | @@ -1988,12 +1991,12 @@ pub const Object = struct { |
| 1988 | const struct_obj = payload.data; | 1991 | const struct_obj = payload.data; |
| 1989 | if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { | 1992 | if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { |
| 1990 | assert(struct_obj.haveLayout()); | 1993 | assert(struct_obj.haveLayout()); |
| 1991 | const info = struct_obj.backing_int_ty.intInfo(target); | 1994 | const info = struct_obj.backing_int_ty.intInfo(mod); |
| 1992 | const dwarf_encoding: c_uint = switch (info.signedness) { | 1995 | const dwarf_encoding: c_uint = switch (info.signedness) { |
| 1993 | .signed => DW.ATE.signed, | 1996 | .signed => DW.ATE.signed, |
| 1994 | .unsigned => DW.ATE.unsigned, | 1997 | .unsigned => DW.ATE.unsigned, |
| 1995 | }; | 1998 | }; |
| 1996 | const di_bits = ty.abiSize(target) * 8; // lldb cannot handle non-byte sized types | 1999 | const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types |
| 1997 | const di_ty = dib.createBasicType(name, di_bits, dwarf_encoding); | 2000 | const di_ty = dib.createBasicType(name, di_bits, dwarf_encoding); |
| 1998 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty); | 2001 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty); |
| 1999 | return di_ty; | 2002 | return di_ty; |
| ... | @@ -2026,10 +2029,10 @@ pub const Object = struct { | ... | @@ -2026,10 +2029,10 @@ pub const Object = struct { |
| 2026 | 2029 | ||
| 2027 | for (tuple.types, 0..) |field_ty, i| { | 2030 | for (tuple.types, 0..) |field_ty, i| { |
| 2028 | const field_val = tuple.values[i]; | 2031 | const field_val = tuple.values[i]; |
| 2029 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue; | 2032 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; |
| 2030 | 2033 | ||
| 2031 | const field_size = field_ty.abiSize(target); | 2034 | const field_size = field_ty.abiSize(mod); |
| 2032 | const field_align = field_ty.abiAlignment(target); | 2035 | const field_align = field_ty.abiAlignment(mod); |
| 2033 | const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align); | 2036 | const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| 2034 | offset = field_offset + field_size; | 2037 | offset = field_offset + field_size; |
| 2035 | 2038 | ||
| ... | @@ -2057,8 +2060,8 @@ pub const Object = struct { | ... | @@ -2057,8 +2060,8 @@ pub const Object = struct { |
| 2057 | name.ptr, | 2060 | name.ptr, |
| 2058 | null, // file | 2061 | null, // file |
| 2059 | 0, // line | 2062 | 0, // line |
| 2060 | ty.abiSize(target) * 8, // size in bits | 2063 | ty.abiSize(mod) * 8, // size in bits |
| 2061 | ty.abiAlignment(target) * 8, // align in bits | 2064 | ty.abiAlignment(mod) * 8, // align in bits |
| 2062 | 0, // flags | 2065 | 0, // flags |
| 2063 | null, // derived from | 2066 | null, // derived from |
| 2064 | di_fields.items.ptr, | 2067 | di_fields.items.ptr, |
| ... | @@ -2093,7 +2096,7 @@ pub const Object = struct { | ... | @@ -2093,7 +2096,7 @@ pub const Object = struct { |
| 2093 | } | 2096 | } |
| 2094 | } | 2097 | } |
| 2095 | 2098 | ||
| 2096 | if (!ty.hasRuntimeBitsIgnoreComptime()) { | 2099 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2097 | const owner_decl_index = ty.getOwnerDecl(); | 2100 | const owner_decl_index = ty.getOwnerDecl(); |
| 2098 | const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); | 2101 | const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); |
| 2099 | dib.replaceTemporary(fwd_decl, struct_di_ty); | 2102 | dib.replaceTemporary(fwd_decl, struct_di_ty); |
| ... | @@ -2114,11 +2117,11 @@ pub const Object = struct { | ... | @@ -2114,11 +2117,11 @@ pub const Object = struct { |
| 2114 | comptime assert(struct_layout_version == 2); | 2117 | comptime assert(struct_layout_version == 2); |
| 2115 | var offset: u64 = 0; | 2118 | var offset: u64 = 0; |
| 2116 | 2119 | ||
| 2117 | var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator(); | 2120 | var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator(mod); |
| 2118 | while (it.next()) |field_and_index| { | 2121 | while (it.next()) |field_and_index| { |
| 2119 | const field = field_and_index.field; | 2122 | const field = field_and_index.field; |
| 2120 | const field_size = field.ty.abiSize(target); | 2123 | const field_size = field.ty.abiSize(mod); |
| 2121 | const field_align = field.alignment(target, layout); | 2124 | const field_align = field.alignment(mod, layout); |
| 2122 | const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align); | 2125 | const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| 2123 | offset = field_offset + field_size; | 2126 | offset = field_offset + field_size; |
| 2124 | 2127 | ||
| ... | @@ -2143,8 +2146,8 @@ pub const Object = struct { | ... | @@ -2143,8 +2146,8 @@ pub const Object = struct { |
| 2143 | name.ptr, | 2146 | name.ptr, |
| 2144 | null, // file | 2147 | null, // file |
| 2145 | 0, // line | 2148 | 0, // line |
| 2146 | ty.abiSize(target) * 8, // size in bits | 2149 | ty.abiSize(mod) * 8, // size in bits |
| 2147 | ty.abiAlignment(target) * 8, // align in bits | 2150 | ty.abiAlignment(mod) * 8, // align in bits |
| 2148 | 0, // flags | 2151 | 0, // flags |
| 2149 | null, // derived from | 2152 | null, // derived from |
| 2150 | di_fields.items.ptr, | 2153 | di_fields.items.ptr, |
| ... | @@ -2179,7 +2182,7 @@ pub const Object = struct { | ... | @@ -2179,7 +2182,7 @@ pub const Object = struct { |
| 2179 | }; | 2182 | }; |
| 2180 | 2183 | ||
| 2181 | const union_obj = ty.cast(Type.Payload.Union).?.data; | 2184 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 2182 | if (!union_obj.haveFieldTypes() or !ty.hasRuntimeBitsIgnoreComptime()) { | 2185 | if (!union_obj.haveFieldTypes() or !ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2183 | const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); | 2186 | const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); |
| 2184 | dib.replaceTemporary(fwd_decl, union_di_ty); | 2187 | dib.replaceTemporary(fwd_decl, union_di_ty); |
| 2185 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` | 2188 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| ... | @@ -2188,7 +2191,7 @@ pub const Object = struct { | ... | @@ -2188,7 +2191,7 @@ pub const Object = struct { |
| 2188 | return union_di_ty; | 2191 | return union_di_ty; |
| 2189 | } | 2192 | } |
| 2190 | 2193 | ||
| 2191 | const layout = ty.unionGetLayout(target); | 2194 | const layout = ty.unionGetLayout(mod); |
| 2192 | 2195 | ||
| 2193 | if (layout.payload_size == 0) { | 2196 | if (layout.payload_size == 0) { |
| 2194 | const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full); | 2197 | const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full); |
| ... | @@ -2198,8 +2201,8 @@ pub const Object = struct { | ... | @@ -2198,8 +2201,8 @@ pub const Object = struct { |
| 2198 | name.ptr, | 2201 | name.ptr, |
| 2199 | null, // file | 2202 | null, // file |
| 2200 | 0, // line | 2203 | 0, // line |
| 2201 | ty.abiSize(target) * 8, // size in bits | 2204 | ty.abiSize(mod) * 8, // size in bits |
| 2202 | ty.abiAlignment(target) * 8, // align in bits | 2205 | ty.abiAlignment(mod) * 8, // align in bits |
| 2203 | 0, // flags | 2206 | 0, // flags |
| 2204 | null, // derived from | 2207 | null, // derived from |
| 2205 | &di_fields, | 2208 | &di_fields, |
| ... | @@ -2225,10 +2228,10 @@ pub const Object = struct { | ... | @@ -2225,10 +2228,10 @@ pub const Object = struct { |
| 2225 | const field_name = kv.key_ptr.*; | 2228 | const field_name = kv.key_ptr.*; |
| 2226 | const field = kv.value_ptr.*; | 2229 | const field = kv.value_ptr.*; |
| 2227 | 2230 | ||
| 2228 | if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue; | 2231 | if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2229 | 2232 | ||
| 2230 | const field_size = field.ty.abiSize(target); | 2233 | const field_size = field.ty.abiSize(mod); |
| 2231 | const field_align = field.normalAlignment(target); | 2234 | const field_align = field.normalAlignment(mod); |
| 2232 | 2235 | ||
| 2233 | const field_name_copy = try gpa.dupeZ(u8, field_name); | 2236 | const field_name_copy = try gpa.dupeZ(u8, field_name); |
| 2234 | defer gpa.free(field_name_copy); | 2237 | defer gpa.free(field_name_copy); |
| ... | @@ -2258,8 +2261,8 @@ pub const Object = struct { | ... | @@ -2258,8 +2261,8 @@ pub const Object = struct { |
| 2258 | union_name.ptr, | 2261 | union_name.ptr, |
| 2259 | null, // file | 2262 | null, // file |
| 2260 | 0, // line | 2263 | 0, // line |
| 2261 | ty.abiSize(target) * 8, // size in bits | 2264 | ty.abiSize(mod) * 8, // size in bits |
| 2262 | ty.abiAlignment(target) * 8, // align in bits | 2265 | ty.abiAlignment(mod) * 8, // align in bits |
| 2263 | 0, // flags | 2266 | 0, // flags |
| 2264 | di_fields.items.ptr, | 2267 | di_fields.items.ptr, |
| 2265 | @intCast(c_int, di_fields.items.len), | 2268 | @intCast(c_int, di_fields.items.len), |
| ... | @@ -2319,8 +2322,8 @@ pub const Object = struct { | ... | @@ -2319,8 +2322,8 @@ pub const Object = struct { |
| 2319 | name.ptr, | 2322 | name.ptr, |
| 2320 | null, // file | 2323 | null, // file |
| 2321 | 0, // line | 2324 | 0, // line |
| 2322 | ty.abiSize(target) * 8, // size in bits | 2325 | ty.abiSize(mod) * 8, // size in bits |
| 2323 | ty.abiAlignment(target) * 8, // align in bits | 2326 | ty.abiAlignment(mod) * 8, // align in bits |
| 2324 | 0, // flags | 2327 | 0, // flags |
| 2325 | null, // derived from | 2328 | null, // derived from |
| 2326 | &full_di_fields, | 2329 | &full_di_fields, |
| ... | @@ -2341,8 +2344,8 @@ pub const Object = struct { | ... | @@ -2341,8 +2344,8 @@ pub const Object = struct { |
| 2341 | defer param_di_types.deinit(); | 2344 | defer param_di_types.deinit(); |
| 2342 | 2345 | ||
| 2343 | // Return type goes first. | 2346 | // Return type goes first. |
| 2344 | if (fn_info.return_type.hasRuntimeBitsIgnoreComptime()) { | 2347 | if (fn_info.return_type.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2345 | const sret = firstParamSRet(fn_info, target); | 2348 | const sret = firstParamSRet(fn_info, mod); |
| 2346 | const di_ret_ty = if (sret) Type.void else fn_info.return_type; | 2349 | const di_ret_ty = if (sret) Type.void else fn_info.return_type; |
| 2347 | try param_di_types.append(try o.lowerDebugType(di_ret_ty, .full)); | 2350 | try param_di_types.append(try o.lowerDebugType(di_ret_ty, .full)); |
| 2348 | 2351 | ||
| ... | @@ -2358,7 +2361,7 @@ pub const Object = struct { | ... | @@ -2358,7 +2361,7 @@ pub const Object = struct { |
| 2358 | try param_di_types.append(try o.lowerDebugType(Type.void, .full)); | 2361 | try param_di_types.append(try o.lowerDebugType(Type.void, .full)); |
| 2359 | } | 2362 | } |
| 2360 | 2363 | ||
| 2361 | if (fn_info.return_type.isError() and | 2364 | if (fn_info.return_type.isError(mod) and |
| 2362 | o.module.comp.bin_file.options.error_return_tracing) | 2365 | o.module.comp.bin_file.options.error_return_tracing) |
| 2363 | { | 2366 | { |
| 2364 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 2367 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| ... | @@ -2370,9 +2373,9 @@ pub const Object = struct { | ... | @@ -2370,9 +2373,9 @@ pub const Object = struct { |
| 2370 | } | 2373 | } |
| 2371 | 2374 | ||
| 2372 | for (fn_info.param_types) |param_ty| { | 2375 | for (fn_info.param_types) |param_ty| { |
| 2373 | if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue; | 2376 | if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2374 | 2377 | ||
| 2375 | if (isByRef(param_ty)) { | 2378 | if (isByRef(param_ty, mod)) { |
| 2376 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 2379 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 2377 | .base = .{ .tag = .single_mut_pointer }, | 2380 | .base = .{ .tag = .single_mut_pointer }, |
| 2378 | .data = param_ty, | 2381 | .data = param_ty, |
| ... | @@ -2450,7 +2453,7 @@ pub const Object = struct { | ... | @@ -2450,7 +2453,7 @@ pub const Object = struct { |
| 2450 | 2453 | ||
| 2451 | const stack_trace_str: []const u8 = "StackTrace"; | 2454 | const stack_trace_str: []const u8 = "StackTrace"; |
| 2452 | // buffer is only used for int_type, `builtin` is a struct. | 2455 | // buffer is only used for int_type, `builtin` is a struct. |
| 2453 | const builtin_ty = mod.declPtr(builtin_decl).val.toType(undefined); | 2456 | const builtin_ty = mod.declPtr(builtin_decl).val.toType(); |
| 2454 | const builtin_namespace = builtin_ty.getNamespace().?; | 2457 | const builtin_namespace = builtin_ty.getNamespace().?; |
| 2455 | const stack_trace_decl_index = builtin_namespace.decls | 2458 | const stack_trace_decl_index = builtin_namespace.decls |
| 2456 | .getKeyAdapted(stack_trace_str, Module.DeclAdapter{ .mod = mod }).?; | 2459 | .getKeyAdapted(stack_trace_str, Module.DeclAdapter{ .mod = mod }).?; |
| ... | @@ -2458,7 +2461,7 @@ pub const Object = struct { | ... | @@ -2458,7 +2461,7 @@ pub const Object = struct { |
| 2458 | 2461 | ||
| 2459 | // Sema should have ensured that StackTrace was analyzed. | 2462 | // Sema should have ensured that StackTrace was analyzed. |
| 2460 | assert(stack_trace_decl.has_tv); | 2463 | assert(stack_trace_decl.has_tv); |
| 2461 | return stack_trace_decl.val.toType(undefined); | 2464 | return stack_trace_decl.val.toType(); |
| 2462 | } | 2465 | } |
| 2463 | }; | 2466 | }; |
| 2464 | 2467 | ||
| ... | @@ -2495,9 +2498,10 @@ pub const DeclGen = struct { | ... | @@ -2495,9 +2498,10 @@ pub const DeclGen = struct { |
| 2495 | if (decl.val.castTag(.extern_fn)) |extern_fn| { | 2498 | if (decl.val.castTag(.extern_fn)) |extern_fn| { |
| 2496 | _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl); | 2499 | _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl); |
| 2497 | } else { | 2500 | } else { |
| 2498 | const target = dg.module.getTarget(); | 2501 | const mod = dg.module; |
| 2502 | const target = mod.getTarget(); | ||
| 2499 | var global = try dg.resolveGlobalDecl(decl_index); | 2503 | var global = try dg.resolveGlobalDecl(decl_index); |
| 2500 | global.setAlignment(decl.getAlignment(target)); | 2504 | global.setAlignment(decl.getAlignment(mod)); |
| 2501 | if (decl.@"linksection") |section| global.setSection(section); | 2505 | if (decl.@"linksection") |section| global.setSection(section); |
| 2502 | assert(decl.has_tv); | 2506 | assert(decl.has_tv); |
| 2503 | const init_val = if (decl.val.castTag(.variable)) |payload| init_val: { | 2507 | const init_val = if (decl.val.castTag(.variable)) |payload| init_val: { |
| ... | @@ -2569,19 +2573,20 @@ pub const DeclGen = struct { | ... | @@ -2569,19 +2573,20 @@ pub const DeclGen = struct { |
| 2569 | /// Note that this can be called before the function's semantic analysis has | 2573 | /// Note that this can be called before the function's semantic analysis has |
| 2570 | /// completed, so if any attributes rely on that, they must be done in updateFunc, not here. | 2574 | /// completed, so if any attributes rely on that, they must be done in updateFunc, not here. |
| 2571 | fn resolveLlvmFunction(dg: *DeclGen, decl_index: Module.Decl.Index) !*llvm.Value { | 2575 | fn resolveLlvmFunction(dg: *DeclGen, decl_index: Module.Decl.Index) !*llvm.Value { |
| 2572 | const decl = dg.module.declPtr(decl_index); | 2576 | const mod = dg.module; |
| 2577 | const decl = mod.declPtr(decl_index); | ||
| 2573 | const zig_fn_type = decl.ty; | 2578 | const zig_fn_type = decl.ty; |
| 2574 | const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl_index); | 2579 | const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl_index); |
| 2575 | if (gop.found_existing) return gop.value_ptr.*; | 2580 | if (gop.found_existing) return gop.value_ptr.*; |
| 2576 | 2581 | ||
| 2577 | assert(decl.has_tv); | 2582 | assert(decl.has_tv); |
| 2578 | const fn_info = zig_fn_type.fnInfo(); | 2583 | const fn_info = zig_fn_type.fnInfo(); |
| 2579 | const target = dg.module.getTarget(); | 2584 | const target = mod.getTarget(); |
| 2580 | const sret = firstParamSRet(fn_info, target); | 2585 | const sret = firstParamSRet(fn_info, mod); |
| 2581 | 2586 | ||
| 2582 | const fn_type = try dg.lowerType(zig_fn_type); | 2587 | const fn_type = try dg.lowerType(zig_fn_type); |
| 2583 | 2588 | ||
| 2584 | const fqn = try decl.getFullyQualifiedName(dg.module); | 2589 | const fqn = try decl.getFullyQualifiedName(mod); |
| 2585 | defer dg.gpa.free(fqn); | 2590 | defer dg.gpa.free(fqn); |
| 2586 | 2591 | ||
| 2587 | const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); | 2592 | const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); |
| ... | @@ -2593,7 +2598,7 @@ pub const DeclGen = struct { | ... | @@ -2593,7 +2598,7 @@ pub const DeclGen = struct { |
| 2593 | llvm_fn.setLinkage(.Internal); | 2598 | llvm_fn.setLinkage(.Internal); |
| 2594 | llvm_fn.setUnnamedAddr(.True); | 2599 | llvm_fn.setUnnamedAddr(.True); |
| 2595 | } else { | 2600 | } else { |
| 2596 | if (dg.module.getTarget().isWasm()) { | 2601 | if (target.isWasm()) { |
| 2597 | dg.addFnAttrString(llvm_fn, "wasm-import-name", std.mem.sliceTo(decl.name, 0)); | 2602 | dg.addFnAttrString(llvm_fn, "wasm-import-name", std.mem.sliceTo(decl.name, 0)); |
| 2598 | if (decl.getExternFn().?.lib_name) |lib_name| { | 2603 | if (decl.getExternFn().?.lib_name) |lib_name| { |
| 2599 | const module_name = std.mem.sliceTo(lib_name, 0); | 2604 | const module_name = std.mem.sliceTo(lib_name, 0); |
| ... | @@ -2612,8 +2617,8 @@ pub const DeclGen = struct { | ... | @@ -2612,8 +2617,8 @@ pub const DeclGen = struct { |
| 2612 | llvm_fn.addSretAttr(raw_llvm_ret_ty); | 2617 | llvm_fn.addSretAttr(raw_llvm_ret_ty); |
| 2613 | } | 2618 | } |
| 2614 | 2619 | ||
| 2615 | const err_return_tracing = fn_info.return_type.isError() and | 2620 | const err_return_tracing = fn_info.return_type.isError(mod) and |
| 2616 | dg.module.comp.bin_file.options.error_return_tracing; | 2621 | mod.comp.bin_file.options.error_return_tracing; |
| 2617 | 2622 | ||
| 2618 | if (err_return_tracing) { | 2623 | if (err_return_tracing) { |
| 2619 | dg.addArgAttr(llvm_fn, @boolToInt(sret), "nonnull"); | 2624 | dg.addArgAttr(llvm_fn, @boolToInt(sret), "nonnull"); |
| ... | @@ -2656,14 +2661,14 @@ pub const DeclGen = struct { | ... | @@ -2656,14 +2661,14 @@ pub const DeclGen = struct { |
| 2656 | .byval => { | 2661 | .byval => { |
| 2657 | const param_index = it.zig_index - 1; | 2662 | const param_index = it.zig_index - 1; |
| 2658 | const param_ty = fn_info.param_types[param_index]; | 2663 | const param_ty = fn_info.param_types[param_index]; |
| 2659 | if (!isByRef(param_ty)) { | 2664 | if (!isByRef(param_ty, mod)) { |
| 2660 | dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); | 2665 | dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); |
| 2661 | } | 2666 | } |
| 2662 | }, | 2667 | }, |
| 2663 | .byref => { | 2668 | .byref => { |
| 2664 | const param_ty = fn_info.param_types[it.zig_index - 1]; | 2669 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 2665 | const param_llvm_ty = try dg.lowerType(param_ty); | 2670 | const param_llvm_ty = try dg.lowerType(param_ty); |
| 2666 | const alignment = param_ty.abiAlignment(target); | 2671 | const alignment = param_ty.abiAlignment(mod); |
| 2667 | dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); | 2672 | dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); |
| 2668 | }, | 2673 | }, |
| 2669 | .byref_mut => { | 2674 | .byref_mut => { |
| ... | @@ -2784,12 +2789,13 @@ pub const DeclGen = struct { | ... | @@ -2784,12 +2789,13 @@ pub const DeclGen = struct { |
| 2784 | 2789 | ||
| 2785 | fn lowerType(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type { | 2790 | fn lowerType(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type { |
| 2786 | const llvm_ty = try lowerTypeInner(dg, t); | 2791 | const llvm_ty = try lowerTypeInner(dg, t); |
| 2792 | const mod = dg.module; | ||
| 2787 | if (std.debug.runtime_safety and false) check: { | 2793 | if (std.debug.runtime_safety and false) check: { |
| 2788 | if (t.zigTypeTag() == .Opaque) break :check; | 2794 | if (t.zigTypeTag(mod) == .Opaque) break :check; |
| 2789 | if (!t.hasRuntimeBits()) break :check; | 2795 | if (!t.hasRuntimeBits(mod)) break :check; |
| 2790 | if (!llvm_ty.isSized().toBool()) break :check; | 2796 | if (!llvm_ty.isSized().toBool()) break :check; |
| 2791 | 2797 | ||
| 2792 | const zig_size = t.abiSize(dg.module.getTarget()); | 2798 | const zig_size = t.abiSize(mod); |
| 2793 | const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty); | 2799 | const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty); |
| 2794 | if (llvm_size != zig_size) { | 2800 | if (llvm_size != zig_size) { |
| 2795 | log.err("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}", .{ | 2801 | log.err("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}", .{ |
| ... | @@ -2802,18 +2808,18 @@ pub const DeclGen = struct { | ... | @@ -2802,18 +2808,18 @@ pub const DeclGen = struct { |
| 2802 | 2808 | ||
| 2803 | fn lowerTypeInner(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type { | 2809 | fn lowerTypeInner(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type { |
| 2804 | const gpa = dg.gpa; | 2810 | const gpa = dg.gpa; |
| 2805 | const target = dg.module.getTarget(); | 2811 | const mod = dg.module; |
| 2806 | switch (t.zigTypeTag()) { | 2812 | const target = mod.getTarget(); |
| 2813 | switch (t.zigTypeTag(mod)) { | ||
| 2807 | .Void, .NoReturn => return dg.context.voidType(), | 2814 | .Void, .NoReturn => return dg.context.voidType(), |
| 2808 | .Int => { | 2815 | .Int => { |
| 2809 | const info = t.intInfo(target); | 2816 | const info = t.intInfo(mod); |
| 2810 | assert(info.bits != 0); | 2817 | assert(info.bits != 0); |
| 2811 | return dg.context.intType(info.bits); | 2818 | return dg.context.intType(info.bits); |
| 2812 | }, | 2819 | }, |
| 2813 | .Enum => { | 2820 | .Enum => { |
| 2814 | var buffer: Type.Payload.Bits = undefined; | 2821 | const int_ty = t.intTagType(); |
| 2815 | const int_ty = t.intTagType(&buffer); | 2822 | const bit_count = int_ty.intInfo(mod).bits; |
| 2816 | const bit_count = int_ty.intInfo(target).bits; | ||
| 2817 | assert(bit_count != 0); | 2823 | assert(bit_count != 0); |
| 2818 | return dg.context.intType(bit_count); | 2824 | return dg.context.intType(bit_count); |
| 2819 | }, | 2825 | }, |
| ... | @@ -2863,7 +2869,7 @@ pub const DeclGen = struct { | ... | @@ -2863,7 +2869,7 @@ pub const DeclGen = struct { |
| 2863 | }, | 2869 | }, |
| 2864 | .Array => { | 2870 | .Array => { |
| 2865 | const elem_ty = t.childType(); | 2871 | const elem_ty = t.childType(); |
| 2866 | assert(elem_ty.onePossibleValue() == null); | 2872 | assert(elem_ty.onePossibleValue(mod) == null); |
| 2867 | const elem_llvm_ty = try dg.lowerType(elem_ty); | 2873 | const elem_llvm_ty = try dg.lowerType(elem_ty); |
| 2868 | const total_len = t.arrayLen() + @boolToInt(t.sentinel() != null); | 2874 | const total_len = t.arrayLen() + @boolToInt(t.sentinel() != null); |
| 2869 | return elem_llvm_ty.arrayType(@intCast(c_uint, total_len)); | 2875 | return elem_llvm_ty.arrayType(@intCast(c_uint, total_len)); |
| ... | @@ -2875,11 +2881,11 @@ pub const DeclGen = struct { | ... | @@ -2875,11 +2881,11 @@ pub const DeclGen = struct { |
| 2875 | .Optional => { | 2881 | .Optional => { |
| 2876 | var buf: Type.Payload.ElemType = undefined; | 2882 | var buf: Type.Payload.ElemType = undefined; |
| 2877 | const child_ty = t.optionalChild(&buf); | 2883 | const child_ty = t.optionalChild(&buf); |
| 2878 | if (!child_ty.hasRuntimeBitsIgnoreComptime()) { | 2884 | if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2879 | return dg.context.intType(8); | 2885 | return dg.context.intType(8); |
| 2880 | } | 2886 | } |
| 2881 | const payload_llvm_ty = try dg.lowerType(child_ty); | 2887 | const payload_llvm_ty = try dg.lowerType(child_ty); |
| 2882 | if (t.optionalReprIsPayload()) { | 2888 | if (t.optionalReprIsPayload(mod)) { |
| 2883 | return payload_llvm_ty; | 2889 | return payload_llvm_ty; |
| 2884 | } | 2890 | } |
| 2885 | 2891 | ||
| ... | @@ -2887,8 +2893,8 @@ pub const DeclGen = struct { | ... | @@ -2887,8 +2893,8 @@ pub const DeclGen = struct { |
| 2887 | var fields_buf: [3]*llvm.Type = .{ | 2893 | var fields_buf: [3]*llvm.Type = .{ |
| 2888 | payload_llvm_ty, dg.context.intType(8), undefined, | 2894 | payload_llvm_ty, dg.context.intType(8), undefined, |
| 2889 | }; | 2895 | }; |
| 2890 | const offset = child_ty.abiSize(target) + 1; | 2896 | const offset = child_ty.abiSize(mod) + 1; |
| 2891 | const abi_size = t.abiSize(target); | 2897 | const abi_size = t.abiSize(mod); |
| 2892 | const padding = @intCast(c_uint, abi_size - offset); | 2898 | const padding = @intCast(c_uint, abi_size - offset); |
| 2893 | if (padding == 0) { | 2899 | if (padding == 0) { |
| 2894 | return dg.context.structType(&fields_buf, 2, .False); | 2900 | return dg.context.structType(&fields_buf, 2, .False); |
| ... | @@ -2898,17 +2904,17 @@ pub const DeclGen = struct { | ... | @@ -2898,17 +2904,17 @@ pub const DeclGen = struct { |
| 2898 | }, | 2904 | }, |
| 2899 | .ErrorUnion => { | 2905 | .ErrorUnion => { |
| 2900 | const payload_ty = t.errorUnionPayload(); | 2906 | const payload_ty = t.errorUnionPayload(); |
| 2901 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 2907 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2902 | return try dg.lowerType(Type.anyerror); | 2908 | return try dg.lowerType(Type.anyerror); |
| 2903 | } | 2909 | } |
| 2904 | const llvm_error_type = try dg.lowerType(Type.anyerror); | 2910 | const llvm_error_type = try dg.lowerType(Type.anyerror); |
| 2905 | const llvm_payload_type = try dg.lowerType(payload_ty); | 2911 | const llvm_payload_type = try dg.lowerType(payload_ty); |
| 2906 | 2912 | ||
| 2907 | const payload_align = payload_ty.abiAlignment(target); | 2913 | const payload_align = payload_ty.abiAlignment(mod); |
| 2908 | const error_align = Type.anyerror.abiAlignment(target); | 2914 | const error_align = Type.anyerror.abiAlignment(mod); |
| 2909 | 2915 | ||
| 2910 | const payload_size = payload_ty.abiSize(target); | 2916 | const payload_size = payload_ty.abiSize(mod); |
| 2911 | const error_size = Type.anyerror.abiSize(target); | 2917 | const error_size = Type.anyerror.abiSize(mod); |
| 2912 | 2918 | ||
| 2913 | var fields_buf: [3]*llvm.Type = undefined; | 2919 | var fields_buf: [3]*llvm.Type = undefined; |
| 2914 | if (error_align > payload_align) { | 2920 | if (error_align > payload_align) { |
| ... | @@ -2964,9 +2970,9 @@ pub const DeclGen = struct { | ... | @@ -2964,9 +2970,9 @@ pub const DeclGen = struct { |
| 2964 | 2970 | ||
| 2965 | for (tuple.types, 0..) |field_ty, i| { | 2971 | for (tuple.types, 0..) |field_ty, i| { |
| 2966 | const field_val = tuple.values[i]; | 2972 | const field_val = tuple.values[i]; |
| 2967 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue; | 2973 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; |
| 2968 | 2974 | ||
| 2969 | const field_align = field_ty.abiAlignment(target); | 2975 | const field_align = field_ty.abiAlignment(mod); |
| 2970 | big_align = @max(big_align, field_align); | 2976 | big_align = @max(big_align, field_align); |
| 2971 | const prev_offset = offset; | 2977 | const prev_offset = offset; |
| 2972 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); | 2978 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| ... | @@ -2979,7 +2985,7 @@ pub const DeclGen = struct { | ... | @@ -2979,7 +2985,7 @@ pub const DeclGen = struct { |
| 2979 | const field_llvm_ty = try dg.lowerType(field_ty); | 2985 | const field_llvm_ty = try dg.lowerType(field_ty); |
| 2980 | try llvm_field_types.append(gpa, field_llvm_ty); | 2986 | try llvm_field_types.append(gpa, field_llvm_ty); |
| 2981 | 2987 | ||
| 2982 | offset += field_ty.abiSize(target); | 2988 | offset += field_ty.abiSize(mod); |
| 2983 | } | 2989 | } |
| 2984 | { | 2990 | { |
| 2985 | const prev_offset = offset; | 2991 | const prev_offset = offset; |
| ... | @@ -3027,11 +3033,11 @@ pub const DeclGen = struct { | ... | @@ -3027,11 +3033,11 @@ pub const DeclGen = struct { |
| 3027 | var big_align: u32 = 1; | 3033 | var big_align: u32 = 1; |
| 3028 | var any_underaligned_fields = false; | 3034 | var any_underaligned_fields = false; |
| 3029 | 3035 | ||
| 3030 | var it = struct_obj.runtimeFieldIterator(); | 3036 | var it = struct_obj.runtimeFieldIterator(mod); |
| 3031 | while (it.next()) |field_and_index| { | 3037 | while (it.next()) |field_and_index| { |
| 3032 | const field = field_and_index.field; | 3038 | const field = field_and_index.field; |
| 3033 | const field_align = field.alignment(target, struct_obj.layout); | 3039 | const field_align = field.alignment(mod, struct_obj.layout); |
| 3034 | const field_ty_align = field.ty.abiAlignment(target); | 3040 | const field_ty_align = field.ty.abiAlignment(mod); |
| 3035 | any_underaligned_fields = any_underaligned_fields or | 3041 | any_underaligned_fields = any_underaligned_fields or |
| 3036 | field_align < field_ty_align; | 3042 | field_align < field_ty_align; |
| 3037 | big_align = @max(big_align, field_align); | 3043 | big_align = @max(big_align, field_align); |
| ... | @@ -3046,7 +3052,7 @@ pub const DeclGen = struct { | ... | @@ -3046,7 +3052,7 @@ pub const DeclGen = struct { |
| 3046 | const field_llvm_ty = try dg.lowerType(field.ty); | 3052 | const field_llvm_ty = try dg.lowerType(field.ty); |
| 3047 | try llvm_field_types.append(gpa, field_llvm_ty); | 3053 | try llvm_field_types.append(gpa, field_llvm_ty); |
| 3048 | 3054 | ||
| 3049 | offset += field.ty.abiSize(target); | 3055 | offset += field.ty.abiSize(mod); |
| 3050 | } | 3056 | } |
| 3051 | { | 3057 | { |
| 3052 | const prev_offset = offset; | 3058 | const prev_offset = offset; |
| ... | @@ -3074,11 +3080,11 @@ pub const DeclGen = struct { | ... | @@ -3074,11 +3080,11 @@ pub const DeclGen = struct { |
| 3074 | // reference, we need to copy it here. | 3080 | // reference, we need to copy it here. |
| 3075 | gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator()); | 3081 | gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator()); |
| 3076 | 3082 | ||
| 3077 | const layout = t.unionGetLayout(target); | 3083 | const layout = t.unionGetLayout(mod); |
| 3078 | const union_obj = t.cast(Type.Payload.Union).?.data; | 3084 | const union_obj = t.cast(Type.Payload.Union).?.data; |
| 3079 | 3085 | ||
| 3080 | if (union_obj.layout == .Packed) { | 3086 | if (union_obj.layout == .Packed) { |
| 3081 | const bitsize = @intCast(c_uint, t.bitSize(target)); | 3087 | const bitsize = @intCast(c_uint, t.bitSize(mod)); |
| 3082 | const int_llvm_ty = dg.context.intType(bitsize); | 3088 | const int_llvm_ty = dg.context.intType(bitsize); |
| 3083 | gop.value_ptr.* = int_llvm_ty; | 3089 | gop.value_ptr.* = int_llvm_ty; |
| 3084 | return int_llvm_ty; | 3090 | return int_llvm_ty; |
| ... | @@ -3155,19 +3161,19 @@ pub const DeclGen = struct { | ... | @@ -3155,19 +3161,19 @@ pub const DeclGen = struct { |
| 3155 | } | 3161 | } |
| 3156 | 3162 | ||
| 3157 | fn lowerTypeFn(dg: *DeclGen, fn_ty: Type) Allocator.Error!*llvm.Type { | 3163 | fn lowerTypeFn(dg: *DeclGen, fn_ty: Type) Allocator.Error!*llvm.Type { |
| 3158 | const target = dg.module.getTarget(); | 3164 | const mod = dg.module; |
| 3159 | const fn_info = fn_ty.fnInfo(); | 3165 | const fn_info = fn_ty.fnInfo(); |
| 3160 | const llvm_ret_ty = try lowerFnRetTy(dg, fn_info); | 3166 | const llvm_ret_ty = try lowerFnRetTy(dg, fn_info); |
| 3161 | 3167 | ||
| 3162 | var llvm_params = std.ArrayList(*llvm.Type).init(dg.gpa); | 3168 | var llvm_params = std.ArrayList(*llvm.Type).init(dg.gpa); |
| 3163 | defer llvm_params.deinit(); | 3169 | defer llvm_params.deinit(); |
| 3164 | 3170 | ||
| 3165 | if (firstParamSRet(fn_info, target)) { | 3171 | if (firstParamSRet(fn_info, mod)) { |
| 3166 | try llvm_params.append(dg.context.pointerType(0)); | 3172 | try llvm_params.append(dg.context.pointerType(0)); |
| 3167 | } | 3173 | } |
| 3168 | 3174 | ||
| 3169 | if (fn_info.return_type.isError() and | 3175 | if (fn_info.return_type.isError(mod) and |
| 3170 | dg.module.comp.bin_file.options.error_return_tracing) | 3176 | mod.comp.bin_file.options.error_return_tracing) |
| 3171 | { | 3177 | { |
| 3172 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 3178 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 3173 | .base = .{ .tag = .single_mut_pointer }, | 3179 | .base = .{ .tag = .single_mut_pointer }, |
| ... | @@ -3189,14 +3195,14 @@ pub const DeclGen = struct { | ... | @@ -3189,14 +3195,14 @@ pub const DeclGen = struct { |
| 3189 | }, | 3195 | }, |
| 3190 | .abi_sized_int => { | 3196 | .abi_sized_int => { |
| 3191 | const param_ty = fn_info.param_types[it.zig_index - 1]; | 3197 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 3192 | const abi_size = @intCast(c_uint, param_ty.abiSize(target)); | 3198 | const abi_size = @intCast(c_uint, param_ty.abiSize(mod)); |
| 3193 | try llvm_params.append(dg.context.intType(abi_size * 8)); | 3199 | try llvm_params.append(dg.context.intType(abi_size * 8)); |
| 3194 | }, | 3200 | }, |
| 3195 | .slice => { | 3201 | .slice => { |
| 3196 | const param_ty = fn_info.param_types[it.zig_index - 1]; | 3202 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 3197 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 3203 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 3198 | var opt_buf: Type.Payload.ElemType = undefined; | 3204 | var opt_buf: Type.Payload.ElemType = undefined; |
| 3199 | const ptr_ty = if (param_ty.zigTypeTag() == .Optional) | 3205 | const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional) |
| 3200 | param_ty.optionalChild(&opt_buf).slicePtrFieldType(&buf) | 3206 | param_ty.optionalChild(&opt_buf).slicePtrFieldType(&buf) |
| 3201 | else | 3207 | else |
| 3202 | param_ty.slicePtrFieldType(&buf); | 3208 | param_ty.slicePtrFieldType(&buf); |
| ... | @@ -3215,7 +3221,7 @@ pub const DeclGen = struct { | ... | @@ -3215,7 +3221,7 @@ pub const DeclGen = struct { |
| 3215 | }, | 3221 | }, |
| 3216 | .float_array => |count| { | 3222 | .float_array => |count| { |
| 3217 | const param_ty = fn_info.param_types[it.zig_index - 1]; | 3223 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 3218 | const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty).?); | 3224 | const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?); |
| 3219 | const field_count = @intCast(c_uint, count); | 3225 | const field_count = @intCast(c_uint, count); |
| 3220 | const arr_ty = float_ty.arrayType(field_count); | 3226 | const arr_ty = float_ty.arrayType(field_count); |
| 3221 | try llvm_params.append(arr_ty); | 3227 | try llvm_params.append(arr_ty); |
| ... | @@ -3239,11 +3245,12 @@ pub const DeclGen = struct { | ... | @@ -3239,11 +3245,12 @@ pub const DeclGen = struct { |
| 3239 | /// being a zero bit type, but it should still be lowered as an i8 in such case. | 3245 | /// being a zero bit type, but it should still be lowered as an i8 in such case. |
| 3240 | /// There are other similar cases handled here as well. | 3246 | /// There are other similar cases handled here as well. |
| 3241 | fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*llvm.Type { | 3247 | fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*llvm.Type { |
| 3242 | const lower_elem_ty = switch (elem_ty.zigTypeTag()) { | 3248 | const mod = dg.module; |
| 3249 | const lower_elem_ty = switch (elem_ty.zigTypeTag(mod)) { | ||
| 3243 | .Opaque => true, | 3250 | .Opaque => true, |
| 3244 | .Fn => !elem_ty.fnInfo().is_generic, | 3251 | .Fn => !elem_ty.fnInfo().is_generic, |
| 3245 | .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(), | 3252 | .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(mod), |
| 3246 | else => elem_ty.hasRuntimeBitsIgnoreComptime(), | 3253 | else => elem_ty.hasRuntimeBitsIgnoreComptime(mod), |
| 3247 | }; | 3254 | }; |
| 3248 | const llvm_elem_ty = if (lower_elem_ty) | 3255 | const llvm_elem_ty = if (lower_elem_ty) |
| 3249 | try dg.lowerType(elem_ty) | 3256 | try dg.lowerType(elem_ty) |
| ... | @@ -3262,9 +3269,9 @@ pub const DeclGen = struct { | ... | @@ -3262,9 +3269,9 @@ pub const DeclGen = struct { |
| 3262 | const llvm_type = try dg.lowerType(tv.ty); | 3269 | const llvm_type = try dg.lowerType(tv.ty); |
| 3263 | return llvm_type.getUndef(); | 3270 | return llvm_type.getUndef(); |
| 3264 | } | 3271 | } |
| 3265 | const target = dg.module.getTarget(); | 3272 | const mod = dg.module; |
| 3266 | 3273 | const target = mod.getTarget(); | |
| 3267 | switch (tv.ty.zigTypeTag()) { | 3274 | switch (tv.ty.zigTypeTag(mod)) { |
| 3268 | .Bool => { | 3275 | .Bool => { |
| 3269 | const llvm_type = try dg.lowerType(tv.ty); | 3276 | const llvm_type = try dg.lowerType(tv.ty); |
| 3270 | return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(); | 3277 | return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(); |
| ... | @@ -3276,8 +3283,8 @@ pub const DeclGen = struct { | ... | @@ -3276,8 +3283,8 @@ pub const DeclGen = struct { |
| 3276 | .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data), | 3283 | .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data), |
| 3277 | else => { | 3284 | else => { |
| 3278 | var bigint_space: Value.BigIntSpace = undefined; | 3285 | var bigint_space: Value.BigIntSpace = undefined; |
| 3279 | const bigint = tv.val.toBigInt(&bigint_space, target); | 3286 | const bigint = tv.val.toBigInt(&bigint_space, mod); |
| 3280 | const int_info = tv.ty.intInfo(target); | 3287 | const int_info = tv.ty.intInfo(mod); |
| 3281 | assert(int_info.bits != 0); | 3288 | assert(int_info.bits != 0); |
| 3282 | const llvm_type = dg.context.intType(int_info.bits); | 3289 | const llvm_type = dg.context.intType(int_info.bits); |
| 3283 | 3290 | ||
| ... | @@ -3304,9 +3311,9 @@ pub const DeclGen = struct { | ... | @@ -3304,9 +3311,9 @@ pub const DeclGen = struct { |
| 3304 | const int_val = tv.enumToInt(&int_buffer); | 3311 | const int_val = tv.enumToInt(&int_buffer); |
| 3305 | 3312 | ||
| 3306 | var bigint_space: Value.BigIntSpace = undefined; | 3313 | var bigint_space: Value.BigIntSpace = undefined; |
| 3307 | const bigint = int_val.toBigInt(&bigint_space, target); | 3314 | const bigint = int_val.toBigInt(&bigint_space, mod); |
| 3308 | 3315 | ||
| 3309 | const int_info = tv.ty.intInfo(target); | 3316 | const int_info = tv.ty.intInfo(mod); |
| 3310 | const llvm_type = dg.context.intType(int_info.bits); | 3317 | const llvm_type = dg.context.intType(int_info.bits); |
| 3311 | 3318 | ||
| 3312 | const unsigned_val = v: { | 3319 | const unsigned_val = v: { |
| ... | @@ -3408,7 +3415,7 @@ pub const DeclGen = struct { | ... | @@ -3408,7 +3415,7 @@ pub const DeclGen = struct { |
| 3408 | }, | 3415 | }, |
| 3409 | .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { | 3416 | .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { |
| 3410 | const llvm_usize = try dg.lowerType(Type.usize); | 3417 | const llvm_usize = try dg.lowerType(Type.usize); |
| 3411 | const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(target), .False); | 3418 | const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(mod), .False); |
| 3412 | return llvm_int.constIntToPtr(try dg.lowerType(tv.ty)); | 3419 | return llvm_int.constIntToPtr(try dg.lowerType(tv.ty)); |
| 3413 | }, | 3420 | }, |
| 3414 | .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => { | 3421 | .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => { |
| ... | @@ -3439,7 +3446,7 @@ pub const DeclGen = struct { | ... | @@ -3439,7 +3446,7 @@ pub const DeclGen = struct { |
| 3439 | const str_lit = tv.val.castTag(.str_lit).?.data; | 3446 | const str_lit = tv.val.castTag(.str_lit).?.data; |
| 3440 | const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | 3447 | const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; |
| 3441 | if (tv.ty.sentinel()) |sent_val| { | 3448 | if (tv.ty.sentinel()) |sent_val| { |
| 3442 | const byte = @intCast(u8, sent_val.toUnsignedInt(target)); | 3449 | const byte = @intCast(u8, sent_val.toUnsignedInt(mod)); |
| 3443 | if (byte == 0 and bytes.len > 0) { | 3450 | if (byte == 0 and bytes.len > 0) { |
| 3444 | return dg.context.constString( | 3451 | return dg.context.constString( |
| 3445 | bytes.ptr, | 3452 | bytes.ptr, |
| ... | @@ -3549,13 +3556,13 @@ pub const DeclGen = struct { | ... | @@ -3549,13 +3556,13 @@ pub const DeclGen = struct { |
| 3549 | const payload_ty = tv.ty.optionalChild(&buf); | 3556 | const payload_ty = tv.ty.optionalChild(&buf); |
| 3550 | 3557 | ||
| 3551 | const llvm_i8 = dg.context.intType(8); | 3558 | const llvm_i8 = dg.context.intType(8); |
| 3552 | const is_pl = !tv.val.isNull(); | 3559 | const is_pl = !tv.val.isNull(mod); |
| 3553 | const non_null_bit = if (is_pl) llvm_i8.constInt(1, .False) else llvm_i8.constNull(); | 3560 | const non_null_bit = if (is_pl) llvm_i8.constInt(1, .False) else llvm_i8.constNull(); |
| 3554 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 3561 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3555 | return non_null_bit; | 3562 | return non_null_bit; |
| 3556 | } | 3563 | } |
| 3557 | const llvm_ty = try dg.lowerType(tv.ty); | 3564 | const llvm_ty = try dg.lowerType(tv.ty); |
| 3558 | if (tv.ty.optionalReprIsPayload()) { | 3565 | if (tv.ty.optionalReprIsPayload(mod)) { |
| 3559 | if (tv.val.castTag(.opt_payload)) |payload| { | 3566 | if (tv.val.castTag(.opt_payload)) |payload| { |
| 3560 | return dg.lowerValue(.{ .ty = payload_ty, .val = payload.data }); | 3567 | return dg.lowerValue(.{ .ty = payload_ty, .val = payload.data }); |
| 3561 | } else if (is_pl) { | 3568 | } else if (is_pl) { |
| ... | @@ -3564,7 +3571,7 @@ pub const DeclGen = struct { | ... | @@ -3564,7 +3571,7 @@ pub const DeclGen = struct { |
| 3564 | return llvm_ty.constNull(); | 3571 | return llvm_ty.constNull(); |
| 3565 | } | 3572 | } |
| 3566 | } | 3573 | } |
| 3567 | assert(payload_ty.zigTypeTag() != .Fn); | 3574 | assert(payload_ty.zigTypeTag(mod) != .Fn); |
| 3568 | 3575 | ||
| 3569 | const llvm_field_count = llvm_ty.countStructElementTypes(); | 3576 | const llvm_field_count = llvm_ty.countStructElementTypes(); |
| 3570 | var fields_buf: [3]*llvm.Value = undefined; | 3577 | var fields_buf: [3]*llvm.Value = undefined; |
| ... | @@ -3607,14 +3614,14 @@ pub const DeclGen = struct { | ... | @@ -3607,14 +3614,14 @@ pub const DeclGen = struct { |
| 3607 | const payload_type = tv.ty.errorUnionPayload(); | 3614 | const payload_type = tv.ty.errorUnionPayload(); |
| 3608 | const is_pl = tv.val.errorUnionIsPayload(); | 3615 | const is_pl = tv.val.errorUnionIsPayload(); |
| 3609 | 3616 | ||
| 3610 | if (!payload_type.hasRuntimeBitsIgnoreComptime()) { | 3617 | if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3611 | // We use the error type directly as the type. | 3618 | // We use the error type directly as the type. |
| 3612 | const err_val = if (!is_pl) tv.val else Value.initTag(.zero); | 3619 | const err_val = if (!is_pl) tv.val else Value.initTag(.zero); |
| 3613 | return dg.lowerValue(.{ .ty = Type.anyerror, .val = err_val }); | 3620 | return dg.lowerValue(.{ .ty = Type.anyerror, .val = err_val }); |
| 3614 | } | 3621 | } |
| 3615 | 3622 | ||
| 3616 | const payload_align = payload_type.abiAlignment(target); | 3623 | const payload_align = payload_type.abiAlignment(mod); |
| 3617 | const error_align = Type.anyerror.abiAlignment(target); | 3624 | const error_align = Type.anyerror.abiAlignment(mod); |
| 3618 | const llvm_error_value = try dg.lowerValue(.{ | 3625 | const llvm_error_value = try dg.lowerValue(.{ |
| 3619 | .ty = Type.anyerror, | 3626 | .ty = Type.anyerror, |
| 3620 | .val = if (is_pl) Value.initTag(.zero) else tv.val, | 3627 | .val = if (is_pl) Value.initTag(.zero) else tv.val, |
| ... | @@ -3661,9 +3668,9 @@ pub const DeclGen = struct { | ... | @@ -3661,9 +3668,9 @@ pub const DeclGen = struct { |
| 3661 | 3668 | ||
| 3662 | for (tuple.types, 0..) |field_ty, i| { | 3669 | for (tuple.types, 0..) |field_ty, i| { |
| 3663 | if (tuple.values[i].tag() != .unreachable_value) continue; | 3670 | if (tuple.values[i].tag() != .unreachable_value) continue; |
| 3664 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue; | 3671 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 3665 | 3672 | ||
| 3666 | const field_align = field_ty.abiAlignment(target); | 3673 | const field_align = field_ty.abiAlignment(mod); |
| 3667 | big_align = @max(big_align, field_align); | 3674 | big_align = @max(big_align, field_align); |
| 3668 | const prev_offset = offset; | 3675 | const prev_offset = offset; |
| 3669 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); | 3676 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| ... | @@ -3685,7 +3692,7 @@ pub const DeclGen = struct { | ... | @@ -3685,7 +3692,7 @@ pub const DeclGen = struct { |
| 3685 | 3692 | ||
| 3686 | llvm_fields.appendAssumeCapacity(field_llvm_val); | 3693 | llvm_fields.appendAssumeCapacity(field_llvm_val); |
| 3687 | 3694 | ||
| 3688 | offset += field_ty.abiSize(target); | 3695 | offset += field_ty.abiSize(mod); |
| 3689 | } | 3696 | } |
| 3690 | { | 3697 | { |
| 3691 | const prev_offset = offset; | 3698 | const prev_offset = offset; |
| ... | @@ -3715,7 +3722,7 @@ pub const DeclGen = struct { | ... | @@ -3715,7 +3722,7 @@ pub const DeclGen = struct { |
| 3715 | 3722 | ||
| 3716 | if (struct_obj.layout == .Packed) { | 3723 | if (struct_obj.layout == .Packed) { |
| 3717 | assert(struct_obj.haveLayout()); | 3724 | assert(struct_obj.haveLayout()); |
| 3718 | const big_bits = struct_obj.backing_int_ty.bitSize(target); | 3725 | const big_bits = struct_obj.backing_int_ty.bitSize(mod); |
| 3719 | const int_llvm_ty = dg.context.intType(@intCast(c_uint, big_bits)); | 3726 | const int_llvm_ty = dg.context.intType(@intCast(c_uint, big_bits)); |
| 3720 | const fields = struct_obj.fields.values(); | 3727 | const fields = struct_obj.fields.values(); |
| 3721 | comptime assert(Type.packed_struct_layout_version == 2); | 3728 | comptime assert(Type.packed_struct_layout_version == 2); |
| ... | @@ -3723,15 +3730,15 @@ pub const DeclGen = struct { | ... | @@ -3723,15 +3730,15 @@ pub const DeclGen = struct { |
| 3723 | var running_bits: u16 = 0; | 3730 | var running_bits: u16 = 0; |
| 3724 | for (field_vals, 0..) |field_val, i| { | 3731 | for (field_vals, 0..) |field_val, i| { |
| 3725 | const field = fields[i]; | 3732 | const field = fields[i]; |
| 3726 | if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue; | 3733 | if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 3727 | 3734 | ||
| 3728 | const non_int_val = try dg.lowerValue(.{ | 3735 | const non_int_val = try dg.lowerValue(.{ |
| 3729 | .ty = field.ty, | 3736 | .ty = field.ty, |
| 3730 | .val = field_val, | 3737 | .val = field_val, |
| 3731 | }); | 3738 | }); |
| 3732 | const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); | 3739 | const ty_bit_size = @intCast(u16, field.ty.bitSize(mod)); |
| 3733 | const small_int_ty = dg.context.intType(ty_bit_size); | 3740 | const small_int_ty = dg.context.intType(ty_bit_size); |
| 3734 | const small_int_val = if (field.ty.isPtrAtRuntime()) | 3741 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) |
| 3735 | non_int_val.constPtrToInt(small_int_ty) | 3742 | non_int_val.constPtrToInt(small_int_ty) |
| 3736 | else | 3743 | else |
| 3737 | non_int_val.constBitCast(small_int_ty); | 3744 | non_int_val.constBitCast(small_int_ty); |
| ... | @@ -3756,10 +3763,10 @@ pub const DeclGen = struct { | ... | @@ -3756,10 +3763,10 @@ pub const DeclGen = struct { |
| 3756 | var big_align: u32 = 0; | 3763 | var big_align: u32 = 0; |
| 3757 | var need_unnamed = false; | 3764 | var need_unnamed = false; |
| 3758 | 3765 | ||
| 3759 | var it = struct_obj.runtimeFieldIterator(); | 3766 | var it = struct_obj.runtimeFieldIterator(mod); |
| 3760 | while (it.next()) |field_and_index| { | 3767 | while (it.next()) |field_and_index| { |
| 3761 | const field = field_and_index.field; | 3768 | const field = field_and_index.field; |
| 3762 | const field_align = field.alignment(target, struct_obj.layout); | 3769 | const field_align = field.alignment(mod, struct_obj.layout); |
| 3763 | big_align = @max(big_align, field_align); | 3770 | big_align = @max(big_align, field_align); |
| 3764 | const prev_offset = offset; | 3771 | const prev_offset = offset; |
| 3765 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); | 3772 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| ... | @@ -3781,7 +3788,7 @@ pub const DeclGen = struct { | ... | @@ -3781,7 +3788,7 @@ pub const DeclGen = struct { |
| 3781 | 3788 | ||
| 3782 | llvm_fields.appendAssumeCapacity(field_llvm_val); | 3789 | llvm_fields.appendAssumeCapacity(field_llvm_val); |
| 3783 | 3790 | ||
| 3784 | offset += field.ty.abiSize(target); | 3791 | offset += field.ty.abiSize(mod); |
| 3785 | } | 3792 | } |
| 3786 | { | 3793 | { |
| 3787 | const prev_offset = offset; | 3794 | const prev_offset = offset; |
| ... | @@ -3810,7 +3817,7 @@ pub const DeclGen = struct { | ... | @@ -3810,7 +3817,7 @@ pub const DeclGen = struct { |
| 3810 | const llvm_union_ty = try dg.lowerType(tv.ty); | 3817 | const llvm_union_ty = try dg.lowerType(tv.ty); |
| 3811 | const tag_and_val = tv.val.castTag(.@"union").?.data; | 3818 | const tag_and_val = tv.val.castTag(.@"union").?.data; |
| 3812 | 3819 | ||
| 3813 | const layout = tv.ty.unionGetLayout(target); | 3820 | const layout = tv.ty.unionGetLayout(mod); |
| 3814 | 3821 | ||
| 3815 | if (layout.payload_size == 0) { | 3822 | if (layout.payload_size == 0) { |
| 3816 | return lowerValue(dg, .{ | 3823 | return lowerValue(dg, .{ |
| ... | @@ -3824,12 +3831,12 @@ pub const DeclGen = struct { | ... | @@ -3824,12 +3831,12 @@ pub const DeclGen = struct { |
| 3824 | 3831 | ||
| 3825 | const field_ty = union_obj.fields.values()[field_index].ty; | 3832 | const field_ty = union_obj.fields.values()[field_index].ty; |
| 3826 | if (union_obj.layout == .Packed) { | 3833 | if (union_obj.layout == .Packed) { |
| 3827 | if (!field_ty.hasRuntimeBits()) | 3834 | if (!field_ty.hasRuntimeBits(mod)) |
| 3828 | return llvm_union_ty.constNull(); | 3835 | return llvm_union_ty.constNull(); |
| 3829 | const non_int_val = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val }); | 3836 | const non_int_val = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val }); |
| 3830 | const ty_bit_size = @intCast(u16, field_ty.bitSize(target)); | 3837 | const ty_bit_size = @intCast(u16, field_ty.bitSize(mod)); |
| 3831 | const small_int_ty = dg.context.intType(ty_bit_size); | 3838 | const small_int_ty = dg.context.intType(ty_bit_size); |
| 3832 | const small_int_val = if (field_ty.isPtrAtRuntime()) | 3839 | const small_int_val = if (field_ty.isPtrAtRuntime(mod)) |
| 3833 | non_int_val.constPtrToInt(small_int_ty) | 3840 | non_int_val.constPtrToInt(small_int_ty) |
| 3834 | else | 3841 | else |
| 3835 | non_int_val.constBitCast(small_int_ty); | 3842 | non_int_val.constBitCast(small_int_ty); |
| ... | @@ -3842,13 +3849,13 @@ pub const DeclGen = struct { | ... | @@ -3842,13 +3849,13 @@ pub const DeclGen = struct { |
| 3842 | // must pointer cast to the expected type before accessing the union. | 3849 | // must pointer cast to the expected type before accessing the union. |
| 3843 | var need_unnamed: bool = layout.most_aligned_field != field_index; | 3850 | var need_unnamed: bool = layout.most_aligned_field != field_index; |
| 3844 | const payload = p: { | 3851 | const payload = p: { |
| 3845 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) { | 3852 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3846 | const padding_len = @intCast(c_uint, layout.payload_size); | 3853 | const padding_len = @intCast(c_uint, layout.payload_size); |
| 3847 | break :p dg.context.intType(8).arrayType(padding_len).getUndef(); | 3854 | break :p dg.context.intType(8).arrayType(padding_len).getUndef(); |
| 3848 | } | 3855 | } |
| 3849 | const field = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val }); | 3856 | const field = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val }); |
| 3850 | need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field); | 3857 | need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field); |
| 3851 | const field_size = field_ty.abiSize(target); | 3858 | const field_size = field_ty.abiSize(mod); |
| 3852 | if (field_size == layout.payload_size) { | 3859 | if (field_size == layout.payload_size) { |
| 3853 | break :p field; | 3860 | break :p field; |
| 3854 | } | 3861 | } |
| ... | @@ -4012,7 +4019,8 @@ pub const DeclGen = struct { | ... | @@ -4012,7 +4019,8 @@ pub const DeclGen = struct { |
| 4012 | } | 4019 | } |
| 4013 | 4020 | ||
| 4014 | fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value { | 4021 | fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value { |
| 4015 | const target = dg.module.getTarget(); | 4022 | const mod = dg.module; |
| 4023 | const target = mod.getTarget(); | ||
| 4016 | switch (ptr_val.tag()) { | 4024 | switch (ptr_val.tag()) { |
| 4017 | .decl_ref_mut => { | 4025 | .decl_ref_mut => { |
| 4018 | const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl_index; | 4026 | const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl_index; |
| ... | @@ -4045,13 +4053,13 @@ pub const DeclGen = struct { | ... | @@ -4045,13 +4053,13 @@ pub const DeclGen = struct { |
| 4045 | 4053 | ||
| 4046 | const field_index = @intCast(u32, field_ptr.field_index); | 4054 | const field_index = @intCast(u32, field_ptr.field_index); |
| 4047 | const llvm_u32 = dg.context.intType(32); | 4055 | const llvm_u32 = dg.context.intType(32); |
| 4048 | switch (parent_ty.zigTypeTag()) { | 4056 | switch (parent_ty.zigTypeTag(mod)) { |
| 4049 | .Union => { | 4057 | .Union => { |
| 4050 | if (parent_ty.containerLayout() == .Packed) { | 4058 | if (parent_ty.containerLayout() == .Packed) { |
| 4051 | return parent_llvm_ptr; | 4059 | return parent_llvm_ptr; |
| 4052 | } | 4060 | } |
| 4053 | 4061 | ||
| 4054 | const layout = parent_ty.unionGetLayout(target); | 4062 | const layout = parent_ty.unionGetLayout(mod); |
| 4055 | if (layout.payload_size == 0) { | 4063 | if (layout.payload_size == 0) { |
| 4056 | // In this case a pointer to the union and a pointer to any | 4064 | // In this case a pointer to the union and a pointer to any |
| 4057 | // (void) payload is the same. | 4065 | // (void) payload is the same. |
| ... | @@ -4077,8 +4085,8 @@ pub const DeclGen = struct { | ... | @@ -4077,8 +4085,8 @@ pub const DeclGen = struct { |
| 4077 | const prev_bits = b: { | 4085 | const prev_bits = b: { |
| 4078 | var b: usize = 0; | 4086 | var b: usize = 0; |
| 4079 | for (parent_ty.structFields().values()[0..field_index]) |field| { | 4087 | for (parent_ty.structFields().values()[0..field_index]) |field| { |
| 4080 | if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue; | 4088 | if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 4081 | b += @intCast(usize, field.ty.bitSize(target)); | 4089 | b += @intCast(usize, field.ty.bitSize(mod)); |
| 4082 | } | 4090 | } |
| 4083 | break :b b; | 4091 | break :b b; |
| 4084 | }; | 4092 | }; |
| ... | @@ -4091,14 +4099,14 @@ pub const DeclGen = struct { | ... | @@ -4091,14 +4099,14 @@ pub const DeclGen = struct { |
| 4091 | var ty_buf: Type.Payload.Pointer = undefined; | 4099 | var ty_buf: Type.Payload.Pointer = undefined; |
| 4092 | 4100 | ||
| 4093 | const parent_llvm_ty = try dg.lowerType(parent_ty); | 4101 | const parent_llvm_ty = try dg.lowerType(parent_ty); |
| 4094 | if (llvmFieldIndex(parent_ty, field_index, target, &ty_buf)) |llvm_field_index| { | 4102 | if (llvmFieldIndex(parent_ty, field_index, mod, &ty_buf)) |llvm_field_index| { |
| 4095 | const indices: [2]*llvm.Value = .{ | 4103 | const indices: [2]*llvm.Value = .{ |
| 4096 | llvm_u32.constInt(0, .False), | 4104 | llvm_u32.constInt(0, .False), |
| 4097 | llvm_u32.constInt(llvm_field_index, .False), | 4105 | llvm_u32.constInt(llvm_field_index, .False), |
| 4098 | }; | 4106 | }; |
| 4099 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); | 4107 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 4100 | } else { | 4108 | } else { |
| 4101 | const llvm_index = llvm_u32.constInt(@boolToInt(parent_ty.hasRuntimeBitsIgnoreComptime()), .False); | 4109 | const llvm_index = llvm_u32.constInt(@boolToInt(parent_ty.hasRuntimeBitsIgnoreComptime(mod)), .False); |
| 4102 | const indices: [1]*llvm.Value = .{llvm_index}; | 4110 | const indices: [1]*llvm.Value = .{llvm_index}; |
| 4103 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); | 4111 | return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 4104 | } | 4112 | } |
| ... | @@ -4132,8 +4140,8 @@ pub const DeclGen = struct { | ... | @@ -4132,8 +4140,8 @@ pub const DeclGen = struct { |
| 4132 | var buf: Type.Payload.ElemType = undefined; | 4140 | var buf: Type.Payload.ElemType = undefined; |
| 4133 | 4141 | ||
| 4134 | const payload_ty = opt_payload_ptr.container_ty.optionalChild(&buf); | 4142 | const payload_ty = opt_payload_ptr.container_ty.optionalChild(&buf); |
| 4135 | if (!payload_ty.hasRuntimeBitsIgnoreComptime() or | 4143 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or |
| 4136 | payload_ty.optionalReprIsPayload()) | 4144 | payload_ty.optionalReprIsPayload(mod)) |
| 4137 | { | 4145 | { |
| 4138 | // In this case, we represent pointer to optional the same as pointer | 4146 | // In this case, we represent pointer to optional the same as pointer |
| 4139 | // to the payload. | 4147 | // to the payload. |
| ... | @@ -4153,13 +4161,13 @@ pub const DeclGen = struct { | ... | @@ -4153,13 +4161,13 @@ pub const DeclGen = struct { |
| 4153 | const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, true); | 4161 | const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, true); |
| 4154 | 4162 | ||
| 4155 | const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload(); | 4163 | const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload(); |
| 4156 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 4164 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4157 | // In this case, we represent pointer to error union the same as pointer | 4165 | // In this case, we represent pointer to error union the same as pointer |
| 4158 | // to the payload. | 4166 | // to the payload. |
| 4159 | return parent_llvm_ptr; | 4167 | return parent_llvm_ptr; |
| 4160 | } | 4168 | } |
| 4161 | 4169 | ||
| 4162 | const payload_offset: u8 = if (payload_ty.abiAlignment(target) > Type.anyerror.abiSize(target)) 2 else 1; | 4170 | const payload_offset: u8 = if (payload_ty.abiAlignment(mod) > Type.anyerror.abiSize(mod)) 2 else 1; |
| 4163 | const llvm_u32 = dg.context.intType(32); | 4171 | const llvm_u32 = dg.context.intType(32); |
| 4164 | const indices: [2]*llvm.Value = .{ | 4172 | const indices: [2]*llvm.Value = .{ |
| 4165 | llvm_u32.constInt(0, .False), | 4173 | llvm_u32.constInt(0, .False), |
| ... | @@ -4177,12 +4185,13 @@ pub const DeclGen = struct { | ... | @@ -4177,12 +4185,13 @@ pub const DeclGen = struct { |
| 4177 | tv: TypedValue, | 4185 | tv: TypedValue, |
| 4178 | decl_index: Module.Decl.Index, | 4186 | decl_index: Module.Decl.Index, |
| 4179 | ) Error!*llvm.Value { | 4187 | ) Error!*llvm.Value { |
| 4188 | const mod = self.module; | ||
| 4180 | if (tv.ty.isSlice()) { | 4189 | if (tv.ty.isSlice()) { |
| 4181 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 4190 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 4182 | const ptr_ty = tv.ty.slicePtrFieldType(&buf); | 4191 | const ptr_ty = tv.ty.slicePtrFieldType(&buf); |
| 4183 | var slice_len: Value.Payload.U64 = .{ | 4192 | var slice_len: Value.Payload.U64 = .{ |
| 4184 | .base = .{ .tag = .int_u64 }, | 4193 | .base = .{ .tag = .int_u64 }, |
| 4185 | .data = tv.val.sliceLen(self.module), | 4194 | .data = tv.val.sliceLen(mod), |
| 4186 | }; | 4195 | }; |
| 4187 | const fields: [2]*llvm.Value = .{ | 4196 | const fields: [2]*llvm.Value = .{ |
| 4188 | try self.lowerValue(.{ | 4197 | try self.lowerValue(.{ |
| ... | @@ -4202,7 +4211,7 @@ pub const DeclGen = struct { | ... | @@ -4202,7 +4211,7 @@ pub const DeclGen = struct { |
| 4202 | // const bar = foo; | 4211 | // const bar = foo; |
| 4203 | // ... &bar; | 4212 | // ... &bar; |
| 4204 | // `bar` is just an alias and we actually want to lower a reference to `foo`. | 4213 | // `bar` is just an alias and we actually want to lower a reference to `foo`. |
| 4205 | const decl = self.module.declPtr(decl_index); | 4214 | const decl = mod.declPtr(decl_index); |
| 4206 | if (decl.val.castTag(.function)) |func| { | 4215 | if (decl.val.castTag(.function)) |func| { |
| 4207 | if (func.data.owner_decl != decl_index) { | 4216 | if (func.data.owner_decl != decl_index) { |
| 4208 | return self.lowerDeclRefValue(tv, func.data.owner_decl); | 4217 | return self.lowerDeclRefValue(tv, func.data.owner_decl); |
| ... | @@ -4213,21 +4222,21 @@ pub const DeclGen = struct { | ... | @@ -4213,21 +4222,21 @@ pub const DeclGen = struct { |
| 4213 | } | 4222 | } |
| 4214 | } | 4223 | } |
| 4215 | 4224 | ||
| 4216 | const is_fn_body = decl.ty.zigTypeTag() == .Fn; | 4225 | const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn; |
| 4217 | if ((!is_fn_body and !decl.ty.hasRuntimeBits()) or | 4226 | if ((!is_fn_body and !decl.ty.hasRuntimeBits(mod)) or |
| 4218 | (is_fn_body and decl.ty.fnInfo().is_generic)) | 4227 | (is_fn_body and decl.ty.fnInfo().is_generic)) |
| 4219 | { | 4228 | { |
| 4220 | return self.lowerPtrToVoid(tv.ty); | 4229 | return self.lowerPtrToVoid(tv.ty); |
| 4221 | } | 4230 | } |
| 4222 | 4231 | ||
| 4223 | self.module.markDeclAlive(decl); | 4232 | mod.markDeclAlive(decl); |
| 4224 | 4233 | ||
| 4225 | const llvm_decl_val = if (is_fn_body) | 4234 | const llvm_decl_val = if (is_fn_body) |
| 4226 | try self.resolveLlvmFunction(decl_index) | 4235 | try self.resolveLlvmFunction(decl_index) |
| 4227 | else | 4236 | else |
| 4228 | try self.resolveGlobalDecl(decl_index); | 4237 | try self.resolveGlobalDecl(decl_index); |
| 4229 | 4238 | ||
| 4230 | const target = self.module.getTarget(); | 4239 | const target = mod.getTarget(); |
| 4231 | const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); | 4240 | const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); |
| 4232 | const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); | 4241 | const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); |
| 4233 | const llvm_val = if (llvm_wanted_addrspace != llvm_actual_addrspace) blk: { | 4242 | const llvm_val = if (llvm_wanted_addrspace != llvm_actual_addrspace) blk: { |
| ... | @@ -4236,7 +4245,7 @@ pub const DeclGen = struct { | ... | @@ -4236,7 +4245,7 @@ pub const DeclGen = struct { |
| 4236 | } else llvm_decl_val; | 4245 | } else llvm_decl_val; |
| 4237 | 4246 | ||
| 4238 | const llvm_type = try self.lowerType(tv.ty); | 4247 | const llvm_type = try self.lowerType(tv.ty); |
| 4239 | if (tv.ty.zigTypeTag() == .Int) { | 4248 | if (tv.ty.zigTypeTag(mod) == .Int) { |
| 4240 | return llvm_val.constPtrToInt(llvm_type); | 4249 | return llvm_val.constPtrToInt(llvm_type); |
| 4241 | } else { | 4250 | } else { |
| 4242 | return llvm_val.constBitCast(llvm_type); | 4251 | return llvm_val.constBitCast(llvm_type); |
| ... | @@ -4338,21 +4347,20 @@ pub const DeclGen = struct { | ... | @@ -4338,21 +4347,20 @@ pub const DeclGen = struct { |
| 4338 | /// RMW exchange of floating-point values is bitcasted to same-sized integer | 4347 | /// RMW exchange of floating-point values is bitcasted to same-sized integer |
| 4339 | /// types to work around a LLVM deficiency when targeting ARM/AArch64. | 4348 | /// types to work around a LLVM deficiency when targeting ARM/AArch64. |
| 4340 | fn getAtomicAbiType(dg: *DeclGen, ty: Type, is_rmw_xchg: bool) ?*llvm.Type { | 4349 | fn getAtomicAbiType(dg: *DeclGen, ty: Type, is_rmw_xchg: bool) ?*llvm.Type { |
| 4341 | const target = dg.module.getTarget(); | 4350 | const mod = dg.module; |
| 4342 | var buffer: Type.Payload.Bits = undefined; | 4351 | const int_ty = switch (ty.zigTypeTag(mod)) { |
| 4343 | const int_ty = switch (ty.zigTypeTag()) { | ||
| 4344 | .Int => ty, | 4352 | .Int => ty, |
| 4345 | .Enum => ty.intTagType(&buffer), | 4353 | .Enum => ty.intTagType(), |
| 4346 | .Float => { | 4354 | .Float => { |
| 4347 | if (!is_rmw_xchg) return null; | 4355 | if (!is_rmw_xchg) return null; |
| 4348 | return dg.context.intType(@intCast(c_uint, ty.abiSize(target) * 8)); | 4356 | return dg.context.intType(@intCast(c_uint, ty.abiSize(mod) * 8)); |
| 4349 | }, | 4357 | }, |
| 4350 | .Bool => return dg.context.intType(8), | 4358 | .Bool => return dg.context.intType(8), |
| 4351 | else => return null, | 4359 | else => return null, |
| 4352 | }; | 4360 | }; |
| 4353 | const bit_count = int_ty.intInfo(target).bits; | 4361 | const bit_count = int_ty.intInfo(mod).bits; |
| 4354 | if (!std.math.isPowerOfTwo(bit_count) or (bit_count % 8) != 0) { | 4362 | if (!std.math.isPowerOfTwo(bit_count) or (bit_count % 8) != 0) { |
| 4355 | return dg.context.intType(@intCast(c_uint, int_ty.abiSize(target) * 8)); | 4363 | return dg.context.intType(@intCast(c_uint, int_ty.abiSize(mod) * 8)); |
| 4356 | } else { | 4364 | } else { |
| 4357 | return null; | 4365 | return null; |
| 4358 | } | 4366 | } |
| ... | @@ -4366,15 +4374,15 @@ pub const DeclGen = struct { | ... | @@ -4366,15 +4374,15 @@ pub const DeclGen = struct { |
| 4366 | fn_info: Type.Payload.Function.Data, | 4374 | fn_info: Type.Payload.Function.Data, |
| 4367 | llvm_arg_i: u32, | 4375 | llvm_arg_i: u32, |
| 4368 | ) void { | 4376 | ) void { |
| 4369 | const target = dg.module.getTarget(); | 4377 | const mod = dg.module; |
| 4370 | if (param_ty.isPtrAtRuntime()) { | 4378 | if (param_ty.isPtrAtRuntime(mod)) { |
| 4371 | const ptr_info = param_ty.ptrInfo().data; | 4379 | const ptr_info = param_ty.ptrInfo().data; |
| 4372 | if (math.cast(u5, param_index)) |i| { | 4380 | if (math.cast(u5, param_index)) |i| { |
| 4373 | if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { | 4381 | if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { |
| 4374 | dg.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); | 4382 | dg.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); |
| 4375 | } | 4383 | } |
| 4376 | } | 4384 | } |
| 4377 | if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") { | 4385 | if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.@"allowzero") { |
| 4378 | dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); | 4386 | dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); |
| 4379 | } | 4387 | } |
| 4380 | if (!ptr_info.mutable) { | 4388 | if (!ptr_info.mutable) { |
| ... | @@ -4383,13 +4391,10 @@ pub const DeclGen = struct { | ... | @@ -4383,13 +4391,10 @@ pub const DeclGen = struct { |
| 4383 | if (ptr_info.@"align" != 0) { | 4391 | if (ptr_info.@"align" != 0) { |
| 4384 | dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", ptr_info.@"align"); | 4392 | dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", ptr_info.@"align"); |
| 4385 | } else { | 4393 | } else { |
| 4386 | const elem_align = @max( | 4394 | const elem_align = @max(ptr_info.pointee_type.abiAlignment(mod), 1); |
| 4387 | ptr_info.pointee_type.abiAlignment(target), | ||
| 4388 | 1, | ||
| 4389 | ); | ||
| 4390 | dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align); | 4395 | dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align); |
| 4391 | } | 4396 | } |
| 4392 | } else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) { | 4397 | } else if (ccAbiPromoteInt(fn_info.cc, mod, param_ty)) |s| switch (s) { |
| 4393 | .signed => dg.addArgAttr(llvm_fn, llvm_arg_i, "signext"), | 4398 | .signed => dg.addArgAttr(llvm_fn, llvm_arg_i, "signext"), |
| 4394 | .unsigned => dg.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"), | 4399 | .unsigned => dg.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"), |
| 4395 | }; | 4400 | }; |
| ... | @@ -4490,9 +4495,10 @@ pub const FuncGen = struct { | ... | @@ -4490,9 +4495,10 @@ pub const FuncGen = struct { |
| 4490 | const gop = try self.func_inst_table.getOrPut(self.dg.gpa, inst); | 4495 | const gop = try self.func_inst_table.getOrPut(self.dg.gpa, inst); |
| 4491 | if (gop.found_existing) return gop.value_ptr.*; | 4496 | if (gop.found_existing) return gop.value_ptr.*; |
| 4492 | 4497 | ||
| 4498 | const mod = self.dg.module; | ||
| 4493 | const llvm_val = try self.resolveValue(.{ | 4499 | const llvm_val = try self.resolveValue(.{ |
| 4494 | .ty = self.air.typeOf(inst), | 4500 | .ty = self.air.typeOf(inst), |
| 4495 | .val = self.air.value(inst).?, | 4501 | .val = self.air.value(inst, mod).?, |
| 4496 | }); | 4502 | }); |
| 4497 | gop.value_ptr.* = llvm_val; | 4503 | gop.value_ptr.* = llvm_val; |
| 4498 | return llvm_val; | 4504 | return llvm_val; |
| ... | @@ -4500,11 +4506,12 @@ pub const FuncGen = struct { | ... | @@ -4500,11 +4506,12 @@ pub const FuncGen = struct { |
| 4500 | 4506 | ||
| 4501 | fn resolveValue(self: *FuncGen, tv: TypedValue) !*llvm.Value { | 4507 | fn resolveValue(self: *FuncGen, tv: TypedValue) !*llvm.Value { |
| 4502 | const llvm_val = try self.dg.lowerValue(tv); | 4508 | const llvm_val = try self.dg.lowerValue(tv); |
| 4503 | if (!isByRef(tv.ty)) return llvm_val; | 4509 | const mod = self.dg.module; |
| 4510 | if (!isByRef(tv.ty, mod)) return llvm_val; | ||
| 4504 | 4511 | ||
| 4505 | // We have an LLVM value but we need to create a global constant and | 4512 | // We have an LLVM value but we need to create a global constant and |
| 4506 | // set the value as its initializer, and then return a pointer to the global. | 4513 | // set the value as its initializer, and then return a pointer to the global. |
| 4507 | const target = self.dg.module.getTarget(); | 4514 | const target = mod.getTarget(); |
| 4508 | const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target); | 4515 | const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target); |
| 4509 | const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target); | 4516 | const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target); |
| 4510 | const global = self.dg.object.llvm_module.addGlobalInAddressSpace(llvm_val.typeOf(), "", llvm_actual_addrspace); | 4517 | const global = self.dg.object.llvm_module.addGlobalInAddressSpace(llvm_val.typeOf(), "", llvm_actual_addrspace); |
| ... | @@ -4512,7 +4519,7 @@ pub const FuncGen = struct { | ... | @@ -4512,7 +4519,7 @@ pub const FuncGen = struct { |
| 4512 | global.setLinkage(.Private); | 4519 | global.setLinkage(.Private); |
| 4513 | global.setGlobalConstant(.True); | 4520 | global.setGlobalConstant(.True); |
| 4514 | global.setUnnamedAddr(.True); | 4521 | global.setUnnamedAddr(.True); |
| 4515 | global.setAlignment(tv.ty.abiAlignment(target)); | 4522 | global.setAlignment(tv.ty.abiAlignment(mod)); |
| 4516 | const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace) | 4523 | const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace) |
| 4517 | global.constAddrSpaceCast(self.context.pointerType(llvm_wanted_addrspace)) | 4524 | global.constAddrSpaceCast(self.context.pointerType(llvm_wanted_addrspace)) |
| 4518 | else | 4525 | else |
| ... | @@ -4775,7 +4782,8 @@ pub const FuncGen = struct { | ... | @@ -4775,7 +4782,8 @@ pub const FuncGen = struct { |
| 4775 | const extra = self.air.extraData(Air.Call, pl_op.payload); | 4782 | const extra = self.air.extraData(Air.Call, pl_op.payload); |
| 4776 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); | 4783 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); |
| 4777 | const callee_ty = self.air.typeOf(pl_op.operand); | 4784 | const callee_ty = self.air.typeOf(pl_op.operand); |
| 4778 | const zig_fn_ty = switch (callee_ty.zigTypeTag()) { | 4785 | const mod = self.dg.module; |
| 4786 | const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) { | ||
| 4779 | .Fn => callee_ty, | 4787 | .Fn => callee_ty, |
| 4780 | .Pointer => callee_ty.childType(), | 4788 | .Pointer => callee_ty.childType(), |
| 4781 | else => unreachable, | 4789 | else => unreachable, |
| ... | @@ -4783,20 +4791,20 @@ pub const FuncGen = struct { | ... | @@ -4783,20 +4791,20 @@ pub const FuncGen = struct { |
| 4783 | const fn_info = zig_fn_ty.fnInfo(); | 4791 | const fn_info = zig_fn_ty.fnInfo(); |
| 4784 | const return_type = fn_info.return_type; | 4792 | const return_type = fn_info.return_type; |
| 4785 | const llvm_fn = try self.resolveInst(pl_op.operand); | 4793 | const llvm_fn = try self.resolveInst(pl_op.operand); |
| 4786 | const target = self.dg.module.getTarget(); | 4794 | const target = mod.getTarget(); |
| 4787 | const sret = firstParamSRet(fn_info, target); | 4795 | const sret = firstParamSRet(fn_info, mod); |
| 4788 | 4796 | ||
| 4789 | var llvm_args = std.ArrayList(*llvm.Value).init(self.gpa); | 4797 | var llvm_args = std.ArrayList(*llvm.Value).init(self.gpa); |
| 4790 | defer llvm_args.deinit(); | 4798 | defer llvm_args.deinit(); |
| 4791 | 4799 | ||
| 4792 | const ret_ptr = if (!sret) null else blk: { | 4800 | const ret_ptr = if (!sret) null else blk: { |
| 4793 | const llvm_ret_ty = try self.dg.lowerType(return_type); | 4801 | const llvm_ret_ty = try self.dg.lowerType(return_type); |
| 4794 | const ret_ptr = self.buildAlloca(llvm_ret_ty, return_type.abiAlignment(target)); | 4802 | const ret_ptr = self.buildAlloca(llvm_ret_ty, return_type.abiAlignment(mod)); |
| 4795 | try llvm_args.append(ret_ptr); | 4803 | try llvm_args.append(ret_ptr); |
| 4796 | break :blk ret_ptr; | 4804 | break :blk ret_ptr; |
| 4797 | }; | 4805 | }; |
| 4798 | 4806 | ||
| 4799 | const err_return_tracing = fn_info.return_type.isError() and | 4807 | const err_return_tracing = fn_info.return_type.isError(mod) and |
| 4800 | self.dg.module.comp.bin_file.options.error_return_tracing; | 4808 | self.dg.module.comp.bin_file.options.error_return_tracing; |
| 4801 | if (err_return_tracing) { | 4809 | if (err_return_tracing) { |
| 4802 | try llvm_args.append(self.err_ret_trace.?); | 4810 | try llvm_args.append(self.err_ret_trace.?); |
| ... | @@ -4810,8 +4818,8 @@ pub const FuncGen = struct { | ... | @@ -4810,8 +4818,8 @@ pub const FuncGen = struct { |
| 4810 | const param_ty = self.air.typeOf(arg); | 4818 | const param_ty = self.air.typeOf(arg); |
| 4811 | const llvm_arg = try self.resolveInst(arg); | 4819 | const llvm_arg = try self.resolveInst(arg); |
| 4812 | const llvm_param_ty = try self.dg.lowerType(param_ty); | 4820 | const llvm_param_ty = try self.dg.lowerType(param_ty); |
| 4813 | if (isByRef(param_ty)) { | 4821 | if (isByRef(param_ty, mod)) { |
| 4814 | const alignment = param_ty.abiAlignment(target); | 4822 | const alignment = param_ty.abiAlignment(mod); |
| 4815 | const load_inst = self.builder.buildLoad(llvm_param_ty, llvm_arg, ""); | 4823 | const load_inst = self.builder.buildLoad(llvm_param_ty, llvm_arg, ""); |
| 4816 | load_inst.setAlignment(alignment); | 4824 | load_inst.setAlignment(alignment); |
| 4817 | try llvm_args.append(load_inst); | 4825 | try llvm_args.append(load_inst); |
| ... | @@ -4823,10 +4831,10 @@ pub const FuncGen = struct { | ... | @@ -4823,10 +4831,10 @@ pub const FuncGen = struct { |
| 4823 | const arg = args[it.zig_index - 1]; | 4831 | const arg = args[it.zig_index - 1]; |
| 4824 | const param_ty = self.air.typeOf(arg); | 4832 | const param_ty = self.air.typeOf(arg); |
| 4825 | const llvm_arg = try self.resolveInst(arg); | 4833 | const llvm_arg = try self.resolveInst(arg); |
| 4826 | if (isByRef(param_ty)) { | 4834 | if (isByRef(param_ty, mod)) { |
| 4827 | try llvm_args.append(llvm_arg); | 4835 | try llvm_args.append(llvm_arg); |
| 4828 | } else { | 4836 | } else { |
| 4829 | const alignment = param_ty.abiAlignment(target); | 4837 | const alignment = param_ty.abiAlignment(mod); |
| 4830 | const param_llvm_ty = llvm_arg.typeOf(); | 4838 | const param_llvm_ty = llvm_arg.typeOf(); |
| 4831 | const arg_ptr = self.buildAlloca(param_llvm_ty, alignment); | 4839 | const arg_ptr = self.buildAlloca(param_llvm_ty, alignment); |
| 4832 | const store_inst = self.builder.buildStore(llvm_arg, arg_ptr); | 4840 | const store_inst = self.builder.buildStore(llvm_arg, arg_ptr); |
| ... | @@ -4839,10 +4847,10 @@ pub const FuncGen = struct { | ... | @@ -4839,10 +4847,10 @@ pub const FuncGen = struct { |
| 4839 | const param_ty = self.air.typeOf(arg); | 4847 | const param_ty = self.air.typeOf(arg); |
| 4840 | const llvm_arg = try self.resolveInst(arg); | 4848 | const llvm_arg = try self.resolveInst(arg); |
| 4841 | 4849 | ||
| 4842 | const alignment = param_ty.abiAlignment(target); | 4850 | const alignment = param_ty.abiAlignment(mod); |
| 4843 | const param_llvm_ty = try self.dg.lowerType(param_ty); | 4851 | const param_llvm_ty = try self.dg.lowerType(param_ty); |
| 4844 | const arg_ptr = self.buildAlloca(param_llvm_ty, alignment); | 4852 | const arg_ptr = self.buildAlloca(param_llvm_ty, alignment); |
| 4845 | if (isByRef(param_ty)) { | 4853 | if (isByRef(param_ty, mod)) { |
| 4846 | const load_inst = self.builder.buildLoad(param_llvm_ty, llvm_arg, ""); | 4854 | const load_inst = self.builder.buildLoad(param_llvm_ty, llvm_arg, ""); |
| 4847 | load_inst.setAlignment(alignment); | 4855 | load_inst.setAlignment(alignment); |
| 4848 | 4856 | ||
| ... | @@ -4859,11 +4867,11 @@ pub const FuncGen = struct { | ... | @@ -4859,11 +4867,11 @@ pub const FuncGen = struct { |
| 4859 | const arg = args[it.zig_index - 1]; | 4867 | const arg = args[it.zig_index - 1]; |
| 4860 | const param_ty = self.air.typeOf(arg); | 4868 | const param_ty = self.air.typeOf(arg); |
| 4861 | const llvm_arg = try self.resolveInst(arg); | 4869 | const llvm_arg = try self.resolveInst(arg); |
| 4862 | const abi_size = @intCast(c_uint, param_ty.abiSize(target)); | 4870 | const abi_size = @intCast(c_uint, param_ty.abiSize(mod)); |
| 4863 | const int_llvm_ty = self.context.intType(abi_size * 8); | 4871 | const int_llvm_ty = self.context.intType(abi_size * 8); |
| 4864 | 4872 | ||
| 4865 | if (isByRef(param_ty)) { | 4873 | if (isByRef(param_ty, mod)) { |
| 4866 | const alignment = param_ty.abiAlignment(target); | 4874 | const alignment = param_ty.abiAlignment(mod); |
| 4867 | const load_inst = self.builder.buildLoad(int_llvm_ty, llvm_arg, ""); | 4875 | const load_inst = self.builder.buildLoad(int_llvm_ty, llvm_arg, ""); |
| 4868 | load_inst.setAlignment(alignment); | 4876 | load_inst.setAlignment(alignment); |
| 4869 | try llvm_args.append(load_inst); | 4877 | try llvm_args.append(load_inst); |
| ... | @@ -4871,7 +4879,7 @@ pub const FuncGen = struct { | ... | @@ -4871,7 +4879,7 @@ pub const FuncGen = struct { |
| 4871 | // LLVM does not allow bitcasting structs so we must allocate | 4879 | // LLVM does not allow bitcasting structs so we must allocate |
| 4872 | // a local, store as one type, and then load as another type. | 4880 | // a local, store as one type, and then load as another type. |
| 4873 | const alignment = @max( | 4881 | const alignment = @max( |
| 4874 | param_ty.abiAlignment(target), | 4882 | param_ty.abiAlignment(mod), |
| 4875 | self.dg.object.target_data.abiAlignmentOfType(int_llvm_ty), | 4883 | self.dg.object.target_data.abiAlignmentOfType(int_llvm_ty), |
| 4876 | ); | 4884 | ); |
| 4877 | const int_ptr = self.buildAlloca(int_llvm_ty, alignment); | 4885 | const int_ptr = self.buildAlloca(int_llvm_ty, alignment); |
| ... | @@ -4896,11 +4904,11 @@ pub const FuncGen = struct { | ... | @@ -4896,11 +4904,11 @@ pub const FuncGen = struct { |
| 4896 | const param_ty = self.air.typeOf(arg); | 4904 | const param_ty = self.air.typeOf(arg); |
| 4897 | const llvm_types = it.llvm_types_buffer[0..it.llvm_types_len]; | 4905 | const llvm_types = it.llvm_types_buffer[0..it.llvm_types_len]; |
| 4898 | const llvm_arg = try self.resolveInst(arg); | 4906 | const llvm_arg = try self.resolveInst(arg); |
| 4899 | const is_by_ref = isByRef(param_ty); | 4907 | const is_by_ref = isByRef(param_ty, mod); |
| 4900 | const arg_ptr = if (is_by_ref) llvm_arg else p: { | 4908 | const arg_ptr = if (is_by_ref) llvm_arg else p: { |
| 4901 | const p = self.buildAlloca(llvm_arg.typeOf(), null); | 4909 | const p = self.buildAlloca(llvm_arg.typeOf(), null); |
| 4902 | const store_inst = self.builder.buildStore(llvm_arg, p); | 4910 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 4903 | store_inst.setAlignment(param_ty.abiAlignment(target)); | 4911 | store_inst.setAlignment(param_ty.abiAlignment(mod)); |
| 4904 | break :p p; | 4912 | break :p p; |
| 4905 | }; | 4913 | }; |
| 4906 | 4914 | ||
| ... | @@ -4924,17 +4932,17 @@ pub const FuncGen = struct { | ... | @@ -4924,17 +4932,17 @@ pub const FuncGen = struct { |
| 4924 | const arg = args[it.zig_index - 1]; | 4932 | const arg = args[it.zig_index - 1]; |
| 4925 | const arg_ty = self.air.typeOf(arg); | 4933 | const arg_ty = self.air.typeOf(arg); |
| 4926 | var llvm_arg = try self.resolveInst(arg); | 4934 | var llvm_arg = try self.resolveInst(arg); |
| 4927 | if (!isByRef(arg_ty)) { | 4935 | if (!isByRef(arg_ty, mod)) { |
| 4928 | const p = self.buildAlloca(llvm_arg.typeOf(), null); | 4936 | const p = self.buildAlloca(llvm_arg.typeOf(), null); |
| 4929 | const store_inst = self.builder.buildStore(llvm_arg, p); | 4937 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 4930 | store_inst.setAlignment(arg_ty.abiAlignment(target)); | 4938 | store_inst.setAlignment(arg_ty.abiAlignment(mod)); |
| 4931 | llvm_arg = store_inst; | 4939 | llvm_arg = store_inst; |
| 4932 | } | 4940 | } |
| 4933 | 4941 | ||
| 4934 | const float_ty = try self.dg.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty).?); | 4942 | const float_ty = try self.dg.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, mod).?); |
| 4935 | const array_llvm_ty = float_ty.arrayType(count); | 4943 | const array_llvm_ty = float_ty.arrayType(count); |
| 4936 | 4944 | ||
| 4937 | const alignment = arg_ty.abiAlignment(target); | 4945 | const alignment = arg_ty.abiAlignment(mod); |
| 4938 | const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, ""); | 4946 | const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, ""); |
| 4939 | load_inst.setAlignment(alignment); | 4947 | load_inst.setAlignment(alignment); |
| 4940 | try llvm_args.append(load_inst); | 4948 | try llvm_args.append(load_inst); |
| ... | @@ -4944,15 +4952,15 @@ pub const FuncGen = struct { | ... | @@ -4944,15 +4952,15 @@ pub const FuncGen = struct { |
| 4944 | const arg = args[it.zig_index - 1]; | 4952 | const arg = args[it.zig_index - 1]; |
| 4945 | const arg_ty = self.air.typeOf(arg); | 4953 | const arg_ty = self.air.typeOf(arg); |
| 4946 | var llvm_arg = try self.resolveInst(arg); | 4954 | var llvm_arg = try self.resolveInst(arg); |
| 4947 | if (!isByRef(arg_ty)) { | 4955 | if (!isByRef(arg_ty, mod)) { |
| 4948 | const p = self.buildAlloca(llvm_arg.typeOf(), null); | 4956 | const p = self.buildAlloca(llvm_arg.typeOf(), null); |
| 4949 | const store_inst = self.builder.buildStore(llvm_arg, p); | 4957 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 4950 | store_inst.setAlignment(arg_ty.abiAlignment(target)); | 4958 | store_inst.setAlignment(arg_ty.abiAlignment(mod)); |
| 4951 | llvm_arg = store_inst; | 4959 | llvm_arg = store_inst; |
| 4952 | } | 4960 | } |
| 4953 | 4961 | ||
| 4954 | const array_llvm_ty = self.context.intType(elem_size).arrayType(arr_len); | 4962 | const array_llvm_ty = self.context.intType(elem_size).arrayType(arr_len); |
| 4955 | const alignment = arg_ty.abiAlignment(target); | 4963 | const alignment = arg_ty.abiAlignment(mod); |
| 4956 | const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, ""); | 4964 | const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, ""); |
| 4957 | load_inst.setAlignment(alignment); | 4965 | load_inst.setAlignment(alignment); |
| 4958 | try llvm_args.append(load_inst); | 4966 | try llvm_args.append(load_inst); |
| ... | @@ -4969,7 +4977,7 @@ pub const FuncGen = struct { | ... | @@ -4969,7 +4977,7 @@ pub const FuncGen = struct { |
| 4969 | "", | 4977 | "", |
| 4970 | ); | 4978 | ); |
| 4971 | 4979 | ||
| 4972 | if (callee_ty.zigTypeTag() == .Pointer) { | 4980 | if (callee_ty.zigTypeTag(mod) == .Pointer) { |
| 4973 | // Add argument attributes for function pointer calls. | 4981 | // Add argument attributes for function pointer calls. |
| 4974 | it = iterateParamTypes(self.dg, fn_info); | 4982 | it = iterateParamTypes(self.dg, fn_info); |
| 4975 | it.llvm_index += @boolToInt(sret); | 4983 | it.llvm_index += @boolToInt(sret); |
| ... | @@ -4978,7 +4986,7 @@ pub const FuncGen = struct { | ... | @@ -4978,7 +4986,7 @@ pub const FuncGen = struct { |
| 4978 | .byval => { | 4986 | .byval => { |
| 4979 | const param_index = it.zig_index - 1; | 4987 | const param_index = it.zig_index - 1; |
| 4980 | const param_ty = fn_info.param_types[param_index]; | 4988 | const param_ty = fn_info.param_types[param_index]; |
| 4981 | if (!isByRef(param_ty)) { | 4989 | if (!isByRef(param_ty, mod)) { |
| 4982 | self.dg.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1); | 4990 | self.dg.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1); |
| 4983 | } | 4991 | } |
| 4984 | }, | 4992 | }, |
| ... | @@ -4986,7 +4994,7 @@ pub const FuncGen = struct { | ... | @@ -4986,7 +4994,7 @@ pub const FuncGen = struct { |
| 4986 | const param_index = it.zig_index - 1; | 4994 | const param_index = it.zig_index - 1; |
| 4987 | const param_ty = fn_info.param_types[param_index]; | 4995 | const param_ty = fn_info.param_types[param_index]; |
| 4988 | const param_llvm_ty = try self.dg.lowerType(param_ty); | 4996 | const param_llvm_ty = try self.dg.lowerType(param_ty); |
| 4989 | const alignment = param_ty.abiAlignment(target); | 4997 | const alignment = param_ty.abiAlignment(mod); |
| 4990 | self.dg.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); | 4998 | self.dg.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); |
| 4991 | }, | 4999 | }, |
| 4992 | .byref_mut => { | 5000 | .byref_mut => { |
| ... | @@ -5013,7 +5021,7 @@ pub const FuncGen = struct { | ... | @@ -5013,7 +5021,7 @@ pub const FuncGen = struct { |
| 5013 | self.dg.addArgAttr(call, llvm_arg_i, "noalias"); | 5021 | self.dg.addArgAttr(call, llvm_arg_i, "noalias"); |
| 5014 | } | 5022 | } |
| 5015 | } | 5023 | } |
| 5016 | if (param_ty.zigTypeTag() != .Optional) { | 5024 | if (param_ty.zigTypeTag(mod) != .Optional) { |
| 5017 | self.dg.addArgAttr(call, llvm_arg_i, "nonnull"); | 5025 | self.dg.addArgAttr(call, llvm_arg_i, "nonnull"); |
| 5018 | } | 5026 | } |
| 5019 | if (!ptr_info.mutable) { | 5027 | if (!ptr_info.mutable) { |
| ... | @@ -5022,7 +5030,7 @@ pub const FuncGen = struct { | ... | @@ -5022,7 +5030,7 @@ pub const FuncGen = struct { |
| 5022 | if (ptr_info.@"align" != 0) { | 5030 | if (ptr_info.@"align" != 0) { |
| 5023 | self.dg.addArgAttrInt(call, llvm_arg_i, "align", ptr_info.@"align"); | 5031 | self.dg.addArgAttrInt(call, llvm_arg_i, "align", ptr_info.@"align"); |
| 5024 | } else { | 5032 | } else { |
| 5025 | const elem_align = @max(ptr_info.pointee_type.abiAlignment(target), 1); | 5033 | const elem_align = @max(ptr_info.pointee_type.abiAlignment(mod), 1); |
| 5026 | self.dg.addArgAttrInt(call, llvm_arg_i, "align", elem_align); | 5034 | self.dg.addArgAttrInt(call, llvm_arg_i, "align", elem_align); |
| 5027 | } | 5035 | } |
| 5028 | }, | 5036 | }, |
| ... | @@ -5033,7 +5041,7 @@ pub const FuncGen = struct { | ... | @@ -5033,7 +5041,7 @@ pub const FuncGen = struct { |
| 5033 | return null; | 5041 | return null; |
| 5034 | } | 5042 | } |
| 5035 | 5043 | ||
| 5036 | if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime()) { | 5044 | if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5037 | return null; | 5045 | return null; |
| 5038 | } | 5046 | } |
| 5039 | 5047 | ||
| ... | @@ -5041,12 +5049,12 @@ pub const FuncGen = struct { | ... | @@ -5041,12 +5049,12 @@ pub const FuncGen = struct { |
| 5041 | 5049 | ||
| 5042 | if (ret_ptr) |rp| { | 5050 | if (ret_ptr) |rp| { |
| 5043 | call.setCallSret(llvm_ret_ty); | 5051 | call.setCallSret(llvm_ret_ty); |
| 5044 | if (isByRef(return_type)) { | 5052 | if (isByRef(return_type, mod)) { |
| 5045 | return rp; | 5053 | return rp; |
| 5046 | } else { | 5054 | } else { |
| 5047 | // our by-ref status disagrees with sret so we must load. | 5055 | // our by-ref status disagrees with sret so we must load. |
| 5048 | const loaded = self.builder.buildLoad(llvm_ret_ty, rp, ""); | 5056 | const loaded = self.builder.buildLoad(llvm_ret_ty, rp, ""); |
| 5049 | loaded.setAlignment(return_type.abiAlignment(target)); | 5057 | loaded.setAlignment(return_type.abiAlignment(mod)); |
| 5050 | return loaded; | 5058 | return loaded; |
| 5051 | } | 5059 | } |
| 5052 | } | 5060 | } |
| ... | @@ -5061,7 +5069,7 @@ pub const FuncGen = struct { | ... | @@ -5061,7 +5069,7 @@ pub const FuncGen = struct { |
| 5061 | const rp = self.buildAlloca(llvm_ret_ty, alignment); | 5069 | const rp = self.buildAlloca(llvm_ret_ty, alignment); |
| 5062 | const store_inst = self.builder.buildStore(call, rp); | 5070 | const store_inst = self.builder.buildStore(call, rp); |
| 5063 | store_inst.setAlignment(alignment); | 5071 | store_inst.setAlignment(alignment); |
| 5064 | if (isByRef(return_type)) { | 5072 | if (isByRef(return_type, mod)) { |
| 5065 | return rp; | 5073 | return rp; |
| 5066 | } else { | 5074 | } else { |
| 5067 | const load_inst = self.builder.buildLoad(llvm_ret_ty, rp, ""); | 5075 | const load_inst = self.builder.buildLoad(llvm_ret_ty, rp, ""); |
| ... | @@ -5070,10 +5078,10 @@ pub const FuncGen = struct { | ... | @@ -5070,10 +5078,10 @@ pub const FuncGen = struct { |
| 5070 | } | 5078 | } |
| 5071 | } | 5079 | } |
| 5072 | 5080 | ||
| 5073 | if (isByRef(return_type)) { | 5081 | if (isByRef(return_type, mod)) { |
| 5074 | // our by-ref status disagrees with sret so we must allocate, store, | 5082 | // our by-ref status disagrees with sret so we must allocate, store, |
| 5075 | // and return the allocation pointer. | 5083 | // and return the allocation pointer. |
| 5076 | const alignment = return_type.abiAlignment(target); | 5084 | const alignment = return_type.abiAlignment(mod); |
| 5077 | const rp = self.buildAlloca(llvm_ret_ty, alignment); | 5085 | const rp = self.buildAlloca(llvm_ret_ty, alignment); |
| 5078 | const store_inst = self.builder.buildStore(call, rp); | 5086 | const store_inst = self.builder.buildStore(call, rp); |
| 5079 | store_inst.setAlignment(alignment); | 5087 | store_inst.setAlignment(alignment); |
| ... | @@ -5084,6 +5092,7 @@ pub const FuncGen = struct { | ... | @@ -5084,6 +5092,7 @@ pub const FuncGen = struct { |
| 5084 | } | 5092 | } |
| 5085 | 5093 | ||
| 5086 | fn airRet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 5094 | fn airRet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 5095 | const mod = self.dg.module; | ||
| 5087 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 5096 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 5088 | const ret_ty = self.air.typeOf(un_op); | 5097 | const ret_ty = self.air.typeOf(un_op); |
| 5089 | if (self.ret_ptr) |ret_ptr| { | 5098 | if (self.ret_ptr) |ret_ptr| { |
| ... | @@ -5098,8 +5107,8 @@ pub const FuncGen = struct { | ... | @@ -5098,8 +5107,8 @@ pub const FuncGen = struct { |
| 5098 | return null; | 5107 | return null; |
| 5099 | } | 5108 | } |
| 5100 | const fn_info = self.dg.decl.ty.fnInfo(); | 5109 | const fn_info = self.dg.decl.ty.fnInfo(); |
| 5101 | if (!ret_ty.hasRuntimeBitsIgnoreComptime()) { | 5110 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5102 | if (fn_info.return_type.isError()) { | 5111 | if (fn_info.return_type.isError(mod)) { |
| 5103 | // Functions with an empty error set are emitted with an error code | 5112 | // Functions with an empty error set are emitted with an error code |
| 5104 | // return type and return zero so they can be function pointers coerced | 5113 | // return type and return zero so they can be function pointers coerced |
| 5105 | // to functions that return anyerror. | 5114 | // to functions that return anyerror. |
| ... | @@ -5113,10 +5122,9 @@ pub const FuncGen = struct { | ... | @@ -5113,10 +5122,9 @@ pub const FuncGen = struct { |
| 5113 | 5122 | ||
| 5114 | const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info); | 5123 | const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info); |
| 5115 | const operand = try self.resolveInst(un_op); | 5124 | const operand = try self.resolveInst(un_op); |
| 5116 | const target = self.dg.module.getTarget(); | 5125 | const alignment = ret_ty.abiAlignment(mod); |
| 5117 | const alignment = ret_ty.abiAlignment(target); | ||
| 5118 | 5126 | ||
| 5119 | if (isByRef(ret_ty)) { | 5127 | if (isByRef(ret_ty, mod)) { |
| 5120 | // operand is a pointer however self.ret_ptr is null so that means | 5128 | // operand is a pointer however self.ret_ptr is null so that means |
| 5121 | // we need to return a value. | 5129 | // we need to return a value. |
| 5122 | const load_inst = self.builder.buildLoad(abi_ret_ty, operand, ""); | 5130 | const load_inst = self.builder.buildLoad(abi_ret_ty, operand, ""); |
| ... | @@ -5145,8 +5153,9 @@ pub const FuncGen = struct { | ... | @@ -5145,8 +5153,9 @@ pub const FuncGen = struct { |
| 5145 | const ptr_ty = self.air.typeOf(un_op); | 5153 | const ptr_ty = self.air.typeOf(un_op); |
| 5146 | const ret_ty = ptr_ty.childType(); | 5154 | const ret_ty = ptr_ty.childType(); |
| 5147 | const fn_info = self.dg.decl.ty.fnInfo(); | 5155 | const fn_info = self.dg.decl.ty.fnInfo(); |
| 5148 | if (!ret_ty.hasRuntimeBitsIgnoreComptime()) { | 5156 | const mod = self.dg.module; |
| 5149 | if (fn_info.return_type.isError()) { | 5157 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5158 | if (fn_info.return_type.isError(mod)) { | ||
| 5150 | // Functions with an empty error set are emitted with an error code | 5159 | // Functions with an empty error set are emitted with an error code |
| 5151 | // return type and return zero so they can be function pointers coerced | 5160 | // return type and return zero so they can be function pointers coerced |
| 5152 | // to functions that return anyerror. | 5161 | // to functions that return anyerror. |
| ... | @@ -5162,10 +5171,9 @@ pub const FuncGen = struct { | ... | @@ -5162,10 +5171,9 @@ pub const FuncGen = struct { |
| 5162 | return null; | 5171 | return null; |
| 5163 | } | 5172 | } |
| 5164 | const ptr = try self.resolveInst(un_op); | 5173 | const ptr = try self.resolveInst(un_op); |
| 5165 | const target = self.dg.module.getTarget(); | ||
| 5166 | const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info); | 5174 | const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info); |
| 5167 | const loaded = self.builder.buildLoad(abi_ret_ty, ptr, ""); | 5175 | const loaded = self.builder.buildLoad(abi_ret_ty, ptr, ""); |
| 5168 | loaded.setAlignment(ret_ty.abiAlignment(target)); | 5176 | loaded.setAlignment(ret_ty.abiAlignment(mod)); |
| 5169 | _ = self.builder.buildRet(loaded); | 5177 | _ = self.builder.buildRet(loaded); |
| 5170 | return null; | 5178 | return null; |
| 5171 | } | 5179 | } |
| ... | @@ -5184,9 +5192,9 @@ pub const FuncGen = struct { | ... | @@ -5184,9 +5192,9 @@ pub const FuncGen = struct { |
| 5184 | const src_list = try self.resolveInst(ty_op.operand); | 5192 | const src_list = try self.resolveInst(ty_op.operand); |
| 5185 | const va_list_ty = self.air.getRefType(ty_op.ty); | 5193 | const va_list_ty = self.air.getRefType(ty_op.ty); |
| 5186 | const llvm_va_list_ty = try self.dg.lowerType(va_list_ty); | 5194 | const llvm_va_list_ty = try self.dg.lowerType(va_list_ty); |
| 5195 | const mod = self.dg.module; | ||
| 5187 | 5196 | ||
| 5188 | const target = self.dg.module.getTarget(); | 5197 | const result_alignment = va_list_ty.abiAlignment(mod); |
| 5189 | const result_alignment = va_list_ty.abiAlignment(target); | ||
| 5190 | const dest_list = self.buildAlloca(llvm_va_list_ty, result_alignment); | 5198 | const dest_list = self.buildAlloca(llvm_va_list_ty, result_alignment); |
| 5191 | 5199 | ||
| 5192 | const llvm_fn_name = "llvm.va_copy"; | 5200 | const llvm_fn_name = "llvm.va_copy"; |
| ... | @@ -5202,7 +5210,7 @@ pub const FuncGen = struct { | ... | @@ -5202,7 +5210,7 @@ pub const FuncGen = struct { |
| 5202 | const args: [2]*llvm.Value = .{ dest_list, src_list }; | 5210 | const args: [2]*llvm.Value = .{ dest_list, src_list }; |
| 5203 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); | 5211 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| 5204 | 5212 | ||
| 5205 | if (isByRef(va_list_ty)) { | 5213 | if (isByRef(va_list_ty, mod)) { |
| 5206 | return dest_list; | 5214 | return dest_list; |
| 5207 | } else { | 5215 | } else { |
| 5208 | const loaded = self.builder.buildLoad(llvm_va_list_ty, dest_list, ""); | 5216 | const loaded = self.builder.buildLoad(llvm_va_list_ty, dest_list, ""); |
| ... | @@ -5227,11 +5235,11 @@ pub const FuncGen = struct { | ... | @@ -5227,11 +5235,11 @@ pub const FuncGen = struct { |
| 5227 | } | 5235 | } |
| 5228 | 5236 | ||
| 5229 | fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 5237 | fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 5238 | const mod = self.dg.module; | ||
| 5230 | const va_list_ty = self.air.typeOfIndex(inst); | 5239 | const va_list_ty = self.air.typeOfIndex(inst); |
| 5231 | const llvm_va_list_ty = try self.dg.lowerType(va_list_ty); | 5240 | const llvm_va_list_ty = try self.dg.lowerType(va_list_ty); |
| 5232 | 5241 | ||
| 5233 | const target = self.dg.module.getTarget(); | 5242 | const result_alignment = va_list_ty.abiAlignment(mod); |
| 5234 | const result_alignment = va_list_ty.abiAlignment(target); | ||
| 5235 | const list = self.buildAlloca(llvm_va_list_ty, result_alignment); | 5243 | const list = self.buildAlloca(llvm_va_list_ty, result_alignment); |
| 5236 | 5244 | ||
| 5237 | const llvm_fn_name = "llvm.va_start"; | 5245 | const llvm_fn_name = "llvm.va_start"; |
| ... | @@ -5243,7 +5251,7 @@ pub const FuncGen = struct { | ... | @@ -5243,7 +5251,7 @@ pub const FuncGen = struct { |
| 5243 | const args: [1]*llvm.Value = .{list}; | 5251 | const args: [1]*llvm.Value = .{list}; |
| 5244 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); | 5252 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| 5245 | 5253 | ||
| 5246 | if (isByRef(va_list_ty)) { | 5254 | if (isByRef(va_list_ty, mod)) { |
| 5247 | return list; | 5255 | return list; |
| 5248 | } else { | 5256 | } else { |
| 5249 | const loaded = self.builder.buildLoad(llvm_va_list_ty, list, ""); | 5257 | const loaded = self.builder.buildLoad(llvm_va_list_ty, list, ""); |
| ... | @@ -5292,23 +5300,23 @@ pub const FuncGen = struct { | ... | @@ -5292,23 +5300,23 @@ pub const FuncGen = struct { |
| 5292 | operand_ty: Type, | 5300 | operand_ty: Type, |
| 5293 | op: math.CompareOperator, | 5301 | op: math.CompareOperator, |
| 5294 | ) Allocator.Error!*llvm.Value { | 5302 | ) Allocator.Error!*llvm.Value { |
| 5295 | var int_buffer: Type.Payload.Bits = undefined; | ||
| 5296 | var opt_buffer: Type.Payload.ElemType = undefined; | 5303 | var opt_buffer: Type.Payload.ElemType = undefined; |
| 5297 | 5304 | ||
| 5298 | const scalar_ty = operand_ty.scalarType(); | 5305 | const mod = self.dg.module; |
| 5299 | const int_ty = switch (scalar_ty.zigTypeTag()) { | 5306 | const scalar_ty = operand_ty.scalarType(mod); |
| 5300 | .Enum => scalar_ty.intTagType(&int_buffer), | 5307 | const int_ty = switch (scalar_ty.zigTypeTag(mod)) { |
| 5308 | .Enum => scalar_ty.intTagType(), | ||
| 5301 | .Int, .Bool, .Pointer, .ErrorSet => scalar_ty, | 5309 | .Int, .Bool, .Pointer, .ErrorSet => scalar_ty, |
| 5302 | .Optional => blk: { | 5310 | .Optional => blk: { |
| 5303 | const payload_ty = operand_ty.optionalChild(&opt_buffer); | 5311 | const payload_ty = operand_ty.optionalChild(&opt_buffer); |
| 5304 | if (!payload_ty.hasRuntimeBitsIgnoreComptime() or | 5312 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or |
| 5305 | operand_ty.optionalReprIsPayload()) | 5313 | operand_ty.optionalReprIsPayload(mod)) |
| 5306 | { | 5314 | { |
| 5307 | break :blk operand_ty; | 5315 | break :blk operand_ty; |
| 5308 | } | 5316 | } |
| 5309 | // We need to emit instructions to check for equality/inequality | 5317 | // We need to emit instructions to check for equality/inequality |
| 5310 | // of optionals that are not pointers. | 5318 | // of optionals that are not pointers. |
| 5311 | const is_by_ref = isByRef(scalar_ty); | 5319 | const is_by_ref = isByRef(scalar_ty, mod); |
| 5312 | const opt_llvm_ty = try self.dg.lowerType(scalar_ty); | 5320 | const opt_llvm_ty = try self.dg.lowerType(scalar_ty); |
| 5313 | const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref); | 5321 | const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref); |
| 5314 | const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref); | 5322 | const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref); |
| ... | @@ -5375,7 +5383,7 @@ pub const FuncGen = struct { | ... | @@ -5375,7 +5383,7 @@ pub const FuncGen = struct { |
| 5375 | .Float => return self.buildFloatCmp(op, operand_ty, .{ lhs, rhs }), | 5383 | .Float => return self.buildFloatCmp(op, operand_ty, .{ lhs, rhs }), |
| 5376 | else => unreachable, | 5384 | else => unreachable, |
| 5377 | }; | 5385 | }; |
| 5378 | const is_signed = int_ty.isSignedInt(); | 5386 | const is_signed = int_ty.isSignedInt(mod); |
| 5379 | const operation: llvm.IntPredicate = switch (op) { | 5387 | const operation: llvm.IntPredicate = switch (op) { |
| 5380 | .eq => .EQ, | 5388 | .eq => .EQ, |
| 5381 | .neq => .NE, | 5389 | .neq => .NE, |
| ... | @@ -5393,6 +5401,7 @@ pub const FuncGen = struct { | ... | @@ -5393,6 +5401,7 @@ pub const FuncGen = struct { |
| 5393 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; | 5401 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 5394 | const inst_ty = self.air.typeOfIndex(inst); | 5402 | const inst_ty = self.air.typeOfIndex(inst); |
| 5395 | const parent_bb = self.context.createBasicBlock("Block"); | 5403 | const parent_bb = self.context.createBasicBlock("Block"); |
| 5404 | const mod = self.dg.module; | ||
| 5396 | 5405 | ||
| 5397 | if (inst_ty.isNoReturn()) { | 5406 | if (inst_ty.isNoReturn()) { |
| 5398 | try self.genBody(body); | 5407 | try self.genBody(body); |
| ... | @@ -5414,8 +5423,8 @@ pub const FuncGen = struct { | ... | @@ -5414,8 +5423,8 @@ pub const FuncGen = struct { |
| 5414 | self.builder.positionBuilderAtEnd(parent_bb); | 5423 | self.builder.positionBuilderAtEnd(parent_bb); |
| 5415 | 5424 | ||
| 5416 | // Create a phi node only if the block returns a value. | 5425 | // Create a phi node only if the block returns a value. |
| 5417 | const is_body = inst_ty.zigTypeTag() == .Fn; | 5426 | const is_body = inst_ty.zigTypeTag(mod) == .Fn; |
| 5418 | if (!is_body and !inst_ty.hasRuntimeBitsIgnoreComptime()) return null; | 5427 | if (!is_body and !inst_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; |
| 5419 | 5428 | ||
| 5420 | const raw_llvm_ty = try self.dg.lowerType(inst_ty); | 5429 | const raw_llvm_ty = try self.dg.lowerType(inst_ty); |
| 5421 | 5430 | ||
| ... | @@ -5424,7 +5433,7 @@ pub const FuncGen = struct { | ... | @@ -5424,7 +5433,7 @@ pub const FuncGen = struct { |
| 5424 | // a pointer to it. LLVM IR allows the call instruction to use function bodies instead | 5433 | // a pointer to it. LLVM IR allows the call instruction to use function bodies instead |
| 5425 | // of function pointers, however the phi makes it a runtime value and therefore | 5434 | // of function pointers, however the phi makes it a runtime value and therefore |
| 5426 | // the LLVM type has to be wrapped in a pointer. | 5435 | // the LLVM type has to be wrapped in a pointer. |
| 5427 | if (is_body or isByRef(inst_ty)) { | 5436 | if (is_body or isByRef(inst_ty, mod)) { |
| 5428 | break :ty self.context.pointerType(0); | 5437 | break :ty self.context.pointerType(0); |
| 5429 | } | 5438 | } |
| 5430 | break :ty raw_llvm_ty; | 5439 | break :ty raw_llvm_ty; |
| ... | @@ -5445,7 +5454,8 @@ pub const FuncGen = struct { | ... | @@ -5445,7 +5454,8 @@ pub const FuncGen = struct { |
| 5445 | 5454 | ||
| 5446 | // Add the values to the lists only if the break provides a value. | 5455 | // Add the values to the lists only if the break provides a value. |
| 5447 | const operand_ty = self.air.typeOf(branch.operand); | 5456 | const operand_ty = self.air.typeOf(branch.operand); |
| 5448 | if (operand_ty.hasRuntimeBitsIgnoreComptime() or operand_ty.zigTypeTag() == .Fn) { | 5457 | const mod = self.dg.module; |
| 5458 | if (operand_ty.hasRuntimeBitsIgnoreComptime(mod) or operand_ty.zigTypeTag(mod) == .Fn) { | ||
| 5449 | const val = try self.resolveInst(branch.operand); | 5459 | const val = try self.resolveInst(branch.operand); |
| 5450 | 5460 | ||
| 5451 | // For the phi node, we need the basic blocks and the values of the | 5461 | // For the phi node, we need the basic blocks and the values of the |
| ... | @@ -5481,6 +5491,7 @@ pub const FuncGen = struct { | ... | @@ -5481,6 +5491,7 @@ pub const FuncGen = struct { |
| 5481 | } | 5491 | } |
| 5482 | 5492 | ||
| 5483 | fn airTry(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { | 5493 | fn airTry(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { |
| 5494 | const mod = self.dg.module; | ||
| 5484 | const inst = body_tail[0]; | 5495 | const inst = body_tail[0]; |
| 5485 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 5496 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 5486 | const err_union = try self.resolveInst(pl_op.operand); | 5497 | const err_union = try self.resolveInst(pl_op.operand); |
| ... | @@ -5488,7 +5499,7 @@ pub const FuncGen = struct { | ... | @@ -5488,7 +5499,7 @@ pub const FuncGen = struct { |
| 5488 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; | 5499 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 5489 | const err_union_ty = self.air.typeOf(pl_op.operand); | 5500 | const err_union_ty = self.air.typeOf(pl_op.operand); |
| 5490 | const payload_ty = self.air.typeOfIndex(inst); | 5501 | const payload_ty = self.air.typeOfIndex(inst); |
| 5491 | const can_elide_load = if (isByRef(payload_ty)) self.canElideLoad(body_tail) else false; | 5502 | const can_elide_load = if (isByRef(payload_ty, mod)) self.canElideLoad(body_tail) else false; |
| 5492 | const is_unused = self.liveness.isUnused(inst); | 5503 | const is_unused = self.liveness.isUnused(inst); |
| 5493 | return lowerTry(self, err_union, body, err_union_ty, false, can_elide_load, is_unused); | 5504 | return lowerTry(self, err_union, body, err_union_ty, false, can_elide_load, is_unused); |
| 5494 | } | 5505 | } |
| ... | @@ -5512,9 +5523,9 @@ pub const FuncGen = struct { | ... | @@ -5512,9 +5523,9 @@ pub const FuncGen = struct { |
| 5512 | can_elide_load: bool, | 5523 | can_elide_load: bool, |
| 5513 | is_unused: bool, | 5524 | is_unused: bool, |
| 5514 | ) !?*llvm.Value { | 5525 | ) !?*llvm.Value { |
| 5526 | const mod = fg.dg.module; | ||
| 5515 | const payload_ty = err_union_ty.errorUnionPayload(); | 5527 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 5516 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); | 5528 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod); |
| 5517 | const target = fg.dg.module.getTarget(); | ||
| 5518 | const err_union_llvm_ty = try fg.dg.lowerType(err_union_ty); | 5529 | const err_union_llvm_ty = try fg.dg.lowerType(err_union_ty); |
| 5519 | 5530 | ||
| 5520 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { | 5531 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { |
| ... | @@ -5529,8 +5540,8 @@ pub const FuncGen = struct { | ... | @@ -5529,8 +5540,8 @@ pub const FuncGen = struct { |
| 5529 | err_union; | 5540 | err_union; |
| 5530 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); | 5541 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); |
| 5531 | } | 5542 | } |
| 5532 | const err_field_index = errUnionErrorOffset(payload_ty, target); | 5543 | const err_field_index = errUnionErrorOffset(payload_ty, mod); |
| 5533 | if (operand_is_ptr or isByRef(err_union_ty)) { | 5544 | if (operand_is_ptr or isByRef(err_union_ty, mod)) { |
| 5534 | const err_field_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, err_field_index, ""); | 5545 | const err_field_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, err_field_index, ""); |
| 5535 | // TODO add alignment to this load | 5546 | // TODO add alignment to this load |
| 5536 | const loaded = fg.builder.buildLoad(err_set_ty, err_field_ptr, ""); | 5547 | const loaded = fg.builder.buildLoad(err_set_ty, err_field_ptr, ""); |
| ... | @@ -5555,30 +5566,31 @@ pub const FuncGen = struct { | ... | @@ -5555,30 +5566,31 @@ pub const FuncGen = struct { |
| 5555 | if (!payload_has_bits) { | 5566 | if (!payload_has_bits) { |
| 5556 | return if (operand_is_ptr) err_union else null; | 5567 | return if (operand_is_ptr) err_union else null; |
| 5557 | } | 5568 | } |
| 5558 | const offset = errUnionPayloadOffset(payload_ty, target); | 5569 | const offset = errUnionPayloadOffset(payload_ty, mod); |
| 5559 | if (operand_is_ptr) { | 5570 | if (operand_is_ptr) { |
| 5560 | return fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); | 5571 | return fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); |
| 5561 | } else if (isByRef(err_union_ty)) { | 5572 | } else if (isByRef(err_union_ty, mod)) { |
| 5562 | const payload_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); | 5573 | const payload_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); |
| 5563 | if (isByRef(payload_ty)) { | 5574 | if (isByRef(payload_ty, mod)) { |
| 5564 | if (can_elide_load) | 5575 | if (can_elide_load) |
| 5565 | return payload_ptr; | 5576 | return payload_ptr; |
| 5566 | 5577 | ||
| 5567 | return fg.loadByRef(payload_ptr, payload_ty, payload_ty.abiAlignment(target), false); | 5578 | return fg.loadByRef(payload_ptr, payload_ty, payload_ty.abiAlignment(mod), false); |
| 5568 | } | 5579 | } |
| 5569 | const load_inst = fg.builder.buildLoad(err_union_llvm_ty.structGetTypeAtIndex(offset), payload_ptr, ""); | 5580 | const load_inst = fg.builder.buildLoad(err_union_llvm_ty.structGetTypeAtIndex(offset), payload_ptr, ""); |
| 5570 | load_inst.setAlignment(payload_ty.abiAlignment(target)); | 5581 | load_inst.setAlignment(payload_ty.abiAlignment(mod)); |
| 5571 | return load_inst; | 5582 | return load_inst; |
| 5572 | } | 5583 | } |
| 5573 | return fg.builder.buildExtractValue(err_union, offset, ""); | 5584 | return fg.builder.buildExtractValue(err_union, offset, ""); |
| 5574 | } | 5585 | } |
| 5575 | 5586 | ||
| 5576 | fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 5587 | fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 5588 | const mod = self.dg.module; | ||
| 5577 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 5589 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 5578 | const cond = try self.resolveInst(pl_op.operand); | 5590 | const cond = try self.resolveInst(pl_op.operand); |
| 5579 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); | 5591 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); |
| 5580 | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); | 5592 | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); |
| 5581 | const target = self.dg.module.getTarget(); | 5593 | const target = mod.getTarget(); |
| 5582 | const llvm_usize = self.context.intType(target.ptrBitWidth()); | 5594 | const llvm_usize = self.context.intType(target.ptrBitWidth()); |
| 5583 | const cond_int = if (cond.typeOf().getTypeKind() == .Pointer) | 5595 | const cond_int = if (cond.typeOf().getTypeKind() == .Pointer) |
| 5584 | self.builder.buildPtrToInt(cond, llvm_usize, "") | 5596 | self.builder.buildPtrToInt(cond, llvm_usize, "") |
| ... | @@ -5645,6 +5657,7 @@ pub const FuncGen = struct { | ... | @@ -5645,6 +5657,7 @@ pub const FuncGen = struct { |
| 5645 | } | 5657 | } |
| 5646 | 5658 | ||
| 5647 | fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 5659 | fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 5660 | const mod = self.dg.module; | ||
| 5648 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 5661 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5649 | const operand_ty = self.air.typeOf(ty_op.operand); | 5662 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 5650 | const array_ty = operand_ty.childType(); | 5663 | const array_ty = operand_ty.childType(); |
| ... | @@ -5652,7 +5665,7 @@ pub const FuncGen = struct { | ... | @@ -5652,7 +5665,7 @@ pub const FuncGen = struct { |
| 5652 | const len = llvm_usize.constInt(array_ty.arrayLen(), .False); | 5665 | const len = llvm_usize.constInt(array_ty.arrayLen(), .False); |
| 5653 | const slice_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); | 5666 | const slice_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); |
| 5654 | const operand = try self.resolveInst(ty_op.operand); | 5667 | const operand = try self.resolveInst(ty_op.operand); |
| 5655 | if (!array_ty.hasRuntimeBitsIgnoreComptime()) { | 5668 | if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5656 | const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), operand, 0, ""); | 5669 | const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), operand, 0, ""); |
| 5657 | return self.builder.buildInsertValue(partial, len, 1, ""); | 5670 | return self.builder.buildInsertValue(partial, len, 1, ""); |
| 5658 | } | 5671 | } |
| ... | @@ -5666,30 +5679,31 @@ pub const FuncGen = struct { | ... | @@ -5666,30 +5679,31 @@ pub const FuncGen = struct { |
| 5666 | } | 5679 | } |
| 5667 | 5680 | ||
| 5668 | fn airIntToFloat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 5681 | fn airIntToFloat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 5682 | const mod = self.dg.module; | ||
| 5669 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 5683 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5670 | 5684 | ||
| 5671 | const operand = try self.resolveInst(ty_op.operand); | 5685 | const operand = try self.resolveInst(ty_op.operand); |
| 5672 | const operand_ty = self.air.typeOf(ty_op.operand); | 5686 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 5673 | const operand_scalar_ty = operand_ty.scalarType(); | 5687 | const operand_scalar_ty = operand_ty.scalarType(mod); |
| 5674 | 5688 | ||
| 5675 | const dest_ty = self.air.typeOfIndex(inst); | 5689 | const dest_ty = self.air.typeOfIndex(inst); |
| 5676 | const dest_scalar_ty = dest_ty.scalarType(); | 5690 | const dest_scalar_ty = dest_ty.scalarType(mod); |
| 5677 | const dest_llvm_ty = try self.dg.lowerType(dest_ty); | 5691 | const dest_llvm_ty = try self.dg.lowerType(dest_ty); |
| 5678 | const target = self.dg.module.getTarget(); | 5692 | const target = mod.getTarget(); |
| 5679 | 5693 | ||
| 5680 | if (intrinsicsAllowed(dest_scalar_ty, target)) { | 5694 | if (intrinsicsAllowed(dest_scalar_ty, target)) { |
| 5681 | if (operand_scalar_ty.isSignedInt()) { | 5695 | if (operand_scalar_ty.isSignedInt(mod)) { |
| 5682 | return self.builder.buildSIToFP(operand, dest_llvm_ty, ""); | 5696 | return self.builder.buildSIToFP(operand, dest_llvm_ty, ""); |
| 5683 | } else { | 5697 | } else { |
| 5684 | return self.builder.buildUIToFP(operand, dest_llvm_ty, ""); | 5698 | return self.builder.buildUIToFP(operand, dest_llvm_ty, ""); |
| 5685 | } | 5699 | } |
| 5686 | } | 5700 | } |
| 5687 | 5701 | ||
| 5688 | const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(target)); | 5702 | const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(mod)); |
| 5689 | const rt_int_bits = compilerRtIntBits(operand_bits); | 5703 | const rt_int_bits = compilerRtIntBits(operand_bits); |
| 5690 | const rt_int_ty = self.context.intType(rt_int_bits); | 5704 | const rt_int_ty = self.context.intType(rt_int_bits); |
| 5691 | var extended = e: { | 5705 | var extended = e: { |
| 5692 | if (operand_scalar_ty.isSignedInt()) { | 5706 | if (operand_scalar_ty.isSignedInt(mod)) { |
| 5693 | break :e self.builder.buildSExtOrBitCast(operand, rt_int_ty, ""); | 5707 | break :e self.builder.buildSExtOrBitCast(operand, rt_int_ty, ""); |
| 5694 | } else { | 5708 | } else { |
| 5695 | break :e self.builder.buildZExtOrBitCast(operand, rt_int_ty, ""); | 5709 | break :e self.builder.buildZExtOrBitCast(operand, rt_int_ty, ""); |
| ... | @@ -5698,7 +5712,7 @@ pub const FuncGen = struct { | ... | @@ -5698,7 +5712,7 @@ pub const FuncGen = struct { |
| 5698 | const dest_bits = dest_scalar_ty.floatBits(target); | 5712 | const dest_bits = dest_scalar_ty.floatBits(target); |
| 5699 | const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits); | 5713 | const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits); |
| 5700 | const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits); | 5714 | const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits); |
| 5701 | const sign_prefix = if (operand_scalar_ty.isSignedInt()) "" else "un"; | 5715 | const sign_prefix = if (operand_scalar_ty.isSignedInt(mod)) "" else "un"; |
| 5702 | var fn_name_buf: [64]u8 = undefined; | 5716 | var fn_name_buf: [64]u8 = undefined; |
| 5703 | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__float{s}{s}i{s}f", .{ | 5717 | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__float{s}{s}i{s}f", .{ |
| 5704 | sign_prefix, | 5718 | sign_prefix, |
| ... | @@ -5724,27 +5738,28 @@ pub const FuncGen = struct { | ... | @@ -5724,27 +5738,28 @@ pub const FuncGen = struct { |
| 5724 | fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { | 5738 | fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { |
| 5725 | self.builder.setFastMath(want_fast_math); | 5739 | self.builder.setFastMath(want_fast_math); |
| 5726 | 5740 | ||
| 5727 | const target = self.dg.module.getTarget(); | 5741 | const mod = self.dg.module; |
| 5742 | const target = mod.getTarget(); | ||
| 5728 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 5743 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5729 | 5744 | ||
| 5730 | const operand = try self.resolveInst(ty_op.operand); | 5745 | const operand = try self.resolveInst(ty_op.operand); |
| 5731 | const operand_ty = self.air.typeOf(ty_op.operand); | 5746 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 5732 | const operand_scalar_ty = operand_ty.scalarType(); | 5747 | const operand_scalar_ty = operand_ty.scalarType(mod); |
| 5733 | 5748 | ||
| 5734 | const dest_ty = self.air.typeOfIndex(inst); | 5749 | const dest_ty = self.air.typeOfIndex(inst); |
| 5735 | const dest_scalar_ty = dest_ty.scalarType(); | 5750 | const dest_scalar_ty = dest_ty.scalarType(mod); |
| 5736 | const dest_llvm_ty = try self.dg.lowerType(dest_ty); | 5751 | const dest_llvm_ty = try self.dg.lowerType(dest_ty); |
| 5737 | 5752 | ||
| 5738 | if (intrinsicsAllowed(operand_scalar_ty, target)) { | 5753 | if (intrinsicsAllowed(operand_scalar_ty, target)) { |
| 5739 | // TODO set fast math flag | 5754 | // TODO set fast math flag |
| 5740 | if (dest_scalar_ty.isSignedInt()) { | 5755 | if (dest_scalar_ty.isSignedInt(mod)) { |
| 5741 | return self.builder.buildFPToSI(operand, dest_llvm_ty, ""); | 5756 | return self.builder.buildFPToSI(operand, dest_llvm_ty, ""); |
| 5742 | } else { | 5757 | } else { |
| 5743 | return self.builder.buildFPToUI(operand, dest_llvm_ty, ""); | 5758 | return self.builder.buildFPToUI(operand, dest_llvm_ty, ""); |
| 5744 | } | 5759 | } |
| 5745 | } | 5760 | } |
| 5746 | 5761 | ||
| 5747 | const rt_int_bits = compilerRtIntBits(@intCast(u16, dest_scalar_ty.bitSize(target))); | 5762 | const rt_int_bits = compilerRtIntBits(@intCast(u16, dest_scalar_ty.bitSize(mod))); |
| 5748 | const ret_ty = self.context.intType(rt_int_bits); | 5763 | const ret_ty = self.context.intType(rt_int_bits); |
| 5749 | const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: { | 5764 | const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: { |
| 5750 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard | 5765 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard |
| ... | @@ -5756,7 +5771,7 @@ pub const FuncGen = struct { | ... | @@ -5756,7 +5771,7 @@ pub const FuncGen = struct { |
| 5756 | const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits); | 5771 | const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits); |
| 5757 | 5772 | ||
| 5758 | const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits); | 5773 | const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits); |
| 5759 | const sign_prefix = if (dest_scalar_ty.isSignedInt()) "" else "uns"; | 5774 | const sign_prefix = if (dest_scalar_ty.isSignedInt(mod)) "" else "uns"; |
| 5760 | 5775 | ||
| 5761 | var fn_name_buf: [64]u8 = undefined; | 5776 | var fn_name_buf: [64]u8 = undefined; |
| 5762 | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}{s}f{s}i", .{ | 5777 | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}{s}f{s}i", .{ |
| ... | @@ -5786,13 +5801,14 @@ pub const FuncGen = struct { | ... | @@ -5786,13 +5801,14 @@ pub const FuncGen = struct { |
| 5786 | } | 5801 | } |
| 5787 | 5802 | ||
| 5788 | fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value { | 5803 | fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value { |
| 5789 | const target = fg.dg.module.getTarget(); | 5804 | const mod = fg.dg.module; |
| 5805 | const target = mod.getTarget(); | ||
| 5790 | const llvm_usize_ty = fg.context.intType(target.ptrBitWidth()); | 5806 | const llvm_usize_ty = fg.context.intType(target.ptrBitWidth()); |
| 5791 | switch (ty.ptrSize()) { | 5807 | switch (ty.ptrSize()) { |
| 5792 | .Slice => { | 5808 | .Slice => { |
| 5793 | const len = fg.builder.buildExtractValue(ptr, 1, ""); | 5809 | const len = fg.builder.buildExtractValue(ptr, 1, ""); |
| 5794 | const elem_ty = ty.childType(); | 5810 | const elem_ty = ty.childType(); |
| 5795 | const abi_size = elem_ty.abiSize(target); | 5811 | const abi_size = elem_ty.abiSize(mod); |
| 5796 | if (abi_size == 1) return len; | 5812 | if (abi_size == 1) return len; |
| 5797 | const abi_size_llvm_val = llvm_usize_ty.constInt(abi_size, .False); | 5813 | const abi_size_llvm_val = llvm_usize_ty.constInt(abi_size, .False); |
| 5798 | return fg.builder.buildMul(len, abi_size_llvm_val, ""); | 5814 | return fg.builder.buildMul(len, abi_size_llvm_val, ""); |
| ... | @@ -5800,7 +5816,7 @@ pub const FuncGen = struct { | ... | @@ -5800,7 +5816,7 @@ pub const FuncGen = struct { |
| 5800 | .One => { | 5816 | .One => { |
| 5801 | const array_ty = ty.childType(); | 5817 | const array_ty = ty.childType(); |
| 5802 | const elem_ty = array_ty.childType(); | 5818 | const elem_ty = array_ty.childType(); |
| 5803 | const abi_size = elem_ty.abiSize(target); | 5819 | const abi_size = elem_ty.abiSize(mod); |
| 5804 | return llvm_usize_ty.constInt(array_ty.arrayLen() * abi_size, .False); | 5820 | return llvm_usize_ty.constInt(array_ty.arrayLen() * abi_size, .False); |
| 5805 | }, | 5821 | }, |
| 5806 | .Many, .C => unreachable, | 5822 | .Many, .C => unreachable, |
| ... | @@ -5823,6 +5839,7 @@ pub const FuncGen = struct { | ... | @@ -5823,6 +5839,7 @@ pub const FuncGen = struct { |
| 5823 | } | 5839 | } |
| 5824 | 5840 | ||
| 5825 | fn airSliceElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { | 5841 | fn airSliceElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { |
| 5842 | const mod = self.dg.module; | ||
| 5826 | const inst = body_tail[0]; | 5843 | const inst = body_tail[0]; |
| 5827 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 5844 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 5828 | const slice_ty = self.air.typeOf(bin_op.lhs); | 5845 | const slice_ty = self.air.typeOf(bin_op.lhs); |
| ... | @@ -5833,12 +5850,11 @@ pub const FuncGen = struct { | ... | @@ -5833,12 +5850,11 @@ pub const FuncGen = struct { |
| 5833 | const base_ptr = self.builder.buildExtractValue(slice, 0, ""); | 5850 | const base_ptr = self.builder.buildExtractValue(slice, 0, ""); |
| 5834 | const indices: [1]*llvm.Value = .{index}; | 5851 | const indices: [1]*llvm.Value = .{index}; |
| 5835 | const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); | 5852 | const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 5836 | if (isByRef(elem_ty)) { | 5853 | if (isByRef(elem_ty, mod)) { |
| 5837 | if (self.canElideLoad(body_tail)) | 5854 | if (self.canElideLoad(body_tail)) |
| 5838 | return ptr; | 5855 | return ptr; |
| 5839 | 5856 | ||
| 5840 | const target = self.dg.module.getTarget(); | 5857 | return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(mod), false); |
| 5841 | return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(target), false); | ||
| 5842 | } | 5858 | } |
| 5843 | 5859 | ||
| 5844 | return self.load(ptr, slice_ty); | 5860 | return self.load(ptr, slice_ty); |
| ... | @@ -5858,6 +5874,7 @@ pub const FuncGen = struct { | ... | @@ -5858,6 +5874,7 @@ pub const FuncGen = struct { |
| 5858 | } | 5874 | } |
| 5859 | 5875 | ||
| 5860 | fn airArrayElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { | 5876 | fn airArrayElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { |
| 5877 | const mod = self.dg.module; | ||
| 5861 | const inst = body_tail[0]; | 5878 | const inst = body_tail[0]; |
| 5862 | 5879 | ||
| 5863 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 5880 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| ... | @@ -5866,15 +5883,14 @@ pub const FuncGen = struct { | ... | @@ -5866,15 +5883,14 @@ pub const FuncGen = struct { |
| 5866 | const rhs = try self.resolveInst(bin_op.rhs); | 5883 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5867 | const array_llvm_ty = try self.dg.lowerType(array_ty); | 5884 | const array_llvm_ty = try self.dg.lowerType(array_ty); |
| 5868 | const elem_ty = array_ty.childType(); | 5885 | const elem_ty = array_ty.childType(); |
| 5869 | if (isByRef(array_ty)) { | 5886 | if (isByRef(array_ty, mod)) { |
| 5870 | const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs }; | 5887 | const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs }; |
| 5871 | if (isByRef(elem_ty)) { | 5888 | if (isByRef(elem_ty, mod)) { |
| 5872 | const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, ""); | 5889 | const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, ""); |
| 5873 | if (canElideLoad(self, body_tail)) | 5890 | if (canElideLoad(self, body_tail)) |
| 5874 | return elem_ptr; | 5891 | return elem_ptr; |
| 5875 | 5892 | ||
| 5876 | const target = self.dg.module.getTarget(); | 5893 | return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(mod), false); |
| 5877 | return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(target), false); | ||
| 5878 | } else { | 5894 | } else { |
| 5879 | const lhs_index = Air.refToIndex(bin_op.lhs).?; | 5895 | const lhs_index = Air.refToIndex(bin_op.lhs).?; |
| 5880 | const elem_llvm_ty = try self.dg.lowerType(elem_ty); | 5896 | const elem_llvm_ty = try self.dg.lowerType(elem_ty); |
| ... | @@ -5901,6 +5917,7 @@ pub const FuncGen = struct { | ... | @@ -5901,6 +5917,7 @@ pub const FuncGen = struct { |
| 5901 | } | 5917 | } |
| 5902 | 5918 | ||
| 5903 | fn airPtrElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { | 5919 | fn airPtrElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { |
| 5920 | const mod = self.dg.module; | ||
| 5904 | const inst = body_tail[0]; | 5921 | const inst = body_tail[0]; |
| 5905 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 5922 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 5906 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 5923 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| ... | @@ -5917,23 +5934,23 @@ pub const FuncGen = struct { | ... | @@ -5917,23 +5934,23 @@ pub const FuncGen = struct { |
| 5917 | const indices: [1]*llvm.Value = .{rhs}; | 5934 | const indices: [1]*llvm.Value = .{rhs}; |
| 5918 | break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); | 5935 | break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 5919 | }; | 5936 | }; |
| 5920 | if (isByRef(elem_ty)) { | 5937 | if (isByRef(elem_ty, mod)) { |
| 5921 | if (self.canElideLoad(body_tail)) | 5938 | if (self.canElideLoad(body_tail)) |
| 5922 | return ptr; | 5939 | return ptr; |
| 5923 | 5940 | ||
| 5924 | const target = self.dg.module.getTarget(); | 5941 | return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(mod), false); |
| 5925 | return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(target), false); | ||
| 5926 | } | 5942 | } |
| 5927 | 5943 | ||
| 5928 | return self.load(ptr, ptr_ty); | 5944 | return self.load(ptr, ptr_ty); |
| 5929 | } | 5945 | } |
| 5930 | 5946 | ||
| 5931 | fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 5947 | fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 5948 | const mod = self.dg.module; | ||
| 5932 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 5949 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 5933 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 5950 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 5934 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 5951 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 5935 | const elem_ty = ptr_ty.childType(); | 5952 | const elem_ty = ptr_ty.childType(); |
| 5936 | if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty); | 5953 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty); |
| 5937 | 5954 | ||
| 5938 | const base_ptr = try self.resolveInst(bin_op.lhs); | 5955 | const base_ptr = try self.resolveInst(bin_op.lhs); |
| 5939 | const rhs = try self.resolveInst(bin_op.rhs); | 5956 | const rhs = try self.resolveInst(bin_op.rhs); |
| ... | @@ -5972,6 +5989,7 @@ pub const FuncGen = struct { | ... | @@ -5972,6 +5989,7 @@ pub const FuncGen = struct { |
| 5972 | } | 5989 | } |
| 5973 | 5990 | ||
| 5974 | fn airStructFieldVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { | 5991 | fn airStructFieldVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { |
| 5992 | const mod = self.dg.module; | ||
| 5975 | const inst = body_tail[0]; | 5993 | const inst = body_tail[0]; |
| 5976 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 5994 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 5977 | const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; | 5995 | const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; |
| ... | @@ -5979,29 +5997,28 @@ pub const FuncGen = struct { | ... | @@ -5979,29 +5997,28 @@ pub const FuncGen = struct { |
| 5979 | const struct_llvm_val = try self.resolveInst(struct_field.struct_operand); | 5997 | const struct_llvm_val = try self.resolveInst(struct_field.struct_operand); |
| 5980 | const field_index = struct_field.field_index; | 5998 | const field_index = struct_field.field_index; |
| 5981 | const field_ty = struct_ty.structFieldType(field_index); | 5999 | const field_ty = struct_ty.structFieldType(field_index); |
| 5982 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) { | 6000 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 5983 | return null; | 6001 | return null; |
| 5984 | } | 6002 | } |
| 5985 | const target = self.dg.module.getTarget(); | ||
| 5986 | 6003 | ||
| 5987 | if (!isByRef(struct_ty)) { | 6004 | if (!isByRef(struct_ty, mod)) { |
| 5988 | assert(!isByRef(field_ty)); | 6005 | assert(!isByRef(field_ty, mod)); |
| 5989 | switch (struct_ty.zigTypeTag()) { | 6006 | switch (struct_ty.zigTypeTag(mod)) { |
| 5990 | .Struct => switch (struct_ty.containerLayout()) { | 6007 | .Struct => switch (struct_ty.containerLayout()) { |
| 5991 | .Packed => { | 6008 | .Packed => { |
| 5992 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 6009 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 5993 | const bit_offset = struct_obj.packedFieldBitOffset(target, field_index); | 6010 | const bit_offset = struct_obj.packedFieldBitOffset(mod, field_index); |
| 5994 | const containing_int = struct_llvm_val; | 6011 | const containing_int = struct_llvm_val; |
| 5995 | const shift_amt = containing_int.typeOf().constInt(bit_offset, .False); | 6012 | const shift_amt = containing_int.typeOf().constInt(bit_offset, .False); |
| 5996 | const shifted_value = self.builder.buildLShr(containing_int, shift_amt, ""); | 6013 | const shifted_value = self.builder.buildLShr(containing_int, shift_amt, ""); |
| 5997 | const elem_llvm_ty = try self.dg.lowerType(field_ty); | 6014 | const elem_llvm_ty = try self.dg.lowerType(field_ty); |
| 5998 | if (field_ty.zigTypeTag() == .Float or field_ty.zigTypeTag() == .Vector) { | 6015 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { |
| 5999 | const elem_bits = @intCast(c_uint, field_ty.bitSize(target)); | 6016 | const elem_bits = @intCast(c_uint, field_ty.bitSize(mod)); |
| 6000 | const same_size_int = self.context.intType(elem_bits); | 6017 | const same_size_int = self.context.intType(elem_bits); |
| 6001 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 6018 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 6002 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); | 6019 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 6003 | } else if (field_ty.isPtrAtRuntime()) { | 6020 | } else if (field_ty.isPtrAtRuntime(mod)) { |
| 6004 | const elem_bits = @intCast(c_uint, field_ty.bitSize(target)); | 6021 | const elem_bits = @intCast(c_uint, field_ty.bitSize(mod)); |
| 6005 | const same_size_int = self.context.intType(elem_bits); | 6022 | const same_size_int = self.context.intType(elem_bits); |
| 6006 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 6023 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 6007 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); | 6024 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| ... | @@ -6010,7 +6027,7 @@ pub const FuncGen = struct { | ... | @@ -6010,7 +6027,7 @@ pub const FuncGen = struct { |
| 6010 | }, | 6027 | }, |
| 6011 | else => { | 6028 | else => { |
| 6012 | var ptr_ty_buf: Type.Payload.Pointer = undefined; | 6029 | var ptr_ty_buf: Type.Payload.Pointer = undefined; |
| 6013 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; | 6030 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?; |
| 6014 | return self.builder.buildExtractValue(struct_llvm_val, llvm_field_index, ""); | 6031 | return self.builder.buildExtractValue(struct_llvm_val, llvm_field_index, ""); |
| 6015 | }, | 6032 | }, |
| 6016 | }, | 6033 | }, |
| ... | @@ -6018,13 +6035,13 @@ pub const FuncGen = struct { | ... | @@ -6018,13 +6035,13 @@ pub const FuncGen = struct { |
| 6018 | assert(struct_ty.containerLayout() == .Packed); | 6035 | assert(struct_ty.containerLayout() == .Packed); |
| 6019 | const containing_int = struct_llvm_val; | 6036 | const containing_int = struct_llvm_val; |
| 6020 | const elem_llvm_ty = try self.dg.lowerType(field_ty); | 6037 | const elem_llvm_ty = try self.dg.lowerType(field_ty); |
| 6021 | if (field_ty.zigTypeTag() == .Float or field_ty.zigTypeTag() == .Vector) { | 6038 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { |
| 6022 | const elem_bits = @intCast(c_uint, field_ty.bitSize(target)); | 6039 | const elem_bits = @intCast(c_uint, field_ty.bitSize(mod)); |
| 6023 | const same_size_int = self.context.intType(elem_bits); | 6040 | const same_size_int = self.context.intType(elem_bits); |
| 6024 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); | 6041 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); |
| 6025 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); | 6042 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 6026 | } else if (field_ty.isPtrAtRuntime()) { | 6043 | } else if (field_ty.isPtrAtRuntime(mod)) { |
| 6027 | const elem_bits = @intCast(c_uint, field_ty.bitSize(target)); | 6044 | const elem_bits = @intCast(c_uint, field_ty.bitSize(mod)); |
| 6028 | const same_size_int = self.context.intType(elem_bits); | 6045 | const same_size_int = self.context.intType(elem_bits); |
| 6029 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); | 6046 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); |
| 6030 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); | 6047 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| ... | @@ -6035,30 +6052,30 @@ pub const FuncGen = struct { | ... | @@ -6035,30 +6052,30 @@ pub const FuncGen = struct { |
| 6035 | } | 6052 | } |
| 6036 | } | 6053 | } |
| 6037 | 6054 | ||
| 6038 | switch (struct_ty.zigTypeTag()) { | 6055 | switch (struct_ty.zigTypeTag(mod)) { |
| 6039 | .Struct => { | 6056 | .Struct => { |
| 6040 | assert(struct_ty.containerLayout() != .Packed); | 6057 | assert(struct_ty.containerLayout() != .Packed); |
| 6041 | var ptr_ty_buf: Type.Payload.Pointer = undefined; | 6058 | var ptr_ty_buf: Type.Payload.Pointer = undefined; |
| 6042 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; | 6059 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?; |
| 6043 | const struct_llvm_ty = try self.dg.lowerType(struct_ty); | 6060 | const struct_llvm_ty = try self.dg.lowerType(struct_ty); |
| 6044 | const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field_index, ""); | 6061 | const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field_index, ""); |
| 6045 | const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); | 6062 | const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); |
| 6046 | if (isByRef(field_ty)) { | 6063 | if (isByRef(field_ty, mod)) { |
| 6047 | if (canElideLoad(self, body_tail)) | 6064 | if (canElideLoad(self, body_tail)) |
| 6048 | return field_ptr; | 6065 | return field_ptr; |
| 6049 | 6066 | ||
| 6050 | return self.loadByRef(field_ptr, field_ty, ptr_ty_buf.data.alignment(target), false); | 6067 | return self.loadByRef(field_ptr, field_ty, ptr_ty_buf.data.alignment(mod), false); |
| 6051 | } else { | 6068 | } else { |
| 6052 | return self.load(field_ptr, field_ptr_ty); | 6069 | return self.load(field_ptr, field_ptr_ty); |
| 6053 | } | 6070 | } |
| 6054 | }, | 6071 | }, |
| 6055 | .Union => { | 6072 | .Union => { |
| 6056 | const union_llvm_ty = try self.dg.lowerType(struct_ty); | 6073 | const union_llvm_ty = try self.dg.lowerType(struct_ty); |
| 6057 | const layout = struct_ty.unionGetLayout(target); | 6074 | const layout = struct_ty.unionGetLayout(mod); |
| 6058 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); | 6075 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); |
| 6059 | const field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_llvm_val, payload_index, ""); | 6076 | const field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_llvm_val, payload_index, ""); |
| 6060 | const llvm_field_ty = try self.dg.lowerType(field_ty); | 6077 | const llvm_field_ty = try self.dg.lowerType(field_ty); |
| 6061 | if (isByRef(field_ty)) { | 6078 | if (isByRef(field_ty, mod)) { |
| 6062 | if (canElideLoad(self, body_tail)) | 6079 | if (canElideLoad(self, body_tail)) |
| 6063 | return field_ptr; | 6080 | return field_ptr; |
| 6064 | 6081 | ||
| ... | @@ -6072,6 +6089,7 @@ pub const FuncGen = struct { | ... | @@ -6072,6 +6089,7 @@ pub const FuncGen = struct { |
| 6072 | } | 6089 | } |
| 6073 | 6090 | ||
| 6074 | fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 6091 | fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 6092 | const mod = self.dg.module; | ||
| 6075 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 6093 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 6076 | const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | 6094 | const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 6077 | 6095 | ||
| ... | @@ -6079,7 +6097,7 @@ pub const FuncGen = struct { | ... | @@ -6079,7 +6097,7 @@ pub const FuncGen = struct { |
| 6079 | 6097 | ||
| 6080 | const target = self.dg.module.getTarget(); | 6098 | const target = self.dg.module.getTarget(); |
| 6081 | const parent_ty = self.air.getRefType(ty_pl.ty).childType(); | 6099 | const parent_ty = self.air.getRefType(ty_pl.ty).childType(); |
| 6082 | const field_offset = parent_ty.structFieldOffset(extra.field_index, target); | 6100 | const field_offset = parent_ty.structFieldOffset(extra.field_index, mod); |
| 6083 | 6101 | ||
| 6084 | const res_ty = try self.dg.lowerType(self.air.getRefType(ty_pl.ty)); | 6102 | const res_ty = try self.dg.lowerType(self.air.getRefType(ty_pl.ty)); |
| 6085 | if (field_offset == 0) { | 6103 | if (field_offset == 0) { |
| ... | @@ -6119,12 +6137,13 @@ pub const FuncGen = struct { | ... | @@ -6119,12 +6137,13 @@ pub const FuncGen = struct { |
| 6119 | } | 6137 | } |
| 6120 | 6138 | ||
| 6121 | fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 6139 | fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 6140 | const mod = self.dg.module; | ||
| 6122 | const dib = self.dg.object.di_builder orelse return null; | 6141 | const dib = self.dg.object.di_builder orelse return null; |
| 6123 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 6142 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 6124 | 6143 | ||
| 6125 | const func = self.air.values[ty_pl.payload].castTag(.function).?.data; | 6144 | const func = self.air.values[ty_pl.payload].castTag(.function).?.data; |
| 6126 | const decl_index = func.owner_decl; | 6145 | const decl_index = func.owner_decl; |
| 6127 | const decl = self.dg.module.declPtr(decl_index); | 6146 | const decl = mod.declPtr(decl_index); |
| 6128 | const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope); | 6147 | const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope); |
| 6129 | self.di_file = di_file; | 6148 | self.di_file = di_file; |
| 6130 | const line_number = decl.src_line + 1; | 6149 | const line_number = decl.src_line + 1; |
| ... | @@ -6136,22 +6155,41 @@ pub const FuncGen = struct { | ... | @@ -6136,22 +6155,41 @@ pub const FuncGen = struct { |
| 6136 | .base_line = self.base_line, | 6155 | .base_line = self.base_line, |
| 6137 | }); | 6156 | }); |
| 6138 | 6157 | ||
| 6139 | const fqn = try decl.getFullyQualifiedName(self.dg.module); | 6158 | const fqn = try decl.getFullyQualifiedName(mod); |
| 6140 | defer self.gpa.free(fqn); | 6159 | defer self.gpa.free(fqn); |
| 6141 | 6160 | ||
| 6142 | const is_internal_linkage = !self.dg.module.decl_exports.contains(decl_index); | 6161 | const is_internal_linkage = !mod.decl_exports.contains(decl_index); |
| 6162 | var fn_ty_pl: Type.Payload.Function = .{ | ||
| 6163 | .base = .{ .tag = .function }, | ||
| 6164 | .data = .{ | ||
| 6165 | .param_types = &.{}, | ||
| 6166 | .comptime_params = undefined, | ||
| 6167 | .return_type = Type.void, | ||
| 6168 | .alignment = 0, | ||
| 6169 | .noalias_bits = 0, | ||
| 6170 | .cc = .Unspecified, | ||
| 6171 | .is_var_args = false, | ||
| 6172 | .is_generic = false, | ||
| 6173 | .is_noinline = false, | ||
| 6174 | .align_is_generic = false, | ||
| 6175 | .cc_is_generic = false, | ||
| 6176 | .section_is_generic = false, | ||
| 6177 | .addrspace_is_generic = false, | ||
| 6178 | }, | ||
| 6179 | }; | ||
| 6180 | const fn_ty = Type.initPayload(&fn_ty_pl.base); | ||
| 6143 | const subprogram = dib.createFunction( | 6181 | const subprogram = dib.createFunction( |
| 6144 | di_file.toScope(), | 6182 | di_file.toScope(), |
| 6145 | decl.name, | 6183 | decl.name, |
| 6146 | fqn, | 6184 | fqn, |
| 6147 | di_file, | 6185 | di_file, |
| 6148 | line_number, | 6186 | line_number, |
| 6149 | try self.dg.object.lowerDebugType(Type.initTag(.fn_void_no_args), .full), | 6187 | try self.dg.object.lowerDebugType(fn_ty, .full), |
| 6150 | is_internal_linkage, | 6188 | is_internal_linkage, |
| 6151 | true, // is definition | 6189 | true, // is definition |
| 6152 | line_number + func.lbrace_line, // scope line | 6190 | line_number + func.lbrace_line, // scope line |
| 6153 | llvm.DIFlags.StaticMember, | 6191 | llvm.DIFlags.StaticMember, |
| 6154 | self.dg.module.comp.bin_file.options.optimize_mode != .Debug, | 6192 | mod.comp.bin_file.options.optimize_mode != .Debug, |
| 6155 | null, // decl_subprogram | 6193 | null, // decl_subprogram |
| 6156 | ); | 6194 | ); |
| 6157 | 6195 | ||
| ... | @@ -6243,10 +6281,11 @@ pub const FuncGen = struct { | ... | @@ -6243,10 +6281,11 @@ pub const FuncGen = struct { |
| 6243 | null; | 6281 | null; |
| 6244 | const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at); | 6282 | const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at); |
| 6245 | const insert_block = self.builder.getInsertBlock(); | 6283 | const insert_block = self.builder.getInsertBlock(); |
| 6246 | if (isByRef(operand_ty)) { | 6284 | const mod = self.dg.module; |
| 6285 | if (isByRef(operand_ty, mod)) { | ||
| 6247 | _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block); | 6286 | _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block); |
| 6248 | } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) { | 6287 | } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) { |
| 6249 | const alignment = operand_ty.abiAlignment(self.dg.module.getTarget()); | 6288 | const alignment = operand_ty.abiAlignment(mod); |
| 6250 | const alloca = self.buildAlloca(operand.typeOf(), alignment); | 6289 | const alloca = self.buildAlloca(operand.typeOf(), alignment); |
| 6251 | const store_inst = self.builder.buildStore(operand, alloca); | 6290 | const store_inst = self.builder.buildStore(operand, alloca); |
| 6252 | store_inst.setAlignment(alignment); | 6291 | store_inst.setAlignment(alignment); |
| ... | @@ -6294,7 +6333,8 @@ pub const FuncGen = struct { | ... | @@ -6294,7 +6333,8 @@ pub const FuncGen = struct { |
| 6294 | // This stores whether we need to add an elementtype attribute and | 6333 | // This stores whether we need to add an elementtype attribute and |
| 6295 | // if so, the element type itself. | 6334 | // if so, the element type itself. |
| 6296 | const llvm_param_attrs = try arena.alloc(?*llvm.Type, max_param_count); | 6335 | const llvm_param_attrs = try arena.alloc(?*llvm.Type, max_param_count); |
| 6297 | const target = self.dg.module.getTarget(); | 6336 | const mod = self.dg.module; |
| 6337 | const target = mod.getTarget(); | ||
| 6298 | 6338 | ||
| 6299 | var llvm_ret_i: usize = 0; | 6339 | var llvm_ret_i: usize = 0; |
| 6300 | var llvm_param_i: usize = 0; | 6340 | var llvm_param_i: usize = 0; |
| ... | @@ -6322,7 +6362,7 @@ pub const FuncGen = struct { | ... | @@ -6322,7 +6362,7 @@ pub const FuncGen = struct { |
| 6322 | if (output != .none) { | 6362 | if (output != .none) { |
| 6323 | const output_inst = try self.resolveInst(output); | 6363 | const output_inst = try self.resolveInst(output); |
| 6324 | const output_ty = self.air.typeOf(output); | 6364 | const output_ty = self.air.typeOf(output); |
| 6325 | assert(output_ty.zigTypeTag() == .Pointer); | 6365 | assert(output_ty.zigTypeTag(mod) == .Pointer); |
| 6326 | const elem_llvm_ty = try self.dg.lowerPtrElemTy(output_ty.childType()); | 6366 | const elem_llvm_ty = try self.dg.lowerPtrElemTy(output_ty.childType()); |
| 6327 | 6367 | ||
| 6328 | if (llvm_ret_indirect[i]) { | 6368 | if (llvm_ret_indirect[i]) { |
| ... | @@ -6376,13 +6416,13 @@ pub const FuncGen = struct { | ... | @@ -6376,13 +6416,13 @@ pub const FuncGen = struct { |
| 6376 | const arg_llvm_value = try self.resolveInst(input); | 6416 | const arg_llvm_value = try self.resolveInst(input); |
| 6377 | const arg_ty = self.air.typeOf(input); | 6417 | const arg_ty = self.air.typeOf(input); |
| 6378 | var llvm_elem_ty: ?*llvm.Type = null; | 6418 | var llvm_elem_ty: ?*llvm.Type = null; |
| 6379 | if (isByRef(arg_ty)) { | 6419 | if (isByRef(arg_ty, mod)) { |
| 6380 | llvm_elem_ty = try self.dg.lowerPtrElemTy(arg_ty); | 6420 | llvm_elem_ty = try self.dg.lowerPtrElemTy(arg_ty); |
| 6381 | if (constraintAllowsMemory(constraint)) { | 6421 | if (constraintAllowsMemory(constraint)) { |
| 6382 | llvm_param_values[llvm_param_i] = arg_llvm_value; | 6422 | llvm_param_values[llvm_param_i] = arg_llvm_value; |
| 6383 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); | 6423 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); |
| 6384 | } else { | 6424 | } else { |
| 6385 | const alignment = arg_ty.abiAlignment(target); | 6425 | const alignment = arg_ty.abiAlignment(mod); |
| 6386 | const arg_llvm_ty = try self.dg.lowerType(arg_ty); | 6426 | const arg_llvm_ty = try self.dg.lowerType(arg_ty); |
| 6387 | const load_inst = self.builder.buildLoad(arg_llvm_ty, arg_llvm_value, ""); | 6427 | const load_inst = self.builder.buildLoad(arg_llvm_ty, arg_llvm_value, ""); |
| 6388 | load_inst.setAlignment(alignment); | 6428 | load_inst.setAlignment(alignment); |
| ... | @@ -6394,7 +6434,7 @@ pub const FuncGen = struct { | ... | @@ -6394,7 +6434,7 @@ pub const FuncGen = struct { |
| 6394 | llvm_param_values[llvm_param_i] = arg_llvm_value; | 6434 | llvm_param_values[llvm_param_i] = arg_llvm_value; |
| 6395 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); | 6435 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); |
| 6396 | } else { | 6436 | } else { |
| 6397 | const alignment = arg_ty.abiAlignment(target); | 6437 | const alignment = arg_ty.abiAlignment(mod); |
| 6398 | const arg_ptr = self.buildAlloca(arg_llvm_value.typeOf(), alignment); | 6438 | const arg_ptr = self.buildAlloca(arg_llvm_value.typeOf(), alignment); |
| 6399 | const store_inst = self.builder.buildStore(arg_llvm_value, arg_ptr); | 6439 | const store_inst = self.builder.buildStore(arg_llvm_value, arg_ptr); |
| 6400 | store_inst.setAlignment(alignment); | 6440 | store_inst.setAlignment(alignment); |
| ... | @@ -6599,7 +6639,7 @@ pub const FuncGen = struct { | ... | @@ -6599,7 +6639,7 @@ pub const FuncGen = struct { |
| 6599 | const output_ptr_ty = self.air.typeOf(output); | 6639 | const output_ptr_ty = self.air.typeOf(output); |
| 6600 | 6640 | ||
| 6601 | const store_inst = self.builder.buildStore(output_value, output_ptr); | 6641 | const store_inst = self.builder.buildStore(output_value, output_ptr); |
| 6602 | store_inst.setAlignment(output_ptr_ty.ptrAlignment(target)); | 6642 | store_inst.setAlignment(output_ptr_ty.ptrAlignment(mod)); |
| 6603 | } else { | 6643 | } else { |
| 6604 | ret_val = output_value; | 6644 | ret_val = output_value; |
| 6605 | } | 6645 | } |
| ... | @@ -6622,7 +6662,8 @@ pub const FuncGen = struct { | ... | @@ -6622,7 +6662,8 @@ pub const FuncGen = struct { |
| 6622 | const optional_llvm_ty = try self.dg.lowerType(optional_ty); | 6662 | const optional_llvm_ty = try self.dg.lowerType(optional_ty); |
| 6623 | var buf: Type.Payload.ElemType = undefined; | 6663 | var buf: Type.Payload.ElemType = undefined; |
| 6624 | const payload_ty = optional_ty.optionalChild(&buf); | 6664 | const payload_ty = optional_ty.optionalChild(&buf); |
| 6625 | if (optional_ty.optionalReprIsPayload()) { | 6665 | const mod = self.dg.module; |
| 6666 | if (optional_ty.optionalReprIsPayload(mod)) { | ||
| 6626 | const loaded = if (operand_is_ptr) | 6667 | const loaded = if (operand_is_ptr) |
| 6627 | self.builder.buildLoad(optional_llvm_ty, operand, "") | 6668 | self.builder.buildLoad(optional_llvm_ty, operand, "") |
| 6628 | else | 6669 | else |
| ... | @@ -6638,7 +6679,7 @@ pub const FuncGen = struct { | ... | @@ -6638,7 +6679,7 @@ pub const FuncGen = struct { |
| 6638 | 6679 | ||
| 6639 | comptime assert(optional_layout_version == 3); | 6680 | comptime assert(optional_layout_version == 3); |
| 6640 | 6681 | ||
| 6641 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 6682 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6642 | const loaded = if (operand_is_ptr) | 6683 | const loaded = if (operand_is_ptr) |
| 6643 | self.builder.buildLoad(optional_llvm_ty, operand, "") | 6684 | self.builder.buildLoad(optional_llvm_ty, operand, "") |
| 6644 | else | 6685 | else |
| ... | @@ -6647,7 +6688,7 @@ pub const FuncGen = struct { | ... | @@ -6647,7 +6688,7 @@ pub const FuncGen = struct { |
| 6647 | return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), ""); | 6688 | return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), ""); |
| 6648 | } | 6689 | } |
| 6649 | 6690 | ||
| 6650 | const is_by_ref = operand_is_ptr or isByRef(optional_ty); | 6691 | const is_by_ref = operand_is_ptr or isByRef(optional_ty, mod); |
| 6651 | const non_null_bit = self.optIsNonNull(optional_llvm_ty, operand, is_by_ref); | 6692 | const non_null_bit = self.optIsNonNull(optional_llvm_ty, operand, is_by_ref); |
| 6652 | if (pred == .EQ) { | 6693 | if (pred == .EQ) { |
| 6653 | return self.builder.buildNot(non_null_bit, ""); | 6694 | return self.builder.buildNot(non_null_bit, ""); |
| ... | @@ -6662,6 +6703,7 @@ pub const FuncGen = struct { | ... | @@ -6662,6 +6703,7 @@ pub const FuncGen = struct { |
| 6662 | op: llvm.IntPredicate, | 6703 | op: llvm.IntPredicate, |
| 6663 | operand_is_ptr: bool, | 6704 | operand_is_ptr: bool, |
| 6664 | ) !?*llvm.Value { | 6705 | ) !?*llvm.Value { |
| 6706 | const mod = self.dg.module; | ||
| 6665 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 6707 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 6666 | const operand = try self.resolveInst(un_op); | 6708 | const operand = try self.resolveInst(un_op); |
| 6667 | const operand_ty = self.air.typeOf(un_op); | 6709 | const operand_ty = self.air.typeOf(un_op); |
| ... | @@ -6679,7 +6721,7 @@ pub const FuncGen = struct { | ... | @@ -6679,7 +6721,7 @@ pub const FuncGen = struct { |
| 6679 | } | 6721 | } |
| 6680 | } | 6722 | } |
| 6681 | 6723 | ||
| 6682 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 6724 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6683 | const loaded = if (operand_is_ptr) | 6725 | const loaded = if (operand_is_ptr) |
| 6684 | self.builder.buildLoad(try self.dg.lowerType(err_union_ty), operand, "") | 6726 | self.builder.buildLoad(try self.dg.lowerType(err_union_ty), operand, "") |
| 6685 | else | 6727 | else |
| ... | @@ -6687,10 +6729,9 @@ pub const FuncGen = struct { | ... | @@ -6687,10 +6729,9 @@ pub const FuncGen = struct { |
| 6687 | return self.builder.buildICmp(op, loaded, zero, ""); | 6729 | return self.builder.buildICmp(op, loaded, zero, ""); |
| 6688 | } | 6730 | } |
| 6689 | 6731 | ||
| 6690 | const target = self.dg.module.getTarget(); | 6732 | const err_field_index = errUnionErrorOffset(payload_ty, mod); |
| 6691 | const err_field_index = errUnionErrorOffset(payload_ty, target); | ||
| 6692 | 6733 | ||
| 6693 | if (operand_is_ptr or isByRef(err_union_ty)) { | 6734 | if (operand_is_ptr or isByRef(err_union_ty, mod)) { |
| 6694 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); | 6735 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); |
| 6695 | const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, err_field_index, ""); | 6736 | const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, err_field_index, ""); |
| 6696 | const loaded = self.builder.buildLoad(err_set_ty, err_field_ptr, ""); | 6737 | const loaded = self.builder.buildLoad(err_set_ty, err_field_ptr, ""); |
| ... | @@ -6702,17 +6743,18 @@ pub const FuncGen = struct { | ... | @@ -6702,17 +6743,18 @@ pub const FuncGen = struct { |
| 6702 | } | 6743 | } |
| 6703 | 6744 | ||
| 6704 | fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 6745 | fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 6746 | const mod = self.dg.module; | ||
| 6705 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 6747 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6706 | const operand = try self.resolveInst(ty_op.operand); | 6748 | const operand = try self.resolveInst(ty_op.operand); |
| 6707 | const optional_ty = self.air.typeOf(ty_op.operand).childType(); | 6749 | const optional_ty = self.air.typeOf(ty_op.operand).childType(); |
| 6708 | var buf: Type.Payload.ElemType = undefined; | 6750 | var buf: Type.Payload.ElemType = undefined; |
| 6709 | const payload_ty = optional_ty.optionalChild(&buf); | 6751 | const payload_ty = optional_ty.optionalChild(&buf); |
| 6710 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 6752 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6711 | // We have a pointer to a zero-bit value and we need to return | 6753 | // We have a pointer to a zero-bit value and we need to return |
| 6712 | // a pointer to a zero-bit value. | 6754 | // a pointer to a zero-bit value. |
| 6713 | return operand; | 6755 | return operand; |
| 6714 | } | 6756 | } |
| 6715 | if (optional_ty.optionalReprIsPayload()) { | 6757 | if (optional_ty.optionalReprIsPayload(mod)) { |
| 6716 | // The payload and the optional are the same value. | 6758 | // The payload and the optional are the same value. |
| 6717 | return operand; | 6759 | return operand; |
| 6718 | } | 6760 | } |
| ... | @@ -6723,18 +6765,19 @@ pub const FuncGen = struct { | ... | @@ -6723,18 +6765,19 @@ pub const FuncGen = struct { |
| 6723 | fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 6765 | fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 6724 | comptime assert(optional_layout_version == 3); | 6766 | comptime assert(optional_layout_version == 3); |
| 6725 | 6767 | ||
| 6768 | const mod = self.dg.module; | ||
| 6726 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 6769 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6727 | const operand = try self.resolveInst(ty_op.operand); | 6770 | const operand = try self.resolveInst(ty_op.operand); |
| 6728 | const optional_ty = self.air.typeOf(ty_op.operand).childType(); | 6771 | const optional_ty = self.air.typeOf(ty_op.operand).childType(); |
| 6729 | var buf: Type.Payload.ElemType = undefined; | 6772 | var buf: Type.Payload.ElemType = undefined; |
| 6730 | const payload_ty = optional_ty.optionalChild(&buf); | 6773 | const payload_ty = optional_ty.optionalChild(&buf); |
| 6731 | const non_null_bit = self.context.intType(8).constInt(1, .False); | 6774 | const non_null_bit = self.context.intType(8).constInt(1, .False); |
| 6732 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 6775 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6733 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. | 6776 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. |
| 6734 | _ = self.builder.buildStore(non_null_bit, operand); | 6777 | _ = self.builder.buildStore(non_null_bit, operand); |
| 6735 | return operand; | 6778 | return operand; |
| 6736 | } | 6779 | } |
| 6737 | if (optional_ty.optionalReprIsPayload()) { | 6780 | if (optional_ty.optionalReprIsPayload(mod)) { |
| 6738 | // The payload and the optional are the same value. | 6781 | // The payload and the optional are the same value. |
| 6739 | // Setting to non-null will be done when the payload is set. | 6782 | // Setting to non-null will be done when the payload is set. |
| 6740 | return operand; | 6783 | return operand; |
| ... | @@ -6754,20 +6797,21 @@ pub const FuncGen = struct { | ... | @@ -6754,20 +6797,21 @@ pub const FuncGen = struct { |
| 6754 | } | 6797 | } |
| 6755 | 6798 | ||
| 6756 | fn airOptionalPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { | 6799 | fn airOptionalPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { |
| 6800 | const mod = self.dg.module; | ||
| 6757 | const inst = body_tail[0]; | 6801 | const inst = body_tail[0]; |
| 6758 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 6802 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6759 | const operand = try self.resolveInst(ty_op.operand); | 6803 | const operand = try self.resolveInst(ty_op.operand); |
| 6760 | const optional_ty = self.air.typeOf(ty_op.operand); | 6804 | const optional_ty = self.air.typeOf(ty_op.operand); |
| 6761 | const payload_ty = self.air.typeOfIndex(inst); | 6805 | const payload_ty = self.air.typeOfIndex(inst); |
| 6762 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return null; | 6806 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; |
| 6763 | 6807 | ||
| 6764 | if (optional_ty.optionalReprIsPayload()) { | 6808 | if (optional_ty.optionalReprIsPayload(mod)) { |
| 6765 | // Payload value is the same as the optional value. | 6809 | // Payload value is the same as the optional value. |
| 6766 | return operand; | 6810 | return operand; |
| 6767 | } | 6811 | } |
| 6768 | 6812 | ||
| 6769 | const opt_llvm_ty = try self.dg.lowerType(optional_ty); | 6813 | const opt_llvm_ty = try self.dg.lowerType(optional_ty); |
| 6770 | const can_elide_load = if (isByRef(payload_ty)) self.canElideLoad(body_tail) else false; | 6814 | const can_elide_load = if (isByRef(payload_ty, mod)) self.canElideLoad(body_tail) else false; |
| 6771 | return self.optPayloadHandle(opt_llvm_ty, operand, optional_ty, can_elide_load); | 6815 | return self.optPayloadHandle(opt_llvm_ty, operand, optional_ty, can_elide_load); |
| 6772 | } | 6816 | } |
| 6773 | 6817 | ||
| ... | @@ -6776,6 +6820,7 @@ pub const FuncGen = struct { | ... | @@ -6776,6 +6820,7 @@ pub const FuncGen = struct { |
| 6776 | body_tail: []const Air.Inst.Index, | 6820 | body_tail: []const Air.Inst.Index, |
| 6777 | operand_is_ptr: bool, | 6821 | operand_is_ptr: bool, |
| 6778 | ) !?*llvm.Value { | 6822 | ) !?*llvm.Value { |
| 6823 | const mod = self.dg.module; | ||
| 6779 | const inst = body_tail[0]; | 6824 | const inst = body_tail[0]; |
| 6780 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 6825 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6781 | const operand = try self.resolveInst(ty_op.operand); | 6826 | const operand = try self.resolveInst(ty_op.operand); |
| ... | @@ -6783,25 +6828,24 @@ pub const FuncGen = struct { | ... | @@ -6783,25 +6828,24 @@ pub const FuncGen = struct { |
| 6783 | const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; | 6828 | const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; |
| 6784 | const result_ty = self.air.typeOfIndex(inst); | 6829 | const result_ty = self.air.typeOfIndex(inst); |
| 6785 | const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty; | 6830 | const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty; |
| 6786 | const target = self.dg.module.getTarget(); | ||
| 6787 | 6831 | ||
| 6788 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 6832 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6789 | return if (operand_is_ptr) operand else null; | 6833 | return if (operand_is_ptr) operand else null; |
| 6790 | } | 6834 | } |
| 6791 | const offset = errUnionPayloadOffset(payload_ty, target); | 6835 | const offset = errUnionPayloadOffset(payload_ty, mod); |
| 6792 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); | 6836 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); |
| 6793 | if (operand_is_ptr) { | 6837 | if (operand_is_ptr) { |
| 6794 | return self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); | 6838 | return self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); |
| 6795 | } else if (isByRef(err_union_ty)) { | 6839 | } else if (isByRef(err_union_ty, mod)) { |
| 6796 | const payload_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); | 6840 | const payload_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); |
| 6797 | if (isByRef(payload_ty)) { | 6841 | if (isByRef(payload_ty, mod)) { |
| 6798 | if (self.canElideLoad(body_tail)) | 6842 | if (self.canElideLoad(body_tail)) |
| 6799 | return payload_ptr; | 6843 | return payload_ptr; |
| 6800 | 6844 | ||
| 6801 | return self.loadByRef(payload_ptr, payload_ty, payload_ty.abiAlignment(target), false); | 6845 | return self.loadByRef(payload_ptr, payload_ty, payload_ty.abiAlignment(mod), false); |
| 6802 | } | 6846 | } |
| 6803 | const load_inst = self.builder.buildLoad(err_union_llvm_ty.structGetTypeAtIndex(offset), payload_ptr, ""); | 6847 | const load_inst = self.builder.buildLoad(err_union_llvm_ty.structGetTypeAtIndex(offset), payload_ptr, ""); |
| 6804 | load_inst.setAlignment(payload_ty.abiAlignment(target)); | 6848 | load_inst.setAlignment(payload_ty.abiAlignment(mod)); |
| 6805 | return load_inst; | 6849 | return load_inst; |
| 6806 | } | 6850 | } |
| 6807 | return self.builder.buildExtractValue(operand, offset, ""); | 6851 | return self.builder.buildExtractValue(operand, offset, ""); |
| ... | @@ -6812,6 +6856,7 @@ pub const FuncGen = struct { | ... | @@ -6812,6 +6856,7 @@ pub const FuncGen = struct { |
| 6812 | inst: Air.Inst.Index, | 6856 | inst: Air.Inst.Index, |
| 6813 | operand_is_ptr: bool, | 6857 | operand_is_ptr: bool, |
| 6814 | ) !?*llvm.Value { | 6858 | ) !?*llvm.Value { |
| 6859 | const mod = self.dg.module; | ||
| 6815 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 6860 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6816 | const operand = try self.resolveInst(ty_op.operand); | 6861 | const operand = try self.resolveInst(ty_op.operand); |
| 6817 | const operand_ty = self.air.typeOf(ty_op.operand); | 6862 | const operand_ty = self.air.typeOf(ty_op.operand); |
| ... | @@ -6828,15 +6873,14 @@ pub const FuncGen = struct { | ... | @@ -6828,15 +6873,14 @@ pub const FuncGen = struct { |
| 6828 | const err_set_llvm_ty = try self.dg.lowerType(Type.anyerror); | 6873 | const err_set_llvm_ty = try self.dg.lowerType(Type.anyerror); |
| 6829 | 6874 | ||
| 6830 | const payload_ty = err_union_ty.errorUnionPayload(); | 6875 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 6831 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 6876 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6832 | if (!operand_is_ptr) return operand; | 6877 | if (!operand_is_ptr) return operand; |
| 6833 | return self.builder.buildLoad(err_set_llvm_ty, operand, ""); | 6878 | return self.builder.buildLoad(err_set_llvm_ty, operand, ""); |
| 6834 | } | 6879 | } |
| 6835 | 6880 | ||
| 6836 | const target = self.dg.module.getTarget(); | 6881 | const offset = errUnionErrorOffset(payload_ty, mod); |
| 6837 | const offset = errUnionErrorOffset(payload_ty, target); | ||
| 6838 | 6882 | ||
| 6839 | if (operand_is_ptr or isByRef(err_union_ty)) { | 6883 | if (operand_is_ptr or isByRef(err_union_ty, mod)) { |
| 6840 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); | 6884 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); |
| 6841 | const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); | 6885 | const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); |
| 6842 | return self.builder.buildLoad(err_set_llvm_ty, err_field_ptr, ""); | 6886 | return self.builder.buildLoad(err_set_llvm_ty, err_field_ptr, ""); |
| ... | @@ -6846,30 +6890,30 @@ pub const FuncGen = struct { | ... | @@ -6846,30 +6890,30 @@ pub const FuncGen = struct { |
| 6846 | } | 6890 | } |
| 6847 | 6891 | ||
| 6848 | fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 6892 | fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 6893 | const mod = self.dg.module; | ||
| 6849 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 6894 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6850 | const operand = try self.resolveInst(ty_op.operand); | 6895 | const operand = try self.resolveInst(ty_op.operand); |
| 6851 | const err_union_ty = self.air.typeOf(ty_op.operand).childType(); | 6896 | const err_union_ty = self.air.typeOf(ty_op.operand).childType(); |
| 6852 | 6897 | ||
| 6853 | const payload_ty = err_union_ty.errorUnionPayload(); | 6898 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 6854 | const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero }); | 6899 | const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero }); |
| 6855 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 6900 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6856 | _ = self.builder.buildStore(non_error_val, operand); | 6901 | _ = self.builder.buildStore(non_error_val, operand); |
| 6857 | return operand; | 6902 | return operand; |
| 6858 | } | 6903 | } |
| 6859 | const target = self.dg.module.getTarget(); | ||
| 6860 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); | 6904 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); |
| 6861 | { | 6905 | { |
| 6862 | const error_offset = errUnionErrorOffset(payload_ty, target); | 6906 | const error_offset = errUnionErrorOffset(payload_ty, mod); |
| 6863 | // First set the non-error value. | 6907 | // First set the non-error value. |
| 6864 | const non_null_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, error_offset, ""); | 6908 | const non_null_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, error_offset, ""); |
| 6865 | const store_inst = self.builder.buildStore(non_error_val, non_null_ptr); | 6909 | const store_inst = self.builder.buildStore(non_error_val, non_null_ptr); |
| 6866 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); | 6910 | store_inst.setAlignment(Type.anyerror.abiAlignment(mod)); |
| 6867 | } | 6911 | } |
| 6868 | // Then return the payload pointer (only if it is used). | 6912 | // Then return the payload pointer (only if it is used). |
| 6869 | if (self.liveness.isUnused(inst)) | 6913 | if (self.liveness.isUnused(inst)) |
| 6870 | return null; | 6914 | return null; |
| 6871 | 6915 | ||
| 6872 | const payload_offset = errUnionPayloadOffset(payload_ty, target); | 6916 | const payload_offset = errUnionPayloadOffset(payload_ty, mod); |
| 6873 | return self.builder.buildStructGEP(err_union_llvm_ty, operand, payload_offset, ""); | 6917 | return self.builder.buildStructGEP(err_union_llvm_ty, operand, payload_offset, ""); |
| 6874 | } | 6918 | } |
| 6875 | 6919 | ||
| ... | @@ -6885,15 +6929,14 @@ pub const FuncGen = struct { | ... | @@ -6885,15 +6929,14 @@ pub const FuncGen = struct { |
| 6885 | } | 6929 | } |
| 6886 | 6930 | ||
| 6887 | fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 6931 | fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 6888 | const target = self.dg.module.getTarget(); | ||
| 6889 | |||
| 6890 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 6932 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 6891 | //const struct_ty = try self.resolveInst(ty_pl.ty); | 6933 | //const struct_ty = try self.resolveInst(ty_pl.ty); |
| 6892 | const struct_ty = self.air.getRefType(ty_pl.ty); | 6934 | const struct_ty = self.air.getRefType(ty_pl.ty); |
| 6893 | const field_index = ty_pl.payload; | 6935 | const field_index = ty_pl.payload; |
| 6894 | 6936 | ||
| 6895 | var ptr_ty_buf: Type.Payload.Pointer = undefined; | 6937 | var ptr_ty_buf: Type.Payload.Pointer = undefined; |
| 6896 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; | 6938 | const mod = self.dg.module; |
| 6939 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?; | ||
| 6897 | const struct_llvm_ty = try self.dg.lowerType(struct_ty); | 6940 | const struct_llvm_ty = try self.dg.lowerType(struct_ty); |
| 6898 | const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field_index, ""); | 6941 | const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field_index, ""); |
| 6899 | const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); | 6942 | const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); |
| ... | @@ -6901,20 +6944,20 @@ pub const FuncGen = struct { | ... | @@ -6901,20 +6944,20 @@ pub const FuncGen = struct { |
| 6901 | } | 6944 | } |
| 6902 | 6945 | ||
| 6903 | fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 6946 | fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 6947 | const mod = self.dg.module; | ||
| 6904 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 6948 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6905 | const payload_ty = self.air.typeOf(ty_op.operand); | 6949 | const payload_ty = self.air.typeOf(ty_op.operand); |
| 6906 | const non_null_bit = self.context.intType(8).constInt(1, .False); | 6950 | const non_null_bit = self.context.intType(8).constInt(1, .False); |
| 6907 | comptime assert(optional_layout_version == 3); | 6951 | comptime assert(optional_layout_version == 3); |
| 6908 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return non_null_bit; | 6952 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return non_null_bit; |
| 6909 | const operand = try self.resolveInst(ty_op.operand); | 6953 | const operand = try self.resolveInst(ty_op.operand); |
| 6910 | const optional_ty = self.air.typeOfIndex(inst); | 6954 | const optional_ty = self.air.typeOfIndex(inst); |
| 6911 | if (optional_ty.optionalReprIsPayload()) { | 6955 | if (optional_ty.optionalReprIsPayload(mod)) { |
| 6912 | return operand; | 6956 | return operand; |
| 6913 | } | 6957 | } |
| 6914 | const llvm_optional_ty = try self.dg.lowerType(optional_ty); | 6958 | const llvm_optional_ty = try self.dg.lowerType(optional_ty); |
| 6915 | if (isByRef(optional_ty)) { | 6959 | if (isByRef(optional_ty, mod)) { |
| 6916 | const target = self.dg.module.getTarget(); | 6960 | const optional_ptr = self.buildAlloca(llvm_optional_ty, optional_ty.abiAlignment(mod)); |
| 6917 | const optional_ptr = self.buildAlloca(llvm_optional_ty, optional_ty.abiAlignment(target)); | ||
| 6918 | const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); | 6961 | const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); |
| 6919 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 6962 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 6920 | .base = .{ .tag = .single_mut_pointer }, | 6963 | .base = .{ .tag = .single_mut_pointer }, |
| ... | @@ -6931,24 +6974,24 @@ pub const FuncGen = struct { | ... | @@ -6931,24 +6974,24 @@ pub const FuncGen = struct { |
| 6931 | } | 6974 | } |
| 6932 | 6975 | ||
| 6933 | fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 6976 | fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 6977 | const mod = self.dg.module; | ||
| 6934 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 6978 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6935 | const err_un_ty = self.air.typeOfIndex(inst); | 6979 | const err_un_ty = self.air.typeOfIndex(inst); |
| 6936 | const operand = try self.resolveInst(ty_op.operand); | 6980 | const operand = try self.resolveInst(ty_op.operand); |
| 6937 | const payload_ty = self.air.typeOf(ty_op.operand); | 6981 | const payload_ty = self.air.typeOf(ty_op.operand); |
| 6938 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 6982 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6939 | return operand; | 6983 | return operand; |
| 6940 | } | 6984 | } |
| 6941 | const ok_err_code = (try self.dg.lowerType(Type.anyerror)).constNull(); | 6985 | const ok_err_code = (try self.dg.lowerType(Type.anyerror)).constNull(); |
| 6942 | const err_un_llvm_ty = try self.dg.lowerType(err_un_ty); | 6986 | const err_un_llvm_ty = try self.dg.lowerType(err_un_ty); |
| 6943 | 6987 | ||
| 6944 | const target = self.dg.module.getTarget(); | 6988 | const payload_offset = errUnionPayloadOffset(payload_ty, mod); |
| 6945 | const payload_offset = errUnionPayloadOffset(payload_ty, target); | 6989 | const error_offset = errUnionErrorOffset(payload_ty, mod); |
| 6946 | const error_offset = errUnionErrorOffset(payload_ty, target); | 6990 | if (isByRef(err_un_ty, mod)) { |
| 6947 | if (isByRef(err_un_ty)) { | 6991 | const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(mod)); |
| 6948 | const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(target)); | ||
| 6949 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); | 6992 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); |
| 6950 | const store_inst = self.builder.buildStore(ok_err_code, err_ptr); | 6993 | const store_inst = self.builder.buildStore(ok_err_code, err_ptr); |
| 6951 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); | 6994 | store_inst.setAlignment(Type.anyerror.abiAlignment(mod)); |
| 6952 | const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); | 6995 | const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); |
| 6953 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 6996 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 6954 | .base = .{ .tag = .single_mut_pointer }, | 6997 | .base = .{ .tag = .single_mut_pointer }, |
| ... | @@ -6964,23 +7007,23 @@ pub const FuncGen = struct { | ... | @@ -6964,23 +7007,23 @@ pub const FuncGen = struct { |
| 6964 | } | 7007 | } |
| 6965 | 7008 | ||
| 6966 | fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7009 | fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7010 | const mod = self.dg.module; | ||
| 6967 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 7011 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6968 | const err_un_ty = self.air.typeOfIndex(inst); | 7012 | const err_un_ty = self.air.typeOfIndex(inst); |
| 6969 | const payload_ty = err_un_ty.errorUnionPayload(); | 7013 | const payload_ty = err_un_ty.errorUnionPayload(); |
| 6970 | const operand = try self.resolveInst(ty_op.operand); | 7014 | const operand = try self.resolveInst(ty_op.operand); |
| 6971 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 7015 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6972 | return operand; | 7016 | return operand; |
| 6973 | } | 7017 | } |
| 6974 | const err_un_llvm_ty = try self.dg.lowerType(err_un_ty); | 7018 | const err_un_llvm_ty = try self.dg.lowerType(err_un_ty); |
| 6975 | 7019 | ||
| 6976 | const target = self.dg.module.getTarget(); | 7020 | const payload_offset = errUnionPayloadOffset(payload_ty, mod); |
| 6977 | const payload_offset = errUnionPayloadOffset(payload_ty, target); | 7021 | const error_offset = errUnionErrorOffset(payload_ty, mod); |
| 6978 | const error_offset = errUnionErrorOffset(payload_ty, target); | 7022 | if (isByRef(err_un_ty, mod)) { |
| 6979 | if (isByRef(err_un_ty)) { | 7023 | const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(mod)); |
| 6980 | const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(target)); | ||
| 6981 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); | 7024 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); |
| 6982 | const store_inst = self.builder.buildStore(operand, err_ptr); | 7025 | const store_inst = self.builder.buildStore(operand, err_ptr); |
| 6983 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); | 7026 | store_inst.setAlignment(Type.anyerror.abiAlignment(mod)); |
| 6984 | const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); | 7027 | const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); |
| 6985 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 7028 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 6986 | .base = .{ .tag = .single_mut_pointer }, | 7029 | .base = .{ .tag = .single_mut_pointer }, |
| ... | @@ -7021,6 +7064,7 @@ pub const FuncGen = struct { | ... | @@ -7021,6 +7064,7 @@ pub const FuncGen = struct { |
| 7021 | } | 7064 | } |
| 7022 | 7065 | ||
| 7023 | fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7066 | fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7067 | const mod = self.dg.module; | ||
| 7024 | const data = self.air.instructions.items(.data)[inst].vector_store_elem; | 7068 | const data = self.air.instructions.items(.data)[inst].vector_store_elem; |
| 7025 | const extra = self.air.extraData(Air.Bin, data.payload).data; | 7069 | const extra = self.air.extraData(Air.Bin, data.payload).data; |
| 7026 | 7070 | ||
| ... | @@ -7032,8 +7076,7 @@ pub const FuncGen = struct { | ... | @@ -7032,8 +7076,7 @@ pub const FuncGen = struct { |
| 7032 | const loaded_vector = blk: { | 7076 | const loaded_vector = blk: { |
| 7033 | const elem_llvm_ty = try self.dg.lowerType(vector_ptr_ty.childType()); | 7077 | const elem_llvm_ty = try self.dg.lowerType(vector_ptr_ty.childType()); |
| 7034 | const load_inst = self.builder.buildLoad(elem_llvm_ty, vector_ptr, ""); | 7078 | const load_inst = self.builder.buildLoad(elem_llvm_ty, vector_ptr, ""); |
| 7035 | const target = self.dg.module.getTarget(); | 7079 | load_inst.setAlignment(vector_ptr_ty.ptrAlignment(mod)); |
| 7036 | load_inst.setAlignment(vector_ptr_ty.ptrAlignment(target)); | ||
| 7037 | load_inst.setVolatile(llvm.Bool.fromBool(vector_ptr_ty.isVolatilePtr())); | 7080 | load_inst.setVolatile(llvm.Bool.fromBool(vector_ptr_ty.isVolatilePtr())); |
| 7038 | break :blk load_inst; | 7081 | break :blk load_inst; |
| 7039 | }; | 7082 | }; |
| ... | @@ -7043,24 +7086,26 @@ pub const FuncGen = struct { | ... | @@ -7043,24 +7086,26 @@ pub const FuncGen = struct { |
| 7043 | } | 7086 | } |
| 7044 | 7087 | ||
| 7045 | fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7088 | fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7089 | const mod = self.dg.module; | ||
| 7046 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7090 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7047 | const lhs = try self.resolveInst(bin_op.lhs); | 7091 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7048 | const rhs = try self.resolveInst(bin_op.rhs); | 7092 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7049 | const scalar_ty = self.air.typeOfIndex(inst).scalarType(); | 7093 | const scalar_ty = self.air.typeOfIndex(inst).scalarType(mod); |
| 7050 | 7094 | ||
| 7051 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, scalar_ty, 2, .{ lhs, rhs }); | 7095 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, scalar_ty, 2, .{ lhs, rhs }); |
| 7052 | if (scalar_ty.isSignedInt()) return self.builder.buildSMin(lhs, rhs, ""); | 7096 | if (scalar_ty.isSignedInt(mod)) return self.builder.buildSMin(lhs, rhs, ""); |
| 7053 | return self.builder.buildUMin(lhs, rhs, ""); | 7097 | return self.builder.buildUMin(lhs, rhs, ""); |
| 7054 | } | 7098 | } |
| 7055 | 7099 | ||
| 7056 | fn airMax(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7100 | fn airMax(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7101 | const mod = self.dg.module; | ||
| 7057 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7102 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7058 | const lhs = try self.resolveInst(bin_op.lhs); | 7103 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7059 | const rhs = try self.resolveInst(bin_op.rhs); | 7104 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7060 | const scalar_ty = self.air.typeOfIndex(inst).scalarType(); | 7105 | const scalar_ty = self.air.typeOfIndex(inst).scalarType(mod); |
| 7061 | 7106 | ||
| 7062 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, scalar_ty, 2, .{ lhs, rhs }); | 7107 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, scalar_ty, 2, .{ lhs, rhs }); |
| 7063 | if (scalar_ty.isSignedInt()) return self.builder.buildSMax(lhs, rhs, ""); | 7108 | if (scalar_ty.isSignedInt(mod)) return self.builder.buildSMax(lhs, rhs, ""); |
| 7064 | return self.builder.buildUMax(lhs, rhs, ""); | 7109 | return self.builder.buildUMax(lhs, rhs, ""); |
| 7065 | } | 7110 | } |
| 7066 | 7111 | ||
| ... | @@ -7081,14 +7126,15 @@ pub const FuncGen = struct { | ... | @@ -7081,14 +7126,15 @@ pub const FuncGen = struct { |
| 7081 | fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { | 7126 | fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { |
| 7082 | self.builder.setFastMath(want_fast_math); | 7127 | self.builder.setFastMath(want_fast_math); |
| 7083 | 7128 | ||
| 7129 | const mod = self.dg.module; | ||
| 7084 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7130 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7085 | const lhs = try self.resolveInst(bin_op.lhs); | 7131 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7086 | const rhs = try self.resolveInst(bin_op.rhs); | 7132 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7087 | const inst_ty = self.air.typeOfIndex(inst); | 7133 | const inst_ty = self.air.typeOfIndex(inst); |
| 7088 | const scalar_ty = inst_ty.scalarType(); | 7134 | const scalar_ty = inst_ty.scalarType(mod); |
| 7089 | 7135 | ||
| 7090 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.add, inst_ty, 2, .{ lhs, rhs }); | 7136 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.add, inst_ty, 2, .{ lhs, rhs }); |
| 7091 | if (scalar_ty.isSignedInt()) return self.builder.buildNSWAdd(lhs, rhs, ""); | 7137 | if (scalar_ty.isSignedInt(mod)) return self.builder.buildNSWAdd(lhs, rhs, ""); |
| 7092 | return self.builder.buildNUWAdd(lhs, rhs, ""); | 7138 | return self.builder.buildNUWAdd(lhs, rhs, ""); |
| 7093 | } | 7139 | } |
| 7094 | 7140 | ||
| ... | @@ -7103,14 +7149,15 @@ pub const FuncGen = struct { | ... | @@ -7103,14 +7149,15 @@ pub const FuncGen = struct { |
| 7103 | } | 7149 | } |
| 7104 | 7150 | ||
| 7105 | fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7151 | fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7152 | const mod = self.dg.module; | ||
| 7106 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7153 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7107 | const lhs = try self.resolveInst(bin_op.lhs); | 7154 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7108 | const rhs = try self.resolveInst(bin_op.rhs); | 7155 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7109 | const inst_ty = self.air.typeOfIndex(inst); | 7156 | const inst_ty = self.air.typeOfIndex(inst); |
| 7110 | const scalar_ty = inst_ty.scalarType(); | 7157 | const scalar_ty = inst_ty.scalarType(mod); |
| 7111 | 7158 | ||
| 7112 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{}); | 7159 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{}); |
| 7113 | if (scalar_ty.isSignedInt()) return self.builder.buildSAddSat(lhs, rhs, ""); | 7160 | if (scalar_ty.isSignedInt(mod)) return self.builder.buildSAddSat(lhs, rhs, ""); |
| 7114 | 7161 | ||
| 7115 | return self.builder.buildUAddSat(lhs, rhs, ""); | 7162 | return self.builder.buildUAddSat(lhs, rhs, ""); |
| 7116 | } | 7163 | } |
| ... | @@ -7118,14 +7165,15 @@ pub const FuncGen = struct { | ... | @@ -7118,14 +7165,15 @@ pub const FuncGen = struct { |
| 7118 | fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { | 7165 | fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { |
| 7119 | self.builder.setFastMath(want_fast_math); | 7166 | self.builder.setFastMath(want_fast_math); |
| 7120 | 7167 | ||
| 7168 | const mod = self.dg.module; | ||
| 7121 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7169 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7122 | const lhs = try self.resolveInst(bin_op.lhs); | 7170 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7123 | const rhs = try self.resolveInst(bin_op.rhs); | 7171 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7124 | const inst_ty = self.air.typeOfIndex(inst); | 7172 | const inst_ty = self.air.typeOfIndex(inst); |
| 7125 | const scalar_ty = inst_ty.scalarType(); | 7173 | const scalar_ty = inst_ty.scalarType(mod); |
| 7126 | 7174 | ||
| 7127 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.sub, inst_ty, 2, .{ lhs, rhs }); | 7175 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.sub, inst_ty, 2, .{ lhs, rhs }); |
| 7128 | if (scalar_ty.isSignedInt()) return self.builder.buildNSWSub(lhs, rhs, ""); | 7176 | if (scalar_ty.isSignedInt(mod)) return self.builder.buildNSWSub(lhs, rhs, ""); |
| 7129 | return self.builder.buildNUWSub(lhs, rhs, ""); | 7177 | return self.builder.buildNUWSub(lhs, rhs, ""); |
| 7130 | } | 7178 | } |
| 7131 | 7179 | ||
| ... | @@ -7140,28 +7188,30 @@ pub const FuncGen = struct { | ... | @@ -7140,28 +7188,30 @@ pub const FuncGen = struct { |
| 7140 | } | 7188 | } |
| 7141 | 7189 | ||
| 7142 | fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7190 | fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7191 | const mod = self.dg.module; | ||
| 7143 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7192 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7144 | const lhs = try self.resolveInst(bin_op.lhs); | 7193 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7145 | const rhs = try self.resolveInst(bin_op.rhs); | 7194 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7146 | const inst_ty = self.air.typeOfIndex(inst); | 7195 | const inst_ty = self.air.typeOfIndex(inst); |
| 7147 | const scalar_ty = inst_ty.scalarType(); | 7196 | const scalar_ty = inst_ty.scalarType(mod); |
| 7148 | 7197 | ||
| 7149 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{}); | 7198 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{}); |
| 7150 | if (scalar_ty.isSignedInt()) return self.builder.buildSSubSat(lhs, rhs, ""); | 7199 | if (scalar_ty.isSignedInt(mod)) return self.builder.buildSSubSat(lhs, rhs, ""); |
| 7151 | return self.builder.buildUSubSat(lhs, rhs, ""); | 7200 | return self.builder.buildUSubSat(lhs, rhs, ""); |
| 7152 | } | 7201 | } |
| 7153 | 7202 | ||
| 7154 | fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { | 7203 | fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { |
| 7155 | self.builder.setFastMath(want_fast_math); | 7204 | self.builder.setFastMath(want_fast_math); |
| 7156 | 7205 | ||
| 7206 | const mod = self.dg.module; | ||
| 7157 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7207 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7158 | const lhs = try self.resolveInst(bin_op.lhs); | 7208 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7159 | const rhs = try self.resolveInst(bin_op.rhs); | 7209 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7160 | const inst_ty = self.air.typeOfIndex(inst); | 7210 | const inst_ty = self.air.typeOfIndex(inst); |
| 7161 | const scalar_ty = inst_ty.scalarType(); | 7211 | const scalar_ty = inst_ty.scalarType(mod); |
| 7162 | 7212 | ||
| 7163 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.mul, inst_ty, 2, .{ lhs, rhs }); | 7213 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.mul, inst_ty, 2, .{ lhs, rhs }); |
| 7164 | if (scalar_ty.isSignedInt()) return self.builder.buildNSWMul(lhs, rhs, ""); | 7214 | if (scalar_ty.isSignedInt(mod)) return self.builder.buildNSWMul(lhs, rhs, ""); |
| 7165 | return self.builder.buildNUWMul(lhs, rhs, ""); | 7215 | return self.builder.buildNUWMul(lhs, rhs, ""); |
| 7166 | } | 7216 | } |
| 7167 | 7217 | ||
| ... | @@ -7176,14 +7226,15 @@ pub const FuncGen = struct { | ... | @@ -7176,14 +7226,15 @@ pub const FuncGen = struct { |
| 7176 | } | 7226 | } |
| 7177 | 7227 | ||
| 7178 | fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7228 | fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7229 | const mod = self.dg.module; | ||
| 7179 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7230 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7180 | const lhs = try self.resolveInst(bin_op.lhs); | 7231 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7181 | const rhs = try self.resolveInst(bin_op.rhs); | 7232 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7182 | const inst_ty = self.air.typeOfIndex(inst); | 7233 | const inst_ty = self.air.typeOfIndex(inst); |
| 7183 | const scalar_ty = inst_ty.scalarType(); | 7234 | const scalar_ty = inst_ty.scalarType(mod); |
| 7184 | 7235 | ||
| 7185 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{}); | 7236 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{}); |
| 7186 | if (scalar_ty.isSignedInt()) return self.builder.buildSMulFixSat(lhs, rhs, ""); | 7237 | if (scalar_ty.isSignedInt(mod)) return self.builder.buildSMulFixSat(lhs, rhs, ""); |
| 7187 | return self.builder.buildUMulFixSat(lhs, rhs, ""); | 7238 | return self.builder.buildUMulFixSat(lhs, rhs, ""); |
| 7188 | } | 7239 | } |
| 7189 | 7240 | ||
| ... | @@ -7201,38 +7252,39 @@ pub const FuncGen = struct { | ... | @@ -7201,38 +7252,39 @@ pub const FuncGen = struct { |
| 7201 | fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { | 7252 | fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { |
| 7202 | self.builder.setFastMath(want_fast_math); | 7253 | self.builder.setFastMath(want_fast_math); |
| 7203 | 7254 | ||
| 7255 | const mod = self.dg.module; | ||
| 7204 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7256 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7205 | const lhs = try self.resolveInst(bin_op.lhs); | 7257 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7206 | const rhs = try self.resolveInst(bin_op.rhs); | 7258 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7207 | const inst_ty = self.air.typeOfIndex(inst); | 7259 | const inst_ty = self.air.typeOfIndex(inst); |
| 7208 | const scalar_ty = inst_ty.scalarType(); | 7260 | const scalar_ty = inst_ty.scalarType(mod); |
| 7209 | 7261 | ||
| 7210 | if (scalar_ty.isRuntimeFloat()) { | 7262 | if (scalar_ty.isRuntimeFloat()) { |
| 7211 | const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs }); | 7263 | const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs }); |
| 7212 | return self.buildFloatOp(.trunc, inst_ty, 1, .{result}); | 7264 | return self.buildFloatOp(.trunc, inst_ty, 1, .{result}); |
| 7213 | } | 7265 | } |
| 7214 | if (scalar_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, ""); | 7266 | if (scalar_ty.isSignedInt(mod)) return self.builder.buildSDiv(lhs, rhs, ""); |
| 7215 | return self.builder.buildUDiv(lhs, rhs, ""); | 7267 | return self.builder.buildUDiv(lhs, rhs, ""); |
| 7216 | } | 7268 | } |
| 7217 | 7269 | ||
| 7218 | fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { | 7270 | fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { |
| 7219 | self.builder.setFastMath(want_fast_math); | 7271 | self.builder.setFastMath(want_fast_math); |
| 7220 | 7272 | ||
| 7273 | const mod = self.dg.module; | ||
| 7221 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7274 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7222 | const lhs = try self.resolveInst(bin_op.lhs); | 7275 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7223 | const rhs = try self.resolveInst(bin_op.rhs); | 7276 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7224 | const inst_ty = self.air.typeOfIndex(inst); | 7277 | const inst_ty = self.air.typeOfIndex(inst); |
| 7225 | const scalar_ty = inst_ty.scalarType(); | 7278 | const scalar_ty = inst_ty.scalarType(mod); |
| 7226 | 7279 | ||
| 7227 | if (scalar_ty.isRuntimeFloat()) { | 7280 | if (scalar_ty.isRuntimeFloat()) { |
| 7228 | const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs }); | 7281 | const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs }); |
| 7229 | return self.buildFloatOp(.floor, inst_ty, 1, .{result}); | 7282 | return self.buildFloatOp(.floor, inst_ty, 1, .{result}); |
| 7230 | } | 7283 | } |
| 7231 | if (scalar_ty.isSignedInt()) { | 7284 | if (scalar_ty.isSignedInt(mod)) { |
| 7232 | const target = self.dg.module.getTarget(); | ||
| 7233 | const inst_llvm_ty = try self.dg.lowerType(inst_ty); | 7285 | const inst_llvm_ty = try self.dg.lowerType(inst_ty); |
| 7234 | const scalar_bit_size_minus_one = scalar_ty.bitSize(target) - 1; | 7286 | const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1; |
| 7235 | const bit_size_minus_one = if (inst_ty.zigTypeTag() == .Vector) const_vector: { | 7287 | const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: { |
| 7236 | const vec_len = inst_ty.vectorLen(); | 7288 | const vec_len = inst_ty.vectorLen(); |
| 7237 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); | 7289 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); |
| 7238 | 7290 | ||
| ... | @@ -7258,40 +7310,43 @@ pub const FuncGen = struct { | ... | @@ -7258,40 +7310,43 @@ pub const FuncGen = struct { |
| 7258 | fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { | 7310 | fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { |
| 7259 | self.builder.setFastMath(want_fast_math); | 7311 | self.builder.setFastMath(want_fast_math); |
| 7260 | 7312 | ||
| 7313 | const mod = self.dg.module; | ||
| 7261 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7314 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7262 | const lhs = try self.resolveInst(bin_op.lhs); | 7315 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7263 | const rhs = try self.resolveInst(bin_op.rhs); | 7316 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7264 | const inst_ty = self.air.typeOfIndex(inst); | 7317 | const inst_ty = self.air.typeOfIndex(inst); |
| 7265 | const scalar_ty = inst_ty.scalarType(); | 7318 | const scalar_ty = inst_ty.scalarType(mod); |
| 7266 | 7319 | ||
| 7267 | if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs }); | 7320 | if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs }); |
| 7268 | if (scalar_ty.isSignedInt()) return self.builder.buildExactSDiv(lhs, rhs, ""); | 7321 | if (scalar_ty.isSignedInt(mod)) return self.builder.buildExactSDiv(lhs, rhs, ""); |
| 7269 | return self.builder.buildExactUDiv(lhs, rhs, ""); | 7322 | return self.builder.buildExactUDiv(lhs, rhs, ""); |
| 7270 | } | 7323 | } |
| 7271 | 7324 | ||
| 7272 | fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { | 7325 | fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { |
| 7273 | self.builder.setFastMath(want_fast_math); | 7326 | self.builder.setFastMath(want_fast_math); |
| 7274 | 7327 | ||
| 7328 | const mod = self.dg.module; | ||
| 7275 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7329 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7276 | const lhs = try self.resolveInst(bin_op.lhs); | 7330 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7277 | const rhs = try self.resolveInst(bin_op.rhs); | 7331 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7278 | const inst_ty = self.air.typeOfIndex(inst); | 7332 | const inst_ty = self.air.typeOfIndex(inst); |
| 7279 | const scalar_ty = inst_ty.scalarType(); | 7333 | const scalar_ty = inst_ty.scalarType(mod); |
| 7280 | 7334 | ||
| 7281 | if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs }); | 7335 | if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs }); |
| 7282 | if (scalar_ty.isSignedInt()) return self.builder.buildSRem(lhs, rhs, ""); | 7336 | if (scalar_ty.isSignedInt(mod)) return self.builder.buildSRem(lhs, rhs, ""); |
| 7283 | return self.builder.buildURem(lhs, rhs, ""); | 7337 | return self.builder.buildURem(lhs, rhs, ""); |
| 7284 | } | 7338 | } |
| 7285 | 7339 | ||
| 7286 | fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { | 7340 | fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { |
| 7287 | self.builder.setFastMath(want_fast_math); | 7341 | self.builder.setFastMath(want_fast_math); |
| 7288 | 7342 | ||
| 7343 | const mod = self.dg.module; | ||
| 7289 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7344 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7290 | const lhs = try self.resolveInst(bin_op.lhs); | 7345 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7291 | const rhs = try self.resolveInst(bin_op.rhs); | 7346 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7292 | const inst_ty = self.air.typeOfIndex(inst); | 7347 | const inst_ty = self.air.typeOfIndex(inst); |
| 7293 | const inst_llvm_ty = try self.dg.lowerType(inst_ty); | 7348 | const inst_llvm_ty = try self.dg.lowerType(inst_ty); |
| 7294 | const scalar_ty = inst_ty.scalarType(); | 7349 | const scalar_ty = inst_ty.scalarType(mod); |
| 7295 | 7350 | ||
| 7296 | if (scalar_ty.isRuntimeFloat()) { | 7351 | if (scalar_ty.isRuntimeFloat()) { |
| 7297 | const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs }); | 7352 | const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs }); |
| ... | @@ -7301,10 +7356,9 @@ pub const FuncGen = struct { | ... | @@ -7301,10 +7356,9 @@ pub const FuncGen = struct { |
| 7301 | const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero }); | 7356 | const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero }); |
| 7302 | return self.builder.buildSelect(ltz, c, a, ""); | 7357 | return self.builder.buildSelect(ltz, c, a, ""); |
| 7303 | } | 7358 | } |
| 7304 | if (scalar_ty.isSignedInt()) { | 7359 | if (scalar_ty.isSignedInt(mod)) { |
| 7305 | const target = self.dg.module.getTarget(); | 7360 | const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1; |
| 7306 | const scalar_bit_size_minus_one = scalar_ty.bitSize(target) - 1; | 7361 | const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: { |
| 7307 | const bit_size_minus_one = if (inst_ty.zigTypeTag() == .Vector) const_vector: { | ||
| 7308 | const vec_len = inst_ty.vectorLen(); | 7362 | const vec_len = inst_ty.vectorLen(); |
| 7309 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); | 7363 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); |
| 7310 | 7364 | ||
| ... | @@ -7386,6 +7440,7 @@ pub const FuncGen = struct { | ... | @@ -7386,6 +7440,7 @@ pub const FuncGen = struct { |
| 7386 | signed_intrinsic: []const u8, | 7440 | signed_intrinsic: []const u8, |
| 7387 | unsigned_intrinsic: []const u8, | 7441 | unsigned_intrinsic: []const u8, |
| 7388 | ) !?*llvm.Value { | 7442 | ) !?*llvm.Value { |
| 7443 | const mod = self.dg.module; | ||
| 7389 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 7444 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 7390 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 7445 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 7391 | 7446 | ||
| ... | @@ -7393,16 +7448,14 @@ pub const FuncGen = struct { | ... | @@ -7393,16 +7448,14 @@ pub const FuncGen = struct { |
| 7393 | const rhs = try self.resolveInst(extra.rhs); | 7448 | const rhs = try self.resolveInst(extra.rhs); |
| 7394 | 7449 | ||
| 7395 | const lhs_ty = self.air.typeOf(extra.lhs); | 7450 | const lhs_ty = self.air.typeOf(extra.lhs); |
| 7396 | const scalar_ty = lhs_ty.scalarType(); | 7451 | const scalar_ty = lhs_ty.scalarType(mod); |
| 7397 | const dest_ty = self.air.typeOfIndex(inst); | 7452 | const dest_ty = self.air.typeOfIndex(inst); |
| 7398 | 7453 | ||
| 7399 | const intrinsic_name = if (scalar_ty.isSignedInt()) signed_intrinsic else unsigned_intrinsic; | 7454 | const intrinsic_name = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic; |
| 7400 | 7455 | ||
| 7401 | const llvm_lhs_ty = try self.dg.lowerType(lhs_ty); | 7456 | const llvm_lhs_ty = try self.dg.lowerType(lhs_ty); |
| 7402 | const llvm_dest_ty = try self.dg.lowerType(dest_ty); | 7457 | const llvm_dest_ty = try self.dg.lowerType(dest_ty); |
| 7403 | 7458 | ||
| 7404 | const tg = self.dg.module.getTarget(); | ||
| 7405 | |||
| 7406 | const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); | 7459 | const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); |
| 7407 | const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); | 7460 | const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); |
| 7408 | 7461 | ||
| ... | @@ -7410,12 +7463,11 @@ pub const FuncGen = struct { | ... | @@ -7410,12 +7463,11 @@ pub const FuncGen = struct { |
| 7410 | const overflow_bit = self.builder.buildExtractValue(result_struct, 1, ""); | 7463 | const overflow_bit = self.builder.buildExtractValue(result_struct, 1, ""); |
| 7411 | 7464 | ||
| 7412 | var ty_buf: Type.Payload.Pointer = undefined; | 7465 | var ty_buf: Type.Payload.Pointer = undefined; |
| 7413 | const result_index = llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?; | 7466 | const result_index = llvmFieldIndex(dest_ty, 0, mod, &ty_buf).?; |
| 7414 | const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?; | 7467 | const overflow_index = llvmFieldIndex(dest_ty, 1, mod, &ty_buf).?; |
| 7415 | 7468 | ||
| 7416 | if (isByRef(dest_ty)) { | 7469 | if (isByRef(dest_ty, mod)) { |
| 7417 | const target = self.dg.module.getTarget(); | 7470 | const result_alignment = dest_ty.abiAlignment(mod); |
| 7418 | const result_alignment = dest_ty.abiAlignment(target); | ||
| 7419 | const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment); | 7471 | const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment); |
| 7420 | { | 7472 | { |
| 7421 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); | 7473 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); |
| ... | @@ -7486,8 +7538,9 @@ pub const FuncGen = struct { | ... | @@ -7486,8 +7538,9 @@ pub const FuncGen = struct { |
| 7486 | ty: Type, | 7538 | ty: Type, |
| 7487 | params: [2]*llvm.Value, | 7539 | params: [2]*llvm.Value, |
| 7488 | ) !*llvm.Value { | 7540 | ) !*llvm.Value { |
| 7541 | const mod = self.dg.module; | ||
| 7489 | const target = self.dg.module.getTarget(); | 7542 | const target = self.dg.module.getTarget(); |
| 7490 | const scalar_ty = ty.scalarType(); | 7543 | const scalar_ty = ty.scalarType(mod); |
| 7491 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); | 7544 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); |
| 7492 | 7545 | ||
| 7493 | if (intrinsicsAllowed(scalar_ty, target)) { | 7546 | if (intrinsicsAllowed(scalar_ty, target)) { |
| ... | @@ -7531,7 +7584,7 @@ pub const FuncGen = struct { | ... | @@ -7531,7 +7584,7 @@ pub const FuncGen = struct { |
| 7531 | .gte => .SGE, | 7584 | .gte => .SGE, |
| 7532 | }; | 7585 | }; |
| 7533 | 7586 | ||
| 7534 | if (ty.zigTypeTag() == .Vector) { | 7587 | if (ty.zigTypeTag(mod) == .Vector) { |
| 7535 | const vec_len = ty.vectorLen(); | 7588 | const vec_len = ty.vectorLen(); |
| 7536 | const vector_result_ty = llvm_i32.vectorType(vec_len); | 7589 | const vector_result_ty = llvm_i32.vectorType(vec_len); |
| 7537 | 7590 | ||
| ... | @@ -7587,8 +7640,9 @@ pub const FuncGen = struct { | ... | @@ -7587,8 +7640,9 @@ pub const FuncGen = struct { |
| 7587 | comptime params_len: usize, | 7640 | comptime params_len: usize, |
| 7588 | params: [params_len]*llvm.Value, | 7641 | params: [params_len]*llvm.Value, |
| 7589 | ) !*llvm.Value { | 7642 | ) !*llvm.Value { |
| 7590 | const target = self.dg.module.getTarget(); | 7643 | const mod = self.dg.module; |
| 7591 | const scalar_ty = ty.scalarType(); | 7644 | const target = mod.getTarget(); |
| 7645 | const scalar_ty = ty.scalarType(mod); | ||
| 7592 | const llvm_ty = try self.dg.lowerType(ty); | 7646 | const llvm_ty = try self.dg.lowerType(ty); |
| 7593 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); | 7647 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); |
| 7594 | 7648 | ||
| ... | @@ -7615,7 +7669,7 @@ pub const FuncGen = struct { | ... | @@ -7615,7 +7669,7 @@ pub const FuncGen = struct { |
| 7615 | const one = int_llvm_ty.constInt(1, .False); | 7669 | const one = int_llvm_ty.constInt(1, .False); |
| 7616 | const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False); | 7670 | const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False); |
| 7617 | const sign_mask = one.constShl(shift_amt); | 7671 | const sign_mask = one.constShl(shift_amt); |
| 7618 | const result = if (ty.zigTypeTag() == .Vector) blk: { | 7672 | const result = if (ty.zigTypeTag(mod) == .Vector) blk: { |
| 7619 | const splat_sign_mask = self.builder.buildVectorSplat(ty.vectorLen(), sign_mask, ""); | 7673 | const splat_sign_mask = self.builder.buildVectorSplat(ty.vectorLen(), sign_mask, ""); |
| 7620 | const cast_ty = int_llvm_ty.vectorType(ty.vectorLen()); | 7674 | const cast_ty = int_llvm_ty.vectorType(ty.vectorLen()); |
| 7621 | const bitcasted_operand = self.builder.buildBitCast(params[0], cast_ty, ""); | 7675 | const bitcasted_operand = self.builder.buildBitCast(params[0], cast_ty, ""); |
| ... | @@ -7662,7 +7716,7 @@ pub const FuncGen = struct { | ... | @@ -7662,7 +7716,7 @@ pub const FuncGen = struct { |
| 7662 | .libc => |fn_name| b: { | 7716 | .libc => |fn_name| b: { |
| 7663 | const param_types = [3]*llvm.Type{ scalar_llvm_ty, scalar_llvm_ty, scalar_llvm_ty }; | 7717 | const param_types = [3]*llvm.Type{ scalar_llvm_ty, scalar_llvm_ty, scalar_llvm_ty }; |
| 7664 | const libc_fn = self.getLibcFunction(fn_name, param_types[0..params.len], scalar_llvm_ty); | 7718 | const libc_fn = self.getLibcFunction(fn_name, param_types[0..params.len], scalar_llvm_ty); |
| 7665 | if (ty.zigTypeTag() == .Vector) { | 7719 | if (ty.zigTypeTag(mod) == .Vector) { |
| 7666 | const result = llvm_ty.getUndef(); | 7720 | const result = llvm_ty.getUndef(); |
| 7667 | return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen()); | 7721 | return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen()); |
| 7668 | } | 7722 | } |
| ... | @@ -7686,6 +7740,7 @@ pub const FuncGen = struct { | ... | @@ -7686,6 +7740,7 @@ pub const FuncGen = struct { |
| 7686 | } | 7740 | } |
| 7687 | 7741 | ||
| 7688 | fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7742 | fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7743 | const mod = self.dg.module; | ||
| 7689 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 7744 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 7690 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 7745 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 7691 | 7746 | ||
| ... | @@ -7694,21 +7749,19 @@ pub const FuncGen = struct { | ... | @@ -7694,21 +7749,19 @@ pub const FuncGen = struct { |
| 7694 | 7749 | ||
| 7695 | const lhs_ty = self.air.typeOf(extra.lhs); | 7750 | const lhs_ty = self.air.typeOf(extra.lhs); |
| 7696 | const rhs_ty = self.air.typeOf(extra.rhs); | 7751 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 7697 | const lhs_scalar_ty = lhs_ty.scalarType(); | 7752 | const lhs_scalar_ty = lhs_ty.scalarType(mod); |
| 7698 | const rhs_scalar_ty = rhs_ty.scalarType(); | 7753 | const rhs_scalar_ty = rhs_ty.scalarType(mod); |
| 7699 | 7754 | ||
| 7700 | const dest_ty = self.air.typeOfIndex(inst); | 7755 | const dest_ty = self.air.typeOfIndex(inst); |
| 7701 | const llvm_dest_ty = try self.dg.lowerType(dest_ty); | 7756 | const llvm_dest_ty = try self.dg.lowerType(dest_ty); |
| 7702 | 7757 | ||
| 7703 | const tg = self.dg.module.getTarget(); | 7758 | const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod)) |
| 7704 | |||
| 7705 | const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg)) | ||
| 7706 | self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "") | 7759 | self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "") |
| 7707 | else | 7760 | else |
| 7708 | rhs; | 7761 | rhs; |
| 7709 | 7762 | ||
| 7710 | const result = self.builder.buildShl(lhs, casted_rhs, ""); | 7763 | const result = self.builder.buildShl(lhs, casted_rhs, ""); |
| 7711 | const reconstructed = if (lhs_scalar_ty.isSignedInt()) | 7764 | const reconstructed = if (lhs_scalar_ty.isSignedInt(mod)) |
| 7712 | self.builder.buildAShr(result, casted_rhs, "") | 7765 | self.builder.buildAShr(result, casted_rhs, "") |
| 7713 | else | 7766 | else |
| 7714 | self.builder.buildLShr(result, casted_rhs, ""); | 7767 | self.builder.buildLShr(result, casted_rhs, ""); |
| ... | @@ -7716,12 +7769,11 @@ pub const FuncGen = struct { | ... | @@ -7716,12 +7769,11 @@ pub const FuncGen = struct { |
| 7716 | const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, ""); | 7769 | const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, ""); |
| 7717 | 7770 | ||
| 7718 | var ty_buf: Type.Payload.Pointer = undefined; | 7771 | var ty_buf: Type.Payload.Pointer = undefined; |
| 7719 | const result_index = llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?; | 7772 | const result_index = llvmFieldIndex(dest_ty, 0, mod, &ty_buf).?; |
| 7720 | const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?; | 7773 | const overflow_index = llvmFieldIndex(dest_ty, 1, mod, &ty_buf).?; |
| 7721 | 7774 | ||
| 7722 | if (isByRef(dest_ty)) { | 7775 | if (isByRef(dest_ty, mod)) { |
| 7723 | const target = self.dg.module.getTarget(); | 7776 | const result_alignment = dest_ty.abiAlignment(mod); |
| 7724 | const result_alignment = dest_ty.abiAlignment(target); | ||
| 7725 | const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment); | 7777 | const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment); |
| 7726 | { | 7778 | { |
| 7727 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); | 7779 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); |
| ... | @@ -7763,6 +7815,7 @@ pub const FuncGen = struct { | ... | @@ -7763,6 +7815,7 @@ pub const FuncGen = struct { |
| 7763 | } | 7815 | } |
| 7764 | 7816 | ||
| 7765 | fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7817 | fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7818 | const mod = self.dg.module; | ||
| 7766 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7819 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7767 | 7820 | ||
| 7768 | const lhs = try self.resolveInst(bin_op.lhs); | 7821 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | @@ -7770,20 +7823,19 @@ pub const FuncGen = struct { | ... | @@ -7770,20 +7823,19 @@ pub const FuncGen = struct { |
| 7770 | 7823 | ||
| 7771 | const lhs_ty = self.air.typeOf(bin_op.lhs); | 7824 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| 7772 | const rhs_ty = self.air.typeOf(bin_op.rhs); | 7825 | const rhs_ty = self.air.typeOf(bin_op.rhs); |
| 7773 | const lhs_scalar_ty = lhs_ty.scalarType(); | 7826 | const lhs_scalar_ty = lhs_ty.scalarType(mod); |
| 7774 | const rhs_scalar_ty = rhs_ty.scalarType(); | 7827 | const rhs_scalar_ty = rhs_ty.scalarType(mod); |
| 7775 | 7828 | ||
| 7776 | const tg = self.dg.module.getTarget(); | 7829 | const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod)) |
| 7777 | |||
| 7778 | const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg)) | ||
| 7779 | self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "") | 7830 | self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "") |
| 7780 | else | 7831 | else |
| 7781 | rhs; | 7832 | rhs; |
| 7782 | if (lhs_scalar_ty.isSignedInt()) return self.builder.buildNSWShl(lhs, casted_rhs, ""); | 7833 | if (lhs_scalar_ty.isSignedInt(mod)) return self.builder.buildNSWShl(lhs, casted_rhs, ""); |
| 7783 | return self.builder.buildNUWShl(lhs, casted_rhs, ""); | 7834 | return self.builder.buildNUWShl(lhs, casted_rhs, ""); |
| 7784 | } | 7835 | } |
| 7785 | 7836 | ||
| 7786 | fn airShl(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7837 | fn airShl(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7838 | const mod = self.dg.module; | ||
| 7787 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7839 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7788 | 7840 | ||
| 7789 | const lhs = try self.resolveInst(bin_op.lhs); | 7841 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | @@ -7791,12 +7843,10 @@ pub const FuncGen = struct { | ... | @@ -7791,12 +7843,10 @@ pub const FuncGen = struct { |
| 7791 | 7843 | ||
| 7792 | const lhs_type = self.air.typeOf(bin_op.lhs); | 7844 | const lhs_type = self.air.typeOf(bin_op.lhs); |
| 7793 | const rhs_type = self.air.typeOf(bin_op.rhs); | 7845 | const rhs_type = self.air.typeOf(bin_op.rhs); |
| 7794 | const lhs_scalar_ty = lhs_type.scalarType(); | 7846 | const lhs_scalar_ty = lhs_type.scalarType(mod); |
| 7795 | const rhs_scalar_ty = rhs_type.scalarType(); | 7847 | const rhs_scalar_ty = rhs_type.scalarType(mod); |
| 7796 | |||
| 7797 | const tg = self.dg.module.getTarget(); | ||
| 7798 | 7848 | ||
| 7799 | const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg)) | 7849 | const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod)) |
| 7800 | self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_type), "") | 7850 | self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_type), "") |
| 7801 | else | 7851 | else |
| 7802 | rhs; | 7852 | rhs; |
| ... | @@ -7804,6 +7854,7 @@ pub const FuncGen = struct { | ... | @@ -7804,6 +7854,7 @@ pub const FuncGen = struct { |
| 7804 | } | 7854 | } |
| 7805 | 7855 | ||
| 7806 | fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7856 | fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7857 | const mod = self.dg.module; | ||
| 7807 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7858 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7808 | 7859 | ||
| 7809 | const lhs = try self.resolveInst(bin_op.lhs); | 7860 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | @@ -7811,17 +7862,16 @@ pub const FuncGen = struct { | ... | @@ -7811,17 +7862,16 @@ pub const FuncGen = struct { |
| 7811 | 7862 | ||
| 7812 | const lhs_ty = self.air.typeOf(bin_op.lhs); | 7863 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| 7813 | const rhs_ty = self.air.typeOf(bin_op.rhs); | 7864 | const rhs_ty = self.air.typeOf(bin_op.rhs); |
| 7814 | const lhs_scalar_ty = lhs_ty.scalarType(); | 7865 | const lhs_scalar_ty = lhs_ty.scalarType(mod); |
| 7815 | const rhs_scalar_ty = rhs_ty.scalarType(); | 7866 | const rhs_scalar_ty = rhs_ty.scalarType(mod); |
| 7816 | const tg = self.dg.module.getTarget(); | 7867 | const lhs_bits = lhs_scalar_ty.bitSize(mod); |
| 7817 | const lhs_bits = lhs_scalar_ty.bitSize(tg); | ||
| 7818 | 7868 | ||
| 7819 | const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_bits) | 7869 | const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_bits) |
| 7820 | self.builder.buildZExt(rhs, lhs.typeOf(), "") | 7870 | self.builder.buildZExt(rhs, lhs.typeOf(), "") |
| 7821 | else | 7871 | else |
| 7822 | rhs; | 7872 | rhs; |
| 7823 | 7873 | ||
| 7824 | const result = if (lhs_scalar_ty.isSignedInt()) | 7874 | const result = if (lhs_scalar_ty.isSignedInt(mod)) |
| 7825 | self.builder.buildSShlSat(lhs, casted_rhs, "") | 7875 | self.builder.buildSShlSat(lhs, casted_rhs, "") |
| 7826 | else | 7876 | else |
| 7827 | self.builder.buildUShlSat(lhs, casted_rhs, ""); | 7877 | self.builder.buildUShlSat(lhs, casted_rhs, ""); |
| ... | @@ -7834,7 +7884,7 @@ pub const FuncGen = struct { | ... | @@ -7834,7 +7884,7 @@ pub const FuncGen = struct { |
| 7834 | const lhs_scalar_llvm_ty = try self.dg.lowerType(lhs_scalar_ty); | 7884 | const lhs_scalar_llvm_ty = try self.dg.lowerType(lhs_scalar_ty); |
| 7835 | const bits = lhs_scalar_llvm_ty.constInt(lhs_bits, .False); | 7885 | const bits = lhs_scalar_llvm_ty.constInt(lhs_bits, .False); |
| 7836 | const lhs_max = lhs_scalar_llvm_ty.constAllOnes(); | 7886 | const lhs_max = lhs_scalar_llvm_ty.constAllOnes(); |
| 7837 | if (rhs_ty.zigTypeTag() == .Vector) { | 7887 | if (rhs_ty.zigTypeTag(mod) == .Vector) { |
| 7838 | const vec_len = rhs_ty.vectorLen(); | 7888 | const vec_len = rhs_ty.vectorLen(); |
| 7839 | const bits_vec = self.builder.buildVectorSplat(vec_len, bits, ""); | 7889 | const bits_vec = self.builder.buildVectorSplat(vec_len, bits, ""); |
| 7840 | const lhs_max_vec = self.builder.buildVectorSplat(vec_len, lhs_max, ""); | 7890 | const lhs_max_vec = self.builder.buildVectorSplat(vec_len, lhs_max, ""); |
| ... | @@ -7847,6 +7897,7 @@ pub const FuncGen = struct { | ... | @@ -7847,6 +7897,7 @@ pub const FuncGen = struct { |
| 7847 | } | 7897 | } |
| 7848 | 7898 | ||
| 7849 | fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*llvm.Value { | 7899 | fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*llvm.Value { |
| 7900 | const mod = self.dg.module; | ||
| 7850 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7901 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7851 | 7902 | ||
| 7852 | const lhs = try self.resolveInst(bin_op.lhs); | 7903 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | @@ -7854,16 +7905,14 @@ pub const FuncGen = struct { | ... | @@ -7854,16 +7905,14 @@ pub const FuncGen = struct { |
| 7854 | 7905 | ||
| 7855 | const lhs_ty = self.air.typeOf(bin_op.lhs); | 7906 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| 7856 | const rhs_ty = self.air.typeOf(bin_op.rhs); | 7907 | const rhs_ty = self.air.typeOf(bin_op.rhs); |
| 7857 | const lhs_scalar_ty = lhs_ty.scalarType(); | 7908 | const lhs_scalar_ty = lhs_ty.scalarType(mod); |
| 7858 | const rhs_scalar_ty = rhs_ty.scalarType(); | 7909 | const rhs_scalar_ty = rhs_ty.scalarType(mod); |
| 7859 | |||
| 7860 | const tg = self.dg.module.getTarget(); | ||
| 7861 | 7910 | ||
| 7862 | const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg)) | 7911 | const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod)) |
| 7863 | self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "") | 7912 | self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "") |
| 7864 | else | 7913 | else |
| 7865 | rhs; | 7914 | rhs; |
| 7866 | const is_signed_int = lhs_scalar_ty.isSignedInt(); | 7915 | const is_signed_int = lhs_scalar_ty.isSignedInt(mod); |
| 7867 | 7916 | ||
| 7868 | if (is_exact) { | 7917 | if (is_exact) { |
| 7869 | if (is_signed_int) { | 7918 | if (is_signed_int) { |
| ... | @@ -7881,14 +7930,14 @@ pub const FuncGen = struct { | ... | @@ -7881,14 +7930,14 @@ pub const FuncGen = struct { |
| 7881 | } | 7930 | } |
| 7882 | 7931 | ||
| 7883 | fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7932 | fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7884 | const target = self.dg.module.getTarget(); | 7933 | const mod = self.dg.module; |
| 7885 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 7934 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 7886 | const dest_ty = self.air.typeOfIndex(inst); | 7935 | const dest_ty = self.air.typeOfIndex(inst); |
| 7887 | const dest_info = dest_ty.intInfo(target); | 7936 | const dest_info = dest_ty.intInfo(mod); |
| 7888 | const dest_llvm_ty = try self.dg.lowerType(dest_ty); | 7937 | const dest_llvm_ty = try self.dg.lowerType(dest_ty); |
| 7889 | const operand = try self.resolveInst(ty_op.operand); | 7938 | const operand = try self.resolveInst(ty_op.operand); |
| 7890 | const operand_ty = self.air.typeOf(ty_op.operand); | 7939 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 7891 | const operand_info = operand_ty.intInfo(target); | 7940 | const operand_info = operand_ty.intInfo(mod); |
| 7892 | 7941 | ||
| 7893 | if (operand_info.bits < dest_info.bits) { | 7942 | if (operand_info.bits < dest_info.bits) { |
| 7894 | switch (operand_info.signedness) { | 7943 | switch (operand_info.signedness) { |
| ... | @@ -7910,11 +7959,12 @@ pub const FuncGen = struct { | ... | @@ -7910,11 +7959,12 @@ pub const FuncGen = struct { |
| 7910 | } | 7959 | } |
| 7911 | 7960 | ||
| 7912 | fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7961 | fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7962 | const mod = self.dg.module; | ||
| 7913 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 7963 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 7914 | const operand = try self.resolveInst(ty_op.operand); | 7964 | const operand = try self.resolveInst(ty_op.operand); |
| 7915 | const operand_ty = self.air.typeOf(ty_op.operand); | 7965 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 7916 | const dest_ty = self.air.typeOfIndex(inst); | 7966 | const dest_ty = self.air.typeOfIndex(inst); |
| 7917 | const target = self.dg.module.getTarget(); | 7967 | const target = mod.getTarget(); |
| 7918 | const dest_bits = dest_ty.floatBits(target); | 7968 | const dest_bits = dest_ty.floatBits(target); |
| 7919 | const src_bits = operand_ty.floatBits(target); | 7969 | const src_bits = operand_ty.floatBits(target); |
| 7920 | 7970 | ||
| ... | @@ -7939,11 +7989,12 @@ pub const FuncGen = struct { | ... | @@ -7939,11 +7989,12 @@ pub const FuncGen = struct { |
| 7939 | } | 7989 | } |
| 7940 | 7990 | ||
| 7941 | fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7991 | fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7992 | const mod = self.dg.module; | ||
| 7942 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 7993 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 7943 | const operand = try self.resolveInst(ty_op.operand); | 7994 | const operand = try self.resolveInst(ty_op.operand); |
| 7944 | const operand_ty = self.air.typeOf(ty_op.operand); | 7995 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 7945 | const dest_ty = self.air.typeOfIndex(inst); | 7996 | const dest_ty = self.air.typeOfIndex(inst); |
| 7946 | const target = self.dg.module.getTarget(); | 7997 | const target = mod.getTarget(); |
| 7947 | const dest_bits = dest_ty.floatBits(target); | 7998 | const dest_bits = dest_ty.floatBits(target); |
| 7948 | const src_bits = operand_ty.floatBits(target); | 7999 | const src_bits = operand_ty.floatBits(target); |
| 7949 | 8000 | ||
| ... | @@ -7985,10 +8036,10 @@ pub const FuncGen = struct { | ... | @@ -7985,10 +8036,10 @@ pub const FuncGen = struct { |
| 7985 | } | 8036 | } |
| 7986 | 8037 | ||
| 7987 | fn bitCast(self: *FuncGen, operand: *llvm.Value, operand_ty: Type, inst_ty: Type) !*llvm.Value { | 8038 | fn bitCast(self: *FuncGen, operand: *llvm.Value, operand_ty: Type, inst_ty: Type) !*llvm.Value { |
| 7988 | const operand_is_ref = isByRef(operand_ty); | 8039 | const mod = self.dg.module; |
| 7989 | const result_is_ref = isByRef(inst_ty); | 8040 | const operand_is_ref = isByRef(operand_ty, mod); |
| 8041 | const result_is_ref = isByRef(inst_ty, mod); | ||
| 7990 | const llvm_dest_ty = try self.dg.lowerType(inst_ty); | 8042 | const llvm_dest_ty = try self.dg.lowerType(inst_ty); |
| 7991 | const target = self.dg.module.getTarget(); | ||
| 7992 | 8043 | ||
| 7993 | if (operand_is_ref and result_is_ref) { | 8044 | if (operand_is_ref and result_is_ref) { |
| 7994 | // They are both pointers, so just return the same opaque pointer :) | 8045 | // They are both pointers, so just return the same opaque pointer :) |
| ... | @@ -8001,20 +8052,20 @@ pub const FuncGen = struct { | ... | @@ -8001,20 +8052,20 @@ pub const FuncGen = struct { |
| 8001 | return self.builder.buildZExtOrBitCast(operand, llvm_dest_ty, ""); | 8052 | return self.builder.buildZExtOrBitCast(operand, llvm_dest_ty, ""); |
| 8002 | } | 8053 | } |
| 8003 | 8054 | ||
| 8004 | if (operand_ty.zigTypeTag() == .Int and inst_ty.isPtrAtRuntime()) { | 8055 | if (operand_ty.zigTypeTag(mod) == .Int and inst_ty.isPtrAtRuntime(mod)) { |
| 8005 | return self.builder.buildIntToPtr(operand, llvm_dest_ty, ""); | 8056 | return self.builder.buildIntToPtr(operand, llvm_dest_ty, ""); |
| 8006 | } | 8057 | } |
| 8007 | 8058 | ||
| 8008 | if (operand_ty.zigTypeTag() == .Vector and inst_ty.zigTypeTag() == .Array) { | 8059 | if (operand_ty.zigTypeTag(mod) == .Vector and inst_ty.zigTypeTag(mod) == .Array) { |
| 8009 | const elem_ty = operand_ty.childType(); | 8060 | const elem_ty = operand_ty.childType(); |
| 8010 | if (!result_is_ref) { | 8061 | if (!result_is_ref) { |
| 8011 | return self.dg.todo("implement bitcast vector to non-ref array", .{}); | 8062 | return self.dg.todo("implement bitcast vector to non-ref array", .{}); |
| 8012 | } | 8063 | } |
| 8013 | const array_ptr = self.buildAlloca(llvm_dest_ty, null); | 8064 | const array_ptr = self.buildAlloca(llvm_dest_ty, null); |
| 8014 | const bitcast_ok = elem_ty.bitSize(target) == elem_ty.abiSize(target) * 8; | 8065 | const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8; |
| 8015 | if (bitcast_ok) { | 8066 | if (bitcast_ok) { |
| 8016 | const llvm_store = self.builder.buildStore(operand, array_ptr); | 8067 | const llvm_store = self.builder.buildStore(operand, array_ptr); |
| 8017 | llvm_store.setAlignment(inst_ty.abiAlignment(target)); | 8068 | llvm_store.setAlignment(inst_ty.abiAlignment(mod)); |
| 8018 | } else { | 8069 | } else { |
| 8019 | // If the ABI size of the element type is not evenly divisible by size in bits; | 8070 | // If the ABI size of the element type is not evenly divisible by size in bits; |
| 8020 | // a simple bitcast will not work, and we fall back to extractelement. | 8071 | // a simple bitcast will not work, and we fall back to extractelement. |
| ... | @@ -8033,19 +8084,19 @@ pub const FuncGen = struct { | ... | @@ -8033,19 +8084,19 @@ pub const FuncGen = struct { |
| 8033 | } | 8084 | } |
| 8034 | } | 8085 | } |
| 8035 | return array_ptr; | 8086 | return array_ptr; |
| 8036 | } else if (operand_ty.zigTypeTag() == .Array and inst_ty.zigTypeTag() == .Vector) { | 8087 | } else if (operand_ty.zigTypeTag(mod) == .Array and inst_ty.zigTypeTag(mod) == .Vector) { |
| 8037 | const elem_ty = operand_ty.childType(); | 8088 | const elem_ty = operand_ty.childType(); |
| 8038 | const llvm_vector_ty = try self.dg.lowerType(inst_ty); | 8089 | const llvm_vector_ty = try self.dg.lowerType(inst_ty); |
| 8039 | if (!operand_is_ref) { | 8090 | if (!operand_is_ref) { |
| 8040 | return self.dg.todo("implement bitcast non-ref array to vector", .{}); | 8091 | return self.dg.todo("implement bitcast non-ref array to vector", .{}); |
| 8041 | } | 8092 | } |
| 8042 | 8093 | ||
| 8043 | const bitcast_ok = elem_ty.bitSize(target) == elem_ty.abiSize(target) * 8; | 8094 | const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8; |
| 8044 | if (bitcast_ok) { | 8095 | if (bitcast_ok) { |
| 8045 | const vector = self.builder.buildLoad(llvm_vector_ty, operand, ""); | 8096 | const vector = self.builder.buildLoad(llvm_vector_ty, operand, ""); |
| 8046 | // The array is aligned to the element's alignment, while the vector might have a completely | 8097 | // The array is aligned to the element's alignment, while the vector might have a completely |
| 8047 | // different alignment. This means we need to enforce the alignment of this load. | 8098 | // different alignment. This means we need to enforce the alignment of this load. |
| 8048 | vector.setAlignment(elem_ty.abiAlignment(target)); | 8099 | vector.setAlignment(elem_ty.abiAlignment(mod)); |
| 8049 | return vector; | 8100 | return vector; |
| 8050 | } else { | 8101 | } else { |
| 8051 | // If the ABI size of the element type is not evenly divisible by size in bits; | 8102 | // If the ABI size of the element type is not evenly divisible by size in bits; |
| ... | @@ -8073,12 +8124,12 @@ pub const FuncGen = struct { | ... | @@ -8073,12 +8124,12 @@ pub const FuncGen = struct { |
| 8073 | 8124 | ||
| 8074 | if (operand_is_ref) { | 8125 | if (operand_is_ref) { |
| 8075 | const load_inst = self.builder.buildLoad(llvm_dest_ty, operand, ""); | 8126 | const load_inst = self.builder.buildLoad(llvm_dest_ty, operand, ""); |
| 8076 | load_inst.setAlignment(operand_ty.abiAlignment(target)); | 8127 | load_inst.setAlignment(operand_ty.abiAlignment(mod)); |
| 8077 | return load_inst; | 8128 | return load_inst; |
| 8078 | } | 8129 | } |
| 8079 | 8130 | ||
| 8080 | if (result_is_ref) { | 8131 | if (result_is_ref) { |
| 8081 | const alignment = @max(operand_ty.abiAlignment(target), inst_ty.abiAlignment(target)); | 8132 | const alignment = @max(operand_ty.abiAlignment(mod), inst_ty.abiAlignment(mod)); |
| 8082 | const result_ptr = self.buildAlloca(llvm_dest_ty, alignment); | 8133 | const result_ptr = self.buildAlloca(llvm_dest_ty, alignment); |
| 8083 | const store_inst = self.builder.buildStore(operand, result_ptr); | 8134 | const store_inst = self.builder.buildStore(operand, result_ptr); |
| 8084 | store_inst.setAlignment(alignment); | 8135 | store_inst.setAlignment(alignment); |
| ... | @@ -8089,7 +8140,7 @@ pub const FuncGen = struct { | ... | @@ -8089,7 +8140,7 @@ pub const FuncGen = struct { |
| 8089 | // Both our operand and our result are values, not pointers, | 8140 | // Both our operand and our result are values, not pointers, |
| 8090 | // but LLVM won't let us bitcast struct values. | 8141 | // but LLVM won't let us bitcast struct values. |
| 8091 | // Therefore, we store operand to alloca, then load for result. | 8142 | // Therefore, we store operand to alloca, then load for result. |
| 8092 | const alignment = @max(operand_ty.abiAlignment(target), inst_ty.abiAlignment(target)); | 8143 | const alignment = @max(operand_ty.abiAlignment(mod), inst_ty.abiAlignment(mod)); |
| 8093 | const result_ptr = self.buildAlloca(llvm_dest_ty, alignment); | 8144 | const result_ptr = self.buildAlloca(llvm_dest_ty, alignment); |
| 8094 | const store_inst = self.builder.buildStore(operand, result_ptr); | 8145 | const store_inst = self.builder.buildStore(operand, result_ptr); |
| 8095 | store_inst.setAlignment(alignment); | 8146 | store_inst.setAlignment(alignment); |
| ... | @@ -8118,12 +8169,13 @@ pub const FuncGen = struct { | ... | @@ -8118,12 +8169,13 @@ pub const FuncGen = struct { |
| 8118 | } | 8169 | } |
| 8119 | 8170 | ||
| 8120 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; | 8171 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; |
| 8172 | const mod = self.dg.module; | ||
| 8121 | const func = self.dg.decl.getFunction().?; | 8173 | const func = self.dg.decl.getFunction().?; |
| 8122 | const lbrace_line = self.dg.module.declPtr(func.owner_decl).src_line + func.lbrace_line + 1; | 8174 | const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1; |
| 8123 | const lbrace_col = func.lbrace_column + 1; | 8175 | const lbrace_col = func.lbrace_column + 1; |
| 8124 | const di_local_var = dib.createParameterVariable( | 8176 | const di_local_var = dib.createParameterVariable( |
| 8125 | self.di_scope.?, | 8177 | self.di_scope.?, |
| 8126 | func.getParamName(self.dg.module, src_index).ptr, // TODO test 0 bit args | 8178 | func.getParamName(mod, src_index).ptr, // TODO test 0 bit args |
| 8127 | self.di_file.?, | 8179 | self.di_file.?, |
| 8128 | lbrace_line, | 8180 | lbrace_line, |
| 8129 | try self.dg.object.lowerDebugType(inst_ty, .full), | 8181 | try self.dg.object.lowerDebugType(inst_ty, .full), |
| ... | @@ -8134,10 +8186,10 @@ pub const FuncGen = struct { | ... | @@ -8134,10 +8186,10 @@ pub const FuncGen = struct { |
| 8134 | 8186 | ||
| 8135 | const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null); | 8187 | const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null); |
| 8136 | const insert_block = self.builder.getInsertBlock(); | 8188 | const insert_block = self.builder.getInsertBlock(); |
| 8137 | if (isByRef(inst_ty)) { | 8189 | if (isByRef(inst_ty, mod)) { |
| 8138 | _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block); | 8190 | _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block); |
| 8139 | } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) { | 8191 | } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) { |
| 8140 | const alignment = inst_ty.abiAlignment(self.dg.module.getTarget()); | 8192 | const alignment = inst_ty.abiAlignment(mod); |
| 8141 | const alloca = self.buildAlloca(arg_val.typeOf(), alignment); | 8193 | const alloca = self.buildAlloca(arg_val.typeOf(), alignment); |
| 8142 | const store_inst = self.builder.buildStore(arg_val, alloca); | 8194 | const store_inst = self.builder.buildStore(arg_val, alloca); |
| 8143 | store_inst.setAlignment(alignment); | 8195 | store_inst.setAlignment(alignment); |
| ... | @@ -8153,22 +8205,22 @@ pub const FuncGen = struct { | ... | @@ -8153,22 +8205,22 @@ pub const FuncGen = struct { |
| 8153 | fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8205 | fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8154 | const ptr_ty = self.air.typeOfIndex(inst); | 8206 | const ptr_ty = self.air.typeOfIndex(inst); |
| 8155 | const pointee_type = ptr_ty.childType(); | 8207 | const pointee_type = ptr_ty.childType(); |
| 8156 | if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty); | 8208 | const mod = self.dg.module; |
| 8209 | if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty); | ||
| 8157 | 8210 | ||
| 8158 | const pointee_llvm_ty = try self.dg.lowerType(pointee_type); | 8211 | const pointee_llvm_ty = try self.dg.lowerType(pointee_type); |
| 8159 | const target = self.dg.module.getTarget(); | 8212 | const alignment = ptr_ty.ptrAlignment(mod); |
| 8160 | const alignment = ptr_ty.ptrAlignment(target); | ||
| 8161 | return self.buildAlloca(pointee_llvm_ty, alignment); | 8213 | return self.buildAlloca(pointee_llvm_ty, alignment); |
| 8162 | } | 8214 | } |
| 8163 | 8215 | ||
| 8164 | fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8216 | fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8165 | const ptr_ty = self.air.typeOfIndex(inst); | 8217 | const ptr_ty = self.air.typeOfIndex(inst); |
| 8166 | const ret_ty = ptr_ty.childType(); | 8218 | const ret_ty = ptr_ty.childType(); |
| 8167 | if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty); | 8219 | const mod = self.dg.module; |
| 8220 | if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty); | ||
| 8168 | if (self.ret_ptr) |ret_ptr| return ret_ptr; | 8221 | if (self.ret_ptr) |ret_ptr| return ret_ptr; |
| 8169 | const ret_llvm_ty = try self.dg.lowerType(ret_ty); | 8222 | const ret_llvm_ty = try self.dg.lowerType(ret_ty); |
| 8170 | const target = self.dg.module.getTarget(); | 8223 | return self.buildAlloca(ret_llvm_ty, ptr_ty.ptrAlignment(mod)); |
| 8171 | return self.buildAlloca(ret_llvm_ty, ptr_ty.ptrAlignment(target)); | ||
| 8172 | } | 8224 | } |
| 8173 | 8225 | ||
| 8174 | /// Use this instead of builder.buildAlloca, because this function makes sure to | 8226 | /// Use this instead of builder.buildAlloca, because this function makes sure to |
| ... | @@ -8182,8 +8234,9 @@ pub const FuncGen = struct { | ... | @@ -8182,8 +8234,9 @@ pub const FuncGen = struct { |
| 8182 | const dest_ptr = try self.resolveInst(bin_op.lhs); | 8234 | const dest_ptr = try self.resolveInst(bin_op.lhs); |
| 8183 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 8235 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 8184 | const operand_ty = ptr_ty.childType(); | 8236 | const operand_ty = ptr_ty.childType(); |
| 8237 | const mod = self.dg.module; | ||
| 8185 | 8238 | ||
| 8186 | const val_is_undef = if (self.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false; | 8239 | const val_is_undef = if (self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep() else false; |
| 8187 | if (val_is_undef) { | 8240 | if (val_is_undef) { |
| 8188 | // Even if safety is disabled, we still emit a memset to undefined since it conveys | 8241 | // Even if safety is disabled, we still emit a memset to undefined since it conveys |
| 8189 | // extra information to LLVM. However, safety makes the difference between using | 8242 | // extra information to LLVM. However, safety makes the difference between using |
| ... | @@ -8193,13 +8246,12 @@ pub const FuncGen = struct { | ... | @@ -8193,13 +8246,12 @@ pub const FuncGen = struct { |
| 8193 | u8_llvm_ty.constInt(0xaa, .False) | 8246 | u8_llvm_ty.constInt(0xaa, .False) |
| 8194 | else | 8247 | else |
| 8195 | u8_llvm_ty.getUndef(); | 8248 | u8_llvm_ty.getUndef(); |
| 8196 | const target = self.dg.module.getTarget(); | 8249 | const operand_size = operand_ty.abiSize(mod); |
| 8197 | const operand_size = operand_ty.abiSize(target); | ||
| 8198 | const usize_llvm_ty = try self.dg.lowerType(Type.usize); | 8250 | const usize_llvm_ty = try self.dg.lowerType(Type.usize); |
| 8199 | const len = usize_llvm_ty.constInt(operand_size, .False); | 8251 | const len = usize_llvm_ty.constInt(operand_size, .False); |
| 8200 | const dest_ptr_align = ptr_ty.ptrAlignment(target); | 8252 | const dest_ptr_align = ptr_ty.ptrAlignment(mod); |
| 8201 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr()); | 8253 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr()); |
| 8202 | if (safety and self.dg.module.comp.bin_file.options.valgrind) { | 8254 | if (safety and mod.comp.bin_file.options.valgrind) { |
| 8203 | self.valgrindMarkUndef(dest_ptr, len); | 8255 | self.valgrindMarkUndef(dest_ptr, len); |
| 8204 | } | 8256 | } |
| 8205 | return null; | 8257 | return null; |
| ... | @@ -8230,6 +8282,7 @@ pub const FuncGen = struct { | ... | @@ -8230,6 +8282,7 @@ pub const FuncGen = struct { |
| 8230 | } | 8282 | } |
| 8231 | 8283 | ||
| 8232 | fn airLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { | 8284 | fn airLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { |
| 8285 | const mod = fg.dg.module; | ||
| 8233 | const inst = body_tail[0]; | 8286 | const inst = body_tail[0]; |
| 8234 | const ty_op = fg.air.instructions.items(.data)[inst].ty_op; | 8287 | const ty_op = fg.air.instructions.items(.data)[inst].ty_op; |
| 8235 | const ptr_ty = fg.air.typeOf(ty_op.operand); | 8288 | const ptr_ty = fg.air.typeOf(ty_op.operand); |
| ... | @@ -8237,7 +8290,7 @@ pub const FuncGen = struct { | ... | @@ -8237,7 +8290,7 @@ pub const FuncGen = struct { |
| 8237 | const ptr = try fg.resolveInst(ty_op.operand); | 8290 | const ptr = try fg.resolveInst(ty_op.operand); |
| 8238 | 8291 | ||
| 8239 | elide: { | 8292 | elide: { |
| 8240 | if (!isByRef(ptr_info.pointee_type)) break :elide; | 8293 | if (!isByRef(ptr_info.pointee_type, mod)) break :elide; |
| 8241 | if (!canElideLoad(fg, body_tail)) break :elide; | 8294 | if (!canElideLoad(fg, body_tail)) break :elide; |
| 8242 | return ptr; | 8295 | return ptr; |
| 8243 | } | 8296 | } |
| ... | @@ -8261,8 +8314,9 @@ pub const FuncGen = struct { | ... | @@ -8261,8 +8314,9 @@ pub const FuncGen = struct { |
| 8261 | 8314 | ||
| 8262 | fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8315 | fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8263 | _ = inst; | 8316 | _ = inst; |
| 8317 | const mod = self.dg.module; | ||
| 8264 | const llvm_usize = try self.dg.lowerType(Type.usize); | 8318 | const llvm_usize = try self.dg.lowerType(Type.usize); |
| 8265 | const target = self.dg.module.getTarget(); | 8319 | const target = mod.getTarget(); |
| 8266 | if (!target_util.supportsReturnAddress(target)) { | 8320 | if (!target_util.supportsReturnAddress(target)) { |
| 8267 | // https://github.com/ziglang/zig/issues/11946 | 8321 | // https://github.com/ziglang/zig/issues/11946 |
| 8268 | return llvm_usize.constNull(); | 8322 | return llvm_usize.constNull(); |
| ... | @@ -8301,6 +8355,7 @@ pub const FuncGen = struct { | ... | @@ -8301,6 +8355,7 @@ pub const FuncGen = struct { |
| 8301 | } | 8355 | } |
| 8302 | 8356 | ||
| 8303 | fn airCmpxchg(self: *FuncGen, inst: Air.Inst.Index, is_weak: bool) !?*llvm.Value { | 8357 | fn airCmpxchg(self: *FuncGen, inst: Air.Inst.Index, is_weak: bool) !?*llvm.Value { |
| 8358 | const mod = self.dg.module; | ||
| 8304 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 8359 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 8305 | const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | 8360 | const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| 8306 | const ptr = try self.resolveInst(extra.ptr); | 8361 | const ptr = try self.resolveInst(extra.ptr); |
| ... | @@ -8310,7 +8365,7 @@ pub const FuncGen = struct { | ... | @@ -8310,7 +8365,7 @@ pub const FuncGen = struct { |
| 8310 | const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false); | 8365 | const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false); |
| 8311 | if (opt_abi_ty) |abi_ty| { | 8366 | if (opt_abi_ty) |abi_ty| { |
| 8312 | // operand needs widening and truncating | 8367 | // operand needs widening and truncating |
| 8313 | if (operand_ty.isSignedInt()) { | 8368 | if (operand_ty.isSignedInt(mod)) { |
| 8314 | expected_value = self.builder.buildSExt(expected_value, abi_ty, ""); | 8369 | expected_value = self.builder.buildSExt(expected_value, abi_ty, ""); |
| 8315 | new_value = self.builder.buildSExt(new_value, abi_ty, ""); | 8370 | new_value = self.builder.buildSExt(new_value, abi_ty, ""); |
| 8316 | } else { | 8371 | } else { |
| ... | @@ -8336,7 +8391,7 @@ pub const FuncGen = struct { | ... | @@ -8336,7 +8391,7 @@ pub const FuncGen = struct { |
| 8336 | } | 8391 | } |
| 8337 | const success_bit = self.builder.buildExtractValue(result, 1, ""); | 8392 | const success_bit = self.builder.buildExtractValue(result, 1, ""); |
| 8338 | 8393 | ||
| 8339 | if (optional_ty.optionalReprIsPayload()) { | 8394 | if (optional_ty.optionalReprIsPayload(mod)) { |
| 8340 | return self.builder.buildSelect(success_bit, payload.typeOf().constNull(), payload, ""); | 8395 | return self.builder.buildSelect(success_bit, payload.typeOf().constNull(), payload, ""); |
| 8341 | } | 8396 | } |
| 8342 | 8397 | ||
| ... | @@ -8347,13 +8402,14 @@ pub const FuncGen = struct { | ... | @@ -8347,13 +8402,14 @@ pub const FuncGen = struct { |
| 8347 | } | 8402 | } |
| 8348 | 8403 | ||
| 8349 | fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8404 | fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8405 | const mod = self.dg.module; | ||
| 8350 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 8406 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 8351 | const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data; | 8407 | const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data; |
| 8352 | const ptr = try self.resolveInst(pl_op.operand); | 8408 | const ptr = try self.resolveInst(pl_op.operand); |
| 8353 | const ptr_ty = self.air.typeOf(pl_op.operand); | 8409 | const ptr_ty = self.air.typeOf(pl_op.operand); |
| 8354 | const operand_ty = ptr_ty.elemType(); | 8410 | const operand_ty = ptr_ty.elemType(); |
| 8355 | const operand = try self.resolveInst(extra.operand); | 8411 | const operand = try self.resolveInst(extra.operand); |
| 8356 | const is_signed_int = operand_ty.isSignedInt(); | 8412 | const is_signed_int = operand_ty.isSignedInt(mod); |
| 8357 | const is_float = operand_ty.isRuntimeFloat(); | 8413 | const is_float = operand_ty.isRuntimeFloat(); |
| 8358 | const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float); | 8414 | const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float); |
| 8359 | const ordering = toLlvmAtomicOrdering(extra.ordering()); | 8415 | const ordering = toLlvmAtomicOrdering(extra.ordering()); |
| ... | @@ -8402,17 +8458,17 @@ pub const FuncGen = struct { | ... | @@ -8402,17 +8458,17 @@ pub const FuncGen = struct { |
| 8402 | } | 8458 | } |
| 8403 | 8459 | ||
| 8404 | fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8460 | fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8461 | const mod = self.dg.module; | ||
| 8405 | const atomic_load = self.air.instructions.items(.data)[inst].atomic_load; | 8462 | const atomic_load = self.air.instructions.items(.data)[inst].atomic_load; |
| 8406 | const ptr = try self.resolveInst(atomic_load.ptr); | 8463 | const ptr = try self.resolveInst(atomic_load.ptr); |
| 8407 | const ptr_ty = self.air.typeOf(atomic_load.ptr); | 8464 | const ptr_ty = self.air.typeOf(atomic_load.ptr); |
| 8408 | const ptr_info = ptr_ty.ptrInfo().data; | 8465 | const ptr_info = ptr_ty.ptrInfo().data; |
| 8409 | const elem_ty = ptr_info.pointee_type; | 8466 | const elem_ty = ptr_info.pointee_type; |
| 8410 | if (!elem_ty.hasRuntimeBitsIgnoreComptime()) | 8467 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 8411 | return null; | 8468 | return null; |
| 8412 | const ordering = toLlvmAtomicOrdering(atomic_load.order); | 8469 | const ordering = toLlvmAtomicOrdering(atomic_load.order); |
| 8413 | const opt_abi_llvm_ty = self.dg.getAtomicAbiType(elem_ty, false); | 8470 | const opt_abi_llvm_ty = self.dg.getAtomicAbiType(elem_ty, false); |
| 8414 | const target = self.dg.module.getTarget(); | 8471 | const ptr_alignment = ptr_info.alignment(mod); |
| 8415 | const ptr_alignment = ptr_info.alignment(target); | ||
| 8416 | const ptr_volatile = llvm.Bool.fromBool(ptr_info.@"volatile"); | 8472 | const ptr_volatile = llvm.Bool.fromBool(ptr_info.@"volatile"); |
| 8417 | const elem_llvm_ty = try self.dg.lowerType(elem_ty); | 8473 | const elem_llvm_ty = try self.dg.lowerType(elem_ty); |
| 8418 | 8474 | ||
| ... | @@ -8436,17 +8492,18 @@ pub const FuncGen = struct { | ... | @@ -8436,17 +8492,18 @@ pub const FuncGen = struct { |
| 8436 | inst: Air.Inst.Index, | 8492 | inst: Air.Inst.Index, |
| 8437 | ordering: llvm.AtomicOrdering, | 8493 | ordering: llvm.AtomicOrdering, |
| 8438 | ) !?*llvm.Value { | 8494 | ) !?*llvm.Value { |
| 8495 | const mod = self.dg.module; | ||
| 8439 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 8496 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 8440 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 8497 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 8441 | const operand_ty = ptr_ty.childType(); | 8498 | const operand_ty = ptr_ty.childType(); |
| 8442 | if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return null; | 8499 | if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return null; |
| 8443 | const ptr = try self.resolveInst(bin_op.lhs); | 8500 | const ptr = try self.resolveInst(bin_op.lhs); |
| 8444 | var element = try self.resolveInst(bin_op.rhs); | 8501 | var element = try self.resolveInst(bin_op.rhs); |
| 8445 | const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false); | 8502 | const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false); |
| 8446 | 8503 | ||
| 8447 | if (opt_abi_ty) |abi_ty| { | 8504 | if (opt_abi_ty) |abi_ty| { |
| 8448 | // operand needs widening | 8505 | // operand needs widening |
| 8449 | if (operand_ty.isSignedInt()) { | 8506 | if (operand_ty.isSignedInt(mod)) { |
| 8450 | element = self.builder.buildSExt(element, abi_ty, ""); | 8507 | element = self.builder.buildSExt(element, abi_ty, ""); |
| 8451 | } else { | 8508 | } else { |
| 8452 | element = self.builder.buildZExt(element, abi_ty, ""); | 8509 | element = self.builder.buildZExt(element, abi_ty, ""); |
| ... | @@ -8457,18 +8514,19 @@ pub const FuncGen = struct { | ... | @@ -8457,18 +8514,19 @@ pub const FuncGen = struct { |
| 8457 | } | 8514 | } |
| 8458 | 8515 | ||
| 8459 | fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value { | 8516 | fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value { |
| 8517 | const mod = self.dg.module; | ||
| 8460 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 8518 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 8461 | const dest_slice = try self.resolveInst(bin_op.lhs); | 8519 | const dest_slice = try self.resolveInst(bin_op.lhs); |
| 8462 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 8520 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 8463 | const elem_ty = self.air.typeOf(bin_op.rhs); | 8521 | const elem_ty = self.air.typeOf(bin_op.rhs); |
| 8464 | const module = self.dg.module; | 8522 | const module = self.dg.module; |
| 8465 | const target = module.getTarget(); | 8523 | const target = module.getTarget(); |
| 8466 | const dest_ptr_align = ptr_ty.ptrAlignment(target); | 8524 | const dest_ptr_align = ptr_ty.ptrAlignment(mod); |
| 8467 | const u8_llvm_ty = self.context.intType(8); | 8525 | const u8_llvm_ty = self.context.intType(8); |
| 8468 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, ptr_ty); | 8526 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, ptr_ty); |
| 8469 | const is_volatile = ptr_ty.isVolatilePtr(); | 8527 | const is_volatile = ptr_ty.isVolatilePtr(); |
| 8470 | 8528 | ||
| 8471 | if (self.air.value(bin_op.rhs)) |elem_val| { | 8529 | if (self.air.value(bin_op.rhs, mod)) |elem_val| { |
| 8472 | if (elem_val.isUndefDeep()) { | 8530 | if (elem_val.isUndefDeep()) { |
| 8473 | // Even if safety is disabled, we still emit a memset to undefined since it conveys | 8531 | // Even if safety is disabled, we still emit a memset to undefined since it conveys |
| 8474 | // extra information to LLVM. However, safety makes the difference between using | 8532 | // extra information to LLVM. However, safety makes the difference between using |
| ... | @@ -8503,7 +8561,7 @@ pub const FuncGen = struct { | ... | @@ -8503,7 +8561,7 @@ pub const FuncGen = struct { |
| 8503 | } | 8561 | } |
| 8504 | 8562 | ||
| 8505 | const value = try self.resolveInst(bin_op.rhs); | 8563 | const value = try self.resolveInst(bin_op.rhs); |
| 8506 | const elem_abi_size = elem_ty.abiSize(target); | 8564 | const elem_abi_size = elem_ty.abiSize(mod); |
| 8507 | 8565 | ||
| 8508 | if (elem_abi_size == 1) { | 8566 | if (elem_abi_size == 1) { |
| 8509 | // In this case we can take advantage of LLVM's intrinsic. | 8567 | // In this case we can take advantage of LLVM's intrinsic. |
| ... | @@ -8551,9 +8609,9 @@ pub const FuncGen = struct { | ... | @@ -8551,9 +8609,9 @@ pub const FuncGen = struct { |
| 8551 | _ = self.builder.buildCondBr(end, body_block, end_block); | 8609 | _ = self.builder.buildCondBr(end, body_block, end_block); |
| 8552 | 8610 | ||
| 8553 | self.builder.positionBuilderAtEnd(body_block); | 8611 | self.builder.positionBuilderAtEnd(body_block); |
| 8554 | const elem_abi_alignment = elem_ty.abiAlignment(target); | 8612 | const elem_abi_alignment = elem_ty.abiAlignment(mod); |
| 8555 | const it_ptr_alignment = @min(elem_abi_alignment, dest_ptr_align); | 8613 | const it_ptr_alignment = @min(elem_abi_alignment, dest_ptr_align); |
| 8556 | if (isByRef(elem_ty)) { | 8614 | if (isByRef(elem_ty, mod)) { |
| 8557 | _ = self.builder.buildMemCpy( | 8615 | _ = self.builder.buildMemCpy( |
| 8558 | it_ptr, | 8616 | it_ptr, |
| 8559 | it_ptr_alignment, | 8617 | it_ptr_alignment, |
| ... | @@ -8589,13 +8647,13 @@ pub const FuncGen = struct { | ... | @@ -8589,13 +8647,13 @@ pub const FuncGen = struct { |
| 8589 | const src_ptr = self.sliceOrArrayPtr(src_slice, src_ptr_ty); | 8647 | const src_ptr = self.sliceOrArrayPtr(src_slice, src_ptr_ty); |
| 8590 | const len = self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty); | 8648 | const len = self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty); |
| 8591 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, dest_ptr_ty); | 8649 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, dest_ptr_ty); |
| 8650 | const mod = self.dg.module; | ||
| 8592 | const is_volatile = src_ptr_ty.isVolatilePtr() or dest_ptr_ty.isVolatilePtr(); | 8651 | const is_volatile = src_ptr_ty.isVolatilePtr() or dest_ptr_ty.isVolatilePtr(); |
| 8593 | const target = self.dg.module.getTarget(); | ||
| 8594 | _ = self.builder.buildMemCpy( | 8652 | _ = self.builder.buildMemCpy( |
| 8595 | dest_ptr, | 8653 | dest_ptr, |
| 8596 | dest_ptr_ty.ptrAlignment(target), | 8654 | dest_ptr_ty.ptrAlignment(mod), |
| 8597 | src_ptr, | 8655 | src_ptr, |
| 8598 | src_ptr_ty.ptrAlignment(target), | 8656 | src_ptr_ty.ptrAlignment(mod), |
| 8599 | len, | 8657 | len, |
| 8600 | is_volatile, | 8658 | is_volatile, |
| 8601 | ); | 8659 | ); |
| ... | @@ -8603,10 +8661,10 @@ pub const FuncGen = struct { | ... | @@ -8603,10 +8661,10 @@ pub const FuncGen = struct { |
| 8603 | } | 8661 | } |
| 8604 | 8662 | ||
| 8605 | fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8663 | fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8664 | const mod = self.dg.module; | ||
| 8606 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 8665 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 8607 | const un_ty = self.air.typeOf(bin_op.lhs).childType(); | 8666 | const un_ty = self.air.typeOf(bin_op.lhs).childType(); |
| 8608 | const target = self.dg.module.getTarget(); | 8667 | const layout = un_ty.unionGetLayout(mod); |
| 8609 | const layout = un_ty.unionGetLayout(target); | ||
| 8610 | if (layout.tag_size == 0) return null; | 8668 | if (layout.tag_size == 0) return null; |
| 8611 | const union_ptr = try self.resolveInst(bin_op.lhs); | 8669 | const union_ptr = try self.resolveInst(bin_op.lhs); |
| 8612 | const new_tag = try self.resolveInst(bin_op.rhs); | 8670 | const new_tag = try self.resolveInst(bin_op.rhs); |
| ... | @@ -8624,13 +8682,13 @@ pub const FuncGen = struct { | ... | @@ -8624,13 +8682,13 @@ pub const FuncGen = struct { |
| 8624 | } | 8682 | } |
| 8625 | 8683 | ||
| 8626 | fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8684 | fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8685 | const mod = self.dg.module; | ||
| 8627 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 8686 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 8628 | const un_ty = self.air.typeOf(ty_op.operand); | 8687 | const un_ty = self.air.typeOf(ty_op.operand); |
| 8629 | const target = self.dg.module.getTarget(); | 8688 | const layout = un_ty.unionGetLayout(mod); |
| 8630 | const layout = un_ty.unionGetLayout(target); | ||
| 8631 | if (layout.tag_size == 0) return null; | 8689 | if (layout.tag_size == 0) return null; |
| 8632 | const union_handle = try self.resolveInst(ty_op.operand); | 8690 | const union_handle = try self.resolveInst(ty_op.operand); |
| 8633 | if (isByRef(un_ty)) { | 8691 | if (isByRef(un_ty, mod)) { |
| 8634 | const llvm_un_ty = try self.dg.lowerType(un_ty); | 8692 | const llvm_un_ty = try self.dg.lowerType(un_ty); |
| 8635 | if (layout.payload_size == 0) { | 8693 | if (layout.payload_size == 0) { |
| 8636 | return self.builder.buildLoad(llvm_un_ty, union_handle, ""); | 8694 | return self.builder.buildLoad(llvm_un_ty, union_handle, ""); |
| ... | @@ -8666,6 +8724,7 @@ pub const FuncGen = struct { | ... | @@ -8666,6 +8724,7 @@ pub const FuncGen = struct { |
| 8666 | } | 8724 | } |
| 8667 | 8725 | ||
| 8668 | fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value { | 8726 | fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value { |
| 8727 | const mod = self.dg.module; | ||
| 8669 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 8728 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 8670 | const operand_ty = self.air.typeOf(ty_op.operand); | 8729 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 8671 | const operand = try self.resolveInst(ty_op.operand); | 8730 | const operand = try self.resolveInst(ty_op.operand); |
| ... | @@ -8679,9 +8738,8 @@ pub const FuncGen = struct { | ... | @@ -8679,9 +8738,8 @@ pub const FuncGen = struct { |
| 8679 | const result_ty = self.air.typeOfIndex(inst); | 8738 | const result_ty = self.air.typeOfIndex(inst); |
| 8680 | const result_llvm_ty = try self.dg.lowerType(result_ty); | 8739 | const result_llvm_ty = try self.dg.lowerType(result_ty); |
| 8681 | 8740 | ||
| 8682 | const target = self.dg.module.getTarget(); | 8741 | const bits = operand_ty.intInfo(mod).bits; |
| 8683 | const bits = operand_ty.intInfo(target).bits; | 8742 | const result_bits = result_ty.intInfo(mod).bits; |
| 8684 | const result_bits = result_ty.intInfo(target).bits; | ||
| 8685 | if (bits > result_bits) { | 8743 | if (bits > result_bits) { |
| 8686 | return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, ""); | 8744 | return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, ""); |
| 8687 | } else if (bits < result_bits) { | 8745 | } else if (bits < result_bits) { |
| ... | @@ -8692,6 +8750,7 @@ pub const FuncGen = struct { | ... | @@ -8692,6 +8750,7 @@ pub const FuncGen = struct { |
| 8692 | } | 8750 | } |
| 8693 | 8751 | ||
| 8694 | fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value { | 8752 | fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value { |
| 8753 | const mod = self.dg.module; | ||
| 8695 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 8754 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 8696 | const operand_ty = self.air.typeOf(ty_op.operand); | 8755 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 8697 | const operand = try self.resolveInst(ty_op.operand); | 8756 | const operand = try self.resolveInst(ty_op.operand); |
| ... | @@ -8704,9 +8763,8 @@ pub const FuncGen = struct { | ... | @@ -8704,9 +8763,8 @@ pub const FuncGen = struct { |
| 8704 | const result_ty = self.air.typeOfIndex(inst); | 8763 | const result_ty = self.air.typeOfIndex(inst); |
| 8705 | const result_llvm_ty = try self.dg.lowerType(result_ty); | 8764 | const result_llvm_ty = try self.dg.lowerType(result_ty); |
| 8706 | 8765 | ||
| 8707 | const target = self.dg.module.getTarget(); | 8766 | const bits = operand_ty.intInfo(mod).bits; |
| 8708 | const bits = operand_ty.intInfo(target).bits; | 8767 | const result_bits = result_ty.intInfo(mod).bits; |
| 8709 | const result_bits = result_ty.intInfo(target).bits; | ||
| 8710 | if (bits > result_bits) { | 8768 | if (bits > result_bits) { |
| 8711 | return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, ""); | 8769 | return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, ""); |
| 8712 | } else if (bits < result_bits) { | 8770 | } else if (bits < result_bits) { |
| ... | @@ -8717,10 +8775,10 @@ pub const FuncGen = struct { | ... | @@ -8717,10 +8775,10 @@ pub const FuncGen = struct { |
| 8717 | } | 8775 | } |
| 8718 | 8776 | ||
| 8719 | fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value { | 8777 | fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value { |
| 8720 | const target = self.dg.module.getTarget(); | 8778 | const mod = self.dg.module; |
| 8721 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 8779 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 8722 | const operand_ty = self.air.typeOf(ty_op.operand); | 8780 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 8723 | var bits = operand_ty.intInfo(target).bits; | 8781 | var bits = operand_ty.intInfo(mod).bits; |
| 8724 | assert(bits % 8 == 0); | 8782 | assert(bits % 8 == 0); |
| 8725 | 8783 | ||
| 8726 | var operand = try self.resolveInst(ty_op.operand); | 8784 | var operand = try self.resolveInst(ty_op.operand); |
| ... | @@ -8730,7 +8788,7 @@ pub const FuncGen = struct { | ... | @@ -8730,7 +8788,7 @@ pub const FuncGen = struct { |
| 8730 | // If not an even byte-multiple, we need zero-extend + shift-left 1 byte | 8788 | // If not an even byte-multiple, we need zero-extend + shift-left 1 byte |
| 8731 | // The truncated result at the end will be the correct bswap | 8789 | // The truncated result at the end will be the correct bswap |
| 8732 | const scalar_llvm_ty = self.context.intType(bits + 8); | 8790 | const scalar_llvm_ty = self.context.intType(bits + 8); |
| 8733 | if (operand_ty.zigTypeTag() == .Vector) { | 8791 | if (operand_ty.zigTypeTag(mod) == .Vector) { |
| 8734 | const vec_len = operand_ty.vectorLen(); | 8792 | const vec_len = operand_ty.vectorLen(); |
| 8735 | operand_llvm_ty = scalar_llvm_ty.vectorType(vec_len); | 8793 | operand_llvm_ty = scalar_llvm_ty.vectorType(vec_len); |
| 8736 | 8794 | ||
| ... | @@ -8759,7 +8817,7 @@ pub const FuncGen = struct { | ... | @@ -8759,7 +8817,7 @@ pub const FuncGen = struct { |
| 8759 | 8817 | ||
| 8760 | const result_ty = self.air.typeOfIndex(inst); | 8818 | const result_ty = self.air.typeOfIndex(inst); |
| 8761 | const result_llvm_ty = try self.dg.lowerType(result_ty); | 8819 | const result_llvm_ty = try self.dg.lowerType(result_ty); |
| 8762 | const result_bits = result_ty.intInfo(target).bits; | 8820 | const result_bits = result_ty.intInfo(mod).bits; |
| 8763 | if (bits > result_bits) { | 8821 | if (bits > result_bits) { |
| 8764 | return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, ""); | 8822 | return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, ""); |
| 8765 | } else if (bits < result_bits) { | 8823 | } else if (bits < result_bits) { |
| ... | @@ -8770,6 +8828,7 @@ pub const FuncGen = struct { | ... | @@ -8770,6 +8828,7 @@ pub const FuncGen = struct { |
| 8770 | } | 8828 | } |
| 8771 | 8829 | ||
| 8772 | fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8830 | fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8831 | const mod = self.dg.module; | ||
| 8773 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 8832 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 8774 | const operand = try self.resolveInst(ty_op.operand); | 8833 | const operand = try self.resolveInst(ty_op.operand); |
| 8775 | const error_set_ty = self.air.getRefType(ty_op.ty); | 8834 | const error_set_ty = self.air.getRefType(ty_op.ty); |
| ... | @@ -8781,7 +8840,7 @@ pub const FuncGen = struct { | ... | @@ -8781,7 +8840,7 @@ pub const FuncGen = struct { |
| 8781 | const switch_instr = self.builder.buildSwitch(operand, invalid_block, @intCast(c_uint, names.len)); | 8840 | const switch_instr = self.builder.buildSwitch(operand, invalid_block, @intCast(c_uint, names.len)); |
| 8782 | 8841 | ||
| 8783 | for (names) |name| { | 8842 | for (names) |name| { |
| 8784 | const err_int = self.dg.module.global_error_set.get(name).?; | 8843 | const err_int = mod.global_error_set.get(name).?; |
| 8785 | const this_tag_int_value = int: { | 8844 | const this_tag_int_value = int: { |
| 8786 | var tag_val_payload: Value.Payload.U64 = .{ | 8845 | var tag_val_payload: Value.Payload.U64 = .{ |
| 8787 | .base = .{ .tag = .int_u64 }, | 8846 | .base = .{ .tag = .int_u64 }, |
| ... | @@ -8841,8 +8900,7 @@ pub const FuncGen = struct { | ... | @@ -8841,8 +8900,7 @@ pub const FuncGen = struct { |
| 8841 | defer self.gpa.free(fqn); | 8900 | defer self.gpa.free(fqn); |
| 8842 | const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{fqn}); | 8901 | const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{fqn}); |
| 8843 | 8902 | ||
| 8844 | var int_tag_type_buffer: Type.Payload.Bits = undefined; | 8903 | const int_tag_ty = enum_ty.intTagType(); |
| 8845 | const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer); | ||
| 8846 | const param_types = [_]*llvm.Type{try self.dg.lowerType(int_tag_ty)}; | 8904 | const param_types = [_]*llvm.Type{try self.dg.lowerType(int_tag_ty)}; |
| 8847 | 8905 | ||
| 8848 | const llvm_ret_ty = try self.dg.lowerType(Type.bool); | 8906 | const llvm_ret_ty = try self.dg.lowerType(Type.bool); |
| ... | @@ -8923,11 +8981,9 @@ pub const FuncGen = struct { | ... | @@ -8923,11 +8981,9 @@ pub const FuncGen = struct { |
| 8923 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); | 8981 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 8924 | const llvm_ret_ty = try self.dg.lowerType(slice_ty); | 8982 | const llvm_ret_ty = try self.dg.lowerType(slice_ty); |
| 8925 | const usize_llvm_ty = try self.dg.lowerType(Type.usize); | 8983 | const usize_llvm_ty = try self.dg.lowerType(Type.usize); |
| 8926 | const target = self.dg.module.getTarget(); | 8984 | const slice_alignment = slice_ty.abiAlignment(mod); |
| 8927 | const slice_alignment = slice_ty.abiAlignment(target); | ||
| 8928 | 8985 | ||
| 8929 | var int_tag_type_buffer: Type.Payload.Bits = undefined; | 8986 | const int_tag_ty = enum_ty.intTagType(); |
| 8930 | const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer); | ||
| 8931 | const param_types = [_]*llvm.Type{try self.dg.lowerType(int_tag_ty)}; | 8987 | const param_types = [_]*llvm.Type{try self.dg.lowerType(int_tag_ty)}; |
| 8932 | 8988 | ||
| 8933 | const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False); | 8989 | const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False); |
| ... | @@ -9057,6 +9113,7 @@ pub const FuncGen = struct { | ... | @@ -9057,6 +9113,7 @@ pub const FuncGen = struct { |
| 9057 | } | 9113 | } |
| 9058 | 9114 | ||
| 9059 | fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 9115 | fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 9116 | const mod = self.dg.module; | ||
| 9060 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 9117 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 9061 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; | 9118 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; |
| 9062 | const a = try self.resolveInst(extra.a); | 9119 | const a = try self.resolveInst(extra.a); |
| ... | @@ -9077,11 +9134,11 @@ pub const FuncGen = struct { | ... | @@ -9077,11 +9134,11 @@ pub const FuncGen = struct { |
| 9077 | 9134 | ||
| 9078 | for (values, 0..) |*val, i| { | 9135 | for (values, 0..) |*val, i| { |
| 9079 | var buf: Value.ElemValueBuffer = undefined; | 9136 | var buf: Value.ElemValueBuffer = undefined; |
| 9080 | const elem = mask.elemValueBuffer(self.dg.module, i, &buf); | 9137 | const elem = mask.elemValueBuffer(mod, i, &buf); |
| 9081 | if (elem.isUndef()) { | 9138 | if (elem.isUndef()) { |
| 9082 | val.* = llvm_i32.getUndef(); | 9139 | val.* = llvm_i32.getUndef(); |
| 9083 | } else { | 9140 | } else { |
| 9084 | const int = elem.toSignedInt(self.dg.module.getTarget()); | 9141 | const int = elem.toSignedInt(mod); |
| 9085 | const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len); | 9142 | const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len); |
| 9086 | val.* = llvm_i32.constInt(unsigned, .False); | 9143 | val.* = llvm_i32.constInt(unsigned, .False); |
| 9087 | } | 9144 | } |
| ... | @@ -9157,7 +9214,8 @@ pub const FuncGen = struct { | ... | @@ -9157,7 +9214,8 @@ pub const FuncGen = struct { |
| 9157 | 9214 | ||
| 9158 | fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { | 9215 | fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { |
| 9159 | self.builder.setFastMath(want_fast_math); | 9216 | self.builder.setFastMath(want_fast_math); |
| 9160 | const target = self.dg.module.getTarget(); | 9217 | const mod = self.dg.module; |
| 9218 | const target = mod.getTarget(); | ||
| 9161 | 9219 | ||
| 9162 | const reduce = self.air.instructions.items(.data)[inst].reduce; | 9220 | const reduce = self.air.instructions.items(.data)[inst].reduce; |
| 9163 | const operand = try self.resolveInst(reduce.operand); | 9221 | const operand = try self.resolveInst(reduce.operand); |
| ... | @@ -9168,21 +9226,21 @@ pub const FuncGen = struct { | ... | @@ -9168,21 +9226,21 @@ pub const FuncGen = struct { |
| 9168 | .And => return self.builder.buildAndReduce(operand), | 9226 | .And => return self.builder.buildAndReduce(operand), |
| 9169 | .Or => return self.builder.buildOrReduce(operand), | 9227 | .Or => return self.builder.buildOrReduce(operand), |
| 9170 | .Xor => return self.builder.buildXorReduce(operand), | 9228 | .Xor => return self.builder.buildXorReduce(operand), |
| 9171 | .Min => switch (scalar_ty.zigTypeTag()) { | 9229 | .Min => switch (scalar_ty.zigTypeTag(mod)) { |
| 9172 | .Int => return self.builder.buildIntMinReduce(operand, scalar_ty.isSignedInt()), | 9230 | .Int => return self.builder.buildIntMinReduce(operand, scalar_ty.isSignedInt(mod)), |
| 9173 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { | 9231 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { |
| 9174 | return self.builder.buildFPMinReduce(operand); | 9232 | return self.builder.buildFPMinReduce(operand); |
| 9175 | }, | 9233 | }, |
| 9176 | else => unreachable, | 9234 | else => unreachable, |
| 9177 | }, | 9235 | }, |
| 9178 | .Max => switch (scalar_ty.zigTypeTag()) { | 9236 | .Max => switch (scalar_ty.zigTypeTag(mod)) { |
| 9179 | .Int => return self.builder.buildIntMaxReduce(operand, scalar_ty.isSignedInt()), | 9237 | .Int => return self.builder.buildIntMaxReduce(operand, scalar_ty.isSignedInt(mod)), |
| 9180 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { | 9238 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { |
| 9181 | return self.builder.buildFPMaxReduce(operand); | 9239 | return self.builder.buildFPMaxReduce(operand); |
| 9182 | }, | 9240 | }, |
| 9183 | else => unreachable, | 9241 | else => unreachable, |
| 9184 | }, | 9242 | }, |
| 9185 | .Add => switch (scalar_ty.zigTypeTag()) { | 9243 | .Add => switch (scalar_ty.zigTypeTag(mod)) { |
| 9186 | .Int => return self.builder.buildAddReduce(operand), | 9244 | .Int => return self.builder.buildAddReduce(operand), |
| 9187 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { | 9245 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { |
| 9188 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); | 9246 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); |
| ... | @@ -9191,7 +9249,7 @@ pub const FuncGen = struct { | ... | @@ -9191,7 +9249,7 @@ pub const FuncGen = struct { |
| 9191 | }, | 9249 | }, |
| 9192 | else => unreachable, | 9250 | else => unreachable, |
| 9193 | }, | 9251 | }, |
| 9194 | .Mul => switch (scalar_ty.zigTypeTag()) { | 9252 | .Mul => switch (scalar_ty.zigTypeTag(mod)) { |
| 9195 | .Int => return self.builder.buildMulReduce(operand), | 9253 | .Int => return self.builder.buildMulReduce(operand), |
| 9196 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { | 9254 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { |
| 9197 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); | 9255 | const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); |
| ... | @@ -9247,9 +9305,9 @@ pub const FuncGen = struct { | ... | @@ -9247,9 +9305,9 @@ pub const FuncGen = struct { |
| 9247 | const len = @intCast(usize, result_ty.arrayLen()); | 9305 | const len = @intCast(usize, result_ty.arrayLen()); |
| 9248 | const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); | 9306 | const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); |
| 9249 | const llvm_result_ty = try self.dg.lowerType(result_ty); | 9307 | const llvm_result_ty = try self.dg.lowerType(result_ty); |
| 9250 | const target = self.dg.module.getTarget(); | 9308 | const mod = self.dg.module; |
| 9251 | 9309 | ||
| 9252 | switch (result_ty.zigTypeTag()) { | 9310 | switch (result_ty.zigTypeTag(mod)) { |
| 9253 | .Vector => { | 9311 | .Vector => { |
| 9254 | const llvm_u32 = self.context.intType(32); | 9312 | const llvm_u32 = self.context.intType(32); |
| 9255 | 9313 | ||
| ... | @@ -9265,7 +9323,7 @@ pub const FuncGen = struct { | ... | @@ -9265,7 +9323,7 @@ pub const FuncGen = struct { |
| 9265 | if (result_ty.containerLayout() == .Packed) { | 9323 | if (result_ty.containerLayout() == .Packed) { |
| 9266 | const struct_obj = result_ty.castTag(.@"struct").?.data; | 9324 | const struct_obj = result_ty.castTag(.@"struct").?.data; |
| 9267 | assert(struct_obj.haveLayout()); | 9325 | assert(struct_obj.haveLayout()); |
| 9268 | const big_bits = struct_obj.backing_int_ty.bitSize(target); | 9326 | const big_bits = struct_obj.backing_int_ty.bitSize(mod); |
| 9269 | const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits)); | 9327 | const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits)); |
| 9270 | const fields = struct_obj.fields.values(); | 9328 | const fields = struct_obj.fields.values(); |
| 9271 | comptime assert(Type.packed_struct_layout_version == 2); | 9329 | comptime assert(Type.packed_struct_layout_version == 2); |
| ... | @@ -9273,12 +9331,12 @@ pub const FuncGen = struct { | ... | @@ -9273,12 +9331,12 @@ pub const FuncGen = struct { |
| 9273 | var running_bits: u16 = 0; | 9331 | var running_bits: u16 = 0; |
| 9274 | for (elements, 0..) |elem, i| { | 9332 | for (elements, 0..) |elem, i| { |
| 9275 | const field = fields[i]; | 9333 | const field = fields[i]; |
| 9276 | if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue; | 9334 | if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 9277 | 9335 | ||
| 9278 | const non_int_val = try self.resolveInst(elem); | 9336 | const non_int_val = try self.resolveInst(elem); |
| 9279 | const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); | 9337 | const ty_bit_size = @intCast(u16, field.ty.bitSize(mod)); |
| 9280 | const small_int_ty = self.context.intType(ty_bit_size); | 9338 | const small_int_ty = self.context.intType(ty_bit_size); |
| 9281 | const small_int_val = if (field.ty.isPtrAtRuntime()) | 9339 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) |
| 9282 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") | 9340 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") |
| 9283 | else | 9341 | else |
| 9284 | self.builder.buildBitCast(non_int_val, small_int_ty, ""); | 9342 | self.builder.buildBitCast(non_int_val, small_int_ty, ""); |
| ... | @@ -9296,24 +9354,24 @@ pub const FuncGen = struct { | ... | @@ -9296,24 +9354,24 @@ pub const FuncGen = struct { |
| 9296 | 9354 | ||
| 9297 | var ptr_ty_buf: Type.Payload.Pointer = undefined; | 9355 | var ptr_ty_buf: Type.Payload.Pointer = undefined; |
| 9298 | 9356 | ||
| 9299 | if (isByRef(result_ty)) { | 9357 | if (isByRef(result_ty, mod)) { |
| 9300 | const llvm_u32 = self.context.intType(32); | 9358 | const llvm_u32 = self.context.intType(32); |
| 9301 | // TODO in debug builds init to undef so that the padding will be 0xaa | 9359 | // TODO in debug builds init to undef so that the padding will be 0xaa |
| 9302 | // even if we fully populate the fields. | 9360 | // even if we fully populate the fields. |
| 9303 | const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(target)); | 9361 | const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod)); |
| 9304 | 9362 | ||
| 9305 | var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined }; | 9363 | var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined }; |
| 9306 | for (elements, 0..) |elem, i| { | 9364 | for (elements, 0..) |elem, i| { |
| 9307 | if (result_ty.structFieldValueComptime(i) != null) continue; | 9365 | if (result_ty.structFieldValueComptime(mod, i) != null) continue; |
| 9308 | 9366 | ||
| 9309 | const llvm_elem = try self.resolveInst(elem); | 9367 | const llvm_elem = try self.resolveInst(elem); |
| 9310 | const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?; | 9368 | const llvm_i = llvmFieldIndex(result_ty, i, mod, &ptr_ty_buf).?; |
| 9311 | indices[1] = llvm_u32.constInt(llvm_i, .False); | 9369 | indices[1] = llvm_u32.constInt(llvm_i, .False); |
| 9312 | const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); | 9370 | const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); |
| 9313 | var field_ptr_payload: Type.Payload.Pointer = .{ | 9371 | var field_ptr_payload: Type.Payload.Pointer = .{ |
| 9314 | .data = .{ | 9372 | .data = .{ |
| 9315 | .pointee_type = self.air.typeOf(elem), | 9373 | .pointee_type = self.air.typeOf(elem), |
| 9316 | .@"align" = result_ty.structFieldAlign(i, target), | 9374 | .@"align" = result_ty.structFieldAlign(i, mod), |
| 9317 | .@"addrspace" = .generic, | 9375 | .@"addrspace" = .generic, |
| 9318 | }, | 9376 | }, |
| 9319 | }; | 9377 | }; |
| ... | @@ -9325,20 +9383,20 @@ pub const FuncGen = struct { | ... | @@ -9325,20 +9383,20 @@ pub const FuncGen = struct { |
| 9325 | } else { | 9383 | } else { |
| 9326 | var result = llvm_result_ty.getUndef(); | 9384 | var result = llvm_result_ty.getUndef(); |
| 9327 | for (elements, 0..) |elem, i| { | 9385 | for (elements, 0..) |elem, i| { |
| 9328 | if (result_ty.structFieldValueComptime(i) != null) continue; | 9386 | if (result_ty.structFieldValueComptime(mod, i) != null) continue; |
| 9329 | 9387 | ||
| 9330 | const llvm_elem = try self.resolveInst(elem); | 9388 | const llvm_elem = try self.resolveInst(elem); |
| 9331 | const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?; | 9389 | const llvm_i = llvmFieldIndex(result_ty, i, mod, &ptr_ty_buf).?; |
| 9332 | result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, ""); | 9390 | result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, ""); |
| 9333 | } | 9391 | } |
| 9334 | return result; | 9392 | return result; |
| 9335 | } | 9393 | } |
| 9336 | }, | 9394 | }, |
| 9337 | .Array => { | 9395 | .Array => { |
| 9338 | assert(isByRef(result_ty)); | 9396 | assert(isByRef(result_ty, mod)); |
| 9339 | 9397 | ||
| 9340 | const llvm_usize = try self.dg.lowerType(Type.usize); | 9398 | const llvm_usize = try self.dg.lowerType(Type.usize); |
| 9341 | const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(target)); | 9399 | const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod)); |
| 9342 | 9400 | ||
| 9343 | const array_info = result_ty.arrayInfo(); | 9401 | const array_info = result_ty.arrayInfo(); |
| 9344 | var elem_ptr_payload: Type.Payload.Pointer = .{ | 9402 | var elem_ptr_payload: Type.Payload.Pointer = .{ |
| ... | @@ -9379,22 +9437,22 @@ pub const FuncGen = struct { | ... | @@ -9379,22 +9437,22 @@ pub const FuncGen = struct { |
| 9379 | } | 9437 | } |
| 9380 | 9438 | ||
| 9381 | fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 9439 | fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 9440 | const mod = self.dg.module; | ||
| 9382 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 9441 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 9383 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; | 9442 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 9384 | const union_ty = self.air.typeOfIndex(inst); | 9443 | const union_ty = self.air.typeOfIndex(inst); |
| 9385 | const union_llvm_ty = try self.dg.lowerType(union_ty); | 9444 | const union_llvm_ty = try self.dg.lowerType(union_ty); |
| 9386 | const target = self.dg.module.getTarget(); | 9445 | const layout = union_ty.unionGetLayout(mod); |
| 9387 | const layout = union_ty.unionGetLayout(target); | ||
| 9388 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | 9446 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 9389 | 9447 | ||
| 9390 | if (union_obj.layout == .Packed) { | 9448 | if (union_obj.layout == .Packed) { |
| 9391 | const big_bits = union_ty.bitSize(target); | 9449 | const big_bits = union_ty.bitSize(mod); |
| 9392 | const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits)); | 9450 | const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits)); |
| 9393 | const field = union_obj.fields.values()[extra.field_index]; | 9451 | const field = union_obj.fields.values()[extra.field_index]; |
| 9394 | const non_int_val = try self.resolveInst(extra.init); | 9452 | const non_int_val = try self.resolveInst(extra.init); |
| 9395 | const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); | 9453 | const ty_bit_size = @intCast(u16, field.ty.bitSize(mod)); |
| 9396 | const small_int_ty = self.context.intType(ty_bit_size); | 9454 | const small_int_ty = self.context.intType(ty_bit_size); |
| 9397 | const small_int_val = if (field.ty.isPtrAtRuntime()) | 9455 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) |
| 9398 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") | 9456 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") |
| 9399 | else | 9457 | else |
| 9400 | self.builder.buildBitCast(non_int_val, small_int_ty, ""); | 9458 | self.builder.buildBitCast(non_int_val, small_int_ty, ""); |
| ... | @@ -9412,16 +9470,16 @@ pub const FuncGen = struct { | ... | @@ -9412,16 +9470,16 @@ pub const FuncGen = struct { |
| 9412 | const tag_val = Value.initPayload(&tag_val_payload.base); | 9470 | const tag_val = Value.initPayload(&tag_val_payload.base); |
| 9413 | var int_payload: Value.Payload.U64 = undefined; | 9471 | var int_payload: Value.Payload.U64 = undefined; |
| 9414 | const tag_int_val = tag_val.enumToInt(tag_ty, &int_payload); | 9472 | const tag_int_val = tag_val.enumToInt(tag_ty, &int_payload); |
| 9415 | break :blk tag_int_val.toUnsignedInt(target); | 9473 | break :blk tag_int_val.toUnsignedInt(mod); |
| 9416 | }; | 9474 | }; |
| 9417 | if (layout.payload_size == 0) { | 9475 | if (layout.payload_size == 0) { |
| 9418 | if (layout.tag_size == 0) { | 9476 | if (layout.tag_size == 0) { |
| 9419 | return null; | 9477 | return null; |
| 9420 | } | 9478 | } |
| 9421 | assert(!isByRef(union_ty)); | 9479 | assert(!isByRef(union_ty, mod)); |
| 9422 | return union_llvm_ty.constInt(tag_int, .False); | 9480 | return union_llvm_ty.constInt(tag_int, .False); |
| 9423 | } | 9481 | } |
| 9424 | assert(isByRef(union_ty)); | 9482 | assert(isByRef(union_ty, mod)); |
| 9425 | // The llvm type of the alloca will be the named LLVM union type, and will not | 9483 | // The llvm type of the alloca will be the named LLVM union type, and will not |
| 9426 | // necessarily match the format that we need, depending on which tag is active. | 9484 | // necessarily match the format that we need, depending on which tag is active. |
| 9427 | // We must construct the correct unnamed struct type here, in order to then set | 9485 | // We must construct the correct unnamed struct type here, in order to then set |
| ... | @@ -9431,12 +9489,12 @@ pub const FuncGen = struct { | ... | @@ -9431,12 +9489,12 @@ pub const FuncGen = struct { |
| 9431 | assert(union_obj.haveFieldTypes()); | 9489 | assert(union_obj.haveFieldTypes()); |
| 9432 | const field = union_obj.fields.values()[extra.field_index]; | 9490 | const field = union_obj.fields.values()[extra.field_index]; |
| 9433 | const field_llvm_ty = try self.dg.lowerType(field.ty); | 9491 | const field_llvm_ty = try self.dg.lowerType(field.ty); |
| 9434 | const field_size = field.ty.abiSize(target); | 9492 | const field_size = field.ty.abiSize(mod); |
| 9435 | const field_align = field.normalAlignment(target); | 9493 | const field_align = field.normalAlignment(mod); |
| 9436 | 9494 | ||
| 9437 | const llvm_union_ty = t: { | 9495 | const llvm_union_ty = t: { |
| 9438 | const payload = p: { | 9496 | const payload = p: { |
| 9439 | if (!field.ty.hasRuntimeBitsIgnoreComptime()) { | 9497 | if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 9440 | const padding_len = @intCast(c_uint, layout.payload_size); | 9498 | const padding_len = @intCast(c_uint, layout.payload_size); |
| 9441 | break :p self.context.intType(8).arrayType(padding_len); | 9499 | break :p self.context.intType(8).arrayType(padding_len); |
| 9442 | } | 9500 | } |
| ... | @@ -9511,7 +9569,7 @@ pub const FuncGen = struct { | ... | @@ -9511,7 +9569,7 @@ pub const FuncGen = struct { |
| 9511 | const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); | 9569 | const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); |
| 9512 | const llvm_tag = tag_llvm_ty.constInt(tag_int, .False); | 9570 | const llvm_tag = tag_llvm_ty.constInt(tag_int, .False); |
| 9513 | const store_inst = self.builder.buildStore(llvm_tag, field_ptr); | 9571 | const store_inst = self.builder.buildStore(llvm_tag, field_ptr); |
| 9514 | store_inst.setAlignment(union_obj.tag_ty.abiAlignment(target)); | 9572 | store_inst.setAlignment(union_obj.tag_ty.abiAlignment(mod)); |
| 9515 | } | 9573 | } |
| 9516 | 9574 | ||
| 9517 | return result_ptr; | 9575 | return result_ptr; |
| ... | @@ -9535,7 +9593,8 @@ pub const FuncGen = struct { | ... | @@ -9535,7 +9593,8 @@ pub const FuncGen = struct { |
| 9535 | // by the target. | 9593 | // by the target. |
| 9536 | // To work around this, don't emit llvm.prefetch in this case. | 9594 | // To work around this, don't emit llvm.prefetch in this case. |
| 9537 | // See https://bugs.llvm.org/show_bug.cgi?id=21037 | 9595 | // See https://bugs.llvm.org/show_bug.cgi?id=21037 |
| 9538 | const target = self.dg.module.getTarget(); | 9596 | const mod = self.dg.module; |
| 9597 | const target = mod.getTarget(); | ||
| 9539 | switch (prefetch.cache) { | 9598 | switch (prefetch.cache) { |
| 9540 | .instruction => switch (target.cpu.arch) { | 9599 | .instruction => switch (target.cpu.arch) { |
| 9541 | .x86_64, | 9600 | .x86_64, |
| ... | @@ -9658,8 +9717,9 @@ pub const FuncGen = struct { | ... | @@ -9658,8 +9717,9 @@ pub const FuncGen = struct { |
| 9658 | return table; | 9717 | return table; |
| 9659 | } | 9718 | } |
| 9660 | 9719 | ||
| 9720 | const mod = self.dg.module; | ||
| 9661 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); | 9721 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 9662 | const slice_alignment = slice_ty.abiAlignment(self.dg.module.getTarget()); | 9722 | const slice_alignment = slice_ty.abiAlignment(mod); |
| 9663 | const llvm_slice_ptr_ty = self.context.pointerType(0); // TODO: Address space | 9723 | const llvm_slice_ptr_ty = self.context.pointerType(0); // TODO: Address space |
| 9664 | 9724 | ||
| 9665 | const error_name_table_global = self.dg.object.llvm_module.addGlobal(llvm_slice_ptr_ty, "__zig_err_name_table"); | 9725 | const error_name_table_global = self.dg.object.llvm_module.addGlobal(llvm_slice_ptr_ty, "__zig_err_name_table"); |
| ... | @@ -9703,14 +9763,14 @@ pub const FuncGen = struct { | ... | @@ -9703,14 +9763,14 @@ pub const FuncGen = struct { |
| 9703 | ) !*llvm.Value { | 9763 | ) !*llvm.Value { |
| 9704 | var buf: Type.Payload.ElemType = undefined; | 9764 | var buf: Type.Payload.ElemType = undefined; |
| 9705 | const payload_ty = opt_ty.optionalChild(&buf); | 9765 | const payload_ty = opt_ty.optionalChild(&buf); |
| 9766 | const mod = fg.dg.module; | ||
| 9706 | 9767 | ||
| 9707 | if (isByRef(opt_ty)) { | 9768 | if (isByRef(opt_ty, mod)) { |
| 9708 | // We have a pointer and we need to return a pointer to the first field. | 9769 | // We have a pointer and we need to return a pointer to the first field. |
| 9709 | const payload_ptr = fg.builder.buildStructGEP(opt_llvm_ty, opt_handle, 0, ""); | 9770 | const payload_ptr = fg.builder.buildStructGEP(opt_llvm_ty, opt_handle, 0, ""); |
| 9710 | 9771 | ||
| 9711 | const target = fg.dg.module.getTarget(); | 9772 | const payload_alignment = payload_ty.abiAlignment(mod); |
| 9712 | const payload_alignment = payload_ty.abiAlignment(target); | 9773 | if (isByRef(payload_ty, mod)) { |
| 9713 | if (isByRef(payload_ty)) { | ||
| 9714 | if (can_elide_load) | 9774 | if (can_elide_load) |
| 9715 | return payload_ptr; | 9775 | return payload_ptr; |
| 9716 | 9776 | ||
| ... | @@ -9722,7 +9782,7 @@ pub const FuncGen = struct { | ... | @@ -9722,7 +9782,7 @@ pub const FuncGen = struct { |
| 9722 | return load_inst; | 9782 | return load_inst; |
| 9723 | } | 9783 | } |
| 9724 | 9784 | ||
| 9725 | assert(!isByRef(payload_ty)); | 9785 | assert(!isByRef(payload_ty, mod)); |
| 9726 | return fg.builder.buildExtractValue(opt_handle, 0, ""); | 9786 | return fg.builder.buildExtractValue(opt_handle, 0, ""); |
| 9727 | } | 9787 | } |
| 9728 | 9788 | ||
| ... | @@ -9734,10 +9794,10 @@ pub const FuncGen = struct { | ... | @@ -9734,10 +9794,10 @@ pub const FuncGen = struct { |
| 9734 | ) !?*llvm.Value { | 9794 | ) !?*llvm.Value { |
| 9735 | const optional_llvm_ty = try self.dg.lowerType(optional_ty); | 9795 | const optional_llvm_ty = try self.dg.lowerType(optional_ty); |
| 9736 | const non_null_field = self.builder.buildZExt(non_null_bit, self.context.intType(8), ""); | 9796 | const non_null_field = self.builder.buildZExt(non_null_bit, self.context.intType(8), ""); |
| 9797 | const mod = self.dg.module; | ||
| 9737 | 9798 | ||
| 9738 | if (isByRef(optional_ty)) { | 9799 | if (isByRef(optional_ty, mod)) { |
| 9739 | const target = self.dg.module.getTarget(); | 9800 | const payload_alignment = optional_ty.abiAlignment(mod); |
| 9740 | const payload_alignment = optional_ty.abiAlignment(target); | ||
| 9741 | const alloca_inst = self.buildAlloca(optional_llvm_ty, payload_alignment); | 9801 | const alloca_inst = self.buildAlloca(optional_llvm_ty, payload_alignment); |
| 9742 | 9802 | ||
| 9743 | { | 9803 | { |
| ... | @@ -9765,9 +9825,9 @@ pub const FuncGen = struct { | ... | @@ -9765,9 +9825,9 @@ pub const FuncGen = struct { |
| 9765 | struct_ptr_ty: Type, | 9825 | struct_ptr_ty: Type, |
| 9766 | field_index: u32, | 9826 | field_index: u32, |
| 9767 | ) !?*llvm.Value { | 9827 | ) !?*llvm.Value { |
| 9768 | const target = self.dg.object.target; | ||
| 9769 | const struct_ty = struct_ptr_ty.childType(); | 9828 | const struct_ty = struct_ptr_ty.childType(); |
| 9770 | switch (struct_ty.zigTypeTag()) { | 9829 | const mod = self.dg.module; |
| 9830 | switch (struct_ty.zigTypeTag(mod)) { | ||
| 9771 | .Struct => switch (struct_ty.containerLayout()) { | 9831 | .Struct => switch (struct_ty.containerLayout()) { |
| 9772 | .Packed => { | 9832 | .Packed => { |
| 9773 | const result_ty = self.air.typeOfIndex(inst); | 9833 | const result_ty = self.air.typeOfIndex(inst); |
| ... | @@ -9783,7 +9843,7 @@ pub const FuncGen = struct { | ... | @@ -9783,7 +9843,7 @@ pub const FuncGen = struct { |
| 9783 | 9843 | ||
| 9784 | // We have a pointer to a packed struct field that happens to be byte-aligned. | 9844 | // We have a pointer to a packed struct field that happens to be byte-aligned. |
| 9785 | // Offset our operand pointer by the correct number of bytes. | 9845 | // Offset our operand pointer by the correct number of bytes. |
| 9786 | const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, target); | 9846 | const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, mod); |
| 9787 | if (byte_offset == 0) return struct_ptr; | 9847 | if (byte_offset == 0) return struct_ptr; |
| 9788 | const byte_llvm_ty = self.context.intType(8); | 9848 | const byte_llvm_ty = self.context.intType(8); |
| 9789 | const llvm_usize = try self.dg.lowerType(Type.usize); | 9849 | const llvm_usize = try self.dg.lowerType(Type.usize); |
| ... | @@ -9795,7 +9855,7 @@ pub const FuncGen = struct { | ... | @@ -9795,7 +9855,7 @@ pub const FuncGen = struct { |
| 9795 | const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty); | 9855 | const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty); |
| 9796 | 9856 | ||
| 9797 | var ty_buf: Type.Payload.Pointer = undefined; | 9857 | var ty_buf: Type.Payload.Pointer = undefined; |
| 9798 | if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| { | 9858 | if (llvmFieldIndex(struct_ty, field_index, mod, &ty_buf)) |llvm_field_index| { |
| 9799 | return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field_index, ""); | 9859 | return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field_index, ""); |
| 9800 | } else { | 9860 | } else { |
| 9801 | // If we found no index then this means this is a zero sized field at the | 9861 | // If we found no index then this means this is a zero sized field at the |
| ... | @@ -9803,14 +9863,14 @@ pub const FuncGen = struct { | ... | @@ -9803,14 +9863,14 @@ pub const FuncGen = struct { |
| 9803 | // the index to the element at index `1` to get a pointer to the end of | 9863 | // the index to the element at index `1` to get a pointer to the end of |
| 9804 | // the struct. | 9864 | // the struct. |
| 9805 | const llvm_u32 = self.context.intType(32); | 9865 | const llvm_u32 = self.context.intType(32); |
| 9806 | const llvm_index = llvm_u32.constInt(@boolToInt(struct_ty.hasRuntimeBitsIgnoreComptime()), .False); | 9866 | const llvm_index = llvm_u32.constInt(@boolToInt(struct_ty.hasRuntimeBitsIgnoreComptime(mod)), .False); |
| 9807 | const indices: [1]*llvm.Value = .{llvm_index}; | 9867 | const indices: [1]*llvm.Value = .{llvm_index}; |
| 9808 | return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, ""); | 9868 | return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, ""); |
| 9809 | } | 9869 | } |
| 9810 | }, | 9870 | }, |
| 9811 | }, | 9871 | }, |
| 9812 | .Union => { | 9872 | .Union => { |
| 9813 | const layout = struct_ty.unionGetLayout(target); | 9873 | const layout = struct_ty.unionGetLayout(mod); |
| 9814 | if (layout.payload_size == 0 or struct_ty.containerLayout() == .Packed) return struct_ptr; | 9874 | if (layout.payload_size == 0 or struct_ty.containerLayout() == .Packed) return struct_ptr; |
| 9815 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); | 9875 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); |
| 9816 | const union_llvm_ty = try self.dg.lowerType(struct_ty); | 9876 | const union_llvm_ty = try self.dg.lowerType(struct_ty); |
| ... | @@ -9835,12 +9895,12 @@ pub const FuncGen = struct { | ... | @@ -9835,12 +9895,12 @@ pub const FuncGen = struct { |
| 9835 | ptr_alignment: u32, | 9895 | ptr_alignment: u32, |
| 9836 | is_volatile: bool, | 9896 | is_volatile: bool, |
| 9837 | ) !*llvm.Value { | 9897 | ) !*llvm.Value { |
| 9898 | const mod = fg.dg.module; | ||
| 9838 | const pointee_llvm_ty = try fg.dg.lowerType(pointee_type); | 9899 | const pointee_llvm_ty = try fg.dg.lowerType(pointee_type); |
| 9839 | const target = fg.dg.module.getTarget(); | 9900 | const result_align = @max(ptr_alignment, pointee_type.abiAlignment(mod)); |
| 9840 | const result_align = @max(ptr_alignment, pointee_type.abiAlignment(target)); | ||
| 9841 | const result_ptr = fg.buildAlloca(pointee_llvm_ty, result_align); | 9901 | const result_ptr = fg.buildAlloca(pointee_llvm_ty, result_align); |
| 9842 | const llvm_usize = fg.context.intType(Type.usize.intInfo(target).bits); | 9902 | const llvm_usize = fg.context.intType(Type.usize.intInfo(mod).bits); |
| 9843 | const size_bytes = pointee_type.abiSize(target); | 9903 | const size_bytes = pointee_type.abiSize(mod); |
| 9844 | _ = fg.builder.buildMemCpy( | 9904 | _ = fg.builder.buildMemCpy( |
| 9845 | result_ptr, | 9905 | result_ptr, |
| 9846 | result_align, | 9906 | result_align, |
| ... | @@ -9856,11 +9916,11 @@ pub const FuncGen = struct { | ... | @@ -9856,11 +9916,11 @@ pub const FuncGen = struct { |
| 9856 | /// alloca and copies the value into it, then returns the alloca instruction. | 9916 | /// alloca and copies the value into it, then returns the alloca instruction. |
| 9857 | /// For isByRef=false types, it creates a load instruction and returns it. | 9917 | /// For isByRef=false types, it creates a load instruction and returns it. |
| 9858 | fn load(self: *FuncGen, ptr: *llvm.Value, ptr_ty: Type) !?*llvm.Value { | 9918 | fn load(self: *FuncGen, ptr: *llvm.Value, ptr_ty: Type) !?*llvm.Value { |
| 9919 | const mod = self.dg.module; | ||
| 9859 | const info = ptr_ty.ptrInfo().data; | 9920 | const info = ptr_ty.ptrInfo().data; |
| 9860 | if (!info.pointee_type.hasRuntimeBitsIgnoreComptime()) return null; | 9921 | if (!info.pointee_type.hasRuntimeBitsIgnoreComptime(mod)) return null; |
| 9861 | 9922 | ||
| 9862 | const target = self.dg.module.getTarget(); | 9923 | const ptr_alignment = info.alignment(mod); |
| 9863 | const ptr_alignment = info.alignment(target); | ||
| 9864 | const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr()); | 9924 | const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr()); |
| 9865 | 9925 | ||
| 9866 | assert(info.vector_index != .runtime); | 9926 | assert(info.vector_index != .runtime); |
| ... | @@ -9877,7 +9937,7 @@ pub const FuncGen = struct { | ... | @@ -9877,7 +9937,7 @@ pub const FuncGen = struct { |
| 9877 | } | 9937 | } |
| 9878 | 9938 | ||
| 9879 | if (info.host_size == 0) { | 9939 | if (info.host_size == 0) { |
| 9880 | if (isByRef(info.pointee_type)) { | 9940 | if (isByRef(info.pointee_type, mod)) { |
| 9881 | return self.loadByRef(ptr, info.pointee_type, ptr_alignment, info.@"volatile"); | 9941 | return self.loadByRef(ptr, info.pointee_type, ptr_alignment, info.@"volatile"); |
| 9882 | } | 9942 | } |
| 9883 | const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); | 9943 | const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); |
| ... | @@ -9892,13 +9952,13 @@ pub const FuncGen = struct { | ... | @@ -9892,13 +9952,13 @@ pub const FuncGen = struct { |
| 9892 | containing_int.setAlignment(ptr_alignment); | 9952 | containing_int.setAlignment(ptr_alignment); |
| 9893 | containing_int.setVolatile(ptr_volatile); | 9953 | containing_int.setVolatile(ptr_volatile); |
| 9894 | 9954 | ||
| 9895 | const elem_bits = @intCast(c_uint, ptr_ty.elemType().bitSize(target)); | 9955 | const elem_bits = @intCast(c_uint, ptr_ty.elemType().bitSize(mod)); |
| 9896 | const shift_amt = containing_int.typeOf().constInt(info.bit_offset, .False); | 9956 | const shift_amt = containing_int.typeOf().constInt(info.bit_offset, .False); |
| 9897 | const shifted_value = self.builder.buildLShr(containing_int, shift_amt, ""); | 9957 | const shifted_value = self.builder.buildLShr(containing_int, shift_amt, ""); |
| 9898 | const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); | 9958 | const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); |
| 9899 | 9959 | ||
| 9900 | if (isByRef(info.pointee_type)) { | 9960 | if (isByRef(info.pointee_type, mod)) { |
| 9901 | const result_align = info.pointee_type.abiAlignment(target); | 9961 | const result_align = info.pointee_type.abiAlignment(mod); |
| 9902 | const result_ptr = self.buildAlloca(elem_llvm_ty, result_align); | 9962 | const result_ptr = self.buildAlloca(elem_llvm_ty, result_align); |
| 9903 | 9963 | ||
| 9904 | const same_size_int = self.context.intType(elem_bits); | 9964 | const same_size_int = self.context.intType(elem_bits); |
| ... | @@ -9908,13 +9968,13 @@ pub const FuncGen = struct { | ... | @@ -9908,13 +9968,13 @@ pub const FuncGen = struct { |
| 9908 | return result_ptr; | 9968 | return result_ptr; |
| 9909 | } | 9969 | } |
| 9910 | 9970 | ||
| 9911 | if (info.pointee_type.zigTypeTag() == .Float or info.pointee_type.zigTypeTag() == .Vector) { | 9971 | if (info.pointee_type.zigTypeTag(mod) == .Float or info.pointee_type.zigTypeTag(mod) == .Vector) { |
| 9912 | const same_size_int = self.context.intType(elem_bits); | 9972 | const same_size_int = self.context.intType(elem_bits); |
| 9913 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 9973 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 9914 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); | 9974 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 9915 | } | 9975 | } |
| 9916 | 9976 | ||
| 9917 | if (info.pointee_type.isPtrAtRuntime()) { | 9977 | if (info.pointee_type.isPtrAtRuntime(mod)) { |
| 9918 | const same_size_int = self.context.intType(elem_bits); | 9978 | const same_size_int = self.context.intType(elem_bits); |
| 9919 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 9979 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 9920 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); | 9980 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| ... | @@ -9932,11 +9992,11 @@ pub const FuncGen = struct { | ... | @@ -9932,11 +9992,11 @@ pub const FuncGen = struct { |
| 9932 | ) !void { | 9992 | ) !void { |
| 9933 | const info = ptr_ty.ptrInfo().data; | 9993 | const info = ptr_ty.ptrInfo().data; |
| 9934 | const elem_ty = info.pointee_type; | 9994 | const elem_ty = info.pointee_type; |
| 9935 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) { | 9995 | const mod = self.dg.module; |
| 9996 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) { | ||
| 9936 | return; | 9997 | return; |
| 9937 | } | 9998 | } |
| 9938 | const target = self.dg.module.getTarget(); | 9999 | const ptr_alignment = ptr_ty.ptrAlignment(mod); |
| 9939 | const ptr_alignment = ptr_ty.ptrAlignment(target); | ||
| 9940 | const ptr_volatile = llvm.Bool.fromBool(info.@"volatile"); | 10000 | const ptr_volatile = llvm.Bool.fromBool(info.@"volatile"); |
| 9941 | 10001 | ||
| 9942 | assert(info.vector_index != .runtime); | 10002 | assert(info.vector_index != .runtime); |
| ... | @@ -9964,13 +10024,13 @@ pub const FuncGen = struct { | ... | @@ -9964,13 +10024,13 @@ pub const FuncGen = struct { |
| 9964 | assert(ordering == .NotAtomic); | 10024 | assert(ordering == .NotAtomic); |
| 9965 | containing_int.setAlignment(ptr_alignment); | 10025 | containing_int.setAlignment(ptr_alignment); |
| 9966 | containing_int.setVolatile(ptr_volatile); | 10026 | containing_int.setVolatile(ptr_volatile); |
| 9967 | const elem_bits = @intCast(c_uint, ptr_ty.elemType().bitSize(target)); | 10027 | const elem_bits = @intCast(c_uint, ptr_ty.elemType().bitSize(mod)); |
| 9968 | const containing_int_ty = containing_int.typeOf(); | 10028 | const containing_int_ty = containing_int.typeOf(); |
| 9969 | const shift_amt = containing_int_ty.constInt(info.bit_offset, .False); | 10029 | const shift_amt = containing_int_ty.constInt(info.bit_offset, .False); |
| 9970 | // Convert to equally-sized integer type in order to perform the bit | 10030 | // Convert to equally-sized integer type in order to perform the bit |
| 9971 | // operations on the value to store | 10031 | // operations on the value to store |
| 9972 | const value_bits_type = self.context.intType(elem_bits); | 10032 | const value_bits_type = self.context.intType(elem_bits); |
| 9973 | const value_bits = if (elem_ty.isPtrAtRuntime()) | 10033 | const value_bits = if (elem_ty.isPtrAtRuntime(mod)) |
| 9974 | self.builder.buildPtrToInt(elem, value_bits_type, "") | 10034 | self.builder.buildPtrToInt(elem, value_bits_type, "") |
| 9975 | else | 10035 | else |
| 9976 | self.builder.buildBitCast(elem, value_bits_type, ""); | 10036 | self.builder.buildBitCast(elem, value_bits_type, ""); |
| ... | @@ -9991,7 +10051,7 @@ pub const FuncGen = struct { | ... | @@ -9991,7 +10051,7 @@ pub const FuncGen = struct { |
| 9991 | store_inst.setVolatile(ptr_volatile); | 10051 | store_inst.setVolatile(ptr_volatile); |
| 9992 | return; | 10052 | return; |
| 9993 | } | 10053 | } |
| 9994 | if (!isByRef(elem_ty)) { | 10054 | if (!isByRef(elem_ty, mod)) { |
| 9995 | const store_inst = self.builder.buildStore(elem, ptr); | 10055 | const store_inst = self.builder.buildStore(elem, ptr); |
| 9996 | store_inst.setOrdering(ordering); | 10056 | store_inst.setOrdering(ordering); |
| 9997 | store_inst.setAlignment(ptr_alignment); | 10057 | store_inst.setAlignment(ptr_alignment); |
| ... | @@ -9999,13 +10059,13 @@ pub const FuncGen = struct { | ... | @@ -9999,13 +10059,13 @@ pub const FuncGen = struct { |
| 9999 | return; | 10059 | return; |
| 10000 | } | 10060 | } |
| 10001 | assert(ordering == .NotAtomic); | 10061 | assert(ordering == .NotAtomic); |
| 10002 | const size_bytes = elem_ty.abiSize(target); | 10062 | const size_bytes = elem_ty.abiSize(mod); |
| 10003 | _ = self.builder.buildMemCpy( | 10063 | _ = self.builder.buildMemCpy( |
| 10004 | ptr, | 10064 | ptr, |
| 10005 | ptr_alignment, | 10065 | ptr_alignment, |
| 10006 | elem, | 10066 | elem, |
| 10007 | elem_ty.abiAlignment(target), | 10067 | elem_ty.abiAlignment(mod), |
| 10008 | self.context.intType(Type.usize.intInfo(target).bits).constInt(size_bytes, .False), | 10068 | self.context.intType(Type.usize.intInfo(mod).bits).constInt(size_bytes, .False), |
| 10009 | info.@"volatile", | 10069 | info.@"volatile", |
| 10010 | ); | 10070 | ); |
| 10011 | } | 10071 | } |
| ... | @@ -10030,11 +10090,12 @@ pub const FuncGen = struct { | ... | @@ -10030,11 +10090,12 @@ pub const FuncGen = struct { |
| 10030 | a4: *llvm.Value, | 10090 | a4: *llvm.Value, |
| 10031 | a5: *llvm.Value, | 10091 | a5: *llvm.Value, |
| 10032 | ) *llvm.Value { | 10092 | ) *llvm.Value { |
| 10033 | const target = fg.dg.module.getTarget(); | 10093 | const mod = fg.dg.module; |
| 10094 | const target = mod.getTarget(); | ||
| 10034 | if (!target_util.hasValgrindSupport(target)) return default_value; | 10095 | if (!target_util.hasValgrindSupport(target)) return default_value; |
| 10035 | 10096 | ||
| 10036 | const usize_llvm_ty = fg.context.intType(target.ptrBitWidth()); | 10097 | const usize_llvm_ty = fg.context.intType(target.ptrBitWidth()); |
| 10037 | const usize_alignment = @intCast(c_uint, Type.usize.abiSize(target)); | 10098 | const usize_alignment = @intCast(c_uint, Type.usize.abiSize(mod)); |
| 10038 | 10099 | ||
| 10039 | const array_llvm_ty = usize_llvm_ty.arrayType(6); | 10100 | const array_llvm_ty = usize_llvm_ty.arrayType(6); |
| 10040 | const array_ptr = fg.valgrind_client_request_array orelse a: { | 10101 | const array_ptr = fg.valgrind_client_request_array orelse a: { |
| ... | @@ -10451,7 +10512,7 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.builtin.AddressSpace, targ | ... | @@ -10451,7 +10512,7 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.builtin.AddressSpace, targ |
| 10451 | fn llvmFieldIndex( | 10512 | fn llvmFieldIndex( |
| 10452 | ty: Type, | 10513 | ty: Type, |
| 10453 | field_index: usize, | 10514 | field_index: usize, |
| 10454 | target: std.Target, | 10515 | mod: *const Module, |
| 10455 | ptr_pl_buf: *Type.Payload.Pointer, | 10516 | ptr_pl_buf: *Type.Payload.Pointer, |
| 10456 | ) ?c_uint { | 10517 | ) ?c_uint { |
| 10457 | // Detects where we inserted extra padding fields so that we can skip | 10518 | // Detects where we inserted extra padding fields so that we can skip |
| ... | @@ -10464,9 +10525,9 @@ fn llvmFieldIndex( | ... | @@ -10464,9 +10525,9 @@ fn llvmFieldIndex( |
| 10464 | const tuple = ty.tupleFields(); | 10525 | const tuple = ty.tupleFields(); |
| 10465 | var llvm_field_index: c_uint = 0; | 10526 | var llvm_field_index: c_uint = 0; |
| 10466 | for (tuple.types, 0..) |field_ty, i| { | 10527 | for (tuple.types, 0..) |field_ty, i| { |
| 10467 | if (tuple.values[i].tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue; | 10528 | if (tuple.values[i].tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; |
| 10468 | 10529 | ||
| 10469 | const field_align = field_ty.abiAlignment(target); | 10530 | const field_align = field_ty.abiAlignment(mod); |
| 10470 | big_align = @max(big_align, field_align); | 10531 | big_align = @max(big_align, field_align); |
| 10471 | const prev_offset = offset; | 10532 | const prev_offset = offset; |
| 10472 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); | 10533 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| ... | @@ -10488,7 +10549,7 @@ fn llvmFieldIndex( | ... | @@ -10488,7 +10549,7 @@ fn llvmFieldIndex( |
| 10488 | } | 10549 | } |
| 10489 | 10550 | ||
| 10490 | llvm_field_index += 1; | 10551 | llvm_field_index += 1; |
| 10491 | offset += field_ty.abiSize(target); | 10552 | offset += field_ty.abiSize(mod); |
| 10492 | } | 10553 | } |
| 10493 | return null; | 10554 | return null; |
| 10494 | } | 10555 | } |
| ... | @@ -10496,10 +10557,10 @@ fn llvmFieldIndex( | ... | @@ -10496,10 +10557,10 @@ fn llvmFieldIndex( |
| 10496 | assert(layout != .Packed); | 10557 | assert(layout != .Packed); |
| 10497 | 10558 | ||
| 10498 | var llvm_field_index: c_uint = 0; | 10559 | var llvm_field_index: c_uint = 0; |
| 10499 | var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator(); | 10560 | var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator(mod); |
| 10500 | while (it.next()) |field_and_index| { | 10561 | while (it.next()) |field_and_index| { |
| 10501 | const field = field_and_index.field; | 10562 | const field = field_and_index.field; |
| 10502 | const field_align = field.alignment(target, layout); | 10563 | const field_align = field.alignment(mod, layout); |
| 10503 | big_align = @max(big_align, field_align); | 10564 | big_align = @max(big_align, field_align); |
| 10504 | const prev_offset = offset; | 10565 | const prev_offset = offset; |
| 10505 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); | 10566 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| ... | @@ -10521,43 +10582,44 @@ fn llvmFieldIndex( | ... | @@ -10521,43 +10582,44 @@ fn llvmFieldIndex( |
| 10521 | } | 10582 | } |
| 10522 | 10583 | ||
| 10523 | llvm_field_index += 1; | 10584 | llvm_field_index += 1; |
| 10524 | offset += field.ty.abiSize(target); | 10585 | offset += field.ty.abiSize(mod); |
| 10525 | } else { | 10586 | } else { |
| 10526 | // We did not find an llvm field that corresponds to this zig field. | 10587 | // We did not find an llvm field that corresponds to this zig field. |
| 10527 | return null; | 10588 | return null; |
| 10528 | } | 10589 | } |
| 10529 | } | 10590 | } |
| 10530 | 10591 | ||
| 10531 | fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool { | 10592 | fn firstParamSRet(fn_info: Type.Payload.Function.Data, mod: *const Module) bool { |
| 10532 | if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime()) return false; | 10593 | if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime(mod)) return false; |
| 10533 | 10594 | ||
| 10595 | const target = mod.getTarget(); | ||
| 10534 | switch (fn_info.cc) { | 10596 | switch (fn_info.cc) { |
| 10535 | .Unspecified, .Inline => return isByRef(fn_info.return_type), | 10597 | .Unspecified, .Inline => return isByRef(fn_info.return_type, mod), |
| 10536 | .C => switch (target.cpu.arch) { | 10598 | .C => switch (target.cpu.arch) { |
| 10537 | .mips, .mipsel => return false, | 10599 | .mips, .mipsel => return false, |
| 10538 | .x86_64 => switch (target.os.tag) { | 10600 | .x86_64 => switch (target.os.tag) { |
| 10539 | .windows => return x86_64_abi.classifyWindows(fn_info.return_type, target) == .memory, | 10601 | .windows => return x86_64_abi.classifyWindows(fn_info.return_type, mod) == .memory, |
| 10540 | else => return firstParamSRetSystemV(fn_info.return_type, target), | 10602 | else => return firstParamSRetSystemV(fn_info.return_type, mod), |
| 10541 | }, | 10603 | }, |
| 10542 | .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, target)[0] == .indirect, | 10604 | .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, mod)[0] == .indirect, |
| 10543 | .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, target) == .memory, | 10605 | .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, mod) == .memory, |
| 10544 | .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type, target, .ret)) { | 10606 | .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type, mod, .ret)) { |
| 10545 | .memory, .i64_array => return true, | 10607 | .memory, .i64_array => return true, |
| 10546 | .i32_array => |size| return size != 1, | 10608 | .i32_array => |size| return size != 1, |
| 10547 | .byval => return false, | 10609 | .byval => return false, |
| 10548 | }, | 10610 | }, |
| 10549 | .riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type, target) == .memory, | 10611 | .riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type, mod) == .memory, |
| 10550 | else => return false, // TODO investigate C ABI for other architectures | 10612 | else => return false, // TODO investigate C ABI for other architectures |
| 10551 | }, | 10613 | }, |
| 10552 | .SysV => return firstParamSRetSystemV(fn_info.return_type, target), | 10614 | .SysV => return firstParamSRetSystemV(fn_info.return_type, mod), |
| 10553 | .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type, target) == .memory, | 10615 | .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type, mod) == .memory, |
| 10554 | .Stdcall => return !isScalar(fn_info.return_type), | 10616 | .Stdcall => return !isScalar(mod, fn_info.return_type), |
| 10555 | else => return false, | 10617 | else => return false, |
| 10556 | } | 10618 | } |
| 10557 | } | 10619 | } |
| 10558 | 10620 | ||
| 10559 | fn firstParamSRetSystemV(ty: Type, target: std.Target) bool { | 10621 | fn firstParamSRetSystemV(ty: Type, mod: *const Module) bool { |
| 10560 | const class = x86_64_abi.classifySystemV(ty, target, .ret); | 10622 | const class = x86_64_abi.classifySystemV(ty, mod, .ret); |
| 10561 | if (class[0] == .memory) return true; | 10623 | if (class[0] == .memory) return true; |
| 10562 | if (class[0] == .x87 and class[2] != .none) return true; | 10624 | if (class[0] == .x87 and class[2] != .none) return true; |
| 10563 | return false; | 10625 | return false; |
| ... | @@ -10567,20 +10629,21 @@ fn firstParamSRetSystemV(ty: Type, target: std.Target) bool { | ... | @@ -10567,20 +10629,21 @@ fn firstParamSRetSystemV(ty: Type, target: std.Target) bool { |
| 10567 | /// completely differently in the function prototype to honor the C ABI, and then | 10629 | /// completely differently in the function prototype to honor the C ABI, and then |
| 10568 | /// be effectively bitcasted to the actual return type. | 10630 | /// be effectively bitcasted to the actual return type. |
| 10569 | fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { | 10631 | fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { |
| 10570 | if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime()) { | 10632 | const mod = dg.module; |
| 10633 | if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime(mod)) { | ||
| 10571 | // If the return type is an error set or an error union, then we make this | 10634 | // If the return type is an error set or an error union, then we make this |
| 10572 | // anyerror return type instead, so that it can be coerced into a function | 10635 | // anyerror return type instead, so that it can be coerced into a function |
| 10573 | // pointer type which has anyerror as the return type. | 10636 | // pointer type which has anyerror as the return type. |
| 10574 | if (fn_info.return_type.isError()) { | 10637 | if (fn_info.return_type.isError(mod)) { |
| 10575 | return dg.lowerType(Type.anyerror); | 10638 | return dg.lowerType(Type.anyerror); |
| 10576 | } else { | 10639 | } else { |
| 10577 | return dg.context.voidType(); | 10640 | return dg.context.voidType(); |
| 10578 | } | 10641 | } |
| 10579 | } | 10642 | } |
| 10580 | const target = dg.module.getTarget(); | 10643 | const target = mod.getTarget(); |
| 10581 | switch (fn_info.cc) { | 10644 | switch (fn_info.cc) { |
| 10582 | .Unspecified, .Inline => { | 10645 | .Unspecified, .Inline => { |
| 10583 | if (isByRef(fn_info.return_type)) { | 10646 | if (isByRef(fn_info.return_type, mod)) { |
| 10584 | return dg.context.voidType(); | 10647 | return dg.context.voidType(); |
| 10585 | } else { | 10648 | } else { |
| 10586 | return dg.lowerType(fn_info.return_type); | 10649 | return dg.lowerType(fn_info.return_type); |
| ... | @@ -10594,33 +10657,33 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { | ... | @@ -10594,33 +10657,33 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { |
| 10594 | else => return lowerSystemVFnRetTy(dg, fn_info), | 10657 | else => return lowerSystemVFnRetTy(dg, fn_info), |
| 10595 | }, | 10658 | }, |
| 10596 | .wasm32 => { | 10659 | .wasm32 => { |
| 10597 | if (isScalar(fn_info.return_type)) { | 10660 | if (isScalar(mod, fn_info.return_type)) { |
| 10598 | return dg.lowerType(fn_info.return_type); | 10661 | return dg.lowerType(fn_info.return_type); |
| 10599 | } | 10662 | } |
| 10600 | const classes = wasm_c_abi.classifyType(fn_info.return_type, target); | 10663 | const classes = wasm_c_abi.classifyType(fn_info.return_type, mod); |
| 10601 | if (classes[0] == .indirect or classes[0] == .none) { | 10664 | if (classes[0] == .indirect or classes[0] == .none) { |
| 10602 | return dg.context.voidType(); | 10665 | return dg.context.voidType(); |
| 10603 | } | 10666 | } |
| 10604 | 10667 | ||
| 10605 | assert(classes[0] == .direct and classes[1] == .none); | 10668 | assert(classes[0] == .direct and classes[1] == .none); |
| 10606 | const scalar_type = wasm_c_abi.scalarType(fn_info.return_type, target); | 10669 | const scalar_type = wasm_c_abi.scalarType(fn_info.return_type, mod); |
| 10607 | const abi_size = scalar_type.abiSize(target); | 10670 | const abi_size = scalar_type.abiSize(mod); |
| 10608 | return dg.context.intType(@intCast(c_uint, abi_size * 8)); | 10671 | return dg.context.intType(@intCast(c_uint, abi_size * 8)); |
| 10609 | }, | 10672 | }, |
| 10610 | .aarch64, .aarch64_be => { | 10673 | .aarch64, .aarch64_be => { |
| 10611 | switch (aarch64_c_abi.classifyType(fn_info.return_type, target)) { | 10674 | switch (aarch64_c_abi.classifyType(fn_info.return_type, mod)) { |
| 10612 | .memory => return dg.context.voidType(), | 10675 | .memory => return dg.context.voidType(), |
| 10613 | .float_array => return dg.lowerType(fn_info.return_type), | 10676 | .float_array => return dg.lowerType(fn_info.return_type), |
| 10614 | .byval => return dg.lowerType(fn_info.return_type), | 10677 | .byval => return dg.lowerType(fn_info.return_type), |
| 10615 | .integer => { | 10678 | .integer => { |
| 10616 | const bit_size = fn_info.return_type.bitSize(target); | 10679 | const bit_size = fn_info.return_type.bitSize(mod); |
| 10617 | return dg.context.intType(@intCast(c_uint, bit_size)); | 10680 | return dg.context.intType(@intCast(c_uint, bit_size)); |
| 10618 | }, | 10681 | }, |
| 10619 | .double_integer => return dg.context.intType(64).arrayType(2), | 10682 | .double_integer => return dg.context.intType(64).arrayType(2), |
| 10620 | } | 10683 | } |
| 10621 | }, | 10684 | }, |
| 10622 | .arm, .armeb => { | 10685 | .arm, .armeb => { |
| 10623 | switch (arm_c_abi.classifyType(fn_info.return_type, target, .ret)) { | 10686 | switch (arm_c_abi.classifyType(fn_info.return_type, mod, .ret)) { |
| 10624 | .memory, .i64_array => return dg.context.voidType(), | 10687 | .memory, .i64_array => return dg.context.voidType(), |
| 10625 | .i32_array => |len| if (len == 1) { | 10688 | .i32_array => |len| if (len == 1) { |
| 10626 | return dg.context.intType(32); | 10689 | return dg.context.intType(32); |
| ... | @@ -10631,10 +10694,10 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { | ... | @@ -10631,10 +10694,10 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { |
| 10631 | } | 10694 | } |
| 10632 | }, | 10695 | }, |
| 10633 | .riscv32, .riscv64 => { | 10696 | .riscv32, .riscv64 => { |
| 10634 | switch (riscv_c_abi.classifyType(fn_info.return_type, target)) { | 10697 | switch (riscv_c_abi.classifyType(fn_info.return_type, mod)) { |
| 10635 | .memory => return dg.context.voidType(), | 10698 | .memory => return dg.context.voidType(), |
| 10636 | .integer => { | 10699 | .integer => { |
| 10637 | const bit_size = fn_info.return_type.bitSize(target); | 10700 | const bit_size = fn_info.return_type.bitSize(mod); |
| 10638 | return dg.context.intType(@intCast(c_uint, bit_size)); | 10701 | return dg.context.intType(@intCast(c_uint, bit_size)); |
| 10639 | }, | 10702 | }, |
| 10640 | .double_integer => { | 10703 | .double_integer => { |
| ... | @@ -10654,7 +10717,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { | ... | @@ -10654,7 +10717,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { |
| 10654 | .Win64 => return lowerWin64FnRetTy(dg, fn_info), | 10717 | .Win64 => return lowerWin64FnRetTy(dg, fn_info), |
| 10655 | .SysV => return lowerSystemVFnRetTy(dg, fn_info), | 10718 | .SysV => return lowerSystemVFnRetTy(dg, fn_info), |
| 10656 | .Stdcall => { | 10719 | .Stdcall => { |
| 10657 | if (isScalar(fn_info.return_type)) { | 10720 | if (isScalar(mod, fn_info.return_type)) { |
| 10658 | return dg.lowerType(fn_info.return_type); | 10721 | return dg.lowerType(fn_info.return_type); |
| 10659 | } else { | 10722 | } else { |
| 10660 | return dg.context.voidType(); | 10723 | return dg.context.voidType(); |
| ... | @@ -10665,13 +10728,13 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { | ... | @@ -10665,13 +10728,13 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { |
| 10665 | } | 10728 | } |
| 10666 | 10729 | ||
| 10667 | fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { | 10730 | fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { |
| 10668 | const target = dg.module.getTarget(); | 10731 | const mod = dg.module; |
| 10669 | switch (x86_64_abi.classifyWindows(fn_info.return_type, target)) { | 10732 | switch (x86_64_abi.classifyWindows(fn_info.return_type, mod)) { |
| 10670 | .integer => { | 10733 | .integer => { |
| 10671 | if (isScalar(fn_info.return_type)) { | 10734 | if (isScalar(mod, fn_info.return_type)) { |
| 10672 | return dg.lowerType(fn_info.return_type); | 10735 | return dg.lowerType(fn_info.return_type); |
| 10673 | } else { | 10736 | } else { |
| 10674 | const abi_size = fn_info.return_type.abiSize(target); | 10737 | const abi_size = fn_info.return_type.abiSize(mod); |
| 10675 | return dg.context.intType(@intCast(c_uint, abi_size * 8)); | 10738 | return dg.context.intType(@intCast(c_uint, abi_size * 8)); |
| 10676 | } | 10739 | } |
| 10677 | }, | 10740 | }, |
| ... | @@ -10683,11 +10746,11 @@ fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.T | ... | @@ -10683,11 +10746,11 @@ fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.T |
| 10683 | } | 10746 | } |
| 10684 | 10747 | ||
| 10685 | fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { | 10748 | fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { |
| 10686 | if (isScalar(fn_info.return_type)) { | 10749 | const mod = dg.module; |
| 10750 | if (isScalar(mod, fn_info.return_type)) { | ||
| 10687 | return dg.lowerType(fn_info.return_type); | 10751 | return dg.lowerType(fn_info.return_type); |
| 10688 | } | 10752 | } |
| 10689 | const target = dg.module.getTarget(); | 10753 | const classes = x86_64_abi.classifySystemV(fn_info.return_type, mod, .ret); |
| 10690 | const classes = x86_64_abi.classifySystemV(fn_info.return_type, target, .ret); | ||
| 10691 | if (classes[0] == .memory) { | 10754 | if (classes[0] == .memory) { |
| 10692 | return dg.context.voidType(); | 10755 | return dg.context.voidType(); |
| 10693 | } | 10756 | } |
| ... | @@ -10728,7 +10791,7 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm | ... | @@ -10728,7 +10791,7 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm |
| 10728 | } | 10791 | } |
| 10729 | } | 10792 | } |
| 10730 | if (classes[0] == .integer and classes[1] == .none) { | 10793 | if (classes[0] == .integer and classes[1] == .none) { |
| 10731 | const abi_size = fn_info.return_type.abiSize(target); | 10794 | const abi_size = fn_info.return_type.abiSize(mod); |
| 10732 | return dg.context.intType(@intCast(c_uint, abi_size * 8)); | 10795 | return dg.context.intType(@intCast(c_uint, abi_size * 8)); |
| 10733 | } | 10796 | } |
| 10734 | return dg.context.structType(&llvm_types_buffer, llvm_types_index, .False); | 10797 | return dg.context.structType(&llvm_types_buffer, llvm_types_index, .False); |
| ... | @@ -10739,7 +10802,6 @@ const ParamTypeIterator = struct { | ... | @@ -10739,7 +10802,6 @@ const ParamTypeIterator = struct { |
| 10739 | fn_info: Type.Payload.Function.Data, | 10802 | fn_info: Type.Payload.Function.Data, |
| 10740 | zig_index: u32, | 10803 | zig_index: u32, |
| 10741 | llvm_index: u32, | 10804 | llvm_index: u32, |
| 10742 | target: std.Target, | ||
| 10743 | llvm_types_len: u32, | 10805 | llvm_types_len: u32, |
| 10744 | llvm_types_buffer: [8]*llvm.Type, | 10806 | llvm_types_buffer: [8]*llvm.Type, |
| 10745 | byval_attr: bool, | 10807 | byval_attr: bool, |
| ... | @@ -10779,7 +10841,10 @@ const ParamTypeIterator = struct { | ... | @@ -10779,7 +10841,10 @@ const ParamTypeIterator = struct { |
| 10779 | } | 10841 | } |
| 10780 | 10842 | ||
| 10781 | fn nextInner(it: *ParamTypeIterator, ty: Type) ?Lowering { | 10843 | fn nextInner(it: *ParamTypeIterator, ty: Type) ?Lowering { |
| 10782 | if (!ty.hasRuntimeBitsIgnoreComptime()) { | 10844 | const mod = it.dg.module; |
| 10845 | const target = mod.getTarget(); | ||
| 10846 | |||
| 10847 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) { | ||
| 10783 | it.zig_index += 1; | 10848 | it.zig_index += 1; |
| 10784 | return .no_bits; | 10849 | return .no_bits; |
| 10785 | } | 10850 | } |
| ... | @@ -10788,10 +10853,10 @@ const ParamTypeIterator = struct { | ... | @@ -10788,10 +10853,10 @@ const ParamTypeIterator = struct { |
| 10788 | it.zig_index += 1; | 10853 | it.zig_index += 1; |
| 10789 | it.llvm_index += 1; | 10854 | it.llvm_index += 1; |
| 10790 | var buf: Type.Payload.ElemType = undefined; | 10855 | var buf: Type.Payload.ElemType = undefined; |
| 10791 | if (ty.isSlice() or (ty.zigTypeTag() == .Optional and ty.optionalChild(&buf).isSlice())) { | 10856 | if (ty.isSlice() or (ty.zigTypeTag(mod) == .Optional and ty.optionalChild(&buf).isSlice())) { |
| 10792 | it.llvm_index += 1; | 10857 | it.llvm_index += 1; |
| 10793 | return .slice; | 10858 | return .slice; |
| 10794 | } else if (isByRef(ty)) { | 10859 | } else if (isByRef(ty, mod)) { |
| 10795 | return .byref; | 10860 | return .byref; |
| 10796 | } else { | 10861 | } else { |
| 10797 | return .byval; | 10862 | return .byval; |
| ... | @@ -10801,23 +10866,23 @@ const ParamTypeIterator = struct { | ... | @@ -10801,23 +10866,23 @@ const ParamTypeIterator = struct { |
| 10801 | @panic("TODO implement async function lowering in the LLVM backend"); | 10866 | @panic("TODO implement async function lowering in the LLVM backend"); |
| 10802 | }, | 10867 | }, |
| 10803 | .C => { | 10868 | .C => { |
| 10804 | switch (it.target.cpu.arch) { | 10869 | switch (target.cpu.arch) { |
| 10805 | .mips, .mipsel => { | 10870 | .mips, .mipsel => { |
| 10806 | it.zig_index += 1; | 10871 | it.zig_index += 1; |
| 10807 | it.llvm_index += 1; | 10872 | it.llvm_index += 1; |
| 10808 | return .byval; | 10873 | return .byval; |
| 10809 | }, | 10874 | }, |
| 10810 | .x86_64 => switch (it.target.os.tag) { | 10875 | .x86_64 => switch (target.os.tag) { |
| 10811 | .windows => return it.nextWin64(ty), | 10876 | .windows => return it.nextWin64(ty), |
| 10812 | else => return it.nextSystemV(ty), | 10877 | else => return it.nextSystemV(ty), |
| 10813 | }, | 10878 | }, |
| 10814 | .wasm32 => { | 10879 | .wasm32 => { |
| 10815 | it.zig_index += 1; | 10880 | it.zig_index += 1; |
| 10816 | it.llvm_index += 1; | 10881 | it.llvm_index += 1; |
| 10817 | if (isScalar(ty)) { | 10882 | if (isScalar(mod, ty)) { |
| 10818 | return .byval; | 10883 | return .byval; |
| 10819 | } | 10884 | } |
| 10820 | const classes = wasm_c_abi.classifyType(ty, it.target); | 10885 | const classes = wasm_c_abi.classifyType(ty, mod); |
| 10821 | if (classes[0] == .indirect) { | 10886 | if (classes[0] == .indirect) { |
| 10822 | return .byref; | 10887 | return .byref; |
| 10823 | } | 10888 | } |
| ... | @@ -10826,7 +10891,7 @@ const ParamTypeIterator = struct { | ... | @@ -10826,7 +10891,7 @@ const ParamTypeIterator = struct { |
| 10826 | .aarch64, .aarch64_be => { | 10891 | .aarch64, .aarch64_be => { |
| 10827 | it.zig_index += 1; | 10892 | it.zig_index += 1; |
| 10828 | it.llvm_index += 1; | 10893 | it.llvm_index += 1; |
| 10829 | switch (aarch64_c_abi.classifyType(ty, it.target)) { | 10894 | switch (aarch64_c_abi.classifyType(ty, mod)) { |
| 10830 | .memory => return .byref_mut, | 10895 | .memory => return .byref_mut, |
| 10831 | .float_array => |len| return Lowering{ .float_array = len }, | 10896 | .float_array => |len| return Lowering{ .float_array = len }, |
| 10832 | .byval => return .byval, | 10897 | .byval => return .byval, |
| ... | @@ -10841,7 +10906,7 @@ const ParamTypeIterator = struct { | ... | @@ -10841,7 +10906,7 @@ const ParamTypeIterator = struct { |
| 10841 | .arm, .armeb => { | 10906 | .arm, .armeb => { |
| 10842 | it.zig_index += 1; | 10907 | it.zig_index += 1; |
| 10843 | it.llvm_index += 1; | 10908 | it.llvm_index += 1; |
| 10844 | switch (arm_c_abi.classifyType(ty, it.target, .arg)) { | 10909 | switch (arm_c_abi.classifyType(ty, mod, .arg)) { |
| 10845 | .memory => { | 10910 | .memory => { |
| 10846 | it.byval_attr = true; | 10911 | it.byval_attr = true; |
| 10847 | return .byref; | 10912 | return .byref; |
| ... | @@ -10857,7 +10922,7 @@ const ParamTypeIterator = struct { | ... | @@ -10857,7 +10922,7 @@ const ParamTypeIterator = struct { |
| 10857 | if (ty.tag() == .f16) { | 10922 | if (ty.tag() == .f16) { |
| 10858 | return .as_u16; | 10923 | return .as_u16; |
| 10859 | } | 10924 | } |
| 10860 | switch (riscv_c_abi.classifyType(ty, it.target)) { | 10925 | switch (riscv_c_abi.classifyType(ty, mod)) { |
| 10861 | .memory => return .byref_mut, | 10926 | .memory => return .byref_mut, |
| 10862 | .byval => return .byval, | 10927 | .byval => return .byval, |
| 10863 | .integer => return .abi_sized_int, | 10928 | .integer => return .abi_sized_int, |
| ... | @@ -10878,7 +10943,7 @@ const ParamTypeIterator = struct { | ... | @@ -10878,7 +10943,7 @@ const ParamTypeIterator = struct { |
| 10878 | it.zig_index += 1; | 10943 | it.zig_index += 1; |
| 10879 | it.llvm_index += 1; | 10944 | it.llvm_index += 1; |
| 10880 | 10945 | ||
| 10881 | if (isScalar(ty)) { | 10946 | if (isScalar(mod, ty)) { |
| 10882 | return .byval; | 10947 | return .byval; |
| 10883 | } else { | 10948 | } else { |
| 10884 | it.byval_attr = true; | 10949 | it.byval_attr = true; |
| ... | @@ -10894,9 +10959,10 @@ const ParamTypeIterator = struct { | ... | @@ -10894,9 +10959,10 @@ const ParamTypeIterator = struct { |
| 10894 | } | 10959 | } |
| 10895 | 10960 | ||
| 10896 | fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering { | 10961 | fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering { |
| 10897 | switch (x86_64_abi.classifyWindows(ty, it.target)) { | 10962 | const mod = it.dg.module; |
| 10963 | switch (x86_64_abi.classifyWindows(ty, mod)) { | ||
| 10898 | .integer => { | 10964 | .integer => { |
| 10899 | if (isScalar(ty)) { | 10965 | if (isScalar(mod, ty)) { |
| 10900 | it.zig_index += 1; | 10966 | it.zig_index += 1; |
| 10901 | it.llvm_index += 1; | 10967 | it.llvm_index += 1; |
| 10902 | return .byval; | 10968 | return .byval; |
| ... | @@ -10926,14 +10992,15 @@ const ParamTypeIterator = struct { | ... | @@ -10926,14 +10992,15 @@ const ParamTypeIterator = struct { |
| 10926 | } | 10992 | } |
| 10927 | 10993 | ||
| 10928 | fn nextSystemV(it: *ParamTypeIterator, ty: Type) ?Lowering { | 10994 | fn nextSystemV(it: *ParamTypeIterator, ty: Type) ?Lowering { |
| 10929 | const classes = x86_64_abi.classifySystemV(ty, it.target, .arg); | 10995 | const mod = it.dg.module; |
| 10996 | const classes = x86_64_abi.classifySystemV(ty, mod, .arg); | ||
| 10930 | if (classes[0] == .memory) { | 10997 | if (classes[0] == .memory) { |
| 10931 | it.zig_index += 1; | 10998 | it.zig_index += 1; |
| 10932 | it.llvm_index += 1; | 10999 | it.llvm_index += 1; |
| 10933 | it.byval_attr = true; | 11000 | it.byval_attr = true; |
| 10934 | return .byref; | 11001 | return .byref; |
| 10935 | } | 11002 | } |
| 10936 | if (isScalar(ty)) { | 11003 | if (isScalar(mod, ty)) { |
| 10937 | it.zig_index += 1; | 11004 | it.zig_index += 1; |
| 10938 | it.llvm_index += 1; | 11005 | it.llvm_index += 1; |
| 10939 | return .byval; | 11006 | return .byval; |
| ... | @@ -10992,7 +11059,6 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp | ... | @@ -10992,7 +11059,6 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp |
| 10992 | .fn_info = fn_info, | 11059 | .fn_info = fn_info, |
| 10993 | .zig_index = 0, | 11060 | .zig_index = 0, |
| 10994 | .llvm_index = 0, | 11061 | .llvm_index = 0, |
| 10995 | .target = dg.module.getTarget(), | ||
| 10996 | .llvm_types_buffer = undefined, | 11062 | .llvm_types_buffer = undefined, |
| 10997 | .llvm_types_len = 0, | 11063 | .llvm_types_len = 0, |
| 10998 | .byval_attr = false, | 11064 | .byval_attr = false, |
| ... | @@ -11001,16 +11067,17 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp | ... | @@ -11001,16 +11067,17 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp |
| 11001 | 11067 | ||
| 11002 | fn ccAbiPromoteInt( | 11068 | fn ccAbiPromoteInt( |
| 11003 | cc: std.builtin.CallingConvention, | 11069 | cc: std.builtin.CallingConvention, |
| 11004 | target: std.Target, | 11070 | mod: *const Module, |
| 11005 | ty: Type, | 11071 | ty: Type, |
| 11006 | ) ?std.builtin.Signedness { | 11072 | ) ?std.builtin.Signedness { |
| 11073 | const target = mod.getTarget(); | ||
| 11007 | switch (cc) { | 11074 | switch (cc) { |
| 11008 | .Unspecified, .Inline, .Async => return null, | 11075 | .Unspecified, .Inline, .Async => return null, |
| 11009 | else => {}, | 11076 | else => {}, |
| 11010 | } | 11077 | } |
| 11011 | const int_info = switch (ty.zigTypeTag()) { | 11078 | const int_info = switch (ty.zigTypeTag(mod)) { |
| 11012 | .Bool => Type.u1.intInfo(target), | 11079 | .Bool => Type.u1.intInfo(mod), |
| 11013 | .Int, .Enum, .ErrorSet => ty.intInfo(target), | 11080 | .Int, .Enum, .ErrorSet => ty.intInfo(mod), |
| 11014 | else => return null, | 11081 | else => return null, |
| 11015 | }; | 11082 | }; |
| 11016 | if (int_info.bits <= 16) return int_info.signedness; | 11083 | if (int_info.bits <= 16) return int_info.signedness; |
| ... | @@ -11039,12 +11106,12 @@ fn ccAbiPromoteInt( | ... | @@ -11039,12 +11106,12 @@ fn ccAbiPromoteInt( |
| 11039 | 11106 | ||
| 11040 | /// This is the one source of truth for whether a type is passed around as an LLVM pointer, | 11107 | /// This is the one source of truth for whether a type is passed around as an LLVM pointer, |
| 11041 | /// or as an LLVM value. | 11108 | /// or as an LLVM value. |
| 11042 | fn isByRef(ty: Type) bool { | 11109 | fn isByRef(ty: Type, mod: *const Module) bool { |
| 11043 | // For tuples and structs, if there are more than this many non-void | 11110 | // For tuples and structs, if there are more than this many non-void |
| 11044 | // fields, then we make it byref, otherwise byval. | 11111 | // fields, then we make it byref, otherwise byval. |
| 11045 | const max_fields_byval = 0; | 11112 | const max_fields_byval = 0; |
| 11046 | 11113 | ||
| 11047 | switch (ty.zigTypeTag()) { | 11114 | switch (ty.zigTypeTag(mod)) { |
| 11048 | .Type, | 11115 | .Type, |
| 11049 | .ComptimeInt, | 11116 | .ComptimeInt, |
| 11050 | .ComptimeFloat, | 11117 | .ComptimeFloat, |
| ... | @@ -11067,7 +11134,7 @@ fn isByRef(ty: Type) bool { | ... | @@ -11067,7 +11134,7 @@ fn isByRef(ty: Type) bool { |
| 11067 | .AnyFrame, | 11134 | .AnyFrame, |
| 11068 | => return false, | 11135 | => return false, |
| 11069 | 11136 | ||
| 11070 | .Array, .Frame => return ty.hasRuntimeBits(), | 11137 | .Array, .Frame => return ty.hasRuntimeBits(mod), |
| 11071 | .Struct => { | 11138 | .Struct => { |
| 11072 | // Packed structs are represented to LLVM as integers. | 11139 | // Packed structs are represented to LLVM as integers. |
| 11073 | if (ty.containerLayout() == .Packed) return false; | 11140 | if (ty.containerLayout() == .Packed) return false; |
| ... | @@ -11075,32 +11142,32 @@ fn isByRef(ty: Type) bool { | ... | @@ -11075,32 +11142,32 @@ fn isByRef(ty: Type) bool { |
| 11075 | const tuple = ty.tupleFields(); | 11142 | const tuple = ty.tupleFields(); |
| 11076 | var count: usize = 0; | 11143 | var count: usize = 0; |
| 11077 | for (tuple.values, 0..) |field_val, i| { | 11144 | for (tuple.values, 0..) |field_val, i| { |
| 11078 | if (field_val.tag() != .unreachable_value or !tuple.types[i].hasRuntimeBits()) continue; | 11145 | if (field_val.tag() != .unreachable_value or !tuple.types[i].hasRuntimeBits(mod)) continue; |
| 11079 | 11146 | ||
| 11080 | count += 1; | 11147 | count += 1; |
| 11081 | if (count > max_fields_byval) return true; | 11148 | if (count > max_fields_byval) return true; |
| 11082 | if (isByRef(tuple.types[i])) return true; | 11149 | if (isByRef(tuple.types[i], mod)) return true; |
| 11083 | } | 11150 | } |
| 11084 | return false; | 11151 | return false; |
| 11085 | } | 11152 | } |
| 11086 | var count: usize = 0; | 11153 | var count: usize = 0; |
| 11087 | const fields = ty.structFields(); | 11154 | const fields = ty.structFields(); |
| 11088 | for (fields.values()) |field| { | 11155 | for (fields.values()) |field| { |
| 11089 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; | 11156 | if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue; |
| 11090 | 11157 | ||
| 11091 | count += 1; | 11158 | count += 1; |
| 11092 | if (count > max_fields_byval) return true; | 11159 | if (count > max_fields_byval) return true; |
| 11093 | if (isByRef(field.ty)) return true; | 11160 | if (isByRef(field.ty, mod)) return true; |
| 11094 | } | 11161 | } |
| 11095 | return false; | 11162 | return false; |
| 11096 | }, | 11163 | }, |
| 11097 | .Union => switch (ty.containerLayout()) { | 11164 | .Union => switch (ty.containerLayout()) { |
| 11098 | .Packed => return false, | 11165 | .Packed => return false, |
| 11099 | else => return ty.hasRuntimeBits(), | 11166 | else => return ty.hasRuntimeBits(mod), |
| 11100 | }, | 11167 | }, |
| 11101 | .ErrorUnion => { | 11168 | .ErrorUnion => { |
| 11102 | const payload_ty = ty.errorUnionPayload(); | 11169 | const payload_ty = ty.errorUnionPayload(); |
| 11103 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 11170 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 11104 | return false; | 11171 | return false; |
| 11105 | } | 11172 | } |
| 11106 | return true; | 11173 | return true; |
| ... | @@ -11108,10 +11175,10 @@ fn isByRef(ty: Type) bool { | ... | @@ -11108,10 +11175,10 @@ fn isByRef(ty: Type) bool { |
| 11108 | .Optional => { | 11175 | .Optional => { |
| 11109 | var buf: Type.Payload.ElemType = undefined; | 11176 | var buf: Type.Payload.ElemType = undefined; |
| 11110 | const payload_ty = ty.optionalChild(&buf); | 11177 | const payload_ty = ty.optionalChild(&buf); |
| 11111 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 11178 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 11112 | return false; | 11179 | return false; |
| 11113 | } | 11180 | } |
| 11114 | if (ty.optionalReprIsPayload()) { | 11181 | if (ty.optionalReprIsPayload(mod)) { |
| 11115 | return false; | 11182 | return false; |
| 11116 | } | 11183 | } |
| 11117 | return true; | 11184 | return true; |
| ... | @@ -11119,8 +11186,8 @@ fn isByRef(ty: Type) bool { | ... | @@ -11119,8 +11186,8 @@ fn isByRef(ty: Type) bool { |
| 11119 | } | 11186 | } |
| 11120 | } | 11187 | } |
| 11121 | 11188 | ||
| 11122 | fn isScalar(ty: Type) bool { | 11189 | fn isScalar(mod: *const Module, ty: Type) bool { |
| 11123 | return switch (ty.zigTypeTag()) { | 11190 | return switch (ty.zigTypeTag(mod)) { |
| 11124 | .Void, | 11191 | .Void, |
| 11125 | .Bool, | 11192 | .Bool, |
| 11126 | .NoReturn, | 11193 | .NoReturn, |
| ... | @@ -11304,12 +11371,12 @@ fn buildAllocaInner( | ... | @@ -11304,12 +11371,12 @@ fn buildAllocaInner( |
| 11304 | return alloca; | 11371 | return alloca; |
| 11305 | } | 11372 | } |
| 11306 | 11373 | ||
| 11307 | fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u1 { | 11374 | fn errUnionPayloadOffset(payload_ty: Type, mod: *const Module) u1 { |
| 11308 | return @boolToInt(Type.anyerror.abiAlignment(target) > payload_ty.abiAlignment(target)); | 11375 | return @boolToInt(Type.anyerror.abiAlignment(mod) > payload_ty.abiAlignment(mod)); |
| 11309 | } | 11376 | } |
| 11310 | 11377 | ||
| 11311 | fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u1 { | 11378 | fn errUnionErrorOffset(payload_ty: Type, mod: *const Module) u1 { |
| 11312 | return @boolToInt(Type.anyerror.abiAlignment(target) <= payload_ty.abiAlignment(target)); | 11379 | return @boolToInt(Type.anyerror.abiAlignment(mod) <= payload_ty.abiAlignment(mod)); |
| 11313 | } | 11380 | } |
| 11314 | 11381 | ||
| 11315 | /// Returns true for asm constraint (e.g. "=*m", "=r") if it accepts a memory location | 11382 | /// Returns true for asm constraint (e.g. "=*m", "=r") if it accepts a memory location |
src/codegen/spirv.zig+114-94| ... | @@ -231,9 +231,10 @@ pub const DeclGen = struct { | ... | @@ -231,9 +231,10 @@ pub const DeclGen = struct { |
| 231 | 231 | ||
| 232 | /// Fetch the result-id for a previously generated instruction or constant. | 232 | /// Fetch the result-id for a previously generated instruction or constant. |
| 233 | fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !IdRef { | 233 | fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !IdRef { |
| 234 | if (self.air.value(inst)) |val| { | 234 | const mod = self.module; |
| 235 | if (self.air.value(inst, mod)) |val| { | ||
| 235 | const ty = self.air.typeOf(inst); | 236 | const ty = self.air.typeOf(inst); |
| 236 | if (ty.zigTypeTag() == .Fn) { | 237 | if (ty.zigTypeTag(mod) == .Fn) { |
| 237 | const fn_decl_index = switch (val.tag()) { | 238 | const fn_decl_index = switch (val.tag()) { |
| 238 | .extern_fn => val.castTag(.extern_fn).?.data.owner_decl, | 239 | .extern_fn => val.castTag(.extern_fn).?.data.owner_decl, |
| 239 | .function => val.castTag(.function).?.data.owner_decl, | 240 | .function => val.castTag(.function).?.data.owner_decl, |
| ... | @@ -340,8 +341,9 @@ pub const DeclGen = struct { | ... | @@ -340,8 +341,9 @@ pub const DeclGen = struct { |
| 340 | } | 341 | } |
| 341 | 342 | ||
| 342 | fn arithmeticTypeInfo(self: *DeclGen, ty: Type) !ArithmeticTypeInfo { | 343 | fn arithmeticTypeInfo(self: *DeclGen, ty: Type) !ArithmeticTypeInfo { |
| 344 | const mod = self.module; | ||
| 343 | const target = self.getTarget(); | 345 | const target = self.getTarget(); |
| 344 | return switch (ty.zigTypeTag()) { | 346 | return switch (ty.zigTypeTag(mod)) { |
| 345 | .Bool => ArithmeticTypeInfo{ | 347 | .Bool => ArithmeticTypeInfo{ |
| 346 | .bits = 1, // Doesn't matter for this class. | 348 | .bits = 1, // Doesn't matter for this class. |
| 347 | .is_vector = false, | 349 | .is_vector = false, |
| ... | @@ -355,7 +357,7 @@ pub const DeclGen = struct { | ... | @@ -355,7 +357,7 @@ pub const DeclGen = struct { |
| 355 | .class = .float, | 357 | .class = .float, |
| 356 | }, | 358 | }, |
| 357 | .Int => blk: { | 359 | .Int => blk: { |
| 358 | const int_info = ty.intInfo(target); | 360 | const int_info = ty.intInfo(mod); |
| 359 | // TODO: Maybe it's useful to also return this value. | 361 | // TODO: Maybe it's useful to also return this value. |
| 360 | const maybe_backing_bits = self.backingIntBits(int_info.bits); | 362 | const maybe_backing_bits = self.backingIntBits(int_info.bits); |
| 361 | break :blk ArithmeticTypeInfo{ | 363 | break :blk ArithmeticTypeInfo{ |
| ... | @@ -533,21 +535,22 @@ pub const DeclGen = struct { | ... | @@ -533,21 +535,22 @@ pub const DeclGen = struct { |
| 533 | } | 535 | } |
| 534 | 536 | ||
| 535 | fn addInt(self: *@This(), ty: Type, val: Value) !void { | 537 | fn addInt(self: *@This(), ty: Type, val: Value) !void { |
| 536 | const target = self.dg.getTarget(); | 538 | const mod = self.dg.module; |
| 537 | const int_info = ty.intInfo(target); | 539 | const int_info = ty.intInfo(mod); |
| 538 | const int_bits = switch (int_info.signedness) { | 540 | const int_bits = switch (int_info.signedness) { |
| 539 | .signed => @bitCast(u64, val.toSignedInt(target)), | 541 | .signed => @bitCast(u64, val.toSignedInt(mod)), |
| 540 | .unsigned => val.toUnsignedInt(target), | 542 | .unsigned => val.toUnsignedInt(mod), |
| 541 | }; | 543 | }; |
| 542 | 544 | ||
| 543 | // TODO: Swap endianess if the compiler is big endian. | 545 | // TODO: Swap endianess if the compiler is big endian. |
| 544 | const len = ty.abiSize(target); | 546 | const len = ty.abiSize(mod); |
| 545 | try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]); | 547 | try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]); |
| 546 | } | 548 | } |
| 547 | 549 | ||
| 548 | fn addFloat(self: *@This(), ty: Type, val: Value) !void { | 550 | fn addFloat(self: *@This(), ty: Type, val: Value) !void { |
| 551 | const mod = self.dg.module; | ||
| 549 | const target = self.dg.getTarget(); | 552 | const target = self.dg.getTarget(); |
| 550 | const len = ty.abiSize(target); | 553 | const len = ty.abiSize(mod); |
| 551 | 554 | ||
| 552 | // TODO: Swap endianess if the compiler is big endian. | 555 | // TODO: Swap endianess if the compiler is big endian. |
| 553 | switch (ty.floatBits(target)) { | 556 | switch (ty.floatBits(target)) { |
| ... | @@ -607,15 +610,15 @@ pub const DeclGen = struct { | ... | @@ -607,15 +610,15 @@ pub const DeclGen = struct { |
| 607 | } | 610 | } |
| 608 | 611 | ||
| 609 | fn lower(self: *@This(), ty: Type, val: Value) !void { | 612 | fn lower(self: *@This(), ty: Type, val: Value) !void { |
| 610 | const target = self.dg.getTarget(); | ||
| 611 | const dg = self.dg; | 613 | const dg = self.dg; |
| 614 | const mod = dg.module; | ||
| 612 | 615 | ||
| 613 | if (val.isUndef()) { | 616 | if (val.isUndef()) { |
| 614 | const size = ty.abiSize(target); | 617 | const size = ty.abiSize(mod); |
| 615 | return try self.addUndef(size); | 618 | return try self.addUndef(size); |
| 616 | } | 619 | } |
| 617 | 620 | ||
| 618 | switch (ty.zigTypeTag()) { | 621 | switch (ty.zigTypeTag(mod)) { |
| 619 | .Int => try self.addInt(ty, val), | 622 | .Int => try self.addInt(ty, val), |
| 620 | .Float => try self.addFloat(ty, val), | 623 | .Float => try self.addFloat(ty, val), |
| 621 | .Bool => try self.addConstBool(val.toBool()), | 624 | .Bool => try self.addConstBool(val.toBool()), |
| ... | @@ -644,7 +647,7 @@ pub const DeclGen = struct { | ... | @@ -644,7 +647,7 @@ pub const DeclGen = struct { |
| 644 | const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | 647 | const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; |
| 645 | try self.addBytes(bytes); | 648 | try self.addBytes(bytes); |
| 646 | if (ty.sentinel()) |sentinel| { | 649 | if (ty.sentinel()) |sentinel| { |
| 647 | try self.addByte(@intCast(u8, sentinel.toUnsignedInt(target))); | 650 | try self.addByte(@intCast(u8, sentinel.toUnsignedInt(mod))); |
| 648 | } | 651 | } |
| 649 | }, | 652 | }, |
| 650 | .bytes => { | 653 | .bytes => { |
| ... | @@ -690,13 +693,13 @@ pub const DeclGen = struct { | ... | @@ -690,13 +693,13 @@ pub const DeclGen = struct { |
| 690 | const struct_begin = self.size; | 693 | const struct_begin = self.size; |
| 691 | const field_vals = val.castTag(.aggregate).?.data; | 694 | const field_vals = val.castTag(.aggregate).?.data; |
| 692 | for (struct_ty.fields.values(), 0..) |field, i| { | 695 | for (struct_ty.fields.values(), 0..) |field, i| { |
| 693 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; | 696 | if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue; |
| 694 | try self.lower(field.ty, field_vals[i]); | 697 | try self.lower(field.ty, field_vals[i]); |
| 695 | 698 | ||
| 696 | // Add padding if required. | 699 | // Add padding if required. |
| 697 | // TODO: Add to type generation as well? | 700 | // TODO: Add to type generation as well? |
| 698 | const unpadded_field_end = self.size - struct_begin; | 701 | const unpadded_field_end = self.size - struct_begin; |
| 699 | const padded_field_end = ty.structFieldOffset(i + 1, target); | 702 | const padded_field_end = ty.structFieldOffset(i + 1, mod); |
| 700 | const padding = padded_field_end - unpadded_field_end; | 703 | const padding = padded_field_end - unpadded_field_end; |
| 701 | try self.addUndef(padding); | 704 | try self.addUndef(padding); |
| 702 | } | 705 | } |
| ... | @@ -705,13 +708,13 @@ pub const DeclGen = struct { | ... | @@ -705,13 +708,13 @@ pub const DeclGen = struct { |
| 705 | .Optional => { | 708 | .Optional => { |
| 706 | var opt_buf: Type.Payload.ElemType = undefined; | 709 | var opt_buf: Type.Payload.ElemType = undefined; |
| 707 | const payload_ty = ty.optionalChild(&opt_buf); | 710 | const payload_ty = ty.optionalChild(&opt_buf); |
| 708 | const has_payload = !val.isNull(); | 711 | const has_payload = !val.isNull(mod); |
| 709 | const abi_size = ty.abiSize(target); | 712 | const abi_size = ty.abiSize(mod); |
| 710 | 713 | ||
| 711 | if (!payload_ty.hasRuntimeBits()) { | 714 | if (!payload_ty.hasRuntimeBits(mod)) { |
| 712 | try self.addConstBool(has_payload); | 715 | try self.addConstBool(has_payload); |
| 713 | return; | 716 | return; |
| 714 | } else if (ty.optionalReprIsPayload()) { | 717 | } else if (ty.optionalReprIsPayload(mod)) { |
| 715 | // Optional representation is a nullable pointer or slice. | 718 | // Optional representation is a nullable pointer or slice. |
| 716 | if (val.castTag(.opt_payload)) |payload| { | 719 | if (val.castTag(.opt_payload)) |payload| { |
| 717 | try self.lower(payload_ty, payload.data); | 720 | try self.lower(payload_ty, payload.data); |
| ... | @@ -729,7 +732,7 @@ pub const DeclGen = struct { | ... | @@ -729,7 +732,7 @@ pub const DeclGen = struct { |
| 729 | 732 | ||
| 730 | // Subtract 1 for @sizeOf(bool). | 733 | // Subtract 1 for @sizeOf(bool). |
| 731 | // TODO: Make this not hardcoded. | 734 | // TODO: Make this not hardcoded. |
| 732 | const payload_size = payload_ty.abiSize(target); | 735 | const payload_size = payload_ty.abiSize(mod); |
| 733 | const padding = abi_size - payload_size - 1; | 736 | const padding = abi_size - payload_size - 1; |
| 734 | 737 | ||
| 735 | if (val.castTag(.opt_payload)) |payload| { | 738 | if (val.castTag(.opt_payload)) |payload| { |
| ... | @@ -744,14 +747,13 @@ pub const DeclGen = struct { | ... | @@ -744,14 +747,13 @@ pub const DeclGen = struct { |
| 744 | var int_val_buffer: Value.Payload.U64 = undefined; | 747 | var int_val_buffer: Value.Payload.U64 = undefined; |
| 745 | const int_val = val.enumToInt(ty, &int_val_buffer); | 748 | const int_val = val.enumToInt(ty, &int_val_buffer); |
| 746 | 749 | ||
| 747 | var int_ty_buffer: Type.Payload.Bits = undefined; | 750 | const int_ty = ty.intTagType(); |
| 748 | const int_ty = ty.intTagType(&int_ty_buffer); | ||
| 749 | 751 | ||
| 750 | try self.lower(int_ty, int_val); | 752 | try self.lower(int_ty, int_val); |
| 751 | }, | 753 | }, |
| 752 | .Union => { | 754 | .Union => { |
| 753 | const tag_and_val = val.castTag(.@"union").?.data; | 755 | const tag_and_val = val.castTag(.@"union").?.data; |
| 754 | const layout = ty.unionGetLayout(target); | 756 | const layout = ty.unionGetLayout(mod); |
| 755 | 757 | ||
| 756 | if (layout.payload_size == 0) { | 758 | if (layout.payload_size == 0) { |
| 757 | return try self.lower(ty.unionTagTypeSafety().?, tag_and_val.tag); | 759 | return try self.lower(ty.unionTagTypeSafety().?, tag_and_val.tag); |
| ... | @@ -772,9 +774,9 @@ pub const DeclGen = struct { | ... | @@ -772,9 +774,9 @@ pub const DeclGen = struct { |
| 772 | try self.lower(ty.unionTagTypeSafety().?, tag_and_val.tag); | 774 | try self.lower(ty.unionTagTypeSafety().?, tag_and_val.tag); |
| 773 | } | 775 | } |
| 774 | 776 | ||
| 775 | const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime()) blk: { | 777 | const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: { |
| 776 | try self.lower(active_field_ty, tag_and_val.val); | 778 | try self.lower(active_field_ty, tag_and_val.val); |
| 777 | break :blk active_field_ty.abiSize(target); | 779 | break :blk active_field_ty.abiSize(mod); |
| 778 | } else 0; | 780 | } else 0; |
| 779 | 781 | ||
| 780 | const payload_padding_len = layout.payload_size - active_field_size; | 782 | const payload_padding_len = layout.payload_size - active_field_size; |
| ... | @@ -808,9 +810,9 @@ pub const DeclGen = struct { | ... | @@ -808,9 +810,9 @@ pub const DeclGen = struct { |
| 808 | return try self.lower(Type.anyerror, error_val); | 810 | return try self.lower(Type.anyerror, error_val); |
| 809 | } | 811 | } |
| 810 | 812 | ||
| 811 | const payload_size = payload_ty.abiSize(target); | 813 | const payload_size = payload_ty.abiSize(mod); |
| 812 | const error_size = Type.anyerror.abiAlignment(target); | 814 | const error_size = Type.anyerror.abiAlignment(mod); |
| 813 | const ty_size = ty.abiSize(target); | 815 | const ty_size = ty.abiSize(mod); |
| 814 | const padding = ty_size - payload_size - error_size; | 816 | const padding = ty_size - payload_size - error_size; |
| 815 | const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); | 817 | const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); |
| 816 | 818 | ||
| ... | @@ -886,7 +888,7 @@ pub const DeclGen = struct { | ... | @@ -886,7 +888,7 @@ pub const DeclGen = struct { |
| 886 | // .id_result = result_id, | 888 | // .id_result = result_id, |
| 887 | // .storage_class = storage_class, | 889 | // .storage_class = storage_class, |
| 888 | // }); | 890 | // }); |
| 889 | // } else if (ty.abiSize(target) == 0) { | 891 | // } else if (ty.abiSize(mod) == 0) { |
| 890 | // // Special case: if the type has no size, then return an undefined pointer. | 892 | // // Special case: if the type has no size, then return an undefined pointer. |
| 891 | // return try section.emit(self.spv.gpa, .OpUndef, .{ | 893 | // return try section.emit(self.spv.gpa, .OpUndef, .{ |
| 892 | // .id_result_type = self.typeId(ptr_ty_ref), | 894 | // .id_result_type = self.typeId(ptr_ty_ref), |
| ... | @@ -968,6 +970,7 @@ pub const DeclGen = struct { | ... | @@ -968,6 +970,7 @@ pub const DeclGen = struct { |
| 968 | /// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default. | 970 | /// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default. |
| 969 | /// This function should only be called during function code generation. | 971 | /// This function should only be called during function code generation. |
| 970 | fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef { | 972 | fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef { |
| 973 | const mod = self.module; | ||
| 971 | const target = self.getTarget(); | 974 | const target = self.getTarget(); |
| 972 | const result_ty_ref = try self.resolveType(ty, repr); | 975 | const result_ty_ref = try self.resolveType(ty, repr); |
| 973 | 976 | ||
| ... | @@ -977,12 +980,12 @@ pub const DeclGen = struct { | ... | @@ -977,12 +980,12 @@ pub const DeclGen = struct { |
| 977 | return self.spv.constUndef(result_ty_ref); | 980 | return self.spv.constUndef(result_ty_ref); |
| 978 | } | 981 | } |
| 979 | 982 | ||
| 980 | switch (ty.zigTypeTag()) { | 983 | switch (ty.zigTypeTag(mod)) { |
| 981 | .Int => { | 984 | .Int => { |
| 982 | if (ty.isSignedInt()) { | 985 | if (ty.isSignedInt(mod)) { |
| 983 | return try self.spv.constInt(result_ty_ref, val.toSignedInt(target)); | 986 | return try self.spv.constInt(result_ty_ref, val.toSignedInt(mod)); |
| 984 | } else { | 987 | } else { |
| 985 | return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(target)); | 988 | return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(mod)); |
| 986 | } | 989 | } |
| 987 | }, | 990 | }, |
| 988 | .Bool => switch (repr) { | 991 | .Bool => switch (repr) { |
| ... | @@ -1037,7 +1040,7 @@ pub const DeclGen = struct { | ... | @@ -1037,7 +1040,7 @@ pub const DeclGen = struct { |
| 1037 | // The value cannot be generated directly, so generate it as an indirect constant, | 1040 | // The value cannot be generated directly, so generate it as an indirect constant, |
| 1038 | // and then perform an OpLoad. | 1041 | // and then perform an OpLoad. |
| 1039 | const result_id = self.spv.allocId(); | 1042 | const result_id = self.spv.allocId(); |
| 1040 | const alignment = ty.abiAlignment(target); | 1043 | const alignment = ty.abiAlignment(mod); |
| 1041 | const spv_decl_index = try self.spv.allocDecl(.global); | 1044 | const spv_decl_index = try self.spv.allocDecl(.global); |
| 1042 | 1045 | ||
| 1043 | try self.lowerIndirectConstant( | 1046 | try self.lowerIndirectConstant( |
| ... | @@ -1114,8 +1117,8 @@ pub const DeclGen = struct { | ... | @@ -1114,8 +1117,8 @@ pub const DeclGen = struct { |
| 1114 | /// NOTE: When the active field is set to something other than the most aligned field, the | 1117 | /// NOTE: When the active field is set to something other than the most aligned field, the |
| 1115 | /// resulting struct will be *underaligned*. | 1118 | /// resulting struct will be *underaligned*. |
| 1116 | fn resolveUnionType(self: *DeclGen, ty: Type, maybe_active_field: ?usize) !CacheRef { | 1119 | fn resolveUnionType(self: *DeclGen, ty: Type, maybe_active_field: ?usize) !CacheRef { |
| 1117 | const target = self.getTarget(); | 1120 | const mod = self.module; |
| 1118 | const layout = ty.unionGetLayout(target); | 1121 | const layout = ty.unionGetLayout(mod); |
| 1119 | const union_ty = ty.cast(Type.Payload.Union).?.data; | 1122 | const union_ty = ty.cast(Type.Payload.Union).?.data; |
| 1120 | 1123 | ||
| 1121 | if (union_ty.layout == .Packed) { | 1124 | if (union_ty.layout == .Packed) { |
| ... | @@ -1143,11 +1146,11 @@ pub const DeclGen = struct { | ... | @@ -1143,11 +1146,11 @@ pub const DeclGen = struct { |
| 1143 | const active_field = maybe_active_field orelse layout.most_aligned_field; | 1146 | const active_field = maybe_active_field orelse layout.most_aligned_field; |
| 1144 | const active_field_ty = union_ty.fields.values()[active_field].ty; | 1147 | const active_field_ty = union_ty.fields.values()[active_field].ty; |
| 1145 | 1148 | ||
| 1146 | const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime()) blk: { | 1149 | const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: { |
| 1147 | const active_payload_ty_ref = try self.resolveType(active_field_ty, .indirect); | 1150 | const active_payload_ty_ref = try self.resolveType(active_field_ty, .indirect); |
| 1148 | member_types.appendAssumeCapacity(active_payload_ty_ref); | 1151 | member_types.appendAssumeCapacity(active_payload_ty_ref); |
| 1149 | member_names.appendAssumeCapacity(try self.spv.resolveString("payload")); | 1152 | member_names.appendAssumeCapacity(try self.spv.resolveString("payload")); |
| 1150 | break :blk active_field_ty.abiSize(target); | 1153 | break :blk active_field_ty.abiSize(mod); |
| 1151 | } else 0; | 1154 | } else 0; |
| 1152 | 1155 | ||
| 1153 | const payload_padding_len = layout.payload_size - active_field_size; | 1156 | const payload_padding_len = layout.payload_size - active_field_size; |
| ... | @@ -1177,21 +1180,21 @@ pub const DeclGen = struct { | ... | @@ -1177,21 +1180,21 @@ pub const DeclGen = struct { |
| 1177 | 1180 | ||
| 1178 | /// Turn a Zig type into a SPIR-V Type, and return a reference to it. | 1181 | /// Turn a Zig type into a SPIR-V Type, and return a reference to it. |
| 1179 | fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef { | 1182 | fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef { |
| 1183 | const mod = self.module; | ||
| 1180 | log.debug("resolveType: ty = {}", .{ty.fmt(self.module)}); | 1184 | log.debug("resolveType: ty = {}", .{ty.fmt(self.module)}); |
| 1181 | const target = self.getTarget(); | 1185 | const target = self.getTarget(); |
| 1182 | switch (ty.zigTypeTag()) { | 1186 | switch (ty.zigTypeTag(mod)) { |
| 1183 | .Void, .NoReturn => return try self.spv.resolve(.void_type), | 1187 | .Void, .NoReturn => return try self.spv.resolve(.void_type), |
| 1184 | .Bool => switch (repr) { | 1188 | .Bool => switch (repr) { |
| 1185 | .direct => return try self.spv.resolve(.bool_type), | 1189 | .direct => return try self.spv.resolve(.bool_type), |
| 1186 | .indirect => return try self.intType(.unsigned, 1), | 1190 | .indirect => return try self.intType(.unsigned, 1), |
| 1187 | }, | 1191 | }, |
| 1188 | .Int => { | 1192 | .Int => { |
| 1189 | const int_info = ty.intInfo(target); | 1193 | const int_info = ty.intInfo(mod); |
| 1190 | return try self.intType(int_info.signedness, int_info.bits); | 1194 | return try self.intType(int_info.signedness, int_info.bits); |
| 1191 | }, | 1195 | }, |
| 1192 | .Enum => { | 1196 | .Enum => { |
| 1193 | var buffer: Type.Payload.Bits = undefined; | 1197 | const tag_ty = ty.intTagType(); |
| 1194 | const tag_ty = ty.intTagType(&buffer); | ||
| 1195 | return self.resolveType(tag_ty, repr); | 1198 | return self.resolveType(tag_ty, repr); |
| 1196 | }, | 1199 | }, |
| 1197 | .Float => { | 1200 | .Float => { |
| ... | @@ -1290,7 +1293,7 @@ pub const DeclGen = struct { | ... | @@ -1290,7 +1293,7 @@ pub const DeclGen = struct { |
| 1290 | var member_index: usize = 0; | 1293 | var member_index: usize = 0; |
| 1291 | for (tuple.types, 0..) |field_ty, i| { | 1294 | for (tuple.types, 0..) |field_ty, i| { |
| 1292 | const field_val = tuple.values[i]; | 1295 | const field_val = tuple.values[i]; |
| 1293 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue; | 1296 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; |
| 1294 | 1297 | ||
| 1295 | member_types[member_index] = try self.resolveType(field_ty, .indirect); | 1298 | member_types[member_index] = try self.resolveType(field_ty, .indirect); |
| 1296 | member_index += 1; | 1299 | member_index += 1; |
| ... | @@ -1315,7 +1318,7 @@ pub const DeclGen = struct { | ... | @@ -1315,7 +1318,7 @@ pub const DeclGen = struct { |
| 1315 | 1318 | ||
| 1316 | var member_index: usize = 0; | 1319 | var member_index: usize = 0; |
| 1317 | for (struct_ty.fields.values(), 0..) |field, i| { | 1320 | for (struct_ty.fields.values(), 0..) |field, i| { |
| 1318 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; | 1321 | if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue; |
| 1319 | 1322 | ||
| 1320 | member_types[member_index] = try self.resolveType(field.ty, .indirect); | 1323 | member_types[member_index] = try self.resolveType(field.ty, .indirect); |
| 1321 | member_names[member_index] = try self.spv.resolveString(struct_ty.fields.keys()[i]); | 1324 | member_names[member_index] = try self.spv.resolveString(struct_ty.fields.keys()[i]); |
| ... | @@ -1334,7 +1337,7 @@ pub const DeclGen = struct { | ... | @@ -1334,7 +1337,7 @@ pub const DeclGen = struct { |
| 1334 | .Optional => { | 1337 | .Optional => { |
| 1335 | var buf: Type.Payload.ElemType = undefined; | 1338 | var buf: Type.Payload.ElemType = undefined; |
| 1336 | const payload_ty = ty.optionalChild(&buf); | 1339 | const payload_ty = ty.optionalChild(&buf); |
| 1337 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 1340 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 1338 | // Just use a bool. | 1341 | // Just use a bool. |
| 1339 | // Note: Always generate the bool with indirect format, to save on some sanity | 1342 | // Note: Always generate the bool with indirect format, to save on some sanity |
| 1340 | // Perform the conversion to a direct bool when the field is extracted. | 1343 | // Perform the conversion to a direct bool when the field is extracted. |
| ... | @@ -1342,7 +1345,7 @@ pub const DeclGen = struct { | ... | @@ -1342,7 +1345,7 @@ pub const DeclGen = struct { |
| 1342 | } | 1345 | } |
| 1343 | 1346 | ||
| 1344 | const payload_ty_ref = try self.resolveType(payload_ty, .indirect); | 1347 | const payload_ty_ref = try self.resolveType(payload_ty, .indirect); |
| 1345 | if (ty.optionalReprIsPayload()) { | 1348 | if (ty.optionalReprIsPayload(mod)) { |
| 1346 | // Optional is actually a pointer or a slice. | 1349 | // Optional is actually a pointer or a slice. |
| 1347 | return payload_ty_ref; | 1350 | return payload_ty_ref; |
| 1348 | } | 1351 | } |
| ... | @@ -1445,14 +1448,14 @@ pub const DeclGen = struct { | ... | @@ -1445,14 +1448,14 @@ pub const DeclGen = struct { |
| 1445 | }; | 1448 | }; |
| 1446 | 1449 | ||
| 1447 | fn errorUnionLayout(self: *DeclGen, payload_ty: Type) ErrorUnionLayout { | 1450 | fn errorUnionLayout(self: *DeclGen, payload_ty: Type) ErrorUnionLayout { |
| 1448 | const target = self.getTarget(); | 1451 | const mod = self.module; |
| 1449 | 1452 | ||
| 1450 | const error_align = Type.anyerror.abiAlignment(target); | 1453 | const error_align = Type.anyerror.abiAlignment(mod); |
| 1451 | const payload_align = payload_ty.abiAlignment(target); | 1454 | const payload_align = payload_ty.abiAlignment(mod); |
| 1452 | 1455 | ||
| 1453 | const error_first = error_align > payload_align; | 1456 | const error_first = error_align > payload_align; |
| 1454 | return .{ | 1457 | return .{ |
| 1455 | .payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(), | 1458 | .payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod), |
| 1456 | .error_first = error_first, | 1459 | .error_first = error_first, |
| 1457 | }; | 1460 | }; |
| 1458 | } | 1461 | } |
| ... | @@ -1529,14 +1532,15 @@ pub const DeclGen = struct { | ... | @@ -1529,14 +1532,15 @@ pub const DeclGen = struct { |
| 1529 | } | 1532 | } |
| 1530 | 1533 | ||
| 1531 | fn genDecl(self: *DeclGen) !void { | 1534 | fn genDecl(self: *DeclGen) !void { |
| 1532 | const decl = self.module.declPtr(self.decl_index); | 1535 | const mod = self.module; |
| 1536 | const decl = mod.declPtr(self.decl_index); | ||
| 1533 | const spv_decl_index = try self.resolveDecl(self.decl_index); | 1537 | const spv_decl_index = try self.resolveDecl(self.decl_index); |
| 1534 | 1538 | ||
| 1535 | const decl_id = self.spv.declPtr(spv_decl_index).result_id; | 1539 | const decl_id = self.spv.declPtr(spv_decl_index).result_id; |
| 1536 | log.debug("genDecl: id = {}, index = {}, name = {s}", .{ decl_id.id, @enumToInt(spv_decl_index), decl.name }); | 1540 | log.debug("genDecl: id = {}, index = {}, name = {s}", .{ decl_id.id, @enumToInt(spv_decl_index), decl.name }); |
| 1537 | 1541 | ||
| 1538 | if (decl.val.castTag(.function)) |_| { | 1542 | if (decl.val.castTag(.function)) |_| { |
| 1539 | assert(decl.ty.zigTypeTag() == .Fn); | 1543 | assert(decl.ty.zigTypeTag(mod) == .Fn); |
| 1540 | const prototype_id = try self.resolveTypeId(decl.ty); | 1544 | const prototype_id = try self.resolveTypeId(decl.ty); |
| 1541 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ | 1545 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ |
| 1542 | .id_result_type = try self.resolveTypeId(decl.ty.fnReturnType()), | 1546 | .id_result_type = try self.resolveTypeId(decl.ty.fnReturnType()), |
| ... | @@ -1634,7 +1638,8 @@ pub const DeclGen = struct { | ... | @@ -1634,7 +1638,8 @@ pub const DeclGen = struct { |
| 1634 | /// Convert representation from indirect (in memory) to direct (in 'register') | 1638 | /// Convert representation from indirect (in memory) to direct (in 'register') |
| 1635 | /// This converts the argument type from resolveType(ty, .indirect) to resolveType(ty, .direct). | 1639 | /// This converts the argument type from resolveType(ty, .indirect) to resolveType(ty, .direct). |
| 1636 | fn convertToDirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef { | 1640 | fn convertToDirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef { |
| 1637 | return switch (ty.zigTypeTag()) { | 1641 | const mod = self.module; |
| 1642 | return switch (ty.zigTypeTag(mod)) { | ||
| 1638 | .Bool => blk: { | 1643 | .Bool => blk: { |
| 1639 | const direct_bool_ty_ref = try self.resolveType(ty, .direct); | 1644 | const direct_bool_ty_ref = try self.resolveType(ty, .direct); |
| 1640 | const indirect_bool_ty_ref = try self.resolveType(ty, .indirect); | 1645 | const indirect_bool_ty_ref = try self.resolveType(ty, .indirect); |
| ... | @@ -1655,7 +1660,8 @@ pub const DeclGen = struct { | ... | @@ -1655,7 +1660,8 @@ pub const DeclGen = struct { |
| 1655 | /// Convert representation from direct (in 'register) to direct (in memory) | 1660 | /// Convert representation from direct (in 'register) to direct (in memory) |
| 1656 | /// This converts the argument type from resolveType(ty, .direct) to resolveType(ty, .indirect). | 1661 | /// This converts the argument type from resolveType(ty, .direct) to resolveType(ty, .indirect). |
| 1657 | fn convertToIndirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef { | 1662 | fn convertToIndirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef { |
| 1658 | return switch (ty.zigTypeTag()) { | 1663 | const mod = self.module; |
| 1664 | return switch (ty.zigTypeTag(mod)) { | ||
| 1659 | .Bool => blk: { | 1665 | .Bool => blk: { |
| 1660 | const indirect_bool_ty_ref = try self.resolveType(ty, .indirect); | 1666 | const indirect_bool_ty_ref = try self.resolveType(ty, .indirect); |
| 1661 | break :blk self.boolToInt(indirect_bool_ty_ref, operand_id); | 1667 | break :blk self.boolToInt(indirect_bool_ty_ref, operand_id); |
| ... | @@ -2056,6 +2062,7 @@ pub const DeclGen = struct { | ... | @@ -2056,6 +2062,7 @@ pub const DeclGen = struct { |
| 2056 | } | 2062 | } |
| 2057 | 2063 | ||
| 2058 | fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2064 | fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2065 | const mod = self.module; | ||
| 2059 | if (self.liveness.isUnused(inst)) return null; | 2066 | if (self.liveness.isUnused(inst)) return null; |
| 2060 | const ty = self.air.typeOfIndex(inst); | 2067 | const ty = self.air.typeOfIndex(inst); |
| 2061 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2068 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| ... | @@ -2083,7 +2090,7 @@ pub const DeclGen = struct { | ... | @@ -2083,7 +2090,7 @@ pub const DeclGen = struct { |
| 2083 | if (elem.isUndef()) { | 2090 | if (elem.isUndef()) { |
| 2084 | self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF); | 2091 | self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF); |
| 2085 | } else { | 2092 | } else { |
| 2086 | const int = elem.toSignedInt(self.getTarget()); | 2093 | const int = elem.toSignedInt(mod); |
| 2087 | const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len); | 2094 | const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len); |
| 2088 | self.func.body.writeOperand(spec.LiteralInteger, unsigned); | 2095 | self.func.body.writeOperand(spec.LiteralInteger, unsigned); |
| 2089 | } | 2096 | } |
| ... | @@ -2189,13 +2196,13 @@ pub const DeclGen = struct { | ... | @@ -2189,13 +2196,13 @@ pub const DeclGen = struct { |
| 2189 | lhs_id: IdRef, | 2196 | lhs_id: IdRef, |
| 2190 | rhs_id: IdRef, | 2197 | rhs_id: IdRef, |
| 2191 | ) !IdRef { | 2198 | ) !IdRef { |
| 2199 | const mod = self.module; | ||
| 2192 | var cmp_lhs_id = lhs_id; | 2200 | var cmp_lhs_id = lhs_id; |
| 2193 | var cmp_rhs_id = rhs_id; | 2201 | var cmp_rhs_id = rhs_id; |
| 2194 | const opcode: Opcode = opcode: { | 2202 | const opcode: Opcode = opcode: { |
| 2195 | var int_buffer: Type.Payload.Bits = undefined; | 2203 | const op_ty = switch (ty.zigTypeTag(mod)) { |
| 2196 | const op_ty = switch (ty.zigTypeTag()) { | ||
| 2197 | .Int, .Bool, .Float => ty, | 2204 | .Int, .Bool, .Float => ty, |
| 2198 | .Enum => ty.intTagType(&int_buffer), | 2205 | .Enum => ty.intTagType(), |
| 2199 | .ErrorSet => Type.u16, | 2206 | .ErrorSet => Type.u16, |
| 2200 | .Pointer => blk: { | 2207 | .Pointer => blk: { |
| 2201 | // Note that while SPIR-V offers OpPtrEqual and OpPtrNotEqual, they are | 2208 | // Note that while SPIR-V offers OpPtrEqual and OpPtrNotEqual, they are |
| ... | @@ -2303,13 +2310,14 @@ pub const DeclGen = struct { | ... | @@ -2303,13 +2310,14 @@ pub const DeclGen = struct { |
| 2303 | src_ty: Type, | 2310 | src_ty: Type, |
| 2304 | src_id: IdRef, | 2311 | src_id: IdRef, |
| 2305 | ) !IdRef { | 2312 | ) !IdRef { |
| 2313 | const mod = self.module; | ||
| 2306 | const dst_ty_ref = try self.resolveType(dst_ty, .direct); | 2314 | const dst_ty_ref = try self.resolveType(dst_ty, .direct); |
| 2307 | const result_id = self.spv.allocId(); | 2315 | const result_id = self.spv.allocId(); |
| 2308 | 2316 | ||
| 2309 | // TODO: Some more cases are missing here | 2317 | // TODO: Some more cases are missing here |
| 2310 | // See fn bitCast in llvm.zig | 2318 | // See fn bitCast in llvm.zig |
| 2311 | 2319 | ||
| 2312 | if (src_ty.zigTypeTag() == .Int and dst_ty.isPtrAtRuntime()) { | 2320 | if (src_ty.zigTypeTag(mod) == .Int and dst_ty.isPtrAtRuntime(mod)) { |
| 2313 | try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ | 2321 | try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ |
| 2314 | .id_result_type = self.typeId(dst_ty_ref), | 2322 | .id_result_type = self.typeId(dst_ty_ref), |
| 2315 | .id_result = result_id, | 2323 | .id_result = result_id, |
| ... | @@ -2342,8 +2350,8 @@ pub const DeclGen = struct { | ... | @@ -2342,8 +2350,8 @@ pub const DeclGen = struct { |
| 2342 | const dest_ty = self.air.typeOfIndex(inst); | 2350 | const dest_ty = self.air.typeOfIndex(inst); |
| 2343 | const dest_ty_id = try self.resolveTypeId(dest_ty); | 2351 | const dest_ty_id = try self.resolveTypeId(dest_ty); |
| 2344 | 2352 | ||
| 2345 | const target = self.getTarget(); | 2353 | const mod = self.module; |
| 2346 | const dest_info = dest_ty.intInfo(target); | 2354 | const dest_info = dest_ty.intInfo(mod); |
| 2347 | 2355 | ||
| 2348 | // TODO: Masking? | 2356 | // TODO: Masking? |
| 2349 | 2357 | ||
| ... | @@ -2485,8 +2493,9 @@ pub const DeclGen = struct { | ... | @@ -2485,8 +2493,9 @@ pub const DeclGen = struct { |
| 2485 | } | 2493 | } |
| 2486 | 2494 | ||
| 2487 | fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef { | 2495 | fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef { |
| 2496 | const mod = self.module; | ||
| 2488 | // Construct new pointer type for the resulting pointer | 2497 | // Construct new pointer type for the resulting pointer |
| 2489 | const elem_ty = ptr_ty.elemType2(); // use elemType() so that we get T for *[N]T. | 2498 | const elem_ty = ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T. |
| 2490 | const elem_ty_ref = try self.resolveType(elem_ty, .direct); | 2499 | const elem_ty_ref = try self.resolveType(elem_ty, .direct); |
| 2491 | const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(ptr_ty.ptrAddressSpace())); | 2500 | const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(ptr_ty.ptrAddressSpace())); |
| 2492 | if (ptr_ty.isSinglePointer()) { | 2501 | if (ptr_ty.isSinglePointer()) { |
| ... | @@ -2502,12 +2511,13 @@ pub const DeclGen = struct { | ... | @@ -2502,12 +2511,13 @@ pub const DeclGen = struct { |
| 2502 | fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2511 | fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2503 | if (self.liveness.isUnused(inst)) return null; | 2512 | if (self.liveness.isUnused(inst)) return null; |
| 2504 | 2513 | ||
| 2514 | const mod = self.module; | ||
| 2505 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2515 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2506 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 2516 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2507 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 2517 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 2508 | const elem_ty = ptr_ty.childType(); | 2518 | const elem_ty = ptr_ty.childType(); |
| 2509 | // TODO: Make this return a null ptr or something | 2519 | // TODO: Make this return a null ptr or something |
| 2510 | if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null; | 2520 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; |
| 2511 | 2521 | ||
| 2512 | const ptr_id = try self.resolve(bin_op.lhs); | 2522 | const ptr_id = try self.resolve(bin_op.lhs); |
| 2513 | const index_id = try self.resolve(bin_op.rhs); | 2523 | const index_id = try self.resolve(bin_op.rhs); |
| ... | @@ -2536,8 +2546,8 @@ pub const DeclGen = struct { | ... | @@ -2536,8 +2546,8 @@ pub const DeclGen = struct { |
| 2536 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2546 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2537 | const un_ty = self.air.typeOf(ty_op.operand); | 2547 | const un_ty = self.air.typeOf(ty_op.operand); |
| 2538 | 2548 | ||
| 2539 | const target = self.module.getTarget(); | 2549 | const mod = self.module; |
| 2540 | const layout = un_ty.unionGetLayout(target); | 2550 | const layout = un_ty.unionGetLayout(mod); |
| 2541 | if (layout.tag_size == 0) return null; | 2551 | if (layout.tag_size == 0) return null; |
| 2542 | 2552 | ||
| 2543 | const union_handle = try self.resolve(ty_op.operand); | 2553 | const union_handle = try self.resolve(ty_op.operand); |
| ... | @@ -2551,6 +2561,7 @@ pub const DeclGen = struct { | ... | @@ -2551,6 +2561,7 @@ pub const DeclGen = struct { |
| 2551 | fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2561 | fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2552 | if (self.liveness.isUnused(inst)) return null; | 2562 | if (self.liveness.isUnused(inst)) return null; |
| 2553 | 2563 | ||
| 2564 | const mod = self.module; | ||
| 2554 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2565 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2555 | const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; | 2566 | const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; |
| 2556 | 2567 | ||
| ... | @@ -2559,9 +2570,9 @@ pub const DeclGen = struct { | ... | @@ -2559,9 +2570,9 @@ pub const DeclGen = struct { |
| 2559 | const field_index = struct_field.field_index; | 2570 | const field_index = struct_field.field_index; |
| 2560 | const field_ty = struct_ty.structFieldType(field_index); | 2571 | const field_ty = struct_ty.structFieldType(field_index); |
| 2561 | 2572 | ||
| 2562 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) return null; | 2573 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; |
| 2563 | 2574 | ||
| 2564 | assert(struct_ty.zigTypeTag() == .Struct); // Cannot do unions yet. | 2575 | assert(struct_ty.zigTypeTag(mod) == .Struct); // Cannot do unions yet. |
| 2565 | 2576 | ||
| 2566 | return try self.extractField(field_ty, object_id, field_index); | 2577 | return try self.extractField(field_ty, object_id, field_index); |
| 2567 | } | 2578 | } |
| ... | @@ -2573,8 +2584,9 @@ pub const DeclGen = struct { | ... | @@ -2573,8 +2584,9 @@ pub const DeclGen = struct { |
| 2573 | object_ptr: IdRef, | 2584 | object_ptr: IdRef, |
| 2574 | field_index: u32, | 2585 | field_index: u32, |
| 2575 | ) !?IdRef { | 2586 | ) !?IdRef { |
| 2587 | const mod = self.module; | ||
| 2576 | const object_ty = object_ptr_ty.childType(); | 2588 | const object_ty = object_ptr_ty.childType(); |
| 2577 | switch (object_ty.zigTypeTag()) { | 2589 | switch (object_ty.zigTypeTag(mod)) { |
| 2578 | .Struct => switch (object_ty.containerLayout()) { | 2590 | .Struct => switch (object_ty.containerLayout()) { |
| 2579 | .Packed => unreachable, // TODO | 2591 | .Packed => unreachable, // TODO |
| 2580 | else => { | 2592 | else => { |
| ... | @@ -2667,6 +2679,7 @@ pub const DeclGen = struct { | ... | @@ -2667,6 +2679,7 @@ pub const DeclGen = struct { |
| 2667 | // the current block by first generating the code of the block, then a label, and then generate the rest of the current | 2679 | // the current block by first generating the code of the block, then a label, and then generate the rest of the current |
| 2668 | // ir.Block in a different SPIR-V block. | 2680 | // ir.Block in a different SPIR-V block. |
| 2669 | 2681 | ||
| 2682 | const mod = self.module; | ||
| 2670 | const label_id = self.spv.allocId(); | 2683 | const label_id = self.spv.allocId(); |
| 2671 | 2684 | ||
| 2672 | // 4 chosen as arbitrary initial capacity. | 2685 | // 4 chosen as arbitrary initial capacity. |
| ... | @@ -2690,7 +2703,7 @@ pub const DeclGen = struct { | ... | @@ -2690,7 +2703,7 @@ pub const DeclGen = struct { |
| 2690 | try self.beginSpvBlock(label_id); | 2703 | try self.beginSpvBlock(label_id); |
| 2691 | 2704 | ||
| 2692 | // If this block didn't produce a value, simply return here. | 2705 | // If this block didn't produce a value, simply return here. |
| 2693 | if (!ty.hasRuntimeBitsIgnoreComptime()) | 2706 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 2694 | return null; | 2707 | return null; |
| 2695 | 2708 | ||
| 2696 | // Combine the result from the blocks using the Phi instruction. | 2709 | // Combine the result from the blocks using the Phi instruction. |
| ... | @@ -2716,7 +2729,8 @@ pub const DeclGen = struct { | ... | @@ -2716,7 +2729,8 @@ pub const DeclGen = struct { |
| 2716 | const block = self.blocks.get(br.block_inst).?; | 2729 | const block = self.blocks.get(br.block_inst).?; |
| 2717 | const operand_ty = self.air.typeOf(br.operand); | 2730 | const operand_ty = self.air.typeOf(br.operand); |
| 2718 | 2731 | ||
| 2719 | if (operand_ty.hasRuntimeBits()) { | 2732 | const mod = self.module; |
| 2733 | if (operand_ty.hasRuntimeBits(mod)) { | ||
| 2720 | const operand_id = try self.resolve(br.operand); | 2734 | const operand_id = try self.resolve(br.operand); |
| 2721 | // current_block_label_id should not be undefined here, lest there is a br or br_void in the function's body. | 2735 | // current_block_label_id should not be undefined here, lest there is a br or br_void in the function's body. |
| 2722 | try block.incoming_blocks.append(self.gpa, .{ .src_label_id = self.current_block_label_id, .break_value_id = operand_id }); | 2736 | try block.incoming_blocks.append(self.gpa, .{ .src_label_id = self.current_block_label_id, .break_value_id = operand_id }); |
| ... | @@ -2771,13 +2785,14 @@ pub const DeclGen = struct { | ... | @@ -2771,13 +2785,14 @@ pub const DeclGen = struct { |
| 2771 | } | 2785 | } |
| 2772 | 2786 | ||
| 2773 | fn airStore(self: *DeclGen, inst: Air.Inst.Index) !void { | 2787 | fn airStore(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 2788 | const mod = self.module; | ||
| 2774 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 2789 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2775 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 2790 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 2776 | const ptr = try self.resolve(bin_op.lhs); | 2791 | const ptr = try self.resolve(bin_op.lhs); |
| 2777 | const value = try self.resolve(bin_op.rhs); | 2792 | const value = try self.resolve(bin_op.rhs); |
| 2778 | const ptr_ty_ref = try self.resolveType(ptr_ty, .direct); | 2793 | const ptr_ty_ref = try self.resolveType(ptr_ty, .direct); |
| 2779 | 2794 | ||
| 2780 | const val_is_undef = if (self.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false; | 2795 | const val_is_undef = if (self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep() else false; |
| 2781 | if (val_is_undef) { | 2796 | if (val_is_undef) { |
| 2782 | const undef = try self.spv.constUndef(ptr_ty_ref); | 2797 | const undef = try self.spv.constUndef(ptr_ty_ref); |
| 2783 | try self.store(ptr_ty, ptr, undef); | 2798 | try self.store(ptr_ty, ptr, undef); |
| ... | @@ -2805,7 +2820,8 @@ pub const DeclGen = struct { | ... | @@ -2805,7 +2820,8 @@ pub const DeclGen = struct { |
| 2805 | fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void { | 2820 | fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 2806 | const operand = self.air.instructions.items(.data)[inst].un_op; | 2821 | const operand = self.air.instructions.items(.data)[inst].un_op; |
| 2807 | const operand_ty = self.air.typeOf(operand); | 2822 | const operand_ty = self.air.typeOf(operand); |
| 2808 | if (operand_ty.hasRuntimeBits()) { | 2823 | const mod = self.module; |
| 2824 | if (operand_ty.hasRuntimeBits(mod)) { | ||
| 2809 | const operand_id = try self.resolve(operand); | 2825 | const operand_id = try self.resolve(operand); |
| 2810 | try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = operand_id }); | 2826 | try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = operand_id }); |
| 2811 | } else { | 2827 | } else { |
| ... | @@ -2814,11 +2830,12 @@ pub const DeclGen = struct { | ... | @@ -2814,11 +2830,12 @@ pub const DeclGen = struct { |
| 2814 | } | 2830 | } |
| 2815 | 2831 | ||
| 2816 | fn airRetLoad(self: *DeclGen, inst: Air.Inst.Index) !void { | 2832 | fn airRetLoad(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 2833 | const mod = self.module; | ||
| 2817 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 2834 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 2818 | const ptr_ty = self.air.typeOf(un_op); | 2835 | const ptr_ty = self.air.typeOf(un_op); |
| 2819 | const ret_ty = ptr_ty.childType(); | 2836 | const ret_ty = ptr_ty.childType(); |
| 2820 | 2837 | ||
| 2821 | if (!ret_ty.hasRuntimeBitsIgnoreComptime()) { | 2838 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2822 | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); | 2839 | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| 2823 | return; | 2840 | return; |
| 2824 | } | 2841 | } |
| ... | @@ -2946,6 +2963,7 @@ pub const DeclGen = struct { | ... | @@ -2946,6 +2963,7 @@ pub const DeclGen = struct { |
| 2946 | fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef { | 2963 | fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef { |
| 2947 | if (self.liveness.isUnused(inst)) return null; | 2964 | if (self.liveness.isUnused(inst)) return null; |
| 2948 | 2965 | ||
| 2966 | const mod = self.module; | ||
| 2949 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 2967 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 2950 | const operand_id = try self.resolve(un_op); | 2968 | const operand_id = try self.resolve(un_op); |
| 2951 | const optional_ty = self.air.typeOf(un_op); | 2969 | const optional_ty = self.air.typeOf(un_op); |
| ... | @@ -2955,7 +2973,7 @@ pub const DeclGen = struct { | ... | @@ -2955,7 +2973,7 @@ pub const DeclGen = struct { |
| 2955 | 2973 | ||
| 2956 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); | 2974 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); |
| 2957 | 2975 | ||
| 2958 | if (optional_ty.optionalReprIsPayload()) { | 2976 | if (optional_ty.optionalReprIsPayload(mod)) { |
| 2959 | // Pointer payload represents nullability: pointer or slice. | 2977 | // Pointer payload represents nullability: pointer or slice. |
| 2960 | 2978 | ||
| 2961 | var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; | 2979 | var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| ... | @@ -2985,7 +3003,7 @@ pub const DeclGen = struct { | ... | @@ -2985,7 +3003,7 @@ pub const DeclGen = struct { |
| 2985 | return result_id; | 3003 | return result_id; |
| 2986 | } | 3004 | } |
| 2987 | 3005 | ||
| 2988 | const is_non_null_id = if (optional_ty.hasRuntimeBitsIgnoreComptime()) | 3006 | const is_non_null_id = if (optional_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 2989 | try self.extractField(Type.bool, operand_id, 1) | 3007 | try self.extractField(Type.bool, operand_id, 1) |
| 2990 | else | 3008 | else |
| 2991 | // Optional representation is bool indicating whether the optional is set | 3009 | // Optional representation is bool indicating whether the optional is set |
| ... | @@ -3009,14 +3027,15 @@ pub const DeclGen = struct { | ... | @@ -3009,14 +3027,15 @@ pub const DeclGen = struct { |
| 3009 | fn airUnwrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 3027 | fn airUnwrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 3010 | if (self.liveness.isUnused(inst)) return null; | 3028 | if (self.liveness.isUnused(inst)) return null; |
| 3011 | 3029 | ||
| 3030 | const mod = self.module; | ||
| 3012 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3031 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3013 | const operand_id = try self.resolve(ty_op.operand); | 3032 | const operand_id = try self.resolve(ty_op.operand); |
| 3014 | const optional_ty = self.air.typeOf(ty_op.operand); | 3033 | const optional_ty = self.air.typeOf(ty_op.operand); |
| 3015 | const payload_ty = self.air.typeOfIndex(inst); | 3034 | const payload_ty = self.air.typeOfIndex(inst); |
| 3016 | 3035 | ||
| 3017 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return null; | 3036 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; |
| 3018 | 3037 | ||
| 3019 | if (optional_ty.optionalReprIsPayload()) { | 3038 | if (optional_ty.optionalReprIsPayload(mod)) { |
| 3020 | return operand_id; | 3039 | return operand_id; |
| 3021 | } | 3040 | } |
| 3022 | 3041 | ||
| ... | @@ -3026,16 +3045,17 @@ pub const DeclGen = struct { | ... | @@ -3026,16 +3045,17 @@ pub const DeclGen = struct { |
| 3026 | fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 3045 | fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 3027 | if (self.liveness.isUnused(inst)) return null; | 3046 | if (self.liveness.isUnused(inst)) return null; |
| 3028 | 3047 | ||
| 3048 | const mod = self.module; | ||
| 3029 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3049 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3030 | const payload_ty = self.air.typeOf(ty_op.operand); | 3050 | const payload_ty = self.air.typeOf(ty_op.operand); |
| 3031 | 3051 | ||
| 3032 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 3052 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3033 | return try self.constBool(true, .direct); | 3053 | return try self.constBool(true, .direct); |
| 3034 | } | 3054 | } |
| 3035 | 3055 | ||
| 3036 | const operand_id = try self.resolve(ty_op.operand); | 3056 | const operand_id = try self.resolve(ty_op.operand); |
| 3037 | const optional_ty = self.air.typeOfIndex(inst); | 3057 | const optional_ty = self.air.typeOfIndex(inst); |
| 3038 | if (optional_ty.optionalReprIsPayload()) { | 3058 | if (optional_ty.optionalReprIsPayload(mod)) { |
| 3039 | return operand_id; | 3059 | return operand_id; |
| 3040 | } | 3060 | } |
| 3041 | 3061 | ||
| ... | @@ -3045,30 +3065,29 @@ pub const DeclGen = struct { | ... | @@ -3045,30 +3065,29 @@ pub const DeclGen = struct { |
| 3045 | } | 3065 | } |
| 3046 | 3066 | ||
| 3047 | fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void { | 3067 | fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 3048 | const target = self.getTarget(); | 3068 | const mod = self.module; |
| 3049 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 3069 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 3050 | const cond = try self.resolve(pl_op.operand); | 3070 | const cond = try self.resolve(pl_op.operand); |
| 3051 | const cond_ty = self.air.typeOf(pl_op.operand); | 3071 | const cond_ty = self.air.typeOf(pl_op.operand); |
| 3052 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); | 3072 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); |
| 3053 | 3073 | ||
| 3054 | const cond_words: u32 = switch (cond_ty.zigTypeTag()) { | 3074 | const cond_words: u32 = switch (cond_ty.zigTypeTag(mod)) { |
| 3055 | .Int => blk: { | 3075 | .Int => blk: { |
| 3056 | const bits = cond_ty.intInfo(target).bits; | 3076 | const bits = cond_ty.intInfo(mod).bits; |
| 3057 | const backing_bits = self.backingIntBits(bits) orelse { | 3077 | const backing_bits = self.backingIntBits(bits) orelse { |
| 3058 | return self.todo("implement composite int switch", .{}); | 3078 | return self.todo("implement composite int switch", .{}); |
| 3059 | }; | 3079 | }; |
| 3060 | break :blk if (backing_bits <= 32) @as(u32, 1) else 2; | 3080 | break :blk if (backing_bits <= 32) @as(u32, 1) else 2; |
| 3061 | }, | 3081 | }, |
| 3062 | .Enum => blk: { | 3082 | .Enum => blk: { |
| 3063 | var buffer: Type.Payload.Bits = undefined; | 3083 | const int_ty = cond_ty.intTagType(); |
| 3064 | const int_ty = cond_ty.intTagType(&buffer); | 3084 | const int_info = int_ty.intInfo(mod); |
| 3065 | const int_info = int_ty.intInfo(target); | ||
| 3066 | const backing_bits = self.backingIntBits(int_info.bits) orelse { | 3085 | const backing_bits = self.backingIntBits(int_info.bits) orelse { |
| 3067 | return self.todo("implement composite int switch", .{}); | 3086 | return self.todo("implement composite int switch", .{}); |
| 3068 | }; | 3087 | }; |
| 3069 | break :blk if (backing_bits <= 32) @as(u32, 1) else 2; | 3088 | break :blk if (backing_bits <= 32) @as(u32, 1) else 2; |
| 3070 | }, | 3089 | }, |
| 3071 | else => return self.todo("implement switch for type {s}", .{@tagName(cond_ty.zigTypeTag())}), // TODO: Figure out which types apply here, and work around them as we can only do integers. | 3090 | else => return self.todo("implement switch for type {s}", .{@tagName(cond_ty.zigTypeTag(mod))}), // TODO: Figure out which types apply here, and work around them as we can only do integers. |
| 3072 | }; | 3091 | }; |
| 3073 | 3092 | ||
| 3074 | const num_cases = switch_br.data.cases_len; | 3093 | const num_cases = switch_br.data.cases_len; |
| ... | @@ -3112,15 +3131,15 @@ pub const DeclGen = struct { | ... | @@ -3112,15 +3131,15 @@ pub const DeclGen = struct { |
| 3112 | const label = IdRef{ .id = first_case_label.id + case_i }; | 3131 | const label = IdRef{ .id = first_case_label.id + case_i }; |
| 3113 | 3132 | ||
| 3114 | for (items) |item| { | 3133 | for (items) |item| { |
| 3115 | const value = self.air.value(item) orelse { | 3134 | const value = self.air.value(item, mod) orelse { |
| 3116 | return self.todo("switch on runtime value???", .{}); | 3135 | return self.todo("switch on runtime value???", .{}); |
| 3117 | }; | 3136 | }; |
| 3118 | const int_val = switch (cond_ty.zigTypeTag()) { | 3137 | const int_val = switch (cond_ty.zigTypeTag(mod)) { |
| 3119 | .Int => if (cond_ty.isSignedInt()) @bitCast(u64, value.toSignedInt(target)) else value.toUnsignedInt(target), | 3138 | .Int => if (cond_ty.isSignedInt(mod)) @bitCast(u64, value.toSignedInt(mod)) else value.toUnsignedInt(mod), |
| 3120 | .Enum => blk: { | 3139 | .Enum => blk: { |
| 3121 | var int_buffer: Value.Payload.U64 = undefined; | 3140 | var int_buffer: Value.Payload.U64 = undefined; |
| 3122 | // TODO: figure out of cond_ty is correct (something with enum literals) | 3141 | // TODO: figure out of cond_ty is correct (something with enum literals) |
| 3123 | break :blk value.enumToInt(cond_ty, &int_buffer).toUnsignedInt(target); // TODO: composite integer constants | 3142 | break :blk value.enumToInt(cond_ty, &int_buffer).toUnsignedInt(mod); // TODO: composite integer constants |
| 3124 | }, | 3143 | }, |
| 3125 | else => unreachable, | 3144 | else => unreachable, |
| 3126 | }; | 3145 | }; |
| ... | @@ -3294,11 +3313,12 @@ pub const DeclGen = struct { | ... | @@ -3294,11 +3313,12 @@ pub const DeclGen = struct { |
| 3294 | fn airCall(self: *DeclGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !?IdRef { | 3313 | fn airCall(self: *DeclGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !?IdRef { |
| 3295 | _ = modifier; | 3314 | _ = modifier; |
| 3296 | 3315 | ||
| 3316 | const mod = self.module; | ||
| 3297 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 3317 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 3298 | const extra = self.air.extraData(Air.Call, pl_op.payload); | 3318 | const extra = self.air.extraData(Air.Call, pl_op.payload); |
| 3299 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); | 3319 | const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); |
| 3300 | const callee_ty = self.air.typeOf(pl_op.operand); | 3320 | const callee_ty = self.air.typeOf(pl_op.operand); |
| 3301 | const zig_fn_ty = switch (callee_ty.zigTypeTag()) { | 3321 | const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) { |
| 3302 | .Fn => callee_ty, | 3322 | .Fn => callee_ty, |
| 3303 | .Pointer => return self.fail("cannot call function pointers", .{}), | 3323 | .Pointer => return self.fail("cannot call function pointers", .{}), |
| 3304 | else => unreachable, | 3324 | else => unreachable, |
| ... | @@ -3320,7 +3340,7 @@ pub const DeclGen = struct { | ... | @@ -3320,7 +3340,7 @@ pub const DeclGen = struct { |
| 3320 | // temporary params buffer. | 3340 | // temporary params buffer. |
| 3321 | const arg_id = try self.resolve(arg); | 3341 | const arg_id = try self.resolve(arg); |
| 3322 | const arg_ty = self.air.typeOf(arg); | 3342 | const arg_ty = self.air.typeOf(arg); |
| 3323 | if (!arg_ty.hasRuntimeBitsIgnoreComptime()) continue; | 3343 | if (!arg_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 3324 | 3344 | ||
| 3325 | params[n_params] = arg_id; | 3345 | params[n_params] = arg_id; |
| 3326 | n_params += 1; | 3346 | n_params += 1; |
| ... | @@ -3337,7 +3357,7 @@ pub const DeclGen = struct { | ... | @@ -3337,7 +3357,7 @@ pub const DeclGen = struct { |
| 3337 | try self.func.body.emit(self.spv.gpa, .OpUnreachable, {}); | 3357 | try self.func.body.emit(self.spv.gpa, .OpUnreachable, {}); |
| 3338 | } | 3358 | } |
| 3339 | 3359 | ||
| 3340 | if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime()) { | 3360 | if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3341 | return null; | 3361 | return null; |
| 3342 | } | 3362 | } |
| 3343 | 3363 |
src/link/Coff.zig+4-3| ... | @@ -1123,7 +1123,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In | ... | @@ -1123,7 +1123,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In |
| 1123 | }, | 1123 | }, |
| 1124 | }; | 1124 | }; |
| 1125 | 1125 | ||
| 1126 | const required_alignment = tv.ty.abiAlignment(self.base.options.target); | 1126 | const required_alignment = tv.ty.abiAlignment(mod); |
| 1127 | const atom = self.getAtomPtr(atom_index); | 1127 | const atom = self.getAtomPtr(atom_index); |
| 1128 | atom.size = @intCast(u32, code.len); | 1128 | atom.size = @intCast(u32, code.len); |
| 1129 | atom.getSymbolPtr(self).value = try self.allocateAtom(atom_index, atom.size, required_alignment); | 1129 | atom.getSymbolPtr(self).value = try self.allocateAtom(atom_index, atom.size, required_alignment); |
| ... | @@ -1299,7 +1299,8 @@ pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: Module.Decl.Index) !Atom. | ... | @@ -1299,7 +1299,8 @@ pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: Module.Decl.Index) !Atom. |
| 1299 | fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 { | 1299 | fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 { |
| 1300 | const decl = self.base.options.module.?.declPtr(decl_index); | 1300 | const decl = self.base.options.module.?.declPtr(decl_index); |
| 1301 | const ty = decl.ty; | 1301 | const ty = decl.ty; |
| 1302 | const zig_ty = ty.zigTypeTag(); | 1302 | const mod = self.base.options.module.?; |
| 1303 | const zig_ty = ty.zigTypeTag(mod); | ||
| 1303 | const val = decl.val; | 1304 | const val = decl.val; |
| 1304 | const index: u16 = blk: { | 1305 | const index: u16 = blk: { |
| 1305 | if (val.isUndefDeep()) { | 1306 | if (val.isUndefDeep()) { |
| ... | @@ -1330,7 +1331,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, comple | ... | @@ -1330,7 +1331,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, comple |
| 1330 | defer gpa.free(decl_name); | 1331 | defer gpa.free(decl_name); |
| 1331 | 1332 | ||
| 1332 | log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); | 1333 | log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); |
| 1333 | const required_alignment = decl.getAlignment(self.base.options.target); | 1334 | const required_alignment = decl.getAlignment(mod); |
| 1334 | 1335 | ||
| 1335 | const decl_metadata = self.decls.get(decl_index).?; | 1336 | const decl_metadata = self.decls.get(decl_index).?; |
| 1336 | const atom_index = decl_metadata.atom; | 1337 | const atom_index = decl_metadata.atom; |
src/link/Dwarf.zig+52-51| ... | @@ -169,16 +169,16 @@ pub const DeclState = struct { | ... | @@ -169,16 +169,16 @@ pub const DeclState = struct { |
| 169 | 169 | ||
| 170 | fn addDbgInfoType( | 170 | fn addDbgInfoType( |
| 171 | self: *DeclState, | 171 | self: *DeclState, |
| 172 | module: *Module, | 172 | mod: *Module, |
| 173 | atom_index: Atom.Index, | 173 | atom_index: Atom.Index, |
| 174 | ty: Type, | 174 | ty: Type, |
| 175 | ) error{OutOfMemory}!void { | 175 | ) error{OutOfMemory}!void { |
| 176 | const arena = self.abbrev_type_arena.allocator(); | 176 | const arena = self.abbrev_type_arena.allocator(); |
| 177 | const dbg_info_buffer = &self.dbg_info; | 177 | const dbg_info_buffer = &self.dbg_info; |
| 178 | const target = module.getTarget(); | 178 | const target = mod.getTarget(); |
| 179 | const target_endian = target.cpu.arch.endian(); | 179 | const target_endian = target.cpu.arch.endian(); |
| 180 | 180 | ||
| 181 | switch (ty.zigTypeTag()) { | 181 | switch (ty.zigTypeTag(mod)) { |
| 182 | .NoReturn => unreachable, | 182 | .NoReturn => unreachable, |
| 183 | .Void => { | 183 | .Void => { |
| 184 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.pad1)); | 184 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.pad1)); |
| ... | @@ -189,12 +189,12 @@ pub const DeclState = struct { | ... | @@ -189,12 +189,12 @@ pub const DeclState = struct { |
| 189 | // DW.AT.encoding, DW.FORM.data1 | 189 | // DW.AT.encoding, DW.FORM.data1 |
| 190 | dbg_info_buffer.appendAssumeCapacity(DW.ATE.boolean); | 190 | dbg_info_buffer.appendAssumeCapacity(DW.ATE.boolean); |
| 191 | // DW.AT.byte_size, DW.FORM.udata | 191 | // DW.AT.byte_size, DW.FORM.udata |
| 192 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target)); | 192 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod)); |
| 193 | // DW.AT.name, DW.FORM.string | 193 | // DW.AT.name, DW.FORM.string |
| 194 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | 194 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)}); |
| 195 | }, | 195 | }, |
| 196 | .Int => { | 196 | .Int => { |
| 197 | const info = ty.intInfo(target); | 197 | const info = ty.intInfo(mod); |
| 198 | try dbg_info_buffer.ensureUnusedCapacity(12); | 198 | try dbg_info_buffer.ensureUnusedCapacity(12); |
| 199 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type)); | 199 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type)); |
| 200 | // DW.AT.encoding, DW.FORM.data1 | 200 | // DW.AT.encoding, DW.FORM.data1 |
| ... | @@ -203,20 +203,20 @@ pub const DeclState = struct { | ... | @@ -203,20 +203,20 @@ pub const DeclState = struct { |
| 203 | .unsigned => DW.ATE.unsigned, | 203 | .unsigned => DW.ATE.unsigned, |
| 204 | }); | 204 | }); |
| 205 | // DW.AT.byte_size, DW.FORM.udata | 205 | // DW.AT.byte_size, DW.FORM.udata |
| 206 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target)); | 206 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod)); |
| 207 | // DW.AT.name, DW.FORM.string | 207 | // DW.AT.name, DW.FORM.string |
| 208 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | 208 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)}); |
| 209 | }, | 209 | }, |
| 210 | .Optional => { | 210 | .Optional => { |
| 211 | if (ty.isPtrLikeOptional()) { | 211 | if (ty.isPtrLikeOptional(mod)) { |
| 212 | try dbg_info_buffer.ensureUnusedCapacity(12); | 212 | try dbg_info_buffer.ensureUnusedCapacity(12); |
| 213 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type)); | 213 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type)); |
| 214 | // DW.AT.encoding, DW.FORM.data1 | 214 | // DW.AT.encoding, DW.FORM.data1 |
| 215 | dbg_info_buffer.appendAssumeCapacity(DW.ATE.address); | 215 | dbg_info_buffer.appendAssumeCapacity(DW.ATE.address); |
| 216 | // DW.AT.byte_size, DW.FORM.udata | 216 | // DW.AT.byte_size, DW.FORM.udata |
| 217 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target)); | 217 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod)); |
| 218 | // DW.AT.name, DW.FORM.string | 218 | // DW.AT.name, DW.FORM.string |
| 219 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | 219 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)}); |
| 220 | } else { | 220 | } else { |
| 221 | // Non-pointer optionals are structs: struct { .maybe = *, .val = * } | 221 | // Non-pointer optionals are structs: struct { .maybe = *, .val = * } |
| 222 | var buf = try arena.create(Type.Payload.ElemType); | 222 | var buf = try arena.create(Type.Payload.ElemType); |
| ... | @@ -224,10 +224,10 @@ pub const DeclState = struct { | ... | @@ -224,10 +224,10 @@ pub const DeclState = struct { |
| 224 | // DW.AT.structure_type | 224 | // DW.AT.structure_type |
| 225 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type)); | 225 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type)); |
| 226 | // DW.AT.byte_size, DW.FORM.udata | 226 | // DW.AT.byte_size, DW.FORM.udata |
| 227 | const abi_size = ty.abiSize(target); | 227 | const abi_size = ty.abiSize(mod); |
| 228 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); | 228 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); |
| 229 | // DW.AT.name, DW.FORM.string | 229 | // DW.AT.name, DW.FORM.string |
| 230 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | 230 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)}); |
| 231 | // DW.AT.member | 231 | // DW.AT.member |
| 232 | try dbg_info_buffer.ensureUnusedCapacity(7); | 232 | try dbg_info_buffer.ensureUnusedCapacity(7); |
| 233 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member)); | 233 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member)); |
| ... | @@ -251,7 +251,7 @@ pub const DeclState = struct { | ... | @@ -251,7 +251,7 @@ pub const DeclState = struct { |
| 251 | try dbg_info_buffer.resize(index + 4); | 251 | try dbg_info_buffer.resize(index + 4); |
| 252 | try self.addTypeRelocGlobal(atom_index, payload_ty, @intCast(u32, index)); | 252 | try self.addTypeRelocGlobal(atom_index, payload_ty, @intCast(u32, index)); |
| 253 | // DW.AT.data_member_location, DW.FORM.udata | 253 | // DW.AT.data_member_location, DW.FORM.udata |
| 254 | const offset = abi_size - payload_ty.abiSize(target); | 254 | const offset = abi_size - payload_ty.abiSize(mod); |
| 255 | try leb128.writeULEB128(dbg_info_buffer.writer(), offset); | 255 | try leb128.writeULEB128(dbg_info_buffer.writer(), offset); |
| 256 | // DW.AT.structure_type delimit children | 256 | // DW.AT.structure_type delimit children |
| 257 | try dbg_info_buffer.append(0); | 257 | try dbg_info_buffer.append(0); |
| ... | @@ -266,9 +266,9 @@ pub const DeclState = struct { | ... | @@ -266,9 +266,9 @@ pub const DeclState = struct { |
| 266 | try dbg_info_buffer.ensureUnusedCapacity(2); | 266 | try dbg_info_buffer.ensureUnusedCapacity(2); |
| 267 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_type)); | 267 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_type)); |
| 268 | // DW.AT.byte_size, DW.FORM.udata | 268 | // DW.AT.byte_size, DW.FORM.udata |
| 269 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target)); | 269 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod)); |
| 270 | // DW.AT.name, DW.FORM.string | 270 | // DW.AT.name, DW.FORM.string |
| 271 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | 271 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)}); |
| 272 | // DW.AT.member | 272 | // DW.AT.member |
| 273 | try dbg_info_buffer.ensureUnusedCapacity(5); | 273 | try dbg_info_buffer.ensureUnusedCapacity(5); |
| 274 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member)); | 274 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member)); |
| ... | @@ -311,7 +311,7 @@ pub const DeclState = struct { | ... | @@ -311,7 +311,7 @@ pub const DeclState = struct { |
| 311 | // DW.AT.array_type | 311 | // DW.AT.array_type |
| 312 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_type)); | 312 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_type)); |
| 313 | // DW.AT.name, DW.FORM.string | 313 | // DW.AT.name, DW.FORM.string |
| 314 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | 314 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)}); |
| 315 | // DW.AT.type, DW.FORM.ref4 | 315 | // DW.AT.type, DW.FORM.ref4 |
| 316 | var index = dbg_info_buffer.items.len; | 316 | var index = dbg_info_buffer.items.len; |
| 317 | try dbg_info_buffer.resize(index + 4); | 317 | try dbg_info_buffer.resize(index + 4); |
| ... | @@ -332,12 +332,12 @@ pub const DeclState = struct { | ... | @@ -332,12 +332,12 @@ pub const DeclState = struct { |
| 332 | // DW.AT.structure_type | 332 | // DW.AT.structure_type |
| 333 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type)); | 333 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type)); |
| 334 | // DW.AT.byte_size, DW.FORM.udata | 334 | // DW.AT.byte_size, DW.FORM.udata |
| 335 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target)); | 335 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod)); |
| 336 | 336 | ||
| 337 | switch (ty.tag()) { | 337 | switch (ty.tag()) { |
| 338 | .tuple, .anon_struct => { | 338 | .tuple, .anon_struct => { |
| 339 | // DW.AT.name, DW.FORM.string | 339 | // DW.AT.name, DW.FORM.string |
| 340 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | 340 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)}); |
| 341 | 341 | ||
| 342 | const fields = ty.tupleFields(); | 342 | const fields = ty.tupleFields(); |
| 343 | for (fields.types, 0..) |field, field_index| { | 343 | for (fields.types, 0..) |field, field_index| { |
| ... | @@ -350,13 +350,13 @@ pub const DeclState = struct { | ... | @@ -350,13 +350,13 @@ pub const DeclState = struct { |
| 350 | try dbg_info_buffer.resize(index + 4); | 350 | try dbg_info_buffer.resize(index + 4); |
| 351 | try self.addTypeRelocGlobal(atom_index, field, @intCast(u32, index)); | 351 | try self.addTypeRelocGlobal(atom_index, field, @intCast(u32, index)); |
| 352 | // DW.AT.data_member_location, DW.FORM.udata | 352 | // DW.AT.data_member_location, DW.FORM.udata |
| 353 | const field_off = ty.structFieldOffset(field_index, target); | 353 | const field_off = ty.structFieldOffset(field_index, mod); |
| 354 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); | 354 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); |
| 355 | } | 355 | } |
| 356 | }, | 356 | }, |
| 357 | else => { | 357 | else => { |
| 358 | // DW.AT.name, DW.FORM.string | 358 | // DW.AT.name, DW.FORM.string |
| 359 | const struct_name = try ty.nameAllocArena(arena, module); | 359 | const struct_name = try ty.nameAllocArena(arena, mod); |
| 360 | try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1); | 360 | try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1); |
| 361 | dbg_info_buffer.appendSliceAssumeCapacity(struct_name); | 361 | dbg_info_buffer.appendSliceAssumeCapacity(struct_name); |
| 362 | dbg_info_buffer.appendAssumeCapacity(0); | 362 | dbg_info_buffer.appendAssumeCapacity(0); |
| ... | @@ -370,7 +370,7 @@ pub const DeclState = struct { | ... | @@ -370,7 +370,7 @@ pub const DeclState = struct { |
| 370 | const fields = ty.structFields(); | 370 | const fields = ty.structFields(); |
| 371 | for (fields.keys(), 0..) |field_name, field_index| { | 371 | for (fields.keys(), 0..) |field_name, field_index| { |
| 372 | const field = fields.get(field_name).?; | 372 | const field = fields.get(field_name).?; |
| 373 | if (!field.ty.hasRuntimeBits()) continue; | 373 | if (!field.ty.hasRuntimeBits(mod)) continue; |
| 374 | // DW.AT.member | 374 | // DW.AT.member |
| 375 | try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2); | 375 | try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2); |
| 376 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member)); | 376 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member)); |
| ... | @@ -382,7 +382,7 @@ pub const DeclState = struct { | ... | @@ -382,7 +382,7 @@ pub const DeclState = struct { |
| 382 | try dbg_info_buffer.resize(index + 4); | 382 | try dbg_info_buffer.resize(index + 4); |
| 383 | try self.addTypeRelocGlobal(atom_index, field.ty, @intCast(u32, index)); | 383 | try self.addTypeRelocGlobal(atom_index, field.ty, @intCast(u32, index)); |
| 384 | // DW.AT.data_member_location, DW.FORM.udata | 384 | // DW.AT.data_member_location, DW.FORM.udata |
| 385 | const field_off = ty.structFieldOffset(field_index, target); | 385 | const field_off = ty.structFieldOffset(field_index, mod); |
| 386 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); | 386 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); |
| 387 | } | 387 | } |
| 388 | }, | 388 | }, |
| ... | @@ -395,9 +395,9 @@ pub const DeclState = struct { | ... | @@ -395,9 +395,9 @@ pub const DeclState = struct { |
| 395 | // DW.AT.enumeration_type | 395 | // DW.AT.enumeration_type |
| 396 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type)); | 396 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type)); |
| 397 | // DW.AT.byte_size, DW.FORM.udata | 397 | // DW.AT.byte_size, DW.FORM.udata |
| 398 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target)); | 398 | try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod)); |
| 399 | // DW.AT.name, DW.FORM.string | 399 | // DW.AT.name, DW.FORM.string |
| 400 | const enum_name = try ty.nameAllocArena(arena, module); | 400 | const enum_name = try ty.nameAllocArena(arena, mod); |
| 401 | try dbg_info_buffer.ensureUnusedCapacity(enum_name.len + 1); | 401 | try dbg_info_buffer.ensureUnusedCapacity(enum_name.len + 1); |
| 402 | dbg_info_buffer.appendSliceAssumeCapacity(enum_name); | 402 | dbg_info_buffer.appendSliceAssumeCapacity(enum_name); |
| 403 | dbg_info_buffer.appendAssumeCapacity(0); | 403 | dbg_info_buffer.appendAssumeCapacity(0); |
| ... | @@ -424,7 +424,7 @@ pub const DeclState = struct { | ... | @@ -424,7 +424,7 @@ pub const DeclState = struct { |
| 424 | // See https://github.com/ziglang/zig/issues/645 | 424 | // See https://github.com/ziglang/zig/issues/645 |
| 425 | var int_buffer: Value.Payload.U64 = undefined; | 425 | var int_buffer: Value.Payload.U64 = undefined; |
| 426 | const field_int_val = value.enumToInt(ty, &int_buffer); | 426 | const field_int_val = value.enumToInt(ty, &int_buffer); |
| 427 | break :value @bitCast(u64, field_int_val.toSignedInt(target)); | 427 | break :value @bitCast(u64, field_int_val.toSignedInt(mod)); |
| 428 | } else @intCast(u64, field_i); | 428 | } else @intCast(u64, field_i); |
| 429 | mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian); | 429 | mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian); |
| 430 | } | 430 | } |
| ... | @@ -433,12 +433,12 @@ pub const DeclState = struct { | ... | @@ -433,12 +433,12 @@ pub const DeclState = struct { |
| 433 | try dbg_info_buffer.append(0); | 433 | try dbg_info_buffer.append(0); |
| 434 | }, | 434 | }, |
| 435 | .Union => { | 435 | .Union => { |
| 436 | const layout = ty.unionGetLayout(target); | 436 | const layout = ty.unionGetLayout(mod); |
| 437 | const union_obj = ty.cast(Type.Payload.Union).?.data; | 437 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 438 | const payload_offset = if (layout.tag_align >= layout.payload_align) layout.tag_size else 0; | 438 | const payload_offset = if (layout.tag_align >= layout.payload_align) layout.tag_size else 0; |
| 439 | const tag_offset = if (layout.tag_align >= layout.payload_align) 0 else layout.payload_size; | 439 | const tag_offset = if (layout.tag_align >= layout.payload_align) 0 else layout.payload_size; |
| 440 | const is_tagged = layout.tag_size > 0; | 440 | const is_tagged = layout.tag_size > 0; |
| 441 | const union_name = try ty.nameAllocArena(arena, module); | 441 | const union_name = try ty.nameAllocArena(arena, mod); |
| 442 | 442 | ||
| 443 | // TODO this is temporary to match current state of unions in Zig - we don't yet have | 443 | // TODO this is temporary to match current state of unions in Zig - we don't yet have |
| 444 | // safety checks implemented meaning the implicit tag is not yet stored and generated | 444 | // safety checks implemented meaning the implicit tag is not yet stored and generated |
| ... | @@ -481,7 +481,7 @@ pub const DeclState = struct { | ... | @@ -481,7 +481,7 @@ pub const DeclState = struct { |
| 481 | const fields = ty.unionFields(); | 481 | const fields = ty.unionFields(); |
| 482 | for (fields.keys()) |field_name| { | 482 | for (fields.keys()) |field_name| { |
| 483 | const field = fields.get(field_name).?; | 483 | const field = fields.get(field_name).?; |
| 484 | if (!field.ty.hasRuntimeBits()) continue; | 484 | if (!field.ty.hasRuntimeBits(mod)) continue; |
| 485 | // DW.AT.member | 485 | // DW.AT.member |
| 486 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member)); | 486 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member)); |
| 487 | // DW.AT.name, DW.FORM.string | 487 | // DW.AT.name, DW.FORM.string |
| ... | @@ -517,7 +517,7 @@ pub const DeclState = struct { | ... | @@ -517,7 +517,7 @@ pub const DeclState = struct { |
| 517 | .ErrorSet => { | 517 | .ErrorSet => { |
| 518 | try addDbgInfoErrorSet( | 518 | try addDbgInfoErrorSet( |
| 519 | self.abbrev_type_arena.allocator(), | 519 | self.abbrev_type_arena.allocator(), |
| 520 | module, | 520 | mod, |
| 521 | ty, | 521 | ty, |
| 522 | target, | 522 | target, |
| 523 | &self.dbg_info, | 523 | &self.dbg_info, |
| ... | @@ -526,18 +526,18 @@ pub const DeclState = struct { | ... | @@ -526,18 +526,18 @@ pub const DeclState = struct { |
| 526 | .ErrorUnion => { | 526 | .ErrorUnion => { |
| 527 | const error_ty = ty.errorUnionSet(); | 527 | const error_ty = ty.errorUnionSet(); |
| 528 | const payload_ty = ty.errorUnionPayload(); | 528 | const payload_ty = ty.errorUnionPayload(); |
| 529 | const payload_align = if (payload_ty.isNoReturn()) 0 else payload_ty.abiAlignment(target); | 529 | const payload_align = if (payload_ty.isNoReturn()) 0 else payload_ty.abiAlignment(mod); |
| 530 | const error_align = Type.anyerror.abiAlignment(target); | 530 | const error_align = Type.anyerror.abiAlignment(mod); |
| 531 | const abi_size = ty.abiSize(target); | 531 | const abi_size = ty.abiSize(mod); |
| 532 | const payload_off = if (error_align >= payload_align) Type.anyerror.abiSize(target) else 0; | 532 | const payload_off = if (error_align >= payload_align) Type.anyerror.abiSize(mod) else 0; |
| 533 | const error_off = if (error_align >= payload_align) 0 else payload_ty.abiSize(target); | 533 | const error_off = if (error_align >= payload_align) 0 else payload_ty.abiSize(mod); |
| 534 | 534 | ||
| 535 | // DW.AT.structure_type | 535 | // DW.AT.structure_type |
| 536 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type)); | 536 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type)); |
| 537 | // DW.AT.byte_size, DW.FORM.udata | 537 | // DW.AT.byte_size, DW.FORM.udata |
| 538 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); | 538 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); |
| 539 | // DW.AT.name, DW.FORM.string | 539 | // DW.AT.name, DW.FORM.string |
| 540 | const name = try ty.nameAllocArena(arena, module); | 540 | const name = try ty.nameAllocArena(arena, mod); |
| 541 | try dbg_info_buffer.writer().print("{s}\x00", .{name}); | 541 | try dbg_info_buffer.writer().print("{s}\x00", .{name}); |
| 542 | 542 | ||
| 543 | if (!payload_ty.isNoReturn()) { | 543 | if (!payload_ty.isNoReturn()) { |
| ... | @@ -685,7 +685,8 @@ pub const DeclState = struct { | ... | @@ -685,7 +685,8 @@ pub const DeclState = struct { |
| 685 | const atom_index = self.di_atom_decls.get(owner_decl).?; | 685 | const atom_index = self.di_atom_decls.get(owner_decl).?; |
| 686 | const name_with_null = name.ptr[0 .. name.len + 1]; | 686 | const name_with_null = name.ptr[0 .. name.len + 1]; |
| 687 | try dbg_info.append(@enumToInt(AbbrevKind.variable)); | 687 | try dbg_info.append(@enumToInt(AbbrevKind.variable)); |
| 688 | const target = self.mod.getTarget(); | 688 | const mod = self.mod; |
| 689 | const target = mod.getTarget(); | ||
| 689 | const endian = target.cpu.arch.endian(); | 690 | const endian = target.cpu.arch.endian(); |
| 690 | const child_ty = if (is_ptr) ty.childType() else ty; | 691 | const child_ty = if (is_ptr) ty.childType() else ty; |
| 691 | 692 | ||
| ... | @@ -790,9 +791,9 @@ pub const DeclState = struct { | ... | @@ -790,9 +791,9 @@ pub const DeclState = struct { |
| 790 | const fixup = dbg_info.items.len; | 791 | const fixup = dbg_info.items.len; |
| 791 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | 792 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 792 | 1, | 793 | 1, |
| 793 | if (child_ty.isSignedInt()) DW.OP.consts else DW.OP.constu, | 794 | if (child_ty.isSignedInt(mod)) DW.OP.consts else DW.OP.constu, |
| 794 | }); | 795 | }); |
| 795 | if (child_ty.isSignedInt()) { | 796 | if (child_ty.isSignedInt(mod)) { |
| 796 | try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)); | 797 | try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)); |
| 797 | } else { | 798 | } else { |
| 798 | try leb128.writeULEB128(dbg_info.writer(), x); | 799 | try leb128.writeULEB128(dbg_info.writer(), x); |
| ... | @@ -805,7 +806,7 @@ pub const DeclState = struct { | ... | @@ -805,7 +806,7 @@ pub const DeclState = struct { |
| 805 | // DW.AT.location, DW.FORM.exprloc | 806 | // DW.AT.location, DW.FORM.exprloc |
| 806 | // uleb128(exprloc_len) | 807 | // uleb128(exprloc_len) |
| 807 | // DW.OP.implicit_value uleb128(len_of_bytes) bytes | 808 | // DW.OP.implicit_value uleb128(len_of_bytes) bytes |
| 808 | const abi_size = @intCast(u32, child_ty.abiSize(target)); | 809 | const abi_size = @intCast(u32, child_ty.abiSize(mod)); |
| 809 | var implicit_value_len = std.ArrayList(u8).init(self.gpa); | 810 | var implicit_value_len = std.ArrayList(u8).init(self.gpa); |
| 810 | defer implicit_value_len.deinit(); | 811 | defer implicit_value_len.deinit(); |
| 811 | try leb128.writeULEB128(implicit_value_len.writer(), abi_size); | 812 | try leb128.writeULEB128(implicit_value_len.writer(), abi_size); |
| ... | @@ -979,7 +980,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) | ... | @@ -979,7 +980,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) |
| 979 | 980 | ||
| 980 | assert(decl.has_tv); | 981 | assert(decl.has_tv); |
| 981 | 982 | ||
| 982 | switch (decl.ty.zigTypeTag()) { | 983 | switch (decl.ty.zigTypeTag(mod)) { |
| 983 | .Fn => { | 984 | .Fn => { |
| 984 | _ = try self.getOrCreateAtomForDecl(.src_fn, decl_index); | 985 | _ = try self.getOrCreateAtomForDecl(.src_fn, decl_index); |
| 985 | 986 | ||
| ... | @@ -1027,7 +1028,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) | ... | @@ -1027,7 +1028,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) |
| 1027 | try dbg_info_buffer.ensureUnusedCapacity(25 + decl_name_with_null.len); | 1028 | try dbg_info_buffer.ensureUnusedCapacity(25 + decl_name_with_null.len); |
| 1028 | 1029 | ||
| 1029 | const fn_ret_type = decl.ty.fnReturnType(); | 1030 | const fn_ret_type = decl.ty.fnReturnType(); |
| 1030 | const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(); | 1031 | const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod); |
| 1031 | if (fn_ret_has_bits) { | 1032 | if (fn_ret_has_bits) { |
| 1032 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.subprogram)); | 1033 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.subprogram)); |
| 1033 | } else { | 1034 | } else { |
| ... | @@ -1059,7 +1060,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) | ... | @@ -1059,7 +1060,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) |
| 1059 | 1060 | ||
| 1060 | pub fn commitDeclState( | 1061 | pub fn commitDeclState( |
| 1061 | self: *Dwarf, | 1062 | self: *Dwarf, |
| 1062 | module: *Module, | 1063 | mod: *Module, |
| 1063 | decl_index: Module.Decl.Index, | 1064 | decl_index: Module.Decl.Index, |
| 1064 | sym_addr: u64, | 1065 | sym_addr: u64, |
| 1065 | sym_size: u64, | 1066 | sym_size: u64, |
| ... | @@ -1071,12 +1072,12 @@ pub fn commitDeclState( | ... | @@ -1071,12 +1072,12 @@ pub fn commitDeclState( |
| 1071 | const gpa = self.allocator; | 1072 | const gpa = self.allocator; |
| 1072 | var dbg_line_buffer = &decl_state.dbg_line; | 1073 | var dbg_line_buffer = &decl_state.dbg_line; |
| 1073 | var dbg_info_buffer = &decl_state.dbg_info; | 1074 | var dbg_info_buffer = &decl_state.dbg_info; |
| 1074 | const decl = module.declPtr(decl_index); | 1075 | const decl = mod.declPtr(decl_index); |
| 1075 | 1076 | ||
| 1076 | const target_endian = self.target.cpu.arch.endian(); | 1077 | const target_endian = self.target.cpu.arch.endian(); |
| 1077 | 1078 | ||
| 1078 | assert(decl.has_tv); | 1079 | assert(decl.has_tv); |
| 1079 | switch (decl.ty.zigTypeTag()) { | 1080 | switch (decl.ty.zigTypeTag(mod)) { |
| 1080 | .Fn => { | 1081 | .Fn => { |
| 1081 | // Since the Decl is a function, we need to update the .debug_line program. | 1082 | // Since the Decl is a function, we need to update the .debug_line program. |
| 1082 | // Perform the relocations based on vaddr. | 1083 | // Perform the relocations based on vaddr. |
| ... | @@ -1283,7 +1284,7 @@ pub fn commitDeclState( | ... | @@ -1283,7 +1284,7 @@ pub fn commitDeclState( |
| 1283 | if (deferred) continue; | 1284 | if (deferred) continue; |
| 1284 | 1285 | ||
| 1285 | symbol.offset = @intCast(u32, dbg_info_buffer.items.len); | 1286 | symbol.offset = @intCast(u32, dbg_info_buffer.items.len); |
| 1286 | try decl_state.addDbgInfoType(module, di_atom_index, ty); | 1287 | try decl_state.addDbgInfoType(mod, di_atom_index, ty); |
| 1287 | } | 1288 | } |
| 1288 | } | 1289 | } |
| 1289 | 1290 | ||
| ... | @@ -1319,7 +1320,7 @@ pub fn commitDeclState( | ... | @@ -1319,7 +1320,7 @@ pub fn commitDeclState( |
| 1319 | reloc.offset, | 1320 | reloc.offset, |
| 1320 | value, | 1321 | value, |
| 1321 | target, | 1322 | target, |
| 1322 | ty.fmt(module), | 1323 | ty.fmt(mod), |
| 1323 | }); | 1324 | }); |
| 1324 | mem.writeInt( | 1325 | mem.writeInt( |
| 1325 | u32, | 1326 | u32, |
| ... | @@ -2663,7 +2664,7 @@ fn genIncludeDirsAndFileNames(self: *Dwarf, arena: Allocator) !struct { | ... | @@ -2663,7 +2664,7 @@ fn genIncludeDirsAndFileNames(self: *Dwarf, arena: Allocator) !struct { |
| 2663 | 2664 | ||
| 2664 | fn addDbgInfoErrorSet( | 2665 | fn addDbgInfoErrorSet( |
| 2665 | arena: Allocator, | 2666 | arena: Allocator, |
| 2666 | module: *Module, | 2667 | mod: *Module, |
| 2667 | ty: Type, | 2668 | ty: Type, |
| 2668 | target: std.Target, | 2669 | target: std.Target, |
| 2669 | dbg_info_buffer: *std.ArrayList(u8), | 2670 | dbg_info_buffer: *std.ArrayList(u8), |
| ... | @@ -2673,10 +2674,10 @@ fn addDbgInfoErrorSet( | ... | @@ -2673,10 +2674,10 @@ fn addDbgInfoErrorSet( |
| 2673 | // DW.AT.enumeration_type | 2674 | // DW.AT.enumeration_type |
| 2674 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type)); | 2675 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type)); |
| 2675 | // DW.AT.byte_size, DW.FORM.udata | 2676 | // DW.AT.byte_size, DW.FORM.udata |
| 2676 | const abi_size = Type.anyerror.abiSize(target); | 2677 | const abi_size = Type.anyerror.abiSize(mod); |
| 2677 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); | 2678 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); |
| 2678 | // DW.AT.name, DW.FORM.string | 2679 | // DW.AT.name, DW.FORM.string |
| 2679 | const name = try ty.nameAllocArena(arena, module); | 2680 | const name = try ty.nameAllocArena(arena, mod); |
| 2680 | try dbg_info_buffer.writer().print("{s}\x00", .{name}); | 2681 | try dbg_info_buffer.writer().print("{s}\x00", .{name}); |
| 2681 | 2682 | ||
| 2682 | // DW.AT.enumerator | 2683 | // DW.AT.enumerator |
| ... | @@ -2691,7 +2692,7 @@ fn addDbgInfoErrorSet( | ... | @@ -2691,7 +2692,7 @@ fn addDbgInfoErrorSet( |
| 2691 | 2692 | ||
| 2692 | const error_names = ty.errorSetNames(); | 2693 | const error_names = ty.errorSetNames(); |
| 2693 | for (error_names) |error_name| { | 2694 | for (error_names) |error_name| { |
| 2694 | const kv = module.getErrorValue(error_name) catch unreachable; | 2695 | const kv = mod.getErrorValue(error_name) catch unreachable; |
| 2695 | // DW.AT.enumerator | 2696 | // DW.AT.enumerator |
| 2696 | try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64)); | 2697 | try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64)); |
| 2697 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.enum_variant)); | 2698 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.enum_variant)); |
src/link/Elf.zig+5-4| ... | @@ -2449,9 +2449,10 @@ pub fn getOrCreateAtomForDecl(self: *Elf, decl_index: Module.Decl.Index) !Atom.I | ... | @@ -2449,9 +2449,10 @@ pub fn getOrCreateAtomForDecl(self: *Elf, decl_index: Module.Decl.Index) !Atom.I |
| 2449 | } | 2449 | } |
| 2450 | 2450 | ||
| 2451 | fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 { | 2451 | fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 { |
| 2452 | const decl = self.base.options.module.?.declPtr(decl_index); | 2452 | const mod = self.base.options.module.?; |
| 2453 | const decl = mod.declPtr(decl_index); | ||
| 2453 | const ty = decl.ty; | 2454 | const ty = decl.ty; |
| 2454 | const zig_ty = ty.zigTypeTag(); | 2455 | const zig_ty = ty.zigTypeTag(mod); |
| 2455 | const val = decl.val; | 2456 | const val = decl.val; |
| 2456 | const shdr_index: u16 = blk: { | 2457 | const shdr_index: u16 = blk: { |
| 2457 | if (val.isUndefDeep()) { | 2458 | if (val.isUndefDeep()) { |
| ... | @@ -2482,7 +2483,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s | ... | @@ -2482,7 +2483,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s |
| 2482 | defer self.base.allocator.free(decl_name); | 2483 | defer self.base.allocator.free(decl_name); |
| 2483 | 2484 | ||
| 2484 | log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); | 2485 | log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); |
| 2485 | const required_alignment = decl.getAlignment(self.base.options.target); | 2486 | const required_alignment = decl.getAlignment(mod); |
| 2486 | 2487 | ||
| 2487 | const decl_metadata = self.decls.get(decl_index).?; | 2488 | const decl_metadata = self.decls.get(decl_index).?; |
| 2488 | const atom_index = decl_metadata.atom; | 2489 | const atom_index = decl_metadata.atom; |
| ... | @@ -2826,7 +2827,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module | ... | @@ -2826,7 +2827,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 2826 | }, | 2827 | }, |
| 2827 | }; | 2828 | }; |
| 2828 | 2829 | ||
| 2829 | const required_alignment = typed_value.ty.abiAlignment(self.base.options.target); | 2830 | const required_alignment = typed_value.ty.abiAlignment(mod); |
| 2830 | const shdr_index = self.rodata_section_index.?; | 2831 | const shdr_index = self.rodata_section_index.?; |
| 2831 | const phdr_index = self.sections.items(.phdr_index)[shdr_index]; | 2832 | const phdr_index = self.sections.items(.phdr_index)[shdr_index]; |
| 2832 | const local_sym = self.getAtom(atom_index).getSymbolPtr(self); | 2833 | const local_sym = self.getAtom(atom_index).getSymbolPtr(self); |
src/link/MachO.zig+7-4| ... | @@ -1948,7 +1948,8 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu | ... | @@ -1948,7 +1948,8 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu |
| 1948 | }, | 1948 | }, |
| 1949 | }; | 1949 | }; |
| 1950 | 1950 | ||
| 1951 | const required_alignment = typed_value.ty.abiAlignment(self.base.options.target); | 1951 | const mod = self.base.options.module.?; |
| 1952 | const required_alignment = typed_value.ty.abiAlignment(mod); | ||
| 1952 | const atom = self.getAtomPtr(atom_index); | 1953 | const atom = self.getAtomPtr(atom_index); |
| 1953 | atom.size = code.len; | 1954 | atom.size = code.len; |
| 1954 | // TODO: work out logic for disambiguating functions from function pointers | 1955 | // TODO: work out logic for disambiguating functions from function pointers |
| ... | @@ -2152,6 +2153,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In | ... | @@ -2152,6 +2153,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In |
| 2152 | } | 2153 | } |
| 2153 | 2154 | ||
| 2154 | fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void { | 2155 | fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void { |
| 2156 | const mod = self.base.options.module.?; | ||
| 2155 | // Lowering a TLV on macOS involves two stages: | 2157 | // Lowering a TLV on macOS involves two stages: |
| 2156 | // 1. first we lower the initializer into appopriate section (__thread_data or __thread_bss) | 2158 | // 1. first we lower the initializer into appopriate section (__thread_data or __thread_bss) |
| 2157 | // 2. next, we create a corresponding threadlocal variable descriptor in __thread_vars | 2159 | // 2. next, we create a corresponding threadlocal variable descriptor in __thread_vars |
| ... | @@ -2202,7 +2204,7 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D | ... | @@ -2202,7 +2204,7 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D |
| 2202 | }, | 2204 | }, |
| 2203 | }; | 2205 | }; |
| 2204 | 2206 | ||
| 2205 | const required_alignment = decl.getAlignment(self.base.options.target); | 2207 | const required_alignment = decl.getAlignment(mod); |
| 2206 | 2208 | ||
| 2207 | const decl_name = try decl.getFullyQualifiedName(module); | 2209 | const decl_name = try decl.getFullyQualifiedName(module); |
| 2208 | defer gpa.free(decl_name); | 2210 | defer gpa.free(decl_name); |
| ... | @@ -2262,7 +2264,8 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 { | ... | @@ -2262,7 +2264,8 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 { |
| 2262 | const decl = self.base.options.module.?.declPtr(decl_index); | 2264 | const decl = self.base.options.module.?.declPtr(decl_index); |
| 2263 | const ty = decl.ty; | 2265 | const ty = decl.ty; |
| 2264 | const val = decl.val; | 2266 | const val = decl.val; |
| 2265 | const zig_ty = ty.zigTypeTag(); | 2267 | const mod = self.base.options.module.?; |
| 2268 | const zig_ty = ty.zigTypeTag(mod); | ||
| 2266 | const mode = self.base.options.optimize_mode; | 2269 | const mode = self.base.options.optimize_mode; |
| 2267 | const single_threaded = self.base.options.single_threaded; | 2270 | const single_threaded = self.base.options.single_threaded; |
| 2268 | const sect_id: u8 = blk: { | 2271 | const sect_id: u8 = blk: { |
| ... | @@ -2301,7 +2304,7 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64 | ... | @@ -2301,7 +2304,7 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64 |
| 2301 | const mod = self.base.options.module.?; | 2304 | const mod = self.base.options.module.?; |
| 2302 | const decl = mod.declPtr(decl_index); | 2305 | const decl = mod.declPtr(decl_index); |
| 2303 | 2306 | ||
| 2304 | const required_alignment = decl.getAlignment(self.base.options.target); | 2307 | const required_alignment = decl.getAlignment(mod); |
| 2305 | 2308 | ||
| 2306 | const decl_name = try decl.getFullyQualifiedName(mod); | 2309 | const decl_name = try decl.getFullyQualifiedName(mod); |
| 2307 | defer gpa.free(decl_name); | 2310 | defer gpa.free(decl_name); |
src/link/Plan9.zig+5-4| ... | @@ -432,8 +432,9 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) | ... | @@ -432,8 +432,9 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) |
| 432 | } | 432 | } |
| 433 | /// called at the end of update{Decl,Func} | 433 | /// called at the end of update{Decl,Func} |
| 434 | fn updateFinish(self: *Plan9, decl_index: Module.Decl.Index) !void { | 434 | fn updateFinish(self: *Plan9, decl_index: Module.Decl.Index) !void { |
| 435 | const decl = self.base.options.module.?.declPtr(decl_index); | 435 | const mod = self.base.options.module.?; |
| 436 | const is_fn = (decl.ty.zigTypeTag() == .Fn); | 436 | const decl = mod.declPtr(decl_index); |
| 437 | const is_fn = (decl.ty.zigTypeTag(mod) == .Fn); | ||
| 437 | log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name }); | 438 | log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name }); |
| 438 | const sym_t: aout.Sym.Type = if (is_fn) .t else .d; | 439 | const sym_t: aout.Sym.Type = if (is_fn) .t else .d; |
| 439 | 440 | ||
| ... | @@ -704,7 +705,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -704,7 +705,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 704 | log.debug("relocating the address of '{s}' + {d} into '{s}' + {d}", .{ target_decl.name, addend, source_decl.name, offset }); | 705 | log.debug("relocating the address of '{s}' + {d} into '{s}' + {d}", .{ target_decl.name, addend, source_decl.name, offset }); |
| 705 | 706 | ||
| 706 | const code = blk: { | 707 | const code = blk: { |
| 707 | const is_fn = source_decl.ty.zigTypeTag() == .Fn; | 708 | const is_fn = source_decl.ty.zigTypeTag(mod) == .Fn; |
| 708 | if (is_fn) { | 709 | if (is_fn) { |
| 709 | const table = self.fn_decl_table.get(source_decl.getFileScope()).?.functions; | 710 | const table = self.fn_decl_table.get(source_decl.getFileScope()).?.functions; |
| 710 | const output = table.get(source_decl_index).?; | 711 | const output = table.get(source_decl_index).?; |
| ... | @@ -1031,7 +1032,7 @@ pub fn getDeclVAddr( | ... | @@ -1031,7 +1032,7 @@ pub fn getDeclVAddr( |
| 1031 | ) !u64 { | 1032 | ) !u64 { |
| 1032 | const mod = self.base.options.module.?; | 1033 | const mod = self.base.options.module.?; |
| 1033 | const decl = mod.declPtr(decl_index); | 1034 | const decl = mod.declPtr(decl_index); |
| 1034 | if (decl.ty.zigTypeTag() == .Fn) { | 1035 | if (decl.ty.zigTypeTag(mod) == .Fn) { |
| 1035 | var start = self.bases.text; | 1036 | var start = self.bases.text; |
| 1036 | var it_file = self.fn_decl_table.iterator(); | 1037 | var it_file = self.fn_decl_table.iterator(); |
| 1037 | while (it_file.next()) |fentry| { | 1038 | while (it_file.next()) |fentry| { |
src/link/Wasm.zig+8-8| ... | @@ -1473,7 +1473,7 @@ fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8 | ... | @@ -1473,7 +1473,7 @@ fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8 |
| 1473 | 1473 | ||
| 1474 | atom.size = @intCast(u32, code.len); | 1474 | atom.size = @intCast(u32, code.len); |
| 1475 | if (code.len == 0) return; | 1475 | if (code.len == 0) return; |
| 1476 | atom.alignment = decl.ty.abiAlignment(wasm.base.options.target); | 1476 | atom.alignment = decl.ty.abiAlignment(mod); |
| 1477 | } | 1477 | } |
| 1478 | 1478 | ||
| 1479 | /// From a given symbol location, returns its `wasm.GlobalType`. | 1479 | /// From a given symbol location, returns its `wasm.GlobalType`. |
| ... | @@ -1523,9 +1523,8 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type { | ... | @@ -1523,9 +1523,8 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type { |
| 1523 | /// Returns the symbol index of the local | 1523 | /// Returns the symbol index of the local |
| 1524 | /// The given `decl` is the parent decl whom owns the constant. | 1524 | /// The given `decl` is the parent decl whom owns the constant. |
| 1525 | pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { | 1525 | pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { |
| 1526 | assert(tv.ty.zigTypeTag() != .Fn); // cannot create local symbols for functions | ||
| 1527 | |||
| 1528 | const mod = wasm.base.options.module.?; | 1526 | const mod = wasm.base.options.module.?; |
| 1527 | assert(tv.ty.zigTypeTag(mod) != .Fn); // cannot create local symbols for functions | ||
| 1529 | const decl = mod.declPtr(decl_index); | 1528 | const decl = mod.declPtr(decl_index); |
| 1530 | 1529 | ||
| 1531 | // Create and initialize a new local symbol and atom | 1530 | // Create and initialize a new local symbol and atom |
| ... | @@ -1543,7 +1542,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In | ... | @@ -1543,7 +1542,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In |
| 1543 | 1542 | ||
| 1544 | const code = code: { | 1543 | const code = code: { |
| 1545 | const atom = wasm.getAtomPtr(atom_index); | 1544 | const atom = wasm.getAtomPtr(atom_index); |
| 1546 | atom.alignment = tv.ty.abiAlignment(wasm.base.options.target); | 1545 | atom.alignment = tv.ty.abiAlignment(mod); |
| 1547 | wasm.symbols.items[atom.sym_index] = .{ | 1546 | wasm.symbols.items[atom.sym_index] = .{ |
| 1548 | .name = try wasm.string_table.put(wasm.base.allocator, name), | 1547 | .name = try wasm.string_table.put(wasm.base.allocator, name), |
| 1549 | .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL), | 1548 | .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL), |
| ... | @@ -1632,7 +1631,7 @@ pub fn getDeclVAddr( | ... | @@ -1632,7 +1631,7 @@ pub fn getDeclVAddr( |
| 1632 | const atom_index = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?; | 1631 | const atom_index = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?; |
| 1633 | const atom = wasm.getAtomPtr(atom_index); | 1632 | const atom = wasm.getAtomPtr(atom_index); |
| 1634 | const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32; | 1633 | const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32; |
| 1635 | if (decl.ty.zigTypeTag() == .Fn) { | 1634 | if (decl.ty.zigTypeTag(mod) == .Fn) { |
| 1636 | assert(reloc_info.addend == 0); // addend not allowed for function relocations | 1635 | assert(reloc_info.addend == 0); // addend not allowed for function relocations |
| 1637 | // We found a function pointer, so add it to our table, | 1636 | // We found a function pointer, so add it to our table, |
| 1638 | // as function pointers are not allowed to be stored inside the data section. | 1637 | // as function pointers are not allowed to be stored inside the data section. |
| ... | @@ -2933,7 +2932,8 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { | ... | @@ -2933,7 +2932,8 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { |
| 2933 | const atom_index = try wasm.createAtom(); | 2932 | const atom_index = try wasm.createAtom(); |
| 2934 | const atom = wasm.getAtomPtr(atom_index); | 2933 | const atom = wasm.getAtomPtr(atom_index); |
| 2935 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); | 2934 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 2936 | atom.alignment = slice_ty.abiAlignment(wasm.base.options.target); | 2935 | const mod = wasm.base.options.module.?; |
| 2936 | atom.alignment = slice_ty.abiAlignment(mod); | ||
| 2937 | const sym_index = atom.sym_index; | 2937 | const sym_index = atom.sym_index; |
| 2938 | 2938 | ||
| 2939 | const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_name_table"); | 2939 | const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_name_table"); |
| ... | @@ -3000,7 +3000,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void { | ... | @@ -3000,7 +3000,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void { |
| 3000 | .offset = offset, | 3000 | .offset = offset, |
| 3001 | .addend = @intCast(i32, addend), | 3001 | .addend = @intCast(i32, addend), |
| 3002 | }); | 3002 | }); |
| 3003 | atom.size += @intCast(u32, slice_ty.abiSize(wasm.base.options.target)); | 3003 | atom.size += @intCast(u32, slice_ty.abiSize(mod)); |
| 3004 | addend += len; | 3004 | addend += len; |
| 3005 | 3005 | ||
| 3006 | // as we updated the error name table, we now store the actual name within the names atom | 3006 | // as we updated the error name table, we now store the actual name within the names atom |
| ... | @@ -3369,7 +3369,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -3369,7 +3369,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 3369 | if (decl.isExtern()) continue; | 3369 | if (decl.isExtern()) continue; |
| 3370 | const atom_index = entry.value_ptr.*; | 3370 | const atom_index = entry.value_ptr.*; |
| 3371 | const atom = wasm.getAtomPtr(atom_index); | 3371 | const atom = wasm.getAtomPtr(atom_index); |
| 3372 | if (decl.ty.zigTypeTag() == .Fn) { | 3372 | if (decl.ty.zigTypeTag(mod) == .Fn) { |
| 3373 | try wasm.parseAtom(atom_index, .function); | 3373 | try wasm.parseAtom(atom_index, .function); |
| 3374 | } else if (decl.getVariable()) |variable| { | 3374 | } else if (decl.getVariable()) |variable| { |
| 3375 | if (!variable.is_mutable) { | 3375 | if (!variable.is_mutable) { |
src/print_air.zig+4-4| ... | @@ -7,6 +7,7 @@ const Value = @import("value.zig").Value; | ... | @@ -7,6 +7,7 @@ const Value = @import("value.zig").Value; |
| 7 | const Type = @import("type.zig").Type; | 7 | const Type = @import("type.zig").Type; |
| 8 | const Air = @import("Air.zig"); | 8 | const Air = @import("Air.zig"); |
| 9 | const Liveness = @import("Liveness.zig"); | 9 | const Liveness = @import("Liveness.zig"); |
| 10 | const InternPool = @import("InternPool.zig"); | ||
| 10 | 11 | ||
| 11 | pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) void { | 12 | pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) void { |
| 12 | const instruction_bytes = air.instructions.len * | 13 | const instruction_bytes = air.instructions.len * |
| ... | @@ -965,14 +966,13 @@ const Writer = struct { | ... | @@ -965,14 +966,13 @@ const Writer = struct { |
| 965 | operand: Air.Inst.Ref, | 966 | operand: Air.Inst.Ref, |
| 966 | dies: bool, | 967 | dies: bool, |
| 967 | ) @TypeOf(s).Error!void { | 968 | ) @TypeOf(s).Error!void { |
| 968 | var i: usize = @enumToInt(operand); | 969 | const i = @enumToInt(operand); |
| 969 | 970 | ||
| 970 | if (i < Air.Inst.Ref.typed_value_map.len) { | 971 | if (i < InternPool.static_len) { |
| 971 | return s.print("@{}", .{operand}); | 972 | return s.print("@{}", .{operand}); |
| 972 | } | 973 | } |
| 973 | i -= Air.Inst.Ref.typed_value_map.len; | ||
| 974 | 974 | ||
| 975 | return w.writeInstIndex(s, @intCast(Air.Inst.Index, i), dies); | 975 | return w.writeInstIndex(s, i - InternPool.static_len, dies); |
| 976 | } | 976 | } |
| 977 | 977 | ||
| 978 | fn writeInstIndex( | 978 | fn writeInstIndex( |
src/print_zir.zig+4-8| ... | @@ -3,6 +3,7 @@ const mem = std.mem; | ... | @@ -3,6 +3,7 @@ const mem = std.mem; |
| 3 | const Allocator = std.mem.Allocator; | 3 | const Allocator = std.mem.Allocator; |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | const Ast = std.zig.Ast; | 5 | const Ast = std.zig.Ast; |
| 6 | const InternPool = @import("InternPool.zig"); | ||
| 6 | 7 | ||
| 7 | const Zir = @import("Zir.zig"); | 8 | const Zir = @import("Zir.zig"); |
| 8 | const Module = @import("Module.zig"); | 9 | const Module = @import("Module.zig"); |
| ... | @@ -2468,14 +2469,9 @@ const Writer = struct { | ... | @@ -2468,14 +2469,9 @@ const Writer = struct { |
| 2468 | } | 2469 | } |
| 2469 | 2470 | ||
| 2470 | fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void { | 2471 | fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void { |
| 2471 | var i: usize = @enumToInt(ref); | 2472 | const i = @enumToInt(ref); |
| 2472 | 2473 | if (i < InternPool.static_len) return stream.print("@{}", .{@intToEnum(InternPool.Index, i)}); | |
| 2473 | if (i < Zir.Inst.Ref.typed_value_map.len) { | 2474 | return self.writeInstIndex(stream, i - InternPool.static_len); |
| 2474 | return stream.print("@{}", .{ref}); | ||
| 2475 | } | ||
| 2476 | i -= Zir.Inst.Ref.typed_value_map.len; | ||
| 2477 | |||
| 2478 | return self.writeInstIndex(stream, @intCast(Zir.Inst.Index, i)); | ||
| 2479 | } | 2475 | } |
| 2480 | 2476 | ||
| 2481 | fn writeInstIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { | 2477 | fn writeInstIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { |
src/target.zig-128| ... | @@ -512,134 +512,6 @@ pub fn needUnwindTables(target: std.Target) bool { | ... | @@ -512,134 +512,6 @@ pub fn needUnwindTables(target: std.Target) bool { |
| 512 | return target.os.tag == .windows; | 512 | return target.os.tag == .windows; |
| 513 | } | 513 | } |
| 514 | 514 | ||
| 515 | pub const AtomicPtrAlignmentError = error{ | ||
| 516 | FloatTooBig, | ||
| 517 | IntTooBig, | ||
| 518 | BadType, | ||
| 519 | }; | ||
| 520 | |||
| 521 | pub const AtomicPtrAlignmentDiagnostics = struct { | ||
| 522 | bits: u16 = undefined, | ||
| 523 | max_bits: u16 = undefined, | ||
| 524 | }; | ||
| 525 | |||
| 526 | /// If ABI alignment of `ty` is OK for atomic operations, returns 0. | ||
| 527 | /// Otherwise returns the alignment required on a pointer for the target | ||
| 528 | /// to perform atomic operations. | ||
| 529 | // TODO this function does not take into account CPU features, which can affect | ||
| 530 | // this value. Audit this! | ||
| 531 | pub fn atomicPtrAlignment( | ||
| 532 | target: std.Target, | ||
| 533 | ty: Type, | ||
| 534 | diags: *AtomicPtrAlignmentDiagnostics, | ||
| 535 | ) AtomicPtrAlignmentError!u32 { | ||
| 536 | const max_atomic_bits: u16 = switch (target.cpu.arch) { | ||
| 537 | .avr, | ||
| 538 | .msp430, | ||
| 539 | .spu_2, | ||
| 540 | => 16, | ||
| 541 | |||
| 542 | .arc, | ||
| 543 | .arm, | ||
| 544 | .armeb, | ||
| 545 | .hexagon, | ||
| 546 | .m68k, | ||
| 547 | .le32, | ||
| 548 | .mips, | ||
| 549 | .mipsel, | ||
| 550 | .nvptx, | ||
| 551 | .powerpc, | ||
| 552 | .powerpcle, | ||
| 553 | .r600, | ||
| 554 | .riscv32, | ||
| 555 | .sparc, | ||
| 556 | .sparcel, | ||
| 557 | .tce, | ||
| 558 | .tcele, | ||
| 559 | .thumb, | ||
| 560 | .thumbeb, | ||
| 561 | .x86, | ||
| 562 | .xcore, | ||
| 563 | .amdil, | ||
| 564 | .hsail, | ||
| 565 | .spir, | ||
| 566 | .kalimba, | ||
| 567 | .lanai, | ||
| 568 | .shave, | ||
| 569 | .wasm32, | ||
| 570 | .renderscript32, | ||
| 571 | .csky, | ||
| 572 | .spirv32, | ||
| 573 | .dxil, | ||
| 574 | .loongarch32, | ||
| 575 | .xtensa, | ||
| 576 | => 32, | ||
| 577 | |||
| 578 | .amdgcn, | ||
| 579 | .bpfel, | ||
| 580 | .bpfeb, | ||
| 581 | .le64, | ||
| 582 | .mips64, | ||
| 583 | .mips64el, | ||
| 584 | .nvptx64, | ||
| 585 | .powerpc64, | ||
| 586 | .powerpc64le, | ||
| 587 | .riscv64, | ||
| 588 | .sparc64, | ||
| 589 | .s390x, | ||
| 590 | .amdil64, | ||
| 591 | .hsail64, | ||
| 592 | .spir64, | ||
| 593 | .wasm64, | ||
| 594 | .renderscript64, | ||
| 595 | .ve, | ||
| 596 | .spirv64, | ||
| 597 | .loongarch64, | ||
| 598 | => 64, | ||
| 599 | |||
| 600 | .aarch64, | ||
| 601 | .aarch64_be, | ||
| 602 | .aarch64_32, | ||
| 603 | => 128, | ||
| 604 | |||
| 605 | .x86_64 => if (std.Target.x86.featureSetHas(target.cpu.features, .cx16)) 128 else 64, | ||
| 606 | }; | ||
| 607 | |||
| 608 | var buffer: Type.Payload.Bits = undefined; | ||
| 609 | |||
| 610 | const int_ty = switch (ty.zigTypeTag()) { | ||
| 611 | .Int => ty, | ||
| 612 | .Enum => ty.intTagType(&buffer), | ||
| 613 | .Float => { | ||
| 614 | const bit_count = ty.floatBits(target); | ||
| 615 | if (bit_count > max_atomic_bits) { | ||
| 616 | diags.* = .{ | ||
| 617 | .bits = bit_count, | ||
| 618 | .max_bits = max_atomic_bits, | ||
| 619 | }; | ||
| 620 | return error.FloatTooBig; | ||
| 621 | } | ||
| 622 | return 0; | ||
| 623 | }, | ||
| 624 | .Bool => return 0, | ||
| 625 | else => { | ||
| 626 | if (ty.isPtrAtRuntime()) return 0; | ||
| 627 | return error.BadType; | ||
| 628 | }, | ||
| 629 | }; | ||
| 630 | |||
| 631 | const bit_count = int_ty.intInfo(target).bits; | ||
| 632 | if (bit_count > max_atomic_bits) { | ||
| 633 | diags.* = .{ | ||
| 634 | .bits = bit_count, | ||
| 635 | .max_bits = max_atomic_bits, | ||
| 636 | }; | ||
| 637 | return error.IntTooBig; | ||
| 638 | } | ||
| 639 | |||
| 640 | return 0; | ||
| 641 | } | ||
| 642 | |||
| 643 | pub fn defaultAddressSpace( | 515 | pub fn defaultAddressSpace( |
| 644 | target: std.Target, | 516 | target: std.Target, |
| 645 | context: enum { | 517 | context: enum { |
src/type.zig+650-663| ... | @@ -9,27 +9,102 @@ const log = std.log.scoped(.Type); | ... | @@ -9,27 +9,102 @@ const log = std.log.scoped(.Type); |
| 9 | const target_util = @import("target.zig"); | 9 | const target_util = @import("target.zig"); |
| 10 | const TypedValue = @import("TypedValue.zig"); | 10 | const TypedValue = @import("TypedValue.zig"); |
| 11 | const Sema = @import("Sema.zig"); | 11 | const Sema = @import("Sema.zig"); |
| 12 | const InternPool = @import("InternPool.zig"); | ||
| 12 | 13 | ||
| 13 | const file_struct = @This(); | 14 | const file_struct = @This(); |
| 14 | 15 | ||
| 15 | /// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication. | 16 | pub const Type = struct { |
| 16 | /// It's important for this type to be small. | 17 | /// We are migrating towards using this for every Type object. However, many |
| 17 | /// Types are not de-duplicated, which helps with multi-threading since it obviates the requirement | 18 | /// types are still represented the legacy way. This is indicated by using |
| 18 | /// of obtaining a lock on a global type table, as well as making the | 19 | /// InternPool.Index.none. |
| 19 | /// garbage collection bookkeeping simpler. | 20 | ip_index: InternPool.Index, |
| 20 | /// This union takes advantage of the fact that the first page of memory | 21 | |
| 21 | /// is unmapped, giving us 4096 possible enum tags that have no payload. | 22 | /// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication. |
| 22 | pub const Type = extern union { | 23 | /// This union takes advantage of the fact that the first page of memory |
| 23 | /// If the tag value is less than Tag.no_payload_count, then no pointer | 24 | /// is unmapped, giving us 4096 possible enum tags that have no payload. |
| 24 | /// dereference is needed. | 25 | legacy: extern union { |
| 25 | tag_if_small_enough: Tag, | 26 | /// If the tag value is less than Tag.no_payload_count, then no pointer |
| 26 | ptr_otherwise: *Payload, | 27 | /// dereference is needed. |
| 27 | 28 | tag_if_small_enough: Tag, | |
| 28 | pub fn zigTypeTag(ty: Type) std.builtin.TypeId { | 29 | ptr_otherwise: *Payload, |
| 29 | return ty.zigTypeTagOrPoison() catch unreachable; | 30 | }, |
| 30 | } | 31 | |
| 32 | pub fn zigTypeTag(ty: Type, mod: *const Module) std.builtin.TypeId { | ||
| 33 | return ty.zigTypeTagOrPoison(mod) catch unreachable; | ||
| 34 | } | ||
| 35 | |||
| 36 | pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId { | ||
| 37 | if (ty.ip_index != .none) { | ||
| 38 | switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 39 | .int_type => return .Int, | ||
| 40 | .ptr_type => return .Pointer, | ||
| 41 | .array_type => return .Array, | ||
| 42 | .vector_type => return .Vector, | ||
| 43 | .optional_type => return .Optional, | ||
| 44 | .error_union_type => return .ErrorUnion, | ||
| 45 | .struct_type => return .Struct, | ||
| 46 | .simple_type => |s| switch (s) { | ||
| 47 | .f16, | ||
| 48 | .f32, | ||
| 49 | .f64, | ||
| 50 | .f80, | ||
| 51 | .f128, | ||
| 52 | => return .Float, | ||
| 53 | |||
| 54 | .usize, | ||
| 55 | .isize, | ||
| 56 | .c_char, | ||
| 57 | .c_short, | ||
| 58 | .c_ushort, | ||
| 59 | .c_int, | ||
| 60 | .c_uint, | ||
| 61 | .c_long, | ||
| 62 | .c_ulong, | ||
| 63 | .c_longlong, | ||
| 64 | .c_ulonglong, | ||
| 65 | .c_longdouble, | ||
| 66 | => return .Int, | ||
| 67 | |||
| 68 | .anyopaque => return .Opaque, | ||
| 69 | .bool => return .Bool, | ||
| 70 | .void => return .Void, | ||
| 71 | .type => return .Type, | ||
| 72 | .anyerror => return .ErrorSet, | ||
| 73 | .comptime_int => return .ComptimeInt, | ||
| 74 | .comptime_float => return .ComptimeFloat, | ||
| 75 | .noreturn => return .NoReturn, | ||
| 76 | .@"anyframe" => return .AnyFrame, | ||
| 77 | .null => return .Null, | ||
| 78 | .undefined => return .Undefined, | ||
| 79 | .enum_literal => return .EnumLiteral, | ||
| 80 | |||
| 81 | .atomic_order, | ||
| 82 | .atomic_rmw_op, | ||
| 83 | .calling_convention, | ||
| 84 | .address_space, | ||
| 85 | .float_mode, | ||
| 86 | .reduce_op, | ||
| 87 | => return .Enum, | ||
| 88 | |||
| 89 | .call_modifier, | ||
| 90 | .prefetch_options, | ||
| 91 | .export_options, | ||
| 92 | .extern_options, | ||
| 93 | => return .Struct, | ||
| 94 | |||
| 95 | .type_info => return .Union, | ||
| 96 | |||
| 97 | .generic_poison => unreachable, | ||
| 98 | .var_args_param => unreachable, | ||
| 99 | }, | ||
| 31 | 100 | ||
| 32 | pub fn zigTypeTagOrPoison(ty: Type) error{GenericPoison}!std.builtin.TypeId { | 101 | .extern_func, |
| 102 | .int, | ||
| 103 | .enum_tag, | ||
| 104 | .simple_value, | ||
| 105 | => unreachable, // it's a value, not a type | ||
| 106 | } | ||
| 107 | } | ||
| 33 | switch (ty.tag()) { | 108 | switch (ty.tag()) { |
| 34 | .generic_poison => return error.GenericPoison, | 109 | .generic_poison => return error.GenericPoison, |
| 35 | 110 | ||
| ... | @@ -56,8 +131,6 @@ pub const Type = extern union { | ... | @@ -56,8 +131,6 @@ pub const Type = extern union { |
| 56 | .c_ulong, | 131 | .c_ulong, |
| 57 | .c_longlong, | 132 | .c_longlong, |
| 58 | .c_ulonglong, | 133 | .c_ulonglong, |
| 59 | .int_signed, | ||
| 60 | .int_unsigned, | ||
| 61 | => return .Int, | 134 | => return .Int, |
| 62 | 135 | ||
| 63 | .f16, | 136 | .f16, |
| ... | @@ -85,10 +158,6 @@ pub const Type = extern union { | ... | @@ -85,10 +158,6 @@ pub const Type = extern union { |
| 85 | .null => return .Null, | 158 | .null => return .Null, |
| 86 | .undefined => return .Undefined, | 159 | .undefined => return .Undefined, |
| 87 | 160 | ||
| 88 | .fn_noreturn_no_args => return .Fn, | ||
| 89 | .fn_void_no_args => return .Fn, | ||
| 90 | .fn_naked_noreturn_no_args => return .Fn, | ||
| 91 | .fn_ccc_void_no_args => return .Fn, | ||
| 92 | .function => return .Fn, | 161 | .function => return .Fn, |
| 93 | 162 | ||
| 94 | .array, | 163 | .array, |
| ... | @@ -159,26 +228,26 @@ pub const Type = extern union { | ... | @@ -159,26 +228,26 @@ pub const Type = extern union { |
| 159 | } | 228 | } |
| 160 | } | 229 | } |
| 161 | 230 | ||
| 162 | pub fn baseZigTypeTag(self: Type) std.builtin.TypeId { | 231 | pub fn baseZigTypeTag(self: Type, mod: *const Module) std.builtin.TypeId { |
| 163 | return switch (self.zigTypeTag()) { | 232 | return switch (self.zigTypeTag(mod)) { |
| 164 | .ErrorUnion => self.errorUnionPayload().baseZigTypeTag(), | 233 | .ErrorUnion => self.errorUnionPayload().baseZigTypeTag(mod), |
| 165 | .Optional => { | 234 | .Optional => { |
| 166 | var buf: Payload.ElemType = undefined; | 235 | var buf: Payload.ElemType = undefined; |
| 167 | return self.optionalChild(&buf).baseZigTypeTag(); | 236 | return self.optionalChild(&buf).baseZigTypeTag(mod); |
| 168 | }, | 237 | }, |
| 169 | else => |t| t, | 238 | else => |t| t, |
| 170 | }; | 239 | }; |
| 171 | } | 240 | } |
| 172 | 241 | ||
| 173 | pub fn isSelfComparable(ty: Type, is_equality_cmp: bool) bool { | 242 | pub fn isSelfComparable(ty: Type, mod: *const Module, is_equality_cmp: bool) bool { |
| 174 | return switch (ty.zigTypeTag()) { | 243 | return switch (ty.zigTypeTag(mod)) { |
| 175 | .Int, | 244 | .Int, |
| 176 | .Float, | 245 | .Float, |
| 177 | .ComptimeFloat, | 246 | .ComptimeFloat, |
| 178 | .ComptimeInt, | 247 | .ComptimeInt, |
| 179 | => true, | 248 | => true, |
| 180 | 249 | ||
| 181 | .Vector => ty.elemType2().isSelfComparable(is_equality_cmp), | 250 | .Vector => ty.elemType2(mod).isSelfComparable(mod, is_equality_cmp), |
| 182 | 251 | ||
| 183 | .Bool, | 252 | .Bool, |
| 184 | .Type, | 253 | .Type, |
| ... | @@ -205,44 +274,54 @@ pub const Type = extern union { | ... | @@ -205,44 +274,54 @@ pub const Type = extern union { |
| 205 | .Optional => { | 274 | .Optional => { |
| 206 | if (!is_equality_cmp) return false; | 275 | if (!is_equality_cmp) return false; |
| 207 | var buf: Payload.ElemType = undefined; | 276 | var buf: Payload.ElemType = undefined; |
| 208 | return ty.optionalChild(&buf).isSelfComparable(is_equality_cmp); | 277 | return ty.optionalChild(&buf).isSelfComparable(mod, is_equality_cmp); |
| 209 | }, | 278 | }, |
| 210 | }; | 279 | }; |
| 211 | } | 280 | } |
| 212 | 281 | ||
| 213 | pub fn initTag(comptime small_tag: Tag) Type { | 282 | pub fn initTag(comptime small_tag: Tag) Type { |
| 214 | comptime assert(@enumToInt(small_tag) < Tag.no_payload_count); | 283 | comptime assert(@enumToInt(small_tag) < Tag.no_payload_count); |
| 215 | return .{ .tag_if_small_enough = small_tag }; | 284 | return Type{ |
| 285 | .ip_index = .none, | ||
| 286 | .legacy = .{ .tag_if_small_enough = small_tag }, | ||
| 287 | }; | ||
| 216 | } | 288 | } |
| 217 | 289 | ||
| 218 | pub fn initPayload(payload: *Payload) Type { | 290 | pub fn initPayload(payload: *Payload) Type { |
| 219 | assert(@enumToInt(payload.tag) >= Tag.no_payload_count); | 291 | assert(@enumToInt(payload.tag) >= Tag.no_payload_count); |
| 220 | return .{ .ptr_otherwise = payload }; | 292 | return Type{ |
| 293 | .ip_index = .none, | ||
| 294 | .legacy = .{ .ptr_otherwise = payload }, | ||
| 295 | }; | ||
| 221 | } | 296 | } |
| 222 | 297 | ||
| 223 | pub fn tag(self: Type) Tag { | 298 | pub fn tag(ty: Type) Tag { |
| 224 | if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) { | 299 | assert(ty.ip_index == .none); |
| 225 | return self.tag_if_small_enough; | 300 | if (@enumToInt(ty.legacy.tag_if_small_enough) < Tag.no_payload_count) { |
| 301 | return ty.legacy.tag_if_small_enough; | ||
| 226 | } else { | 302 | } else { |
| 227 | return self.ptr_otherwise.tag; | 303 | return ty.legacy.ptr_otherwise.tag; |
| 228 | } | 304 | } |
| 229 | } | 305 | } |
| 230 | 306 | ||
| 231 | /// Prefer `castTag` to this. | 307 | /// Prefer `castTag` to this. |
| 232 | pub fn cast(self: Type, comptime T: type) ?*T { | 308 | pub fn cast(self: Type, comptime T: type) ?*T { |
| 309 | if (self.ip_index != .none) { | ||
| 310 | return null; | ||
| 311 | } | ||
| 233 | if (@hasField(T, "base_tag")) { | 312 | if (@hasField(T, "base_tag")) { |
| 234 | return self.castTag(T.base_tag); | 313 | return self.castTag(T.base_tag); |
| 235 | } | 314 | } |
| 236 | if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) { | 315 | if (@enumToInt(self.legacy.tag_if_small_enough) < Tag.no_payload_count) { |
| 237 | return null; | 316 | return null; |
| 238 | } | 317 | } |
| 239 | inline for (@typeInfo(Tag).Enum.fields) |field| { | 318 | inline for (@typeInfo(Tag).Enum.fields) |field| { |
| 240 | if (field.value < Tag.no_payload_count) | 319 | if (field.value < Tag.no_payload_count) |
| 241 | continue; | 320 | continue; |
| 242 | const t = @intToEnum(Tag, field.value); | 321 | const t = @intToEnum(Tag, field.value); |
| 243 | if (self.ptr_otherwise.tag == t) { | 322 | if (self.legacy.ptr_otherwise.tag == t) { |
| 244 | if (T == t.Type()) { | 323 | if (T == t.Type()) { |
| 245 | return @fieldParentPtr(T, "base", self.ptr_otherwise); | 324 | return @fieldParentPtr(T, "base", self.legacy.ptr_otherwise); |
| 246 | } | 325 | } |
| 247 | return null; | 326 | return null; |
| 248 | } | 327 | } |
| ... | @@ -251,11 +330,14 @@ pub const Type = extern union { | ... | @@ -251,11 +330,14 @@ pub const Type = extern union { |
| 251 | } | 330 | } |
| 252 | 331 | ||
| 253 | pub fn castTag(self: Type, comptime t: Tag) ?*t.Type() { | 332 | pub fn castTag(self: Type, comptime t: Tag) ?*t.Type() { |
| 254 | if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) | 333 | if (self.ip_index != .none) { |
| 334 | return null; | ||
| 335 | } | ||
| 336 | if (@enumToInt(self.legacy.tag_if_small_enough) < Tag.no_payload_count) | ||
| 255 | return null; | 337 | return null; |
| 256 | 338 | ||
| 257 | if (self.ptr_otherwise.tag == t) | 339 | if (self.legacy.ptr_otherwise.tag == t) |
| 258 | return @fieldParentPtr(t.Type(), "base", self.ptr_otherwise); | 340 | return @fieldParentPtr(t.Type(), "base", self.legacy.ptr_otherwise); |
| 259 | 341 | ||
| 260 | return null; | 342 | return null; |
| 261 | } | 343 | } |
| ... | @@ -285,10 +367,10 @@ pub const Type = extern union { | ... | @@ -285,10 +367,10 @@ pub const Type = extern union { |
| 285 | } | 367 | } |
| 286 | 368 | ||
| 287 | /// If it is a function pointer, returns the function type. Otherwise returns null. | 369 | /// If it is a function pointer, returns the function type. Otherwise returns null. |
| 288 | pub fn castPtrToFn(ty: Type) ?Type { | 370 | pub fn castPtrToFn(ty: Type, mod: *const Module) ?Type { |
| 289 | if (ty.zigTypeTag() != .Pointer) return null; | 371 | if (ty.zigTypeTag(mod) != .Pointer) return null; |
| 290 | const elem_ty = ty.childType(); | 372 | const elem_ty = ty.childType(); |
| 291 | if (elem_ty.zigTypeTag() != .Fn) return null; | 373 | if (elem_ty.zigTypeTag(mod) != .Fn) return null; |
| 292 | return elem_ty; | 374 | return elem_ty; |
| 293 | } | 375 | } |
| 294 | 376 | ||
| ... | @@ -536,7 +618,10 @@ pub const Type = extern union { | ... | @@ -536,7 +618,10 @@ pub const Type = extern union { |
| 536 | 618 | ||
| 537 | pub fn eql(a: Type, b: Type, mod: *Module) bool { | 619 | pub fn eql(a: Type, b: Type, mod: *Module) bool { |
| 538 | // As a shortcut, if the small tags / addresses match, we're done. | 620 | // As a shortcut, if the small tags / addresses match, we're done. |
| 539 | if (a.tag_if_small_enough == b.tag_if_small_enough) return true; | 621 | if (a.ip_index != .none or b.ip_index != .none) { |
| 622 | return a.ip_index == b.ip_index; | ||
| 623 | } | ||
| 624 | if (a.legacy.tag_if_small_enough == b.legacy.tag_if_small_enough) return true; | ||
| 540 | 625 | ||
| 541 | switch (a.tag()) { | 626 | switch (a.tag()) { |
| 542 | .generic_poison => unreachable, | 627 | .generic_poison => unreachable, |
| ... | @@ -589,16 +674,11 @@ pub const Type = extern union { | ... | @@ -589,16 +674,11 @@ pub const Type = extern union { |
| 589 | .i64, | 674 | .i64, |
| 590 | .u128, | 675 | .u128, |
| 591 | .i128, | 676 | .i128, |
| 592 | .int_signed, | ||
| 593 | .int_unsigned, | ||
| 594 | => { | 677 | => { |
| 595 | if (b.zigTypeTag() != .Int) return false; | 678 | if (b.zigTypeTag(mod) != .Int) return false; |
| 596 | if (b.isNamedInt()) return false; | 679 | if (b.isNamedInt()) return false; |
| 597 | 680 | const info_a = a.intInfo(mod); | |
| 598 | // Arbitrary sized integers. The target will not be branched upon, | 681 | const info_b = b.intInfo(mod); |
| 599 | // because we handled target-dependent cases above. | ||
| 600 | const info_a = a.intInfo(@as(Target, undefined)); | ||
| 601 | const info_b = b.intInfo(@as(Target, undefined)); | ||
| 602 | return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits; | 682 | return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits; |
| 603 | }, | 683 | }, |
| 604 | 684 | ||
| ... | @@ -641,13 +721,8 @@ pub const Type = extern union { | ... | @@ -641,13 +721,8 @@ pub const Type = extern union { |
| 641 | return opaque_obj_a == opaque_obj_b; | 721 | return opaque_obj_a == opaque_obj_b; |
| 642 | }, | 722 | }, |
| 643 | 723 | ||
| 644 | .fn_noreturn_no_args, | 724 | .function => { |
| 645 | .fn_void_no_args, | 725 | if (b.zigTypeTag(mod) != .Fn) return false; |
| 646 | .fn_naked_noreturn_no_args, | ||
| 647 | .fn_ccc_void_no_args, | ||
| 648 | .function, | ||
| 649 | => { | ||
| 650 | if (b.zigTypeTag() != .Fn) return false; | ||
| 651 | 726 | ||
| 652 | const a_info = a.fnInfo(); | 727 | const a_info = a.fnInfo(); |
| 653 | const b_info = b.fnInfo(); | 728 | const b_info = b.fnInfo(); |
| ... | @@ -699,7 +774,7 @@ pub const Type = extern union { | ... | @@ -699,7 +774,7 @@ pub const Type = extern union { |
| 699 | .array_sentinel, | 774 | .array_sentinel, |
| 700 | .vector, | 775 | .vector, |
| 701 | => { | 776 | => { |
| 702 | if (a.zigTypeTag() != b.zigTypeTag()) return false; | 777 | if (a.zigTypeTag(mod) != b.zigTypeTag(mod)) return false; |
| 703 | 778 | ||
| 704 | if (a.arrayLen() != b.arrayLen()) | 779 | if (a.arrayLen() != b.arrayLen()) |
| 705 | return false; | 780 | return false; |
| ... | @@ -737,7 +812,7 @@ pub const Type = extern union { | ... | @@ -737,7 +812,7 @@ pub const Type = extern union { |
| 737 | .manyptr_const_u8, | 812 | .manyptr_const_u8, |
| 738 | .manyptr_const_u8_sentinel_0, | 813 | .manyptr_const_u8_sentinel_0, |
| 739 | => { | 814 | => { |
| 740 | if (b.zigTypeTag() != .Pointer) return false; | 815 | if (b.zigTypeTag(mod) != .Pointer) return false; |
| 741 | 816 | ||
| 742 | const info_a = a.ptrInfo().data; | 817 | const info_a = a.ptrInfo().data; |
| 743 | const info_b = b.ptrInfo().data; | 818 | const info_b = b.ptrInfo().data; |
| ... | @@ -783,7 +858,7 @@ pub const Type = extern union { | ... | @@ -783,7 +858,7 @@ pub const Type = extern union { |
| 783 | .optional_single_const_pointer, | 858 | .optional_single_const_pointer, |
| 784 | .optional_single_mut_pointer, | 859 | .optional_single_mut_pointer, |
| 785 | => { | 860 | => { |
| 786 | if (b.zigTypeTag() != .Optional) return false; | 861 | if (b.zigTypeTag(mod) != .Optional) return false; |
| 787 | 862 | ||
| 788 | var buf_a: Payload.ElemType = undefined; | 863 | var buf_a: Payload.ElemType = undefined; |
| 789 | var buf_b: Payload.ElemType = undefined; | 864 | var buf_b: Payload.ElemType = undefined; |
| ... | @@ -791,7 +866,7 @@ pub const Type = extern union { | ... | @@ -791,7 +866,7 @@ pub const Type = extern union { |
| 791 | }, | 866 | }, |
| 792 | 867 | ||
| 793 | .anyerror_void_error_union, .error_union => { | 868 | .anyerror_void_error_union, .error_union => { |
| 794 | if (b.zigTypeTag() != .ErrorUnion) return false; | 869 | if (b.zigTypeTag(mod) != .ErrorUnion) return false; |
| 795 | 870 | ||
| 796 | const a_set = a.errorUnionSet(); | 871 | const a_set = a.errorUnionSet(); |
| 797 | const b_set = b.errorUnionSet(); | 872 | const b_set = b.errorUnionSet(); |
| ... | @@ -805,8 +880,8 @@ pub const Type = extern union { | ... | @@ -805,8 +880,8 @@ pub const Type = extern union { |
| 805 | }, | 880 | }, |
| 806 | 881 | ||
| 807 | .anyframe_T => { | 882 | .anyframe_T => { |
| 808 | if (b.zigTypeTag() != .AnyFrame) return false; | 883 | if (b.zigTypeTag(mod) != .AnyFrame) return false; |
| 809 | return a.elemType2().eql(b.elemType2(), mod); | 884 | return a.elemType2(mod).eql(b.elemType2(mod), mod); |
| 810 | }, | 885 | }, |
| 811 | 886 | ||
| 812 | .empty_struct => { | 887 | .empty_struct => { |
| ... | @@ -941,6 +1016,9 @@ pub const Type = extern union { | ... | @@ -941,6 +1016,9 @@ pub const Type = extern union { |
| 941 | } | 1016 | } |
| 942 | 1017 | ||
| 943 | pub fn hashWithHasher(ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void { | 1018 | pub fn hashWithHasher(ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void { |
| 1019 | if (ty.ip_index != .none) { | ||
| 1020 | return mod.intern_pool.indexToKey(ty.ip_index).hashWithHasher(hasher); | ||
| 1021 | } | ||
| 944 | switch (ty.tag()) { | 1022 | switch (ty.tag()) { |
| 945 | .generic_poison => unreachable, | 1023 | .generic_poison => unreachable, |
| 946 | 1024 | ||
| ... | @@ -1007,13 +1085,10 @@ pub const Type = extern union { | ... | @@ -1007,13 +1085,10 @@ pub const Type = extern union { |
| 1007 | .i64, | 1085 | .i64, |
| 1008 | .u128, | 1086 | .u128, |
| 1009 | .i128, | 1087 | .i128, |
| 1010 | .int_signed, | ||
| 1011 | .int_unsigned, | ||
| 1012 | => { | 1088 | => { |
| 1013 | // Arbitrary sized integers. The target will not be branched upon, | 1089 | // Arbitrary sized integers. |
| 1014 | // because we handled target-dependent cases above. | ||
| 1015 | std.hash.autoHash(hasher, std.builtin.TypeId.Int); | 1090 | std.hash.autoHash(hasher, std.builtin.TypeId.Int); |
| 1016 | const info = ty.intInfo(@as(Target, undefined)); | 1091 | const info = ty.intInfo(mod); |
| 1017 | std.hash.autoHash(hasher, info.signedness); | 1092 | std.hash.autoHash(hasher, info.signedness); |
| 1018 | std.hash.autoHash(hasher, info.bits); | 1093 | std.hash.autoHash(hasher, info.bits); |
| 1019 | }, | 1094 | }, |
| ... | @@ -1052,12 +1127,7 @@ pub const Type = extern union { | ... | @@ -1052,12 +1127,7 @@ pub const Type = extern union { |
| 1052 | std.hash.autoHash(hasher, opaque_obj); | 1127 | std.hash.autoHash(hasher, opaque_obj); |
| 1053 | }, | 1128 | }, |
| 1054 | 1129 | ||
| 1055 | .fn_noreturn_no_args, | 1130 | .function => { |
| 1056 | .fn_void_no_args, | ||
| 1057 | .fn_naked_noreturn_no_args, | ||
| 1058 | .fn_ccc_void_no_args, | ||
| 1059 | .function, | ||
| 1060 | => { | ||
| 1061 | std.hash.autoHash(hasher, std.builtin.TypeId.Fn); | 1131 | std.hash.autoHash(hasher, std.builtin.TypeId.Fn); |
| 1062 | 1132 | ||
| 1063 | const fn_info = ty.fnInfo(); | 1133 | const fn_info = ty.fnInfo(); |
| ... | @@ -1275,9 +1345,15 @@ pub const Type = extern union { | ... | @@ -1275,9 +1345,15 @@ pub const Type = extern union { |
| 1275 | }; | 1345 | }; |
| 1276 | 1346 | ||
| 1277 | pub fn copy(self: Type, allocator: Allocator) error{OutOfMemory}!Type { | 1347 | pub fn copy(self: Type, allocator: Allocator) error{OutOfMemory}!Type { |
| 1278 | if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) { | 1348 | if (self.ip_index != .none) { |
| 1279 | return Type{ .tag_if_small_enough = self.tag_if_small_enough }; | 1349 | return Type{ .ip_index = self.ip_index, .legacy = undefined }; |
| 1280 | } else switch (self.ptr_otherwise.tag) { | 1350 | } |
| 1351 | if (@enumToInt(self.legacy.tag_if_small_enough) < Tag.no_payload_count) { | ||
| 1352 | return Type{ | ||
| 1353 | .ip_index = .none, | ||
| 1354 | .legacy = .{ .tag_if_small_enough = self.legacy.tag_if_small_enough }, | ||
| 1355 | }; | ||
| 1356 | } else switch (self.legacy.ptr_otherwise.tag) { | ||
| 1281 | .u1, | 1357 | .u1, |
| 1282 | .u8, | 1358 | .u8, |
| 1283 | .i8, | 1359 | .i8, |
| ... | @@ -1317,10 +1393,6 @@ pub const Type = extern union { | ... | @@ -1317,10 +1393,6 @@ pub const Type = extern union { |
| 1317 | .noreturn, | 1393 | .noreturn, |
| 1318 | .null, | 1394 | .null, |
| 1319 | .undefined, | 1395 | .undefined, |
| 1320 | .fn_noreturn_no_args, | ||
| 1321 | .fn_void_no_args, | ||
| 1322 | .fn_naked_noreturn_no_args, | ||
| 1323 | .fn_ccc_void_no_args, | ||
| 1324 | .single_const_pointer_to_comptime_int, | 1396 | .single_const_pointer_to_comptime_int, |
| 1325 | .const_slice_u8, | 1397 | .const_slice_u8, |
| 1326 | .const_slice_u8_sentinel_0, | 1398 | .const_slice_u8_sentinel_0, |
| ... | @@ -1370,13 +1442,12 @@ pub const Type = extern union { | ... | @@ -1370,13 +1442,12 @@ pub const Type = extern union { |
| 1370 | .base = .{ .tag = payload.base.tag }, | 1442 | .base = .{ .tag = payload.base.tag }, |
| 1371 | .data = try payload.data.copy(allocator), | 1443 | .data = try payload.data.copy(allocator), |
| 1372 | }; | 1444 | }; |
| 1373 | return Type{ .ptr_otherwise = &new_payload.base }; | 1445 | return Type{ |
| 1446 | .ip_index = .none, | ||
| 1447 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 1448 | }; | ||
| 1374 | }, | 1449 | }, |
| 1375 | 1450 | ||
| 1376 | .int_signed, | ||
| 1377 | .int_unsigned, | ||
| 1378 | => return self.copyPayloadShallow(allocator, Payload.Bits), | ||
| 1379 | |||
| 1380 | .vector => { | 1451 | .vector => { |
| 1381 | const payload = self.castTag(.vector).?.data; | 1452 | const payload = self.castTag(.vector).?.data; |
| 1382 | return Tag.vector.create(allocator, .{ | 1453 | return Tag.vector.create(allocator, .{ |
| ... | @@ -1511,7 +1582,10 @@ pub const Type = extern union { | ... | @@ -1511,7 +1582,10 @@ pub const Type = extern union { |
| 1511 | const payload = self.cast(T).?; | 1582 | const payload = self.cast(T).?; |
| 1512 | const new_payload = try allocator.create(T); | 1583 | const new_payload = try allocator.create(T); |
| 1513 | new_payload.* = payload.*; | 1584 | new_payload.* = payload.*; |
| 1514 | return Type{ .ptr_otherwise = &new_payload.base }; | 1585 | return Type{ |
| 1586 | .ip_index = .none, | ||
| 1587 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 1588 | }; | ||
| 1515 | } | 1589 | } |
| 1516 | 1590 | ||
| 1517 | pub fn format(ty: Type, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | 1591 | pub fn format(ty: Type, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| ... | @@ -1550,7 +1624,7 @@ pub const Type = extern union { | ... | @@ -1550,7 +1624,7 @@ pub const Type = extern union { |
| 1550 | } | 1624 | } |
| 1551 | 1625 | ||
| 1552 | /// This is a debug function. In order to print types in a meaningful way | 1626 | /// This is a debug function. In order to print types in a meaningful way |
| 1553 | /// we also need access to the target. | 1627 | /// we also need access to the module. |
| 1554 | pub fn dump( | 1628 | pub fn dump( |
| 1555 | start_type: Type, | 1629 | start_type: Type, |
| 1556 | comptime unused_format_string: []const u8, | 1630 | comptime unused_format_string: []const u8, |
| ... | @@ -1559,10 +1633,13 @@ pub const Type = extern union { | ... | @@ -1559,10 +1633,13 @@ pub const Type = extern union { |
| 1559 | ) @TypeOf(writer).Error!void { | 1633 | ) @TypeOf(writer).Error!void { |
| 1560 | _ = options; | 1634 | _ = options; |
| 1561 | comptime assert(unused_format_string.len == 0); | 1635 | comptime assert(unused_format_string.len == 0); |
| 1636 | if (start_type.ip_index != .none) { | ||
| 1637 | return writer.print("(intern index: {d})", .{@enumToInt(start_type.ip_index)}); | ||
| 1638 | } | ||
| 1562 | if (true) { | 1639 | if (true) { |
| 1563 | // This is disabled to work around a bug where this function | 1640 | // This is disabled to work around a stage2 bug where this function recursively |
| 1564 | // recursively causes more generic function instantiations | 1641 | // causes more generic function instantiations resulting in an infinite loop |
| 1565 | // resulting in an infinite loop in the compiler. | 1642 | // in the compiler. |
| 1566 | try writer.writeAll("[TODO fix internal compiler bug regarding dump]"); | 1643 | try writer.writeAll("[TODO fix internal compiler bug regarding dump]"); |
| 1567 | return; | 1644 | return; |
| 1568 | } | 1645 | } |
| ... | @@ -1656,10 +1733,6 @@ pub const Type = extern union { | ... | @@ -1656,10 +1733,6 @@ pub const Type = extern union { |
| 1656 | .anyerror_void_error_union => return writer.writeAll("anyerror!void"), | 1733 | .anyerror_void_error_union => return writer.writeAll("anyerror!void"), |
| 1657 | .const_slice_u8 => return writer.writeAll("[]const u8"), | 1734 | .const_slice_u8 => return writer.writeAll("[]const u8"), |
| 1658 | .const_slice_u8_sentinel_0 => return writer.writeAll("[:0]const u8"), | 1735 | .const_slice_u8_sentinel_0 => return writer.writeAll("[:0]const u8"), |
| 1659 | .fn_noreturn_no_args => return writer.writeAll("fn() noreturn"), | ||
| 1660 | .fn_void_no_args => return writer.writeAll("fn() void"), | ||
| 1661 | .fn_naked_noreturn_no_args => return writer.writeAll("fn() callconv(.Naked) noreturn"), | ||
| 1662 | .fn_ccc_void_no_args => return writer.writeAll("fn() callconv(.C) void"), | ||
| 1663 | .single_const_pointer_to_comptime_int => return writer.writeAll("*const comptime_int"), | 1736 | .single_const_pointer_to_comptime_int => return writer.writeAll("*const comptime_int"), |
| 1664 | .manyptr_u8 => return writer.writeAll("[*]u8"), | 1737 | .manyptr_u8 => return writer.writeAll("[*]u8"), |
| 1665 | .manyptr_const_u8 => return writer.writeAll("[*]const u8"), | 1738 | .manyptr_const_u8 => return writer.writeAll("[*]const u8"), |
| ... | @@ -1820,14 +1893,6 @@ pub const Type = extern union { | ... | @@ -1820,14 +1893,6 @@ pub const Type = extern union { |
| 1820 | ty = pointee_type; | 1893 | ty = pointee_type; |
| 1821 | continue; | 1894 | continue; |
| 1822 | }, | 1895 | }, |
| 1823 | .int_signed => { | ||
| 1824 | const bits = ty.castTag(.int_signed).?.data; | ||
| 1825 | return writer.print("i{d}", .{bits}); | ||
| 1826 | }, | ||
| 1827 | .int_unsigned => { | ||
| 1828 | const bits = ty.castTag(.int_unsigned).?.data; | ||
| 1829 | return writer.print("u{d}", .{bits}); | ||
| 1830 | }, | ||
| 1831 | .optional => { | 1896 | .optional => { |
| 1832 | const child_type = ty.castTag(.optional).?.data; | 1897 | const child_type = ty.castTag(.optional).?.data; |
| 1833 | try writer.writeByte('?'); | 1898 | try writer.writeByte('?'); |
| ... | @@ -1938,6 +2003,26 @@ pub const Type = extern union { | ... | @@ -1938,6 +2003,26 @@ pub const Type = extern union { |
| 1938 | 2003 | ||
| 1939 | /// Prints a name suitable for `@typeName`. | 2004 | /// Prints a name suitable for `@typeName`. |
| 1940 | pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void { | 2005 | pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void { |
| 2006 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 2007 | .int_type => |int_type| { | ||
| 2008 | const sign_char: u8 = switch (int_type.signedness) { | ||
| 2009 | .signed => 'i', | ||
| 2010 | .unsigned => 'u', | ||
| 2011 | }; | ||
| 2012 | return writer.print("{c}{d}", .{ sign_char, int_type.bits }); | ||
| 2013 | }, | ||
| 2014 | .ptr_type => @panic("TODO"), | ||
| 2015 | .array_type => @panic("TODO"), | ||
| 2016 | .vector_type => @panic("TODO"), | ||
| 2017 | .optional_type => @panic("TODO"), | ||
| 2018 | .error_union_type => @panic("TODO"), | ||
| 2019 | .simple_type => |s| return writer.writeAll(@tagName(s)), | ||
| 2020 | .struct_type => @panic("TODO"), | ||
| 2021 | .simple_value => unreachable, | ||
| 2022 | .extern_func => unreachable, | ||
| 2023 | .int => unreachable, | ||
| 2024 | .enum_tag => unreachable, | ||
| 2025 | }; | ||
| 1941 | const t = ty.tag(); | 2026 | const t = ty.tag(); |
| 1942 | switch (t) { | 2027 | switch (t) { |
| 1943 | .inferred_alloc_const => unreachable, | 2028 | .inferred_alloc_const => unreachable, |
| ... | @@ -2041,10 +2126,6 @@ pub const Type = extern union { | ... | @@ -2041,10 +2126,6 @@ pub const Type = extern union { |
| 2041 | .anyerror_void_error_union => try writer.writeAll("anyerror!void"), | 2126 | .anyerror_void_error_union => try writer.writeAll("anyerror!void"), |
| 2042 | .const_slice_u8 => try writer.writeAll("[]const u8"), | 2127 | .const_slice_u8 => try writer.writeAll("[]const u8"), |
| 2043 | .const_slice_u8_sentinel_0 => try writer.writeAll("[:0]const u8"), | 2128 | .const_slice_u8_sentinel_0 => try writer.writeAll("[:0]const u8"), |
| 2044 | .fn_noreturn_no_args => try writer.writeAll("fn() noreturn"), | ||
| 2045 | .fn_void_no_args => try writer.writeAll("fn() void"), | ||
| 2046 | .fn_naked_noreturn_no_args => try writer.writeAll("fn() callconv(.Naked) noreturn"), | ||
| 2047 | .fn_ccc_void_no_args => try writer.writeAll("fn() callconv(.C) void"), | ||
| 2048 | .single_const_pointer_to_comptime_int => try writer.writeAll("*const comptime_int"), | 2129 | .single_const_pointer_to_comptime_int => try writer.writeAll("*const comptime_int"), |
| 2049 | .manyptr_u8 => try writer.writeAll("[*]u8"), | 2130 | .manyptr_u8 => try writer.writeAll("[*]u8"), |
| 2050 | .manyptr_const_u8 => try writer.writeAll("[*]const u8"), | 2131 | .manyptr_const_u8 => try writer.writeAll("[*]const u8"), |
| ... | @@ -2200,7 +2281,7 @@ pub const Type = extern union { | ... | @@ -2200,7 +2281,7 @@ pub const Type = extern union { |
| 2200 | if (info.@"align" != 0) { | 2281 | if (info.@"align" != 0) { |
| 2201 | try writer.print("align({d}", .{info.@"align"}); | 2282 | try writer.print("align({d}", .{info.@"align"}); |
| 2202 | } else { | 2283 | } else { |
| 2203 | const alignment = info.pointee_type.abiAlignment(mod.getTarget()); | 2284 | const alignment = info.pointee_type.abiAlignment(mod); |
| 2204 | try writer.print("align({d}", .{alignment}); | 2285 | try writer.print("align({d}", .{alignment}); |
| 2205 | } | 2286 | } |
| 2206 | 2287 | ||
| ... | @@ -2224,14 +2305,6 @@ pub const Type = extern union { | ... | @@ -2224,14 +2305,6 @@ pub const Type = extern union { |
| 2224 | try print(info.pointee_type, writer, mod); | 2305 | try print(info.pointee_type, writer, mod); |
| 2225 | }, | 2306 | }, |
| 2226 | 2307 | ||
| 2227 | .int_signed => { | ||
| 2228 | const bits = ty.castTag(.int_signed).?.data; | ||
| 2229 | return writer.print("i{d}", .{bits}); | ||
| 2230 | }, | ||
| 2231 | .int_unsigned => { | ||
| 2232 | const bits = ty.castTag(.int_unsigned).?.data; | ||
| 2233 | return writer.print("u{d}", .{bits}); | ||
| 2234 | }, | ||
| 2235 | .optional => { | 2308 | .optional => { |
| 2236 | const child_type = ty.castTag(.optional).?.data; | 2309 | const child_type = ty.castTag(.optional).?.data; |
| 2237 | try writer.writeByte('?'); | 2310 | try writer.writeByte('?'); |
| ... | @@ -2317,10 +2390,6 @@ pub const Type = extern union { | ... | @@ -2317,10 +2390,6 @@ pub const Type = extern union { |
| 2317 | .noreturn => return Value.initTag(.noreturn_type), | 2390 | .noreturn => return Value.initTag(.noreturn_type), |
| 2318 | .null => return Value.initTag(.null_type), | 2391 | .null => return Value.initTag(.null_type), |
| 2319 | .undefined => return Value.initTag(.undefined_type), | 2392 | .undefined => return Value.initTag(.undefined_type), |
| 2320 | .fn_noreturn_no_args => return Value.initTag(.fn_noreturn_no_args_type), | ||
| 2321 | .fn_void_no_args => return Value.initTag(.fn_void_no_args_type), | ||
| 2322 | .fn_naked_noreturn_no_args => return Value.initTag(.fn_naked_noreturn_no_args_type), | ||
| 2323 | .fn_ccc_void_no_args => return Value.initTag(.fn_ccc_void_no_args_type), | ||
| 2324 | .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type), | 2393 | .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type), |
| 2325 | .const_slice_u8 => return Value.initTag(.const_slice_u8_type), | 2394 | .const_slice_u8 => return Value.initTag(.const_slice_u8_type), |
| 2326 | .const_slice_u8_sentinel_0 => return Value.initTag(.const_slice_u8_sentinel_0_type), | 2395 | .const_slice_u8_sentinel_0 => return Value.initTag(.const_slice_u8_sentinel_0_type), |
| ... | @@ -2360,9 +2429,24 @@ pub const Type = extern union { | ... | @@ -2360,9 +2429,24 @@ pub const Type = extern union { |
| 2360 | /// may return false positives. | 2429 | /// may return false positives. |
| 2361 | pub fn hasRuntimeBitsAdvanced( | 2430 | pub fn hasRuntimeBitsAdvanced( |
| 2362 | ty: Type, | 2431 | ty: Type, |
| 2432 | mod: *const Module, | ||
| 2363 | ignore_comptime_only: bool, | 2433 | ignore_comptime_only: bool, |
| 2364 | strat: AbiAlignmentAdvancedStrat, | 2434 | strat: AbiAlignmentAdvancedStrat, |
| 2365 | ) RuntimeBitsError!bool { | 2435 | ) RuntimeBitsError!bool { |
| 2436 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 2437 | .int_type => |int_type| return int_type.bits != 0, | ||
| 2438 | .ptr_type => @panic("TODO"), | ||
| 2439 | .array_type => @panic("TODO"), | ||
| 2440 | .vector_type => @panic("TODO"), | ||
| 2441 | .optional_type => @panic("TODO"), | ||
| 2442 | .error_union_type => @panic("TODO"), | ||
| 2443 | .simple_type => @panic("TODO"), | ||
| 2444 | .struct_type => @panic("TODO"), | ||
| 2445 | .simple_value => unreachable, | ||
| 2446 | .extern_func => unreachable, | ||
| 2447 | .int => unreachable, | ||
| 2448 | .enum_tag => unreachable, // it's a value, not a type | ||
| 2449 | }; | ||
| 2366 | switch (ty.tag()) { | 2450 | switch (ty.tag()) { |
| 2367 | .u1, | 2451 | .u1, |
| 2368 | .u8, | 2452 | .u8, |
| ... | @@ -2440,12 +2524,12 @@ pub const Type = extern union { | ... | @@ -2440,12 +2524,12 @@ pub const Type = extern union { |
| 2440 | => { | 2524 | => { |
| 2441 | if (ignore_comptime_only) { | 2525 | if (ignore_comptime_only) { |
| 2442 | return true; | 2526 | return true; |
| 2443 | } else if (ty.childType().zigTypeTag() == .Fn) { | 2527 | } else if (ty.childType().zigTypeTag(mod) == .Fn) { |
| 2444 | return !ty.childType().fnInfo().is_generic; | 2528 | return !ty.childType().fnInfo().is_generic; |
| 2445 | } else if (strat == .sema) { | 2529 | } else if (strat == .sema) { |
| 2446 | return !(try strat.sema.typeRequiresComptime(ty)); | 2530 | return !(try strat.sema.typeRequiresComptime(ty)); |
| 2447 | } else { | 2531 | } else { |
| 2448 | return !comptimeOnly(ty); | 2532 | return !comptimeOnly(ty, mod); |
| 2449 | } | 2533 | } |
| 2450 | }, | 2534 | }, |
| 2451 | 2535 | ||
| ... | @@ -2465,10 +2549,6 @@ pub const Type = extern union { | ... | @@ -2465,10 +2549,6 @@ pub const Type = extern union { |
| 2465 | // Special exceptions have to be made when emitting functions due to | 2549 | // Special exceptions have to be made when emitting functions due to |
| 2466 | // this returning false. | 2550 | // this returning false. |
| 2467 | .function, | 2551 | .function, |
| 2468 | .fn_noreturn_no_args, | ||
| 2469 | .fn_void_no_args, | ||
| 2470 | .fn_naked_noreturn_no_args, | ||
| 2471 | .fn_ccc_void_no_args, | ||
| 2472 | => return false, | 2552 | => return false, |
| 2473 | 2553 | ||
| 2474 | .optional => { | 2554 | .optional => { |
| ... | @@ -2483,7 +2563,7 @@ pub const Type = extern union { | ... | @@ -2483,7 +2563,7 @@ pub const Type = extern union { |
| 2483 | } else if (strat == .sema) { | 2563 | } else if (strat == .sema) { |
| 2484 | return !(try strat.sema.typeRequiresComptime(child_ty)); | 2564 | return !(try strat.sema.typeRequiresComptime(child_ty)); |
| 2485 | } else { | 2565 | } else { |
| 2486 | return !comptimeOnly(child_ty); | 2566 | return !comptimeOnly(child_ty, mod); |
| 2487 | } | 2567 | } |
| 2488 | }, | 2568 | }, |
| 2489 | 2569 | ||
| ... | @@ -2502,7 +2582,7 @@ pub const Type = extern union { | ... | @@ -2502,7 +2582,7 @@ pub const Type = extern union { |
| 2502 | } | 2582 | } |
| 2503 | for (struct_obj.fields.values()) |field| { | 2583 | for (struct_obj.fields.values()) |field| { |
| 2504 | if (field.is_comptime) continue; | 2584 | if (field.is_comptime) continue; |
| 2505 | if (try field.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) | 2585 | if (try field.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) |
| 2506 | return true; | 2586 | return true; |
| 2507 | } else { | 2587 | } else { |
| 2508 | return false; | 2588 | return false; |
| ... | @@ -2511,16 +2591,15 @@ pub const Type = extern union { | ... | @@ -2511,16 +2591,15 @@ pub const Type = extern union { |
| 2511 | 2591 | ||
| 2512 | .enum_full => { | 2592 | .enum_full => { |
| 2513 | const enum_full = ty.castTag(.enum_full).?.data; | 2593 | const enum_full = ty.castTag(.enum_full).?.data; |
| 2514 | return enum_full.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat); | 2594 | return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); |
| 2515 | }, | 2595 | }, |
| 2516 | .enum_simple => { | 2596 | .enum_simple => { |
| 2517 | const enum_simple = ty.castTag(.enum_simple).?.data; | 2597 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 2518 | return enum_simple.fields.count() >= 2; | 2598 | return enum_simple.fields.count() >= 2; |
| 2519 | }, | 2599 | }, |
| 2520 | .enum_numbered, .enum_nonexhaustive => { | 2600 | .enum_numbered, .enum_nonexhaustive => { |
| 2521 | var buffer: Payload.Bits = undefined; | 2601 | const int_tag_ty = ty.intTagType(); |
| 2522 | const int_tag_ty = ty.intTagType(&buffer); | 2602 | return int_tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); |
| 2523 | return int_tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat); | ||
| 2524 | }, | 2603 | }, |
| 2525 | 2604 | ||
| 2526 | .@"union" => { | 2605 | .@"union" => { |
| ... | @@ -2537,7 +2616,7 @@ pub const Type = extern union { | ... | @@ -2537,7 +2616,7 @@ pub const Type = extern union { |
| 2537 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, | 2616 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, |
| 2538 | } | 2617 | } |
| 2539 | for (union_obj.fields.values()) |value| { | 2618 | for (union_obj.fields.values()) |value| { |
| 2540 | if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) | 2619 | if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) |
| 2541 | return true; | 2620 | return true; |
| 2542 | } else { | 2621 | } else { |
| 2543 | return false; | 2622 | return false; |
| ... | @@ -2545,7 +2624,7 @@ pub const Type = extern union { | ... | @@ -2545,7 +2624,7 @@ pub const Type = extern union { |
| 2545 | }, | 2624 | }, |
| 2546 | .union_safety_tagged, .union_tagged => { | 2625 | .union_safety_tagged, .union_tagged => { |
| 2547 | const union_obj = ty.cast(Payload.Union).?.data; | 2626 | const union_obj = ty.cast(Payload.Union).?.data; |
| 2548 | if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) { | 2627 | if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) { |
| 2549 | return true; | 2628 | return true; |
| 2550 | } | 2629 | } |
| 2551 | 2630 | ||
| ... | @@ -2555,7 +2634,7 @@ pub const Type = extern union { | ... | @@ -2555,7 +2634,7 @@ pub const Type = extern union { |
| 2555 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, | 2634 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, |
| 2556 | } | 2635 | } |
| 2557 | for (union_obj.fields.values()) |value| { | 2636 | for (union_obj.fields.values()) |value| { |
| 2558 | if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) | 2637 | if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) |
| 2559 | return true; | 2638 | return true; |
| 2560 | } else { | 2639 | } else { |
| 2561 | return false; | 2640 | return false; |
| ... | @@ -2563,18 +2642,16 @@ pub const Type = extern union { | ... | @@ -2563,18 +2642,16 @@ pub const Type = extern union { |
| 2563 | }, | 2642 | }, |
| 2564 | 2643 | ||
| 2565 | .array, .vector => return ty.arrayLen() != 0 and | 2644 | .array, .vector => return ty.arrayLen() != 0 and |
| 2566 | try ty.elemType().hasRuntimeBitsAdvanced(ignore_comptime_only, strat), | 2645 | try ty.elemType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), |
| 2567 | .array_u8 => return ty.arrayLen() != 0, | 2646 | .array_u8 => return ty.arrayLen() != 0, |
| 2568 | .array_sentinel => return ty.childType().hasRuntimeBitsAdvanced(ignore_comptime_only, strat), | 2647 | .array_sentinel => return ty.childType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), |
| 2569 | |||
| 2570 | .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data != 0, | ||
| 2571 | 2648 | ||
| 2572 | .tuple, .anon_struct => { | 2649 | .tuple, .anon_struct => { |
| 2573 | const tuple = ty.tupleFields(); | 2650 | const tuple = ty.tupleFields(); |
| 2574 | for (tuple.types, 0..) |field_ty, i| { | 2651 | for (tuple.types, 0..) |field_ty, i| { |
| 2575 | const val = tuple.values[i]; | 2652 | const val = tuple.values[i]; |
| 2576 | if (val.tag() != .unreachable_value) continue; // comptime field | 2653 | if (val.tag() != .unreachable_value) continue; // comptime field |
| 2577 | if (try field_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) return true; | 2654 | if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true; |
| 2578 | } | 2655 | } |
| 2579 | return false; | 2656 | return false; |
| 2580 | }, | 2657 | }, |
| ... | @@ -2588,7 +2665,21 @@ pub const Type = extern union { | ... | @@ -2588,7 +2665,21 @@ pub const Type = extern union { |
| 2588 | /// true if and only if the type has a well-defined memory layout | 2665 | /// true if and only if the type has a well-defined memory layout |
| 2589 | /// readFrom/writeToMemory are supported only for types with a well- | 2666 | /// readFrom/writeToMemory are supported only for types with a well- |
| 2590 | /// defined memory layout | 2667 | /// defined memory layout |
| 2591 | pub fn hasWellDefinedLayout(ty: Type) bool { | 2668 | pub fn hasWellDefinedLayout(ty: Type, mod: *const Module) bool { |
| 2669 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 2670 | .int_type => return true, | ||
| 2671 | .ptr_type => @panic("TODO"), | ||
| 2672 | .array_type => @panic("TODO"), | ||
| 2673 | .vector_type => @panic("TODO"), | ||
| 2674 | .optional_type => @panic("TODO"), | ||
| 2675 | .error_union_type => @panic("TODO"), | ||
| 2676 | .simple_type => @panic("TODO"), | ||
| 2677 | .struct_type => @panic("TODO"), | ||
| 2678 | .simple_value => unreachable, | ||
| 2679 | .extern_func => unreachable, | ||
| 2680 | .int => unreachable, | ||
| 2681 | .enum_tag => unreachable, // it's a value, not a type | ||
| 2682 | }; | ||
| 2592 | return switch (ty.tag()) { | 2683 | return switch (ty.tag()) { |
| 2593 | .u1, | 2684 | .u1, |
| 2594 | .u8, | 2685 | .u8, |
| ... | @@ -2626,8 +2717,6 @@ pub const Type = extern union { | ... | @@ -2626,8 +2717,6 @@ pub const Type = extern union { |
| 2626 | .manyptr_const_u8_sentinel_0, | 2717 | .manyptr_const_u8_sentinel_0, |
| 2627 | .array_u8, | 2718 | .array_u8, |
| 2628 | .array_u8_sentinel_0, | 2719 | .array_u8_sentinel_0, |
| 2629 | .int_signed, | ||
| 2630 | .int_unsigned, | ||
| 2631 | .pointer, | 2720 | .pointer, |
| 2632 | .single_const_pointer, | 2721 | .single_const_pointer, |
| 2633 | .single_mut_pointer, | 2722 | .single_mut_pointer, |
| ... | @@ -2670,10 +2759,6 @@ pub const Type = extern union { | ... | @@ -2670,10 +2759,6 @@ pub const Type = extern union { |
| 2670 | .enum_literal, | 2759 | .enum_literal, |
| 2671 | .type_info, | 2760 | .type_info, |
| 2672 | // These are function bodies, not function pointers. | 2761 | // These are function bodies, not function pointers. |
| 2673 | .fn_noreturn_no_args, | ||
| 2674 | .fn_void_no_args, | ||
| 2675 | .fn_naked_noreturn_no_args, | ||
| 2676 | .fn_ccc_void_no_args, | ||
| 2677 | .function, | 2762 | .function, |
| 2678 | .const_slice_u8, | 2763 | .const_slice_u8, |
| 2679 | .const_slice_u8_sentinel_0, | 2764 | .const_slice_u8_sentinel_0, |
| ... | @@ -2698,25 +2783,25 @@ pub const Type = extern union { | ... | @@ -2698,25 +2783,25 @@ pub const Type = extern union { |
| 2698 | 2783 | ||
| 2699 | .array, | 2784 | .array, |
| 2700 | .array_sentinel, | 2785 | .array_sentinel, |
| 2701 | => ty.childType().hasWellDefinedLayout(), | 2786 | => ty.childType().hasWellDefinedLayout(mod), |
| 2702 | 2787 | ||
| 2703 | .optional => ty.isPtrLikeOptional(), | 2788 | .optional => ty.isPtrLikeOptional(mod), |
| 2704 | .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto, | 2789 | .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto, |
| 2705 | .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto, | 2790 | .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto, |
| 2706 | .union_tagged => false, | 2791 | .union_tagged => false, |
| 2707 | }; | 2792 | }; |
| 2708 | } | 2793 | } |
| 2709 | 2794 | ||
| 2710 | pub fn hasRuntimeBits(ty: Type) bool { | 2795 | pub fn hasRuntimeBits(ty: Type, mod: *const Module) bool { |
| 2711 | return hasRuntimeBitsAdvanced(ty, false, .eager) catch unreachable; | 2796 | return hasRuntimeBitsAdvanced(ty, mod, false, .eager) catch unreachable; |
| 2712 | } | 2797 | } |
| 2713 | 2798 | ||
| 2714 | pub fn hasRuntimeBitsIgnoreComptime(ty: Type) bool { | 2799 | pub fn hasRuntimeBitsIgnoreComptime(ty: Type, mod: *const Module) bool { |
| 2715 | return hasRuntimeBitsAdvanced(ty, true, .eager) catch unreachable; | 2800 | return hasRuntimeBitsAdvanced(ty, mod, true, .eager) catch unreachable; |
| 2716 | } | 2801 | } |
| 2717 | 2802 | ||
| 2718 | pub fn isFnOrHasRuntimeBits(ty: Type) bool { | 2803 | pub fn isFnOrHasRuntimeBits(ty: Type, mod: *const Module) bool { |
| 2719 | switch (ty.zigTypeTag()) { | 2804 | switch (ty.zigTypeTag(mod)) { |
| 2720 | .Fn => { | 2805 | .Fn => { |
| 2721 | const fn_info = ty.fnInfo(); | 2806 | const fn_info = ty.fnInfo(); |
| 2722 | if (fn_info.is_generic) return false; | 2807 | if (fn_info.is_generic) return false; |
| ... | @@ -2727,18 +2812,18 @@ pub const Type = extern union { | ... | @@ -2727,18 +2812,18 @@ pub const Type = extern union { |
| 2727 | .Inline => return false, | 2812 | .Inline => return false, |
| 2728 | else => {}, | 2813 | else => {}, |
| 2729 | } | 2814 | } |
| 2730 | if (fn_info.return_type.comptimeOnly()) return false; | 2815 | if (fn_info.return_type.comptimeOnly(mod)) return false; |
| 2731 | return true; | 2816 | return true; |
| 2732 | }, | 2817 | }, |
| 2733 | else => return ty.hasRuntimeBits(), | 2818 | else => return ty.hasRuntimeBits(mod), |
| 2734 | } | 2819 | } |
| 2735 | } | 2820 | } |
| 2736 | 2821 | ||
| 2737 | /// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive. | 2822 | /// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive. |
| 2738 | pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type) bool { | 2823 | pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type, mod: *const Module) bool { |
| 2739 | return switch (ty.zigTypeTag()) { | 2824 | return switch (ty.zigTypeTag(mod)) { |
| 2740 | .Fn => true, | 2825 | .Fn => true, |
| 2741 | else => return ty.hasRuntimeBitsIgnoreComptime(), | 2826 | else => return ty.hasRuntimeBitsIgnoreComptime(mod), |
| 2742 | }; | 2827 | }; |
| 2743 | } | 2828 | } |
| 2744 | 2829 | ||
| ... | @@ -2761,11 +2846,11 @@ pub const Type = extern union { | ... | @@ -2761,11 +2846,11 @@ pub const Type = extern union { |
| 2761 | } | 2846 | } |
| 2762 | 2847 | ||
| 2763 | /// Returns 0 if the pointer is naturally aligned and the element type is 0-bit. | 2848 | /// Returns 0 if the pointer is naturally aligned and the element type is 0-bit. |
| 2764 | pub fn ptrAlignment(ty: Type, target: Target) u32 { | 2849 | pub fn ptrAlignment(ty: Type, mod: *const Module) u32 { |
| 2765 | return ptrAlignmentAdvanced(ty, target, null) catch unreachable; | 2850 | return ptrAlignmentAdvanced(ty, mod, null) catch unreachable; |
| 2766 | } | 2851 | } |
| 2767 | 2852 | ||
| 2768 | pub fn ptrAlignmentAdvanced(ty: Type, target: Target, opt_sema: ?*Sema) !u32 { | 2853 | pub fn ptrAlignmentAdvanced(ty: Type, mod: *const Module, opt_sema: ?*Sema) !u32 { |
| 2769 | switch (ty.tag()) { | 2854 | switch (ty.tag()) { |
| 2770 | .single_const_pointer, | 2855 | .single_const_pointer, |
| 2771 | .single_mut_pointer, | 2856 | .single_mut_pointer, |
| ... | @@ -2780,10 +2865,10 @@ pub const Type = extern union { | ... | @@ -2780,10 +2865,10 @@ pub const Type = extern union { |
| 2780 | => { | 2865 | => { |
| 2781 | const child_type = ty.cast(Payload.ElemType).?.data; | 2866 | const child_type = ty.cast(Payload.ElemType).?.data; |
| 2782 | if (opt_sema) |sema| { | 2867 | if (opt_sema) |sema| { |
| 2783 | const res = try child_type.abiAlignmentAdvanced(target, .{ .sema = sema }); | 2868 | const res = try child_type.abiAlignmentAdvanced(mod, .{ .sema = sema }); |
| 2784 | return res.scalar; | 2869 | return res.scalar; |
| 2785 | } | 2870 | } |
| 2786 | return (child_type.abiAlignmentAdvanced(target, .eager) catch unreachable).scalar; | 2871 | return (child_type.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar; |
| 2787 | }, | 2872 | }, |
| 2788 | 2873 | ||
| 2789 | .manyptr_u8, | 2874 | .manyptr_u8, |
| ... | @@ -2798,13 +2883,13 @@ pub const Type = extern union { | ... | @@ -2798,13 +2883,13 @@ pub const Type = extern union { |
| 2798 | if (ptr_info.@"align" != 0) { | 2883 | if (ptr_info.@"align" != 0) { |
| 2799 | return ptr_info.@"align"; | 2884 | return ptr_info.@"align"; |
| 2800 | } else if (opt_sema) |sema| { | 2885 | } else if (opt_sema) |sema| { |
| 2801 | const res = try ptr_info.pointee_type.abiAlignmentAdvanced(target, .{ .sema = sema }); | 2886 | const res = try ptr_info.pointee_type.abiAlignmentAdvanced(mod, .{ .sema = sema }); |
| 2802 | return res.scalar; | 2887 | return res.scalar; |
| 2803 | } else { | 2888 | } else { |
| 2804 | return (ptr_info.pointee_type.abiAlignmentAdvanced(target, .eager) catch unreachable).scalar; | 2889 | return (ptr_info.pointee_type.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar; |
| 2805 | } | 2890 | } |
| 2806 | }, | 2891 | }, |
| 2807 | .optional => return ty.castTag(.optional).?.data.ptrAlignmentAdvanced(target, opt_sema), | 2892 | .optional => return ty.castTag(.optional).?.data.ptrAlignmentAdvanced(mod, opt_sema), |
| 2808 | 2893 | ||
| 2809 | else => unreachable, | 2894 | else => unreachable, |
| 2810 | } | 2895 | } |
| ... | @@ -2843,13 +2928,13 @@ pub const Type = extern union { | ... | @@ -2843,13 +2928,13 @@ pub const Type = extern union { |
| 2843 | } | 2928 | } |
| 2844 | 2929 | ||
| 2845 | /// Returns 0 for 0-bit types. | 2930 | /// Returns 0 for 0-bit types. |
| 2846 | pub fn abiAlignment(ty: Type, target: Target) u32 { | 2931 | pub fn abiAlignment(ty: Type, mod: *const Module) u32 { |
| 2847 | return (ty.abiAlignmentAdvanced(target, .eager) catch unreachable).scalar; | 2932 | return (ty.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar; |
| 2848 | } | 2933 | } |
| 2849 | 2934 | ||
| 2850 | /// May capture a reference to `ty`. | 2935 | /// May capture a reference to `ty`. |
| 2851 | pub fn lazyAbiAlignment(ty: Type, target: Target, arena: Allocator) !Value { | 2936 | pub fn lazyAbiAlignment(ty: Type, mod: *const Module, arena: Allocator) !Value { |
| 2852 | switch (try ty.abiAlignmentAdvanced(target, .{ .lazy = arena })) { | 2937 | switch (try ty.abiAlignmentAdvanced(mod, .{ .lazy = arena })) { |
| 2853 | .val => |val| return val, | 2938 | .val => |val| return val, |
| 2854 | .scalar => |x| return Value.Tag.int_u64.create(arena, x), | 2939 | .scalar => |x| return Value.Tag.int_u64.create(arena, x), |
| 2855 | } | 2940 | } |
| ... | @@ -2874,9 +2959,29 @@ pub const Type = extern union { | ... | @@ -2874,9 +2959,29 @@ pub const Type = extern union { |
| 2874 | /// necessary, possibly returning a CompileError. | 2959 | /// necessary, possibly returning a CompileError. |
| 2875 | pub fn abiAlignmentAdvanced( | 2960 | pub fn abiAlignmentAdvanced( |
| 2876 | ty: Type, | 2961 | ty: Type, |
| 2877 | target: Target, | 2962 | mod: *const Module, |
| 2878 | strat: AbiAlignmentAdvancedStrat, | 2963 | strat: AbiAlignmentAdvancedStrat, |
| 2879 | ) Module.CompileError!AbiAlignmentAdvanced { | 2964 | ) Module.CompileError!AbiAlignmentAdvanced { |
| 2965 | const target = mod.getTarget(); | ||
| 2966 | |||
| 2967 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 2968 | .int_type => |int_type| { | ||
| 2969 | if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 }; | ||
| 2970 | return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(int_type.bits, target) }; | ||
| 2971 | }, | ||
| 2972 | .ptr_type => @panic("TODO"), | ||
| 2973 | .array_type => @panic("TODO"), | ||
| 2974 | .vector_type => @panic("TODO"), | ||
| 2975 | .optional_type => @panic("TODO"), | ||
| 2976 | .error_union_type => @panic("TODO"), | ||
| 2977 | .simple_type => @panic("TODO"), | ||
| 2978 | .struct_type => @panic("TODO"), | ||
| 2979 | .simple_value => unreachable, | ||
| 2980 | .extern_func => unreachable, | ||
| 2981 | .int => unreachable, | ||
| 2982 | .enum_tag => unreachable, // it's a value, not a type | ||
| 2983 | }; | ||
| 2984 | |||
| 2880 | const opt_sema = switch (strat) { | 2985 | const opt_sema = switch (strat) { |
| 2881 | .sema => |sema| sema, | 2986 | .sema => |sema| sema, |
| 2882 | else => null, | 2987 | else => null, |
| ... | @@ -2902,12 +3007,6 @@ pub const Type = extern union { | ... | @@ -2902,12 +3007,6 @@ pub const Type = extern union { |
| 2902 | .anyopaque, | 3007 | .anyopaque, |
| 2903 | => return AbiAlignmentAdvanced{ .scalar = 1 }, | 3008 | => return AbiAlignmentAdvanced{ .scalar = 1 }, |
| 2904 | 3009 | ||
| 2905 | .fn_noreturn_no_args, // represents machine code; not a pointer | ||
| 2906 | .fn_void_no_args, // represents machine code; not a pointer | ||
| 2907 | .fn_naked_noreturn_no_args, // represents machine code; not a pointer | ||
| 2908 | .fn_ccc_void_no_args, // represents machine code; not a pointer | ||
| 2909 | => return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) }, | ||
| 2910 | |||
| 2911 | // represents machine code; not a pointer | 3010 | // represents machine code; not a pointer |
| 2912 | .function => { | 3011 | .function => { |
| 2913 | const alignment = ty.castTag(.function).?.data.alignment; | 3012 | const alignment = ty.castTag(.function).?.data.alignment; |
| ... | @@ -2958,12 +3057,11 @@ pub const Type = extern union { | ... | @@ -2958,12 +3057,11 @@ pub const Type = extern union { |
| 2958 | .f80 => switch (target.c_type_bit_size(.longdouble)) { | 3057 | .f80 => switch (target.c_type_bit_size(.longdouble)) { |
| 2959 | 80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) }, | 3058 | 80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) }, |
| 2960 | else => { | 3059 | else => { |
| 2961 | var payload: Payload.Bits = .{ | 3060 | const u80_ty: Type = .{ |
| 2962 | .base = .{ .tag = .int_unsigned }, | 3061 | .ip_index = .u80_type, |
| 2963 | .data = 80, | 3062 | .legacy = undefined, |
| 2964 | }; | 3063 | }; |
| 2965 | const u80_ty = initPayload(&payload.base); | 3064 | return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, mod) }; |
| 2966 | return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, target) }; | ||
| 2967 | }, | 3065 | }, |
| 2968 | }, | 3066 | }, |
| 2969 | .f128 => switch (target.c_type_bit_size(.longdouble)) { | 3067 | .f128 => switch (target.c_type_bit_size(.longdouble)) { |
| ... | @@ -2980,11 +3078,11 @@ pub const Type = extern union { | ... | @@ -2980,11 +3078,11 @@ pub const Type = extern union { |
| 2980 | .error_set_merged, | 3078 | .error_set_merged, |
| 2981 | => return AbiAlignmentAdvanced{ .scalar = 2 }, | 3079 | => return AbiAlignmentAdvanced{ .scalar = 2 }, |
| 2982 | 3080 | ||
| 2983 | .array, .array_sentinel => return ty.elemType().abiAlignmentAdvanced(target, strat), | 3081 | .array, .array_sentinel => return ty.elemType().abiAlignmentAdvanced(mod, strat), |
| 2984 | 3082 | ||
| 2985 | .vector => { | 3083 | .vector => { |
| 2986 | const len = ty.arrayLen(); | 3084 | const len = ty.arrayLen(); |
| 2987 | const bits = try bitSizeAdvanced(ty.elemType(), target, opt_sema); | 3085 | const bits = try bitSizeAdvanced(ty.elemType(), mod, opt_sema); |
| 2988 | const bytes = ((bits * len) + 7) / 8; | 3086 | const bytes = ((bits * len) + 7) / 8; |
| 2989 | const alignment = std.math.ceilPowerOfTwoAssert(u64, bytes); | 3087 | const alignment = std.math.ceilPowerOfTwoAssert(u64, bytes); |
| 2990 | return AbiAlignmentAdvanced{ .scalar = @intCast(u32, alignment) }; | 3088 | return AbiAlignmentAdvanced{ .scalar = @intCast(u32, alignment) }; |
| ... | @@ -2996,34 +3094,28 @@ pub const Type = extern union { | ... | @@ -2996,34 +3094,28 @@ pub const Type = extern union { |
| 2996 | .i64, .u64 => return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(64, target) }, | 3094 | .i64, .u64 => return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(64, target) }, |
| 2997 | .u128, .i128 => return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(128, target) }, | 3095 | .u128, .i128 => return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(128, target) }, |
| 2998 | 3096 | ||
| 2999 | .int_signed, .int_unsigned => { | ||
| 3000 | const bits: u16 = ty.cast(Payload.Bits).?.data; | ||
| 3001 | if (bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 }; | ||
| 3002 | return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(bits, target) }; | ||
| 3003 | }, | ||
| 3004 | |||
| 3005 | .optional => { | 3097 | .optional => { |
| 3006 | var buf: Payload.ElemType = undefined; | 3098 | var buf: Payload.ElemType = undefined; |
| 3007 | const child_type = ty.optionalChild(&buf); | 3099 | const child_type = ty.optionalChild(&buf); |
| 3008 | 3100 | ||
| 3009 | switch (child_type.zigTypeTag()) { | 3101 | switch (child_type.zigTypeTag(mod)) { |
| 3010 | .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, | 3102 | .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, |
| 3011 | .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, target, strat), | 3103 | .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat), |
| 3012 | .NoReturn => return AbiAlignmentAdvanced{ .scalar = 0 }, | 3104 | .NoReturn => return AbiAlignmentAdvanced{ .scalar = 0 }, |
| 3013 | else => {}, | 3105 | else => {}, |
| 3014 | } | 3106 | } |
| 3015 | 3107 | ||
| 3016 | switch (strat) { | 3108 | switch (strat) { |
| 3017 | .eager, .sema => { | 3109 | .eager, .sema => { |
| 3018 | if (!(child_type.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { | 3110 | if (!(child_type.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { |
| 3019 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, | 3111 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, |
| 3020 | else => |e| return e, | 3112 | else => |e| return e, |
| 3021 | })) { | 3113 | })) { |
| 3022 | return AbiAlignmentAdvanced{ .scalar = 1 }; | 3114 | return AbiAlignmentAdvanced{ .scalar = 1 }; |
| 3023 | } | 3115 | } |
| 3024 | return child_type.abiAlignmentAdvanced(target, strat); | 3116 | return child_type.abiAlignmentAdvanced(mod, strat); |
| 3025 | }, | 3117 | }, |
| 3026 | .lazy => |arena| switch (try child_type.abiAlignmentAdvanced(target, strat)) { | 3118 | .lazy => |arena| switch (try child_type.abiAlignmentAdvanced(mod, strat)) { |
| 3027 | .scalar => |x| return AbiAlignmentAdvanced{ .scalar = @max(x, 1) }, | 3119 | .scalar => |x| return AbiAlignmentAdvanced{ .scalar = @max(x, 1) }, |
| 3028 | .val => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, | 3120 | .val => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) }, |
| 3029 | }, | 3121 | }, |
| ... | @@ -3034,10 +3126,10 @@ pub const Type = extern union { | ... | @@ -3034,10 +3126,10 @@ pub const Type = extern union { |
| 3034 | // This code needs to be kept in sync with the equivalent switch prong | 3126 | // This code needs to be kept in sync with the equivalent switch prong |
| 3035 | // in abiSizeAdvanced. | 3127 | // in abiSizeAdvanced. |
| 3036 | const data = ty.castTag(.error_union).?.data; | 3128 | const data = ty.castTag(.error_union).?.data; |
| 3037 | const code_align = abiAlignment(Type.anyerror, target); | 3129 | const code_align = abiAlignment(Type.anyerror, mod); |
| 3038 | switch (strat) { | 3130 | switch (strat) { |
| 3039 | .eager, .sema => { | 3131 | .eager, .sema => { |
| 3040 | if (!(data.payload.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { | 3132 | if (!(data.payload.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { |
| 3041 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, | 3133 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, |
| 3042 | else => |e| return e, | 3134 | else => |e| return e, |
| 3043 | })) { | 3135 | })) { |
| ... | @@ -3045,11 +3137,11 @@ pub const Type = extern union { | ... | @@ -3045,11 +3137,11 @@ pub const Type = extern union { |
| 3045 | } | 3137 | } |
| 3046 | return AbiAlignmentAdvanced{ .scalar = @max( | 3138 | return AbiAlignmentAdvanced{ .scalar = @max( |
| 3047 | code_align, | 3139 | code_align, |
| 3048 | (try data.payload.abiAlignmentAdvanced(target, strat)).scalar, | 3140 | (try data.payload.abiAlignmentAdvanced(mod, strat)).scalar, |
| 3049 | ) }; | 3141 | ) }; |
| 3050 | }, | 3142 | }, |
| 3051 | .lazy => |arena| { | 3143 | .lazy => |arena| { |
| 3052 | switch (try data.payload.abiAlignmentAdvanced(target, strat)) { | 3144 | switch (try data.payload.abiAlignmentAdvanced(mod, strat)) { |
| 3053 | .scalar => |payload_align| { | 3145 | .scalar => |payload_align| { |
| 3054 | return AbiAlignmentAdvanced{ | 3146 | return AbiAlignmentAdvanced{ |
| 3055 | .scalar = @max(code_align, payload_align), | 3147 | .scalar = @max(code_align, payload_align), |
| ... | @@ -3089,20 +3181,20 @@ pub const Type = extern union { | ... | @@ -3089,20 +3181,20 @@ pub const Type = extern union { |
| 3089 | .eager => {}, | 3181 | .eager => {}, |
| 3090 | } | 3182 | } |
| 3091 | assert(struct_obj.haveLayout()); | 3183 | assert(struct_obj.haveLayout()); |
| 3092 | return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(target) }; | 3184 | return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) }; |
| 3093 | } | 3185 | } |
| 3094 | 3186 | ||
| 3095 | const fields = ty.structFields(); | 3187 | const fields = ty.structFields(); |
| 3096 | var big_align: u32 = 0; | 3188 | var big_align: u32 = 0; |
| 3097 | for (fields.values()) |field| { | 3189 | for (fields.values()) |field| { |
| 3098 | if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { | 3190 | if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { |
| 3099 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, | 3191 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, |
| 3100 | else => |e| return e, | 3192 | else => |e| return e, |
| 3101 | })) continue; | 3193 | })) continue; |
| 3102 | 3194 | ||
| 3103 | const field_align = if (field.abi_align != 0) | 3195 | const field_align = if (field.abi_align != 0) |
| 3104 | field.abi_align | 3196 | field.abi_align |
| 3105 | else switch (try field.ty.abiAlignmentAdvanced(target, strat)) { | 3197 | else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) { |
| 3106 | .scalar => |a| a, | 3198 | .scalar => |a| a, |
| 3107 | .val => switch (strat) { | 3199 | .val => switch (strat) { |
| 3108 | .eager => unreachable, // struct layout not resolved | 3200 | .eager => unreachable, // struct layout not resolved |
| ... | @@ -3114,7 +3206,7 @@ pub const Type = extern union { | ... | @@ -3114,7 +3206,7 @@ pub const Type = extern union { |
| 3114 | 3206 | ||
| 3115 | // This logic is duplicated in Module.Struct.Field.alignment. | 3207 | // This logic is duplicated in Module.Struct.Field.alignment. |
| 3116 | if (struct_obj.layout == .Extern or target.ofmt == .c) { | 3208 | if (struct_obj.layout == .Extern or target.ofmt == .c) { |
| 3117 | if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) { | 3209 | if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) { |
| 3118 | // The C ABI requires 128 bit integer fields of structs | 3210 | // The C ABI requires 128 bit integer fields of structs |
| 3119 | // to be 16-bytes aligned. | 3211 | // to be 16-bytes aligned. |
| 3120 | big_align = @max(big_align, 16); | 3212 | big_align = @max(big_align, 16); |
| ... | @@ -3130,9 +3222,9 @@ pub const Type = extern union { | ... | @@ -3130,9 +3222,9 @@ pub const Type = extern union { |
| 3130 | for (tuple.types, 0..) |field_ty, i| { | 3222 | for (tuple.types, 0..) |field_ty, i| { |
| 3131 | const val = tuple.values[i]; | 3223 | const val = tuple.values[i]; |
| 3132 | if (val.tag() != .unreachable_value) continue; // comptime field | 3224 | if (val.tag() != .unreachable_value) continue; // comptime field |
| 3133 | if (!(field_ty.hasRuntimeBits())) continue; | 3225 | if (!(field_ty.hasRuntimeBits(mod))) continue; |
| 3134 | 3226 | ||
| 3135 | switch (try field_ty.abiAlignmentAdvanced(target, strat)) { | 3227 | switch (try field_ty.abiAlignmentAdvanced(mod, strat)) { |
| 3136 | .scalar => |field_align| big_align = @max(big_align, field_align), | 3228 | .scalar => |field_align| big_align = @max(big_align, field_align), |
| 3137 | .val => switch (strat) { | 3229 | .val => switch (strat) { |
| 3138 | .eager => unreachable, // field type alignment not resolved | 3230 | .eager => unreachable, // field type alignment not resolved |
| ... | @@ -3145,17 +3237,16 @@ pub const Type = extern union { | ... | @@ -3145,17 +3237,16 @@ pub const Type = extern union { |
| 3145 | }, | 3237 | }, |
| 3146 | 3238 | ||
| 3147 | .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => { | 3239 | .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => { |
| 3148 | var buffer: Payload.Bits = undefined; | 3240 | const int_tag_ty = ty.intTagType(); |
| 3149 | const int_tag_ty = ty.intTagType(&buffer); | 3241 | return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(mod) }; |
| 3150 | return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(target) }; | ||
| 3151 | }, | 3242 | }, |
| 3152 | .@"union" => { | 3243 | .@"union" => { |
| 3153 | const union_obj = ty.castTag(.@"union").?.data; | 3244 | const union_obj = ty.castTag(.@"union").?.data; |
| 3154 | return abiAlignmentAdvancedUnion(ty, target, strat, union_obj, false); | 3245 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, false); |
| 3155 | }, | 3246 | }, |
| 3156 | .union_safety_tagged, .union_tagged => { | 3247 | .union_safety_tagged, .union_tagged => { |
| 3157 | const union_obj = ty.cast(Payload.Union).?.data; | 3248 | const union_obj = ty.cast(Payload.Union).?.data; |
| 3158 | return abiAlignmentAdvancedUnion(ty, target, strat, union_obj, true); | 3249 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true); |
| 3159 | }, | 3250 | }, |
| 3160 | 3251 | ||
| 3161 | .empty_struct, | 3252 | .empty_struct, |
| ... | @@ -3181,7 +3272,7 @@ pub const Type = extern union { | ... | @@ -3181,7 +3272,7 @@ pub const Type = extern union { |
| 3181 | 3272 | ||
| 3182 | pub fn abiAlignmentAdvancedUnion( | 3273 | pub fn abiAlignmentAdvancedUnion( |
| 3183 | ty: Type, | 3274 | ty: Type, |
| 3184 | target: Target, | 3275 | mod: *const Module, |
| 3185 | strat: AbiAlignmentAdvancedStrat, | 3276 | strat: AbiAlignmentAdvancedStrat, |
| 3186 | union_obj: *Module.Union, | 3277 | union_obj: *Module.Union, |
| 3187 | have_tag: bool, | 3278 | have_tag: bool, |
| ... | @@ -3195,6 +3286,7 @@ pub const Type = extern union { | ... | @@ -3195,6 +3286,7 @@ pub const Type = extern union { |
| 3195 | // We'll guess "pointer-aligned", if the union has an | 3286 | // We'll guess "pointer-aligned", if the union has an |
| 3196 | // underaligned pointer field then some allocations | 3287 | // underaligned pointer field then some allocations |
| 3197 | // might require explicit alignment. | 3288 | // might require explicit alignment. |
| 3289 | const target = mod.getTarget(); | ||
| 3198 | return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }; | 3290 | return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }; |
| 3199 | } | 3291 | } |
| 3200 | _ = try sema.resolveTypeFields(ty); | 3292 | _ = try sema.resolveTypeFields(ty); |
| ... | @@ -3206,23 +3298,23 @@ pub const Type = extern union { | ... | @@ -3206,23 +3298,23 @@ pub const Type = extern union { |
| 3206 | }; | 3298 | }; |
| 3207 | if (union_obj.fields.count() == 0) { | 3299 | if (union_obj.fields.count() == 0) { |
| 3208 | if (have_tag) { | 3300 | if (have_tag) { |
| 3209 | return abiAlignmentAdvanced(union_obj.tag_ty, target, strat); | 3301 | return abiAlignmentAdvanced(union_obj.tag_ty, mod, strat); |
| 3210 | } else { | 3302 | } else { |
| 3211 | return AbiAlignmentAdvanced{ .scalar = @boolToInt(union_obj.layout == .Extern) }; | 3303 | return AbiAlignmentAdvanced{ .scalar = @boolToInt(union_obj.layout == .Extern) }; |
| 3212 | } | 3304 | } |
| 3213 | } | 3305 | } |
| 3214 | 3306 | ||
| 3215 | var max_align: u32 = 0; | 3307 | var max_align: u32 = 0; |
| 3216 | if (have_tag) max_align = union_obj.tag_ty.abiAlignment(target); | 3308 | if (have_tag) max_align = union_obj.tag_ty.abiAlignment(mod); |
| 3217 | for (union_obj.fields.values()) |field| { | 3309 | for (union_obj.fields.values()) |field| { |
| 3218 | if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { | 3310 | if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { |
| 3219 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, | 3311 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, |
| 3220 | else => |e| return e, | 3312 | else => |e| return e, |
| 3221 | })) continue; | 3313 | })) continue; |
| 3222 | 3314 | ||
| 3223 | const field_align = if (field.abi_align != 0) | 3315 | const field_align = if (field.abi_align != 0) |
| 3224 | field.abi_align | 3316 | field.abi_align |
| 3225 | else switch (try field.ty.abiAlignmentAdvanced(target, strat)) { | 3317 | else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) { |
| 3226 | .scalar => |a| a, | 3318 | .scalar => |a| a, |
| 3227 | .val => switch (strat) { | 3319 | .val => switch (strat) { |
| 3228 | .eager => unreachable, // struct layout not resolved | 3320 | .eager => unreachable, // struct layout not resolved |
| ... | @@ -3236,8 +3328,8 @@ pub const Type = extern union { | ... | @@ -3236,8 +3328,8 @@ pub const Type = extern union { |
| 3236 | } | 3328 | } |
| 3237 | 3329 | ||
| 3238 | /// May capture a reference to `ty`. | 3330 | /// May capture a reference to `ty`. |
| 3239 | pub fn lazyAbiSize(ty: Type, target: Target, arena: Allocator) !Value { | 3331 | pub fn lazyAbiSize(ty: Type, mod: *const Module, arena: Allocator) !Value { |
| 3240 | switch (try ty.abiSizeAdvanced(target, .{ .lazy = arena })) { | 3332 | switch (try ty.abiSizeAdvanced(mod, .{ .lazy = arena })) { |
| 3241 | .val => |val| return val, | 3333 | .val => |val| return val, |
| 3242 | .scalar => |x| return Value.Tag.int_u64.create(arena, x), | 3334 | .scalar => |x| return Value.Tag.int_u64.create(arena, x), |
| 3243 | } | 3335 | } |
| ... | @@ -3245,8 +3337,8 @@ pub const Type = extern union { | ... | @@ -3245,8 +3337,8 @@ pub const Type = extern union { |
| 3245 | 3337 | ||
| 3246 | /// Asserts the type has the ABI size already resolved. | 3338 | /// Asserts the type has the ABI size already resolved. |
| 3247 | /// Types that return false for hasRuntimeBits() return 0. | 3339 | /// Types that return false for hasRuntimeBits() return 0. |
| 3248 | pub fn abiSize(ty: Type, target: Target) u64 { | 3340 | pub fn abiSize(ty: Type, mod: *const Module) u64 { |
| 3249 | return (abiSizeAdvanced(ty, target, .eager) catch unreachable).scalar; | 3341 | return (abiSizeAdvanced(ty, mod, .eager) catch unreachable).scalar; |
| 3250 | } | 3342 | } |
| 3251 | 3343 | ||
| 3252 | const AbiSizeAdvanced = union(enum) { | 3344 | const AbiSizeAdvanced = union(enum) { |
| ... | @@ -3262,14 +3354,30 @@ pub const Type = extern union { | ... | @@ -3262,14 +3354,30 @@ pub const Type = extern union { |
| 3262 | /// necessary, possibly returning a CompileError. | 3354 | /// necessary, possibly returning a CompileError. |
| 3263 | pub fn abiSizeAdvanced( | 3355 | pub fn abiSizeAdvanced( |
| 3264 | ty: Type, | 3356 | ty: Type, |
| 3265 | target: Target, | 3357 | mod: *const Module, |
| 3266 | strat: AbiAlignmentAdvancedStrat, | 3358 | strat: AbiAlignmentAdvancedStrat, |
| 3267 | ) Module.CompileError!AbiSizeAdvanced { | 3359 | ) Module.CompileError!AbiSizeAdvanced { |
| 3360 | const target = mod.getTarget(); | ||
| 3361 | |||
| 3362 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 3363 | .int_type => |int_type| { | ||
| 3364 | if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 }; | ||
| 3365 | return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) }; | ||
| 3366 | }, | ||
| 3367 | .ptr_type => @panic("TODO"), | ||
| 3368 | .array_type => @panic("TODO"), | ||
| 3369 | .vector_type => @panic("TODO"), | ||
| 3370 | .optional_type => @panic("TODO"), | ||
| 3371 | .error_union_type => @panic("TODO"), | ||
| 3372 | .simple_type => @panic("TODO"), | ||
| 3373 | .struct_type => @panic("TODO"), | ||
| 3374 | .simple_value => unreachable, | ||
| 3375 | .extern_func => unreachable, | ||
| 3376 | .int => unreachable, | ||
| 3377 | .enum_tag => unreachable, // it's a value, not a type | ||
| 3378 | }; | ||
| 3379 | |||
| 3268 | switch (ty.tag()) { | 3380 | switch (ty.tag()) { |
| 3269 | .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer | ||
| 3270 | .fn_void_no_args => unreachable, // represents machine code; not a pointer | ||
| 3271 | .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer | ||
| 3272 | .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer | ||
| 3273 | .function => unreachable, // represents machine code; not a pointer | 3381 | .function => unreachable, // represents machine code; not a pointer |
| 3274 | .@"opaque" => unreachable, // no size available | 3382 | .@"opaque" => unreachable, // no size available |
| 3275 | .noreturn => unreachable, | 3383 | .noreturn => unreachable, |
| ... | @@ -3308,7 +3416,7 @@ pub const Type = extern union { | ... | @@ -3308,7 +3416,7 @@ pub const Type = extern union { |
| 3308 | .eager => {}, | 3416 | .eager => {}, |
| 3309 | } | 3417 | } |
| 3310 | assert(struct_obj.haveLayout()); | 3418 | assert(struct_obj.haveLayout()); |
| 3311 | return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(target) }; | 3419 | return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) }; |
| 3312 | }, | 3420 | }, |
| 3313 | else => { | 3421 | else => { |
| 3314 | switch (strat) { | 3422 | switch (strat) { |
| ... | @@ -3327,22 +3435,21 @@ pub const Type = extern union { | ... | @@ -3327,22 +3435,21 @@ pub const Type = extern union { |
| 3327 | if (field_count == 0) { | 3435 | if (field_count == 0) { |
| 3328 | return AbiSizeAdvanced{ .scalar = 0 }; | 3436 | return AbiSizeAdvanced{ .scalar = 0 }; |
| 3329 | } | 3437 | } |
| 3330 | return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, target) }; | 3438 | return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) }; |
| 3331 | }, | 3439 | }, |
| 3332 | }, | 3440 | }, |
| 3333 | 3441 | ||
| 3334 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { | 3442 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { |
| 3335 | var buffer: Payload.Bits = undefined; | 3443 | const int_tag_ty = ty.intTagType(); |
| 3336 | const int_tag_ty = ty.intTagType(&buffer); | 3444 | return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(mod) }; |
| 3337 | return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(target) }; | ||
| 3338 | }, | 3445 | }, |
| 3339 | .@"union" => { | 3446 | .@"union" => { |
| 3340 | const union_obj = ty.castTag(.@"union").?.data; | 3447 | const union_obj = ty.castTag(.@"union").?.data; |
| 3341 | return abiSizeAdvancedUnion(ty, target, strat, union_obj, false); | 3448 | return abiSizeAdvancedUnion(ty, mod, strat, union_obj, false); |
| 3342 | }, | 3449 | }, |
| 3343 | .union_safety_tagged, .union_tagged => { | 3450 | .union_safety_tagged, .union_tagged => { |
| 3344 | const union_obj = ty.cast(Payload.Union).?.data; | 3451 | const union_obj = ty.cast(Payload.Union).?.data; |
| 3345 | return abiSizeAdvancedUnion(ty, target, strat, union_obj, true); | 3452 | return abiSizeAdvancedUnion(ty, mod, strat, union_obj, true); |
| 3346 | }, | 3453 | }, |
| 3347 | 3454 | ||
| 3348 | .u1, | 3455 | .u1, |
| ... | @@ -3361,7 +3468,7 @@ pub const Type = extern union { | ... | @@ -3361,7 +3468,7 @@ pub const Type = extern union { |
| 3361 | .array_u8_sentinel_0 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8_sentinel_0).?.data + 1 }, | 3468 | .array_u8_sentinel_0 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8_sentinel_0).?.data + 1 }, |
| 3362 | .array => { | 3469 | .array => { |
| 3363 | const payload = ty.castTag(.array).?.data; | 3470 | const payload = ty.castTag(.array).?.data; |
| 3364 | switch (try payload.elem_type.abiSizeAdvanced(target, strat)) { | 3471 | switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) { |
| 3365 | .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size }, | 3472 | .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size }, |
| 3366 | .val => switch (strat) { | 3473 | .val => switch (strat) { |
| 3367 | .sema => unreachable, | 3474 | .sema => unreachable, |
| ... | @@ -3372,7 +3479,7 @@ pub const Type = extern union { | ... | @@ -3372,7 +3479,7 @@ pub const Type = extern union { |
| 3372 | }, | 3479 | }, |
| 3373 | .array_sentinel => { | 3480 | .array_sentinel => { |
| 3374 | const payload = ty.castTag(.array_sentinel).?.data; | 3481 | const payload = ty.castTag(.array_sentinel).?.data; |
| 3375 | switch (try payload.elem_type.abiSizeAdvanced(target, strat)) { | 3482 | switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) { |
| 3376 | .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = (payload.len + 1) * elem_size }, | 3483 | .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = (payload.len + 1) * elem_size }, |
| 3377 | .val => switch (strat) { | 3484 | .val => switch (strat) { |
| 3378 | .sema => unreachable, | 3485 | .sema => unreachable, |
| ... | @@ -3391,10 +3498,10 @@ pub const Type = extern union { | ... | @@ -3391,10 +3498,10 @@ pub const Type = extern union { |
| 3391 | .val = try Value.Tag.lazy_size.create(arena, ty), | 3498 | .val = try Value.Tag.lazy_size.create(arena, ty), |
| 3392 | }, | 3499 | }, |
| 3393 | }; | 3500 | }; |
| 3394 | const elem_bits = try payload.elem_type.bitSizeAdvanced(target, opt_sema); | 3501 | const elem_bits = try payload.elem_type.bitSizeAdvanced(mod, opt_sema); |
| 3395 | const total_bits = elem_bits * payload.len; | 3502 | const total_bits = elem_bits * payload.len; |
| 3396 | const total_bytes = (total_bits + 7) / 8; | 3503 | const total_bytes = (total_bits + 7) / 8; |
| 3397 | const alignment = switch (try ty.abiAlignmentAdvanced(target, strat)) { | 3504 | const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) { |
| 3398 | .scalar => |x| x, | 3505 | .scalar => |x| x, |
| 3399 | .val => return AbiSizeAdvanced{ | 3506 | .val => return AbiSizeAdvanced{ |
| 3400 | .val = try Value.Tag.lazy_size.create(strat.lazy, ty), | 3507 | .val = try Value.Tag.lazy_size.create(strat.lazy, ty), |
| ... | @@ -3450,12 +3557,11 @@ pub const Type = extern union { | ... | @@ -3450,12 +3557,11 @@ pub const Type = extern union { |
| 3450 | .f80 => switch (target.c_type_bit_size(.longdouble)) { | 3557 | .f80 => switch (target.c_type_bit_size(.longdouble)) { |
| 3451 | 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) }, | 3558 | 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) }, |
| 3452 | else => { | 3559 | else => { |
| 3453 | var payload: Payload.Bits = .{ | 3560 | const u80_ty: Type = .{ |
| 3454 | .base = .{ .tag = .int_unsigned }, | 3561 | .ip_index = .u80_type, |
| 3455 | .data = 80, | 3562 | .legacy = undefined, |
| 3456 | }; | 3563 | }; |
| 3457 | const u80_ty = initPayload(&payload.base); | 3564 | return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, mod) }; |
| 3458 | return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, target) }; | ||
| 3459 | }, | 3565 | }, |
| 3460 | }, | 3566 | }, |
| 3461 | 3567 | ||
| ... | @@ -3473,11 +3579,6 @@ pub const Type = extern union { | ... | @@ -3473,11 +3579,6 @@ pub const Type = extern union { |
| 3473 | .i32, .u32 => return AbiSizeAdvanced{ .scalar = intAbiSize(32, target) }, | 3579 | .i32, .u32 => return AbiSizeAdvanced{ .scalar = intAbiSize(32, target) }, |
| 3474 | .i64, .u64 => return AbiSizeAdvanced{ .scalar = intAbiSize(64, target) }, | 3580 | .i64, .u64 => return AbiSizeAdvanced{ .scalar = intAbiSize(64, target) }, |
| 3475 | .u128, .i128 => return AbiSizeAdvanced{ .scalar = intAbiSize(128, target) }, | 3581 | .u128, .i128 => return AbiSizeAdvanced{ .scalar = intAbiSize(128, target) }, |
| 3476 | .int_signed, .int_unsigned => { | ||
| 3477 | const bits: u16 = ty.cast(Payload.Bits).?.data; | ||
| 3478 | if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 }; | ||
| 3479 | return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) }; | ||
| 3480 | }, | ||
| 3481 | 3582 | ||
| 3482 | .optional => { | 3583 | .optional => { |
| 3483 | var buf: Payload.ElemType = undefined; | 3584 | var buf: Payload.ElemType = undefined; |
| ... | @@ -3487,16 +3588,16 @@ pub const Type = extern union { | ... | @@ -3487,16 +3588,16 @@ pub const Type = extern union { |
| 3487 | return AbiSizeAdvanced{ .scalar = 0 }; | 3588 | return AbiSizeAdvanced{ .scalar = 0 }; |
| 3488 | } | 3589 | } |
| 3489 | 3590 | ||
| 3490 | if (!(child_type.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { | 3591 | if (!(child_type.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { |
| 3491 | error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) }, | 3592 | error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) }, |
| 3492 | else => |e| return e, | 3593 | else => |e| return e, |
| 3493 | })) return AbiSizeAdvanced{ .scalar = 1 }; | 3594 | })) return AbiSizeAdvanced{ .scalar = 1 }; |
| 3494 | 3595 | ||
| 3495 | if (ty.optionalReprIsPayload()) { | 3596 | if (ty.optionalReprIsPayload(mod)) { |
| 3496 | return abiSizeAdvanced(child_type, target, strat); | 3597 | return abiSizeAdvanced(child_type, mod, strat); |
| 3497 | } | 3598 | } |
| 3498 | 3599 | ||
| 3499 | const payload_size = switch (try child_type.abiSizeAdvanced(target, strat)) { | 3600 | const payload_size = switch (try child_type.abiSizeAdvanced(mod, strat)) { |
| 3500 | .scalar => |elem_size| elem_size, | 3601 | .scalar => |elem_size| elem_size, |
| 3501 | .val => switch (strat) { | 3602 | .val => switch (strat) { |
| 3502 | .sema => unreachable, | 3603 | .sema => unreachable, |
| ... | @@ -3510,7 +3611,7 @@ pub const Type = extern union { | ... | @@ -3510,7 +3611,7 @@ pub const Type = extern union { |
| 3510 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal | 3611 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal |
| 3511 | // to the child type's ABI alignment. | 3612 | // to the child type's ABI alignment. |
| 3512 | return AbiSizeAdvanced{ | 3613 | return AbiSizeAdvanced{ |
| 3513 | .scalar = child_type.abiAlignment(target) + payload_size, | 3614 | .scalar = child_type.abiAlignment(mod) + payload_size, |
| 3514 | }; | 3615 | }; |
| 3515 | }, | 3616 | }, |
| 3516 | 3617 | ||
| ... | @@ -3518,17 +3619,17 @@ pub const Type = extern union { | ... | @@ -3518,17 +3619,17 @@ pub const Type = extern union { |
| 3518 | // This code needs to be kept in sync with the equivalent switch prong | 3619 | // This code needs to be kept in sync with the equivalent switch prong |
| 3519 | // in abiAlignmentAdvanced. | 3620 | // in abiAlignmentAdvanced. |
| 3520 | const data = ty.castTag(.error_union).?.data; | 3621 | const data = ty.castTag(.error_union).?.data; |
| 3521 | const code_size = abiSize(Type.anyerror, target); | 3622 | const code_size = abiSize(Type.anyerror, mod); |
| 3522 | if (!(data.payload.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { | 3623 | if (!(data.payload.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { |
| 3523 | error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) }, | 3624 | error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) }, |
| 3524 | else => |e| return e, | 3625 | else => |e| return e, |
| 3525 | })) { | 3626 | })) { |
| 3526 | // Same as anyerror. | 3627 | // Same as anyerror. |
| 3527 | return AbiSizeAdvanced{ .scalar = code_size }; | 3628 | return AbiSizeAdvanced{ .scalar = code_size }; |
| 3528 | } | 3629 | } |
| 3529 | const code_align = abiAlignment(Type.anyerror, target); | 3630 | const code_align = abiAlignment(Type.anyerror, mod); |
| 3530 | const payload_align = abiAlignment(data.payload, target); | 3631 | const payload_align = abiAlignment(data.payload, mod); |
| 3531 | const payload_size = switch (try data.payload.abiSizeAdvanced(target, strat)) { | 3632 | const payload_size = switch (try data.payload.abiSizeAdvanced(mod, strat)) { |
| 3532 | .scalar => |elem_size| elem_size, | 3633 | .scalar => |elem_size| elem_size, |
| 3533 | .val => switch (strat) { | 3634 | .val => switch (strat) { |
| 3534 | .sema => unreachable, | 3635 | .sema => unreachable, |
| ... | @@ -3556,7 +3657,7 @@ pub const Type = extern union { | ... | @@ -3556,7 +3657,7 @@ pub const Type = extern union { |
| 3556 | 3657 | ||
| 3557 | pub fn abiSizeAdvancedUnion( | 3658 | pub fn abiSizeAdvancedUnion( |
| 3558 | ty: Type, | 3659 | ty: Type, |
| 3559 | target: Target, | 3660 | mod: *const Module, |
| 3560 | strat: AbiAlignmentAdvancedStrat, | 3661 | strat: AbiAlignmentAdvancedStrat, |
| 3561 | union_obj: *Module.Union, | 3662 | union_obj: *Module.Union, |
| 3562 | have_tag: bool, | 3663 | have_tag: bool, |
| ... | @@ -3570,7 +3671,7 @@ pub const Type = extern union { | ... | @@ -3570,7 +3671,7 @@ pub const Type = extern union { |
| 3570 | }, | 3671 | }, |
| 3571 | .eager => {}, | 3672 | .eager => {}, |
| 3572 | } | 3673 | } |
| 3573 | return AbiSizeAdvanced{ .scalar = union_obj.abiSize(target, have_tag) }; | 3674 | return AbiSizeAdvanced{ .scalar = union_obj.abiSize(mod, have_tag) }; |
| 3574 | } | 3675 | } |
| 3575 | 3676 | ||
| 3576 | fn intAbiSize(bits: u16, target: Target) u64 { | 3677 | fn intAbiSize(bits: u16, target: Target) u64 { |
| ... | @@ -3585,8 +3686,8 @@ pub const Type = extern union { | ... | @@ -3585,8 +3686,8 @@ pub const Type = extern union { |
| 3585 | ); | 3686 | ); |
| 3586 | } | 3687 | } |
| 3587 | 3688 | ||
| 3588 | pub fn bitSize(ty: Type, target: Target) u64 { | 3689 | pub fn bitSize(ty: Type, mod: *const Module) u64 { |
| 3589 | return bitSizeAdvanced(ty, target, null) catch unreachable; | 3690 | return bitSizeAdvanced(ty, mod, null) catch unreachable; |
| 3590 | } | 3691 | } |
| 3591 | 3692 | ||
| 3592 | /// If you pass `opt_sema`, any recursive type resolutions will happen if | 3693 | /// If you pass `opt_sema`, any recursive type resolutions will happen if |
| ... | @@ -3594,15 +3695,29 @@ pub const Type = extern union { | ... | @@ -3594,15 +3695,29 @@ pub const Type = extern union { |
| 3594 | /// the type is fully resolved, and there will be no error, guaranteed. | 3695 | /// the type is fully resolved, and there will be no error, guaranteed. |
| 3595 | pub fn bitSizeAdvanced( | 3696 | pub fn bitSizeAdvanced( |
| 3596 | ty: Type, | 3697 | ty: Type, |
| 3597 | target: Target, | 3698 | mod: *const Module, |
| 3598 | opt_sema: ?*Sema, | 3699 | opt_sema: ?*Sema, |
| 3599 | ) Module.CompileError!u64 { | 3700 | ) Module.CompileError!u64 { |
| 3701 | const target = mod.getTarget(); | ||
| 3702 | |||
| 3703 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 3704 | .int_type => |int_type| return int_type.bits, | ||
| 3705 | .ptr_type => @panic("TODO"), | ||
| 3706 | .array_type => @panic("TODO"), | ||
| 3707 | .vector_type => @panic("TODO"), | ||
| 3708 | .optional_type => @panic("TODO"), | ||
| 3709 | .error_union_type => @panic("TODO"), | ||
| 3710 | .simple_type => @panic("TODO"), | ||
| 3711 | .struct_type => @panic("TODO"), | ||
| 3712 | .simple_value => unreachable, | ||
| 3713 | .extern_func => unreachable, | ||
| 3714 | .int => unreachable, | ||
| 3715 | .enum_tag => unreachable, // it's a value, not a type | ||
| 3716 | }; | ||
| 3717 | |||
| 3600 | const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; | 3718 | const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; |
| 3719 | |||
| 3601 | switch (ty.tag()) { | 3720 | switch (ty.tag()) { |
| 3602 | .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer | ||
| 3603 | .fn_void_no_args => unreachable, // represents machine code; not a pointer | ||
| 3604 | .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer | ||
| 3605 | .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer | ||
| 3606 | .function => unreachable, // represents machine code; not a pointer | 3721 | .function => unreachable, // represents machine code; not a pointer |
| 3607 | .anyopaque => unreachable, | 3722 | .anyopaque => unreachable, |
| 3608 | .type => unreachable, | 3723 | .type => unreachable, |
| ... | @@ -3633,68 +3748,67 @@ pub const Type = extern union { | ... | @@ -3633,68 +3748,67 @@ pub const Type = extern union { |
| 3633 | .@"struct" => { | 3748 | .@"struct" => { |
| 3634 | const struct_obj = ty.castTag(.@"struct").?.data; | 3749 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 3635 | if (struct_obj.layout != .Packed) { | 3750 | if (struct_obj.layout != .Packed) { |
| 3636 | return (try ty.abiSizeAdvanced(target, strat)).scalar * 8; | 3751 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; |
| 3637 | } | 3752 | } |
| 3638 | if (opt_sema) |sema| _ = try sema.resolveTypeLayout(ty); | 3753 | if (opt_sema) |sema| _ = try sema.resolveTypeLayout(ty); |
| 3639 | assert(struct_obj.haveLayout()); | 3754 | assert(struct_obj.haveLayout()); |
| 3640 | return try struct_obj.backing_int_ty.bitSizeAdvanced(target, opt_sema); | 3755 | return try struct_obj.backing_int_ty.bitSizeAdvanced(mod, opt_sema); |
| 3641 | }, | 3756 | }, |
| 3642 | 3757 | ||
| 3643 | .tuple, .anon_struct => { | 3758 | .tuple, .anon_struct => { |
| 3644 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); | 3759 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); |
| 3645 | if (ty.containerLayout() != .Packed) { | 3760 | if (ty.containerLayout() != .Packed) { |
| 3646 | return (try ty.abiSizeAdvanced(target, strat)).scalar * 8; | 3761 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; |
| 3647 | } | 3762 | } |
| 3648 | var total: u64 = 0; | 3763 | var total: u64 = 0; |
| 3649 | for (ty.tupleFields().types) |field_ty| { | 3764 | for (ty.tupleFields().types) |field_ty| { |
| 3650 | total += try bitSizeAdvanced(field_ty, target, opt_sema); | 3765 | total += try bitSizeAdvanced(field_ty, mod, opt_sema); |
| 3651 | } | 3766 | } |
| 3652 | return total; | 3767 | return total; |
| 3653 | }, | 3768 | }, |
| 3654 | 3769 | ||
| 3655 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { | 3770 | .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { |
| 3656 | var buffer: Payload.Bits = undefined; | 3771 | const int_tag_ty = ty.intTagType(); |
| 3657 | const int_tag_ty = ty.intTagType(&buffer); | 3772 | return try bitSizeAdvanced(int_tag_ty, mod, opt_sema); |
| 3658 | return try bitSizeAdvanced(int_tag_ty, target, opt_sema); | ||
| 3659 | }, | 3773 | }, |
| 3660 | 3774 | ||
| 3661 | .@"union", .union_safety_tagged, .union_tagged => { | 3775 | .@"union", .union_safety_tagged, .union_tagged => { |
| 3662 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); | 3776 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); |
| 3663 | if (ty.containerLayout() != .Packed) { | 3777 | if (ty.containerLayout() != .Packed) { |
| 3664 | return (try ty.abiSizeAdvanced(target, strat)).scalar * 8; | 3778 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; |
| 3665 | } | 3779 | } |
| 3666 | const union_obj = ty.cast(Payload.Union).?.data; | 3780 | const union_obj = ty.cast(Payload.Union).?.data; |
| 3667 | assert(union_obj.haveFieldTypes()); | 3781 | assert(union_obj.haveFieldTypes()); |
| 3668 | 3782 | ||
| 3669 | var size: u64 = 0; | 3783 | var size: u64 = 0; |
| 3670 | for (union_obj.fields.values()) |field| { | 3784 | for (union_obj.fields.values()) |field| { |
| 3671 | size = @max(size, try bitSizeAdvanced(field.ty, target, opt_sema)); | 3785 | size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema)); |
| 3672 | } | 3786 | } |
| 3673 | return size; | 3787 | return size; |
| 3674 | }, | 3788 | }, |
| 3675 | 3789 | ||
| 3676 | .vector => { | 3790 | .vector => { |
| 3677 | const payload = ty.castTag(.vector).?.data; | 3791 | const payload = ty.castTag(.vector).?.data; |
| 3678 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, opt_sema); | 3792 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema); |
| 3679 | return elem_bit_size * payload.len; | 3793 | return elem_bit_size * payload.len; |
| 3680 | }, | 3794 | }, |
| 3681 | .array_u8 => return 8 * ty.castTag(.array_u8).?.data, | 3795 | .array_u8 => return 8 * ty.castTag(.array_u8).?.data, |
| 3682 | .array_u8_sentinel_0 => return 8 * (ty.castTag(.array_u8_sentinel_0).?.data + 1), | 3796 | .array_u8_sentinel_0 => return 8 * (ty.castTag(.array_u8_sentinel_0).?.data + 1), |
| 3683 | .array => { | 3797 | .array => { |
| 3684 | const payload = ty.castTag(.array).?.data; | 3798 | const payload = ty.castTag(.array).?.data; |
| 3685 | const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target)); | 3799 | const elem_size = std.math.max(payload.elem_type.abiAlignment(mod), payload.elem_type.abiSize(mod)); |
| 3686 | if (elem_size == 0 or payload.len == 0) | 3800 | if (elem_size == 0 or payload.len == 0) |
| 3687 | return @as(u64, 0); | 3801 | return @as(u64, 0); |
| 3688 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, opt_sema); | 3802 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema); |
| 3689 | return (payload.len - 1) * 8 * elem_size + elem_bit_size; | 3803 | return (payload.len - 1) * 8 * elem_size + elem_bit_size; |
| 3690 | }, | 3804 | }, |
| 3691 | .array_sentinel => { | 3805 | .array_sentinel => { |
| 3692 | const payload = ty.castTag(.array_sentinel).?.data; | 3806 | const payload = ty.castTag(.array_sentinel).?.data; |
| 3693 | const elem_size = std.math.max( | 3807 | const elem_size = std.math.max( |
| 3694 | payload.elem_type.abiAlignment(target), | 3808 | payload.elem_type.abiAlignment(mod), |
| 3695 | payload.elem_type.abiSize(target), | 3809 | payload.elem_type.abiSize(mod), |
| 3696 | ); | 3810 | ); |
| 3697 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, opt_sema); | 3811 | const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema); |
| 3698 | return payload.len * 8 * elem_size + elem_bit_size; | 3812 | return payload.len * 8 * elem_size + elem_bit_size; |
| 3699 | }, | 3813 | }, |
| 3700 | 3814 | ||
| ... | @@ -3757,12 +3871,10 @@ pub const Type = extern union { | ... | @@ -3757,12 +3871,10 @@ pub const Type = extern union { |
| 3757 | .error_set_merged, | 3871 | .error_set_merged, |
| 3758 | => return 16, // TODO revisit this when we have the concept of the error tag type | 3872 | => return 16, // TODO revisit this when we have the concept of the error tag type |
| 3759 | 3873 | ||
| 3760 | .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data, | ||
| 3761 | |||
| 3762 | .optional, .error_union => { | 3874 | .optional, .error_union => { |
| 3763 | // Optionals and error unions are not packed so their bitsize | 3875 | // Optionals and error unions are not packed so their bitsize |
| 3764 | // includes padding bits. | 3876 | // includes padding bits. |
| 3765 | return (try abiSizeAdvanced(ty, target, strat)).scalar * 8; | 3877 | return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8; |
| 3766 | }, | 3878 | }, |
| 3767 | 3879 | ||
| 3768 | .atomic_order, | 3880 | .atomic_order, |
| ... | @@ -3782,8 +3894,8 @@ pub const Type = extern union { | ... | @@ -3782,8 +3894,8 @@ pub const Type = extern union { |
| 3782 | 3894 | ||
| 3783 | /// Returns true if the type's layout is already resolved and it is safe | 3895 | /// Returns true if the type's layout is already resolved and it is safe |
| 3784 | /// to use `abiSize`, `abiAlignment` and `bitSize` on it. | 3896 | /// to use `abiSize`, `abiAlignment` and `bitSize` on it. |
| 3785 | pub fn layoutIsResolved(ty: Type) bool { | 3897 | pub fn layoutIsResolved(ty: Type, mod: *const Module) bool { |
| 3786 | switch (ty.zigTypeTag()) { | 3898 | switch (ty.zigTypeTag(mod)) { |
| 3787 | .Struct => { | 3899 | .Struct => { |
| 3788 | if (ty.castTag(.@"struct")) |struct_ty| { | 3900 | if (ty.castTag(.@"struct")) |struct_ty| { |
| 3789 | return struct_ty.data.haveLayout(); | 3901 | return struct_ty.data.haveLayout(); |
| ... | @@ -3798,16 +3910,16 @@ pub const Type = extern union { | ... | @@ -3798,16 +3910,16 @@ pub const Type = extern union { |
| 3798 | }, | 3910 | }, |
| 3799 | .Array => { | 3911 | .Array => { |
| 3800 | if (ty.arrayLenIncludingSentinel() == 0) return true; | 3912 | if (ty.arrayLenIncludingSentinel() == 0) return true; |
| 3801 | return ty.childType().layoutIsResolved(); | 3913 | return ty.childType().layoutIsResolved(mod); |
| 3802 | }, | 3914 | }, |
| 3803 | .Optional => { | 3915 | .Optional => { |
| 3804 | var buf: Type.Payload.ElemType = undefined; | 3916 | var buf: Type.Payload.ElemType = undefined; |
| 3805 | const payload_ty = ty.optionalChild(&buf); | 3917 | const payload_ty = ty.optionalChild(&buf); |
| 3806 | return payload_ty.layoutIsResolved(); | 3918 | return payload_ty.layoutIsResolved(mod); |
| 3807 | }, | 3919 | }, |
| 3808 | .ErrorUnion => { | 3920 | .ErrorUnion => { |
| 3809 | const payload_ty = ty.errorUnionPayload(); | 3921 | const payload_ty = ty.errorUnionPayload(); |
| 3810 | return payload_ty.layoutIsResolved(); | 3922 | return payload_ty.layoutIsResolved(mod); |
| 3811 | }, | 3923 | }, |
| 3812 | else => return true, | 3924 | else => return true, |
| 3813 | } | 3925 | } |
| ... | @@ -3994,13 +4106,13 @@ pub const Type = extern union { | ... | @@ -3994,13 +4106,13 @@ pub const Type = extern union { |
| 3994 | }; | 4106 | }; |
| 3995 | } | 4107 | } |
| 3996 | 4108 | ||
| 3997 | pub fn isAllowzeroPtr(self: Type) bool { | 4109 | pub fn isAllowzeroPtr(self: Type, mod: *const Module) bool { |
| 3998 | return switch (self.tag()) { | 4110 | return switch (self.tag()) { |
| 3999 | .pointer => { | 4111 | .pointer => { |
| 4000 | const payload = self.castTag(.pointer).?.data; | 4112 | const payload = self.castTag(.pointer).?.data; |
| 4001 | return payload.@"allowzero"; | 4113 | return payload.@"allowzero"; |
| 4002 | }, | 4114 | }, |
| 4003 | else => return self.zigTypeTag() == .Optional, | 4115 | else => return self.zigTypeTag(mod) == .Optional, |
| 4004 | }; | 4116 | }; |
| 4005 | } | 4117 | } |
| 4006 | 4118 | ||
| ... | @@ -4016,7 +4128,7 @@ pub const Type = extern union { | ... | @@ -4016,7 +4128,7 @@ pub const Type = extern union { |
| 4016 | }; | 4128 | }; |
| 4017 | } | 4129 | } |
| 4018 | 4130 | ||
| 4019 | pub fn isPtrAtRuntime(self: Type) bool { | 4131 | pub fn isPtrAtRuntime(self: Type, mod: *const Module) bool { |
| 4020 | switch (self.tag()) { | 4132 | switch (self.tag()) { |
| 4021 | .c_const_pointer, | 4133 | .c_const_pointer, |
| 4022 | .c_mut_pointer, | 4134 | .c_mut_pointer, |
| ... | @@ -4040,7 +4152,7 @@ pub const Type = extern union { | ... | @@ -4040,7 +4152,7 @@ pub const Type = extern union { |
| 4040 | .optional => { | 4152 | .optional => { |
| 4041 | var buf: Payload.ElemType = undefined; | 4153 | var buf: Payload.ElemType = undefined; |
| 4042 | const child_type = self.optionalChild(&buf); | 4154 | const child_type = self.optionalChild(&buf); |
| 4043 | if (child_type.zigTypeTag() != .Pointer) return false; | 4155 | if (child_type.zigTypeTag(mod) != .Pointer) return false; |
| 4044 | const info = child_type.ptrInfo().data; | 4156 | const info = child_type.ptrInfo().data; |
| 4045 | switch (info.size) { | 4157 | switch (info.size) { |
| 4046 | .Slice, .C => return false, | 4158 | .Slice, .C => return false, |
| ... | @@ -4054,15 +4166,15 @@ pub const Type = extern union { | ... | @@ -4054,15 +4166,15 @@ pub const Type = extern union { |
| 4054 | 4166 | ||
| 4055 | /// For pointer-like optionals, returns true, otherwise returns the allowzero property | 4167 | /// For pointer-like optionals, returns true, otherwise returns the allowzero property |
| 4056 | /// of pointers. | 4168 | /// of pointers. |
| 4057 | pub fn ptrAllowsZero(ty: Type) bool { | 4169 | pub fn ptrAllowsZero(ty: Type, mod: *const Module) bool { |
| 4058 | if (ty.isPtrLikeOptional()) { | 4170 | if (ty.isPtrLikeOptional(mod)) { |
| 4059 | return true; | 4171 | return true; |
| 4060 | } | 4172 | } |
| 4061 | return ty.ptrInfo().data.@"allowzero"; | 4173 | return ty.ptrInfo().data.@"allowzero"; |
| 4062 | } | 4174 | } |
| 4063 | 4175 | ||
| 4064 | /// See also `isPtrLikeOptional`. | 4176 | /// See also `isPtrLikeOptional`. |
| 4065 | pub fn optionalReprIsPayload(ty: Type) bool { | 4177 | pub fn optionalReprIsPayload(ty: Type, mod: *const Module) bool { |
| 4066 | switch (ty.tag()) { | 4178 | switch (ty.tag()) { |
| 4067 | .optional_single_const_pointer, | 4179 | .optional_single_const_pointer, |
| 4068 | .optional_single_mut_pointer, | 4180 | .optional_single_mut_pointer, |
| ... | @@ -4072,7 +4184,7 @@ pub const Type = extern union { | ... | @@ -4072,7 +4184,7 @@ pub const Type = extern union { |
| 4072 | 4184 | ||
| 4073 | .optional => { | 4185 | .optional => { |
| 4074 | const child_ty = ty.castTag(.optional).?.data; | 4186 | const child_ty = ty.castTag(.optional).?.data; |
| 4075 | switch (child_ty.zigTypeTag()) { | 4187 | switch (child_ty.zigTypeTag(mod)) { |
| 4076 | .Pointer => { | 4188 | .Pointer => { |
| 4077 | const info = child_ty.ptrInfo().data; | 4189 | const info = child_ty.ptrInfo().data; |
| 4078 | switch (info.size) { | 4190 | switch (info.size) { |
| ... | @@ -4093,7 +4205,7 @@ pub const Type = extern union { | ... | @@ -4093,7 +4205,7 @@ pub const Type = extern union { |
| 4093 | 4205 | ||
| 4094 | /// Returns true if the type is optional and would be lowered to a single pointer | 4206 | /// Returns true if the type is optional and would be lowered to a single pointer |
| 4095 | /// address value, using 0 for null. Note that this returns true for C pointers. | 4207 | /// address value, using 0 for null. Note that this returns true for C pointers. |
| 4096 | pub fn isPtrLikeOptional(self: Type) bool { | 4208 | pub fn isPtrLikeOptional(self: Type, mod: *const Module) bool { |
| 4097 | switch (self.tag()) { | 4209 | switch (self.tag()) { |
| 4098 | .optional_single_const_pointer, | 4210 | .optional_single_const_pointer, |
| 4099 | .optional_single_mut_pointer, | 4211 | .optional_single_mut_pointer, |
| ... | @@ -4103,7 +4215,7 @@ pub const Type = extern union { | ... | @@ -4103,7 +4215,7 @@ pub const Type = extern union { |
| 4103 | 4215 | ||
| 4104 | .optional => { | 4216 | .optional => { |
| 4105 | const child_ty = self.castTag(.optional).?.data; | 4217 | const child_ty = self.castTag(.optional).?.data; |
| 4106 | if (child_ty.zigTypeTag() != .Pointer) return false; | 4218 | if (child_ty.zigTypeTag(mod) != .Pointer) return false; |
| 4107 | const info = child_ty.ptrInfo().data; | 4219 | const info = child_ty.ptrInfo().data; |
| 4108 | switch (info.size) { | 4220 | switch (info.size) { |
| 4109 | .Slice, .C => return false, | 4221 | .Slice, .C => return false, |
| ... | @@ -4166,7 +4278,7 @@ pub const Type = extern union { | ... | @@ -4166,7 +4278,7 @@ pub const Type = extern union { |
| 4166 | /// For [N]T, returns T. | 4278 | /// For [N]T, returns T. |
| 4167 | /// For []T, returns T. | 4279 | /// For []T, returns T. |
| 4168 | /// For anyframe->T, returns T. | 4280 | /// For anyframe->T, returns T. |
| 4169 | pub fn elemType2(ty: Type) Type { | 4281 | pub fn elemType2(ty: Type, mod: *const Module) Type { |
| 4170 | return switch (ty.tag()) { | 4282 | return switch (ty.tag()) { |
| 4171 | .vector => ty.castTag(.vector).?.data.elem_type, | 4283 | .vector => ty.castTag(.vector).?.data.elem_type, |
| 4172 | .array => ty.castTag(.array).?.data.elem_type, | 4284 | .array => ty.castTag(.array).?.data.elem_type, |
| ... | @@ -4181,7 +4293,7 @@ pub const Type = extern union { | ... | @@ -4181,7 +4293,7 @@ pub const Type = extern union { |
| 4181 | 4293 | ||
| 4182 | .single_const_pointer, | 4294 | .single_const_pointer, |
| 4183 | .single_mut_pointer, | 4295 | .single_mut_pointer, |
| 4184 | => ty.castPointer().?.data.shallowElemType(), | 4296 | => ty.castPointer().?.data.shallowElemType(mod), |
| 4185 | 4297 | ||
| 4186 | .array_u8, | 4298 | .array_u8, |
| 4187 | .array_u8_sentinel_0, | 4299 | .array_u8_sentinel_0, |
| ... | @@ -4197,7 +4309,7 @@ pub const Type = extern union { | ... | @@ -4197,7 +4309,7 @@ pub const Type = extern union { |
| 4197 | const info = ty.castTag(.pointer).?.data; | 4309 | const info = ty.castTag(.pointer).?.data; |
| 4198 | const child_ty = info.pointee_type; | 4310 | const child_ty = info.pointee_type; |
| 4199 | if (info.size == .One) { | 4311 | if (info.size == .One) { |
| 4200 | return child_ty.shallowElemType(); | 4312 | return child_ty.shallowElemType(mod); |
| 4201 | } else { | 4313 | } else { |
| 4202 | return child_ty; | 4314 | return child_ty; |
| 4203 | } | 4315 | } |
| ... | @@ -4213,16 +4325,16 @@ pub const Type = extern union { | ... | @@ -4213,16 +4325,16 @@ pub const Type = extern union { |
| 4213 | }; | 4325 | }; |
| 4214 | } | 4326 | } |
| 4215 | 4327 | ||
| 4216 | fn shallowElemType(child_ty: Type) Type { | 4328 | fn shallowElemType(child_ty: Type, mod: *const Module) Type { |
| 4217 | return switch (child_ty.zigTypeTag()) { | 4329 | return switch (child_ty.zigTypeTag(mod)) { |
| 4218 | .Array, .Vector => child_ty.childType(), | 4330 | .Array, .Vector => child_ty.childType(), |
| 4219 | else => child_ty, | 4331 | else => child_ty, |
| 4220 | }; | 4332 | }; |
| 4221 | } | 4333 | } |
| 4222 | 4334 | ||
| 4223 | /// For vectors, returns the element type. Otherwise returns self. | 4335 | /// For vectors, returns the element type. Otherwise returns self. |
| 4224 | pub fn scalarType(ty: Type) Type { | 4336 | pub fn scalarType(ty: Type, mod: *const Module) Type { |
| 4225 | return switch (ty.zigTypeTag()) { | 4337 | return switch (ty.zigTypeTag(mod)) { |
| 4226 | .Vector => ty.childType(), | 4338 | .Vector => ty.childType(), |
| 4227 | else => ty, | 4339 | else => ty, |
| 4228 | }; | 4340 | }; |
| ... | @@ -4360,19 +4472,19 @@ pub const Type = extern union { | ... | @@ -4360,19 +4472,19 @@ pub const Type = extern union { |
| 4360 | return union_obj.fields.getIndex(name); | 4472 | return union_obj.fields.getIndex(name); |
| 4361 | } | 4473 | } |
| 4362 | 4474 | ||
| 4363 | pub fn unionHasAllZeroBitFieldTypes(ty: Type) bool { | 4475 | pub fn unionHasAllZeroBitFieldTypes(ty: Type, mod: *const Module) bool { |
| 4364 | return ty.cast(Payload.Union).?.data.hasAllZeroBitFieldTypes(); | 4476 | return ty.cast(Payload.Union).?.data.hasAllZeroBitFieldTypes(mod); |
| 4365 | } | 4477 | } |
| 4366 | 4478 | ||
| 4367 | pub fn unionGetLayout(ty: Type, target: Target) Module.Union.Layout { | 4479 | pub fn unionGetLayout(ty: Type, mod: *const Module) Module.Union.Layout { |
| 4368 | switch (ty.tag()) { | 4480 | switch (ty.tag()) { |
| 4369 | .@"union" => { | 4481 | .@"union" => { |
| 4370 | const union_obj = ty.castTag(.@"union").?.data; | 4482 | const union_obj = ty.castTag(.@"union").?.data; |
| 4371 | return union_obj.getLayout(target, false); | 4483 | return union_obj.getLayout(mod, false); |
| 4372 | }, | 4484 | }, |
| 4373 | .union_safety_tagged, .union_tagged => { | 4485 | .union_safety_tagged, .union_tagged => { |
| 4374 | const union_obj = ty.cast(Payload.Union).?.data; | 4486 | const union_obj = ty.cast(Payload.Union).?.data; |
| 4375 | return union_obj.getLayout(target, true); | 4487 | return union_obj.getLayout(mod, true); |
| 4376 | }, | 4488 | }, |
| 4377 | else => unreachable, | 4489 | else => unreachable, |
| 4378 | } | 4490 | } |
| ... | @@ -4441,8 +4553,8 @@ pub const Type = extern union { | ... | @@ -4441,8 +4553,8 @@ pub const Type = extern union { |
| 4441 | }; | 4553 | }; |
| 4442 | } | 4554 | } |
| 4443 | 4555 | ||
| 4444 | pub fn isError(ty: Type) bool { | 4556 | pub fn isError(ty: Type, mod: *const Module) bool { |
| 4445 | return switch (ty.zigTypeTag()) { | 4557 | return switch (ty.zigTypeTag(mod)) { |
| 4446 | .ErrorUnion, .ErrorSet => true, | 4558 | .ErrorUnion, .ErrorSet => true, |
| 4447 | else => false, | 4559 | else => false, |
| 4448 | }; | 4560 | }; |
| ... | @@ -4543,14 +4655,21 @@ pub const Type = extern union { | ... | @@ -4543,14 +4655,21 @@ pub const Type = extern union { |
| 4543 | } | 4655 | } |
| 4544 | 4656 | ||
| 4545 | /// Returns true if and only if the type is a fixed-width integer. | 4657 | /// Returns true if and only if the type is a fixed-width integer. |
| 4546 | pub fn isInt(self: Type) bool { | 4658 | pub fn isInt(self: Type, mod: *const Module) bool { |
| 4547 | return self.isSignedInt() or self.isUnsignedInt(); | 4659 | return self.isSignedInt(mod) or self.isUnsignedInt(mod); |
| 4548 | } | 4660 | } |
| 4549 | 4661 | ||
| 4550 | /// Returns true if and only if the type is a fixed-width, signed integer. | 4662 | /// Returns true if and only if the type is a fixed-width, signed integer. |
| 4551 | pub fn isSignedInt(self: Type) bool { | 4663 | pub fn isSignedInt(ty: Type, mod: *const Module) bool { |
| 4552 | return switch (self.tag()) { | 4664 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4553 | .int_signed, | 4665 | .int_type => |int_type| return int_type.signedness == .signed, |
| 4666 | .simple_type => |s| return switch (s) { | ||
| 4667 | .c_char, .isize, .c_short, .c_int, .c_long, .c_longlong => true, | ||
| 4668 | else => false, | ||
| 4669 | }, | ||
| 4670 | else => return false, | ||
| 4671 | }; | ||
| 4672 | return switch (ty.tag()) { | ||
| 4554 | .i8, | 4673 | .i8, |
| 4555 | .isize, | 4674 | .isize, |
| 4556 | .c_char, | 4675 | .c_char, |
| ... | @@ -4569,9 +4688,16 @@ pub const Type = extern union { | ... | @@ -4569,9 +4688,16 @@ pub const Type = extern union { |
| 4569 | } | 4688 | } |
| 4570 | 4689 | ||
| 4571 | /// Returns true if and only if the type is a fixed-width, unsigned integer. | 4690 | /// Returns true if and only if the type is a fixed-width, unsigned integer. |
| 4572 | pub fn isUnsignedInt(self: Type) bool { | 4691 | pub fn isUnsignedInt(ty: Type, mod: *const Module) bool { |
| 4573 | return switch (self.tag()) { | 4692 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4574 | .int_unsigned, | 4693 | .int_type => |int_type| return int_type.signedness == .unsigned, |
| 4694 | .simple_type => |s| return switch (s) { | ||
| 4695 | .usize, .c_ushort, .c_uint, .c_ulong, .c_ulonglong => true, | ||
| 4696 | else => false, | ||
| 4697 | }, | ||
| 4698 | else => return false, | ||
| 4699 | }; | ||
| 4700 | return switch (ty.tag()) { | ||
| 4575 | .usize, | 4701 | .usize, |
| 4576 | .c_ushort, | 4702 | .c_ushort, |
| 4577 | .c_uint, | 4703 | .c_uint, |
| ... | @@ -4592,8 +4718,8 @@ pub const Type = extern union { | ... | @@ -4592,8 +4718,8 @@ pub const Type = extern union { |
| 4592 | 4718 | ||
| 4593 | /// Returns true for integers, enums, error sets, and packed structs. | 4719 | /// Returns true for integers, enums, error sets, and packed structs. |
| 4594 | /// If this function returns true, then intInfo() can be called on the type. | 4720 | /// If this function returns true, then intInfo() can be called on the type. |
| 4595 | pub fn isAbiInt(ty: Type) bool { | 4721 | pub fn isAbiInt(ty: Type, mod: *const Module) bool { |
| 4596 | return switch (ty.zigTypeTag()) { | 4722 | return switch (ty.zigTypeTag(mod)) { |
| 4597 | .Int, .Enum, .ErrorSet => true, | 4723 | .Int, .Enum, .ErrorSet => true, |
| 4598 | .Struct => ty.containerLayout() == .Packed, | 4724 | .Struct => ty.containerLayout() == .Packed, |
| 4599 | else => false, | 4725 | else => false, |
| ... | @@ -4601,17 +4727,26 @@ pub const Type = extern union { | ... | @@ -4601,17 +4727,26 @@ pub const Type = extern union { |
| 4601 | } | 4727 | } |
| 4602 | 4728 | ||
| 4603 | /// Asserts the type is an integer, enum, error set, or vector of one of them. | 4729 | /// Asserts the type is an integer, enum, error set, or vector of one of them. |
| 4604 | pub fn intInfo(self: Type, target: Target) std.builtin.Type.Int { | 4730 | pub fn intInfo(starting_ty: Type, mod: *const Module) InternPool.Key.IntType { |
| 4605 | var ty = self; | 4731 | const target = mod.getTarget(); |
| 4732 | var ty = starting_ty; | ||
| 4733 | |||
| 4734 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 4735 | .int_type => |int_type| return int_type, | ||
| 4736 | .ptr_type => @panic("TODO"), | ||
| 4737 | .array_type => @panic("TODO"), | ||
| 4738 | .vector_type => @panic("TODO"), | ||
| 4739 | .optional_type => @panic("TODO"), | ||
| 4740 | .error_union_type => @panic("TODO"), | ||
| 4741 | .simple_type => @panic("TODO"), | ||
| 4742 | .struct_type => unreachable, | ||
| 4743 | .simple_value => unreachable, | ||
| 4744 | .extern_func => unreachable, | ||
| 4745 | .int => unreachable, | ||
| 4746 | .enum_tag => unreachable, // it's a value, not a type | ||
| 4747 | }; | ||
| 4748 | |||
| 4606 | while (true) switch (ty.tag()) { | 4749 | while (true) switch (ty.tag()) { |
| 4607 | .int_unsigned => return .{ | ||
| 4608 | .signedness = .unsigned, | ||
| 4609 | .bits = ty.castTag(.int_unsigned).?.data, | ||
| 4610 | }, | ||
| 4611 | .int_signed => return .{ | ||
| 4612 | .signedness = .signed, | ||
| 4613 | .bits = ty.castTag(.int_signed).?.data, | ||
| 4614 | }, | ||
| 4615 | .u1 => return .{ .signedness = .unsigned, .bits = 1 }, | 4750 | .u1 => return .{ .signedness = .unsigned, .bits = 1 }, |
| 4616 | .u8 => return .{ .signedness = .unsigned, .bits = 8 }, | 4751 | .u8 => return .{ .signedness = .unsigned, .bits = 8 }, |
| 4617 | .i8 => return .{ .signedness = .signed, .bits = 8 }, | 4752 | .i8 => return .{ .signedness = .signed, .bits = 8 }, |
| ... | @@ -4729,32 +4864,14 @@ pub const Type = extern union { | ... | @@ -4729,32 +4864,14 @@ pub const Type = extern union { |
| 4729 | 4864 | ||
| 4730 | /// Asserts the type is a function. | 4865 | /// Asserts the type is a function. |
| 4731 | pub fn fnParamLen(self: Type) usize { | 4866 | pub fn fnParamLen(self: Type) usize { |
| 4732 | return switch (self.tag()) { | 4867 | return self.castTag(.function).?.data.param_types.len; |
| 4733 | .fn_noreturn_no_args => 0, | ||
| 4734 | .fn_void_no_args => 0, | ||
| 4735 | .fn_naked_noreturn_no_args => 0, | ||
| 4736 | .fn_ccc_void_no_args => 0, | ||
| 4737 | .function => self.castTag(.function).?.data.param_types.len, | ||
| 4738 | |||
| 4739 | else => unreachable, | ||
| 4740 | }; | ||
| 4741 | } | 4868 | } |
| 4742 | 4869 | ||
| 4743 | /// Asserts the type is a function. The length of the slice must be at least the length | 4870 | /// Asserts the type is a function. The length of the slice must be at least the length |
| 4744 | /// given by `fnParamLen`. | 4871 | /// given by `fnParamLen`. |
| 4745 | pub fn fnParamTypes(self: Type, types: []Type) void { | 4872 | pub fn fnParamTypes(self: Type, types: []Type) void { |
| 4746 | switch (self.tag()) { | 4873 | const payload = self.castTag(.function).?.data; |
| 4747 | .fn_noreturn_no_args => return, | 4874 | @memcpy(types[0..payload.param_types.len], payload.param_types); |
| 4748 | .fn_void_no_args => return, | ||
| 4749 | .fn_naked_noreturn_no_args => return, | ||
| 4750 | .fn_ccc_void_no_args => return, | ||
| 4751 | .function => { | ||
| 4752 | const payload = self.castTag(.function).?.data; | ||
| 4753 | @memcpy(types[0..payload.param_types.len], payload.param_types); | ||
| 4754 | }, | ||
| 4755 | |||
| 4756 | else => unreachable, | ||
| 4757 | } | ||
| 4758 | } | 4875 | } |
| 4759 | 4876 | ||
| 4760 | /// Asserts the type is a function. | 4877 | /// Asserts the type is a function. |
| ... | @@ -4769,33 +4886,15 @@ pub const Type = extern union { | ... | @@ -4769,33 +4886,15 @@ pub const Type = extern union { |
| 4769 | } | 4886 | } |
| 4770 | } | 4887 | } |
| 4771 | 4888 | ||
| 4772 | /// Asserts the type is a function. | 4889 | /// Asserts the type is a function or a function pointer. |
| 4773 | pub fn fnReturnType(self: Type) Type { | 4890 | pub fn fnReturnType(ty: Type) Type { |
| 4774 | return switch (self.tag()) { | 4891 | const fn_ty = if (ty.castPointer()) |p| p.data else ty; |
| 4775 | .fn_noreturn_no_args => Type.initTag(.noreturn), | 4892 | return fn_ty.castTag(.function).?.data.return_type; |
| 4776 | .fn_naked_noreturn_no_args => Type.initTag(.noreturn), | ||
| 4777 | |||
| 4778 | .fn_void_no_args, | ||
| 4779 | .fn_ccc_void_no_args, | ||
| 4780 | => Type.initTag(.void), | ||
| 4781 | |||
| 4782 | .function => self.castTag(.function).?.data.return_type, | ||
| 4783 | |||
| 4784 | else => unreachable, | ||
| 4785 | }; | ||
| 4786 | } | 4893 | } |
| 4787 | 4894 | ||
| 4788 | /// Asserts the type is a function. | 4895 | /// Asserts the type is a function. |
| 4789 | pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention { | 4896 | pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention { |
| 4790 | return switch (self.tag()) { | 4897 | return self.castTag(.function).?.data.cc; |
| 4791 | .fn_noreturn_no_args => .Unspecified, | ||
| 4792 | .fn_void_no_args => .Unspecified, | ||
| 4793 | .fn_naked_noreturn_no_args => .Naked, | ||
| 4794 | .fn_ccc_void_no_args => .C, | ||
| 4795 | .function => self.castTag(.function).?.data.cc, | ||
| 4796 | |||
| 4797 | else => unreachable, | ||
| 4798 | }; | ||
| 4799 | } | 4898 | } |
| 4800 | 4899 | ||
| 4801 | /// Asserts the type is a function. | 4900 | /// Asserts the type is a function. |
| ... | @@ -4809,15 +4908,15 @@ pub const Type = extern union { | ... | @@ -4809,15 +4908,15 @@ pub const Type = extern union { |
| 4809 | }; | 4908 | }; |
| 4810 | } | 4909 | } |
| 4811 | 4910 | ||
| 4812 | pub fn isValidParamType(self: Type) bool { | 4911 | pub fn isValidParamType(self: Type, mod: *const Module) bool { |
| 4813 | return switch (self.zigTypeTagOrPoison() catch return true) { | 4912 | return switch (self.zigTypeTagOrPoison(mod) catch return true) { |
| 4814 | .Undefined, .Null, .Opaque, .NoReturn => false, | 4913 | .Undefined, .Null, .Opaque, .NoReturn => false, |
| 4815 | else => true, | 4914 | else => true, |
| 4816 | }; | 4915 | }; |
| 4817 | } | 4916 | } |
| 4818 | 4917 | ||
| 4819 | pub fn isValidReturnType(self: Type) bool { | 4918 | pub fn isValidReturnType(self: Type, mod: *const Module) bool { |
| 4820 | return switch (self.zigTypeTagOrPoison() catch return true) { | 4919 | return switch (self.zigTypeTagOrPoison(mod) catch return true) { |
| 4821 | .Undefined, .Null, .Opaque => false, | 4920 | .Undefined, .Null, .Opaque => false, |
| 4822 | else => true, | 4921 | else => true, |
| 4823 | }; | 4922 | }; |
| ... | @@ -4825,87 +4924,43 @@ pub const Type = extern union { | ... | @@ -4825,87 +4924,43 @@ pub const Type = extern union { |
| 4825 | 4924 | ||
| 4826 | /// Asserts the type is a function. | 4925 | /// Asserts the type is a function. |
| 4827 | pub fn fnIsVarArgs(self: Type) bool { | 4926 | pub fn fnIsVarArgs(self: Type) bool { |
| 4828 | return switch (self.tag()) { | 4927 | return self.castTag(.function).?.data.is_var_args; |
| 4829 | .fn_noreturn_no_args => false, | ||
| 4830 | .fn_void_no_args => false, | ||
| 4831 | .fn_naked_noreturn_no_args => false, | ||
| 4832 | .fn_ccc_void_no_args => false, | ||
| 4833 | .function => self.castTag(.function).?.data.is_var_args, | ||
| 4834 | |||
| 4835 | else => unreachable, | ||
| 4836 | }; | ||
| 4837 | } | 4928 | } |
| 4838 | 4929 | ||
| 4839 | pub fn fnInfo(ty: Type) Payload.Function.Data { | 4930 | pub fn fnInfo(ty: Type) Payload.Function.Data { |
| 4840 | return switch (ty.tag()) { | 4931 | return ty.castTag(.function).?.data; |
| 4841 | .fn_noreturn_no_args => .{ | ||
| 4842 | .param_types = &.{}, | ||
| 4843 | .comptime_params = undefined, | ||
| 4844 | .return_type = initTag(.noreturn), | ||
| 4845 | .cc = .Unspecified, | ||
| 4846 | .alignment = 0, | ||
| 4847 | .is_var_args = false, | ||
| 4848 | .is_generic = false, | ||
| 4849 | .is_noinline = false, | ||
| 4850 | .align_is_generic = false, | ||
| 4851 | .cc_is_generic = false, | ||
| 4852 | .section_is_generic = false, | ||
| 4853 | .addrspace_is_generic = false, | ||
| 4854 | .noalias_bits = 0, | ||
| 4855 | }, | ||
| 4856 | .fn_void_no_args => .{ | ||
| 4857 | .param_types = &.{}, | ||
| 4858 | .comptime_params = undefined, | ||
| 4859 | .return_type = initTag(.void), | ||
| 4860 | .cc = .Unspecified, | ||
| 4861 | .alignment = 0, | ||
| 4862 | .is_var_args = false, | ||
| 4863 | .is_generic = false, | ||
| 4864 | .is_noinline = false, | ||
| 4865 | .align_is_generic = false, | ||
| 4866 | .cc_is_generic = false, | ||
| 4867 | .section_is_generic = false, | ||
| 4868 | .addrspace_is_generic = false, | ||
| 4869 | .noalias_bits = 0, | ||
| 4870 | }, | ||
| 4871 | .fn_naked_noreturn_no_args => .{ | ||
| 4872 | .param_types = &.{}, | ||
| 4873 | .comptime_params = undefined, | ||
| 4874 | .return_type = initTag(.noreturn), | ||
| 4875 | .cc = .Naked, | ||
| 4876 | .alignment = 0, | ||
| 4877 | .is_var_args = false, | ||
| 4878 | .is_generic = false, | ||
| 4879 | .is_noinline = false, | ||
| 4880 | .align_is_generic = false, | ||
| 4881 | .cc_is_generic = false, | ||
| 4882 | .section_is_generic = false, | ||
| 4883 | .addrspace_is_generic = false, | ||
| 4884 | .noalias_bits = 0, | ||
| 4885 | }, | ||
| 4886 | .fn_ccc_void_no_args => .{ | ||
| 4887 | .param_types = &.{}, | ||
| 4888 | .comptime_params = undefined, | ||
| 4889 | .return_type = initTag(.void), | ||
| 4890 | .cc = .C, | ||
| 4891 | .alignment = 0, | ||
| 4892 | .is_var_args = false, | ||
| 4893 | .is_generic = false, | ||
| 4894 | .is_noinline = false, | ||
| 4895 | .align_is_generic = false, | ||
| 4896 | .cc_is_generic = false, | ||
| 4897 | .section_is_generic = false, | ||
| 4898 | .addrspace_is_generic = false, | ||
| 4899 | .noalias_bits = 0, | ||
| 4900 | }, | ||
| 4901 | .function => ty.castTag(.function).?.data, | ||
| 4902 | |||
| 4903 | else => unreachable, | ||
| 4904 | }; | ||
| 4905 | } | 4932 | } |
| 4906 | 4933 | ||
| 4907 | pub fn isNumeric(self: Type) bool { | 4934 | pub fn isNumeric(ty: Type, mod: *const Module) bool { |
| 4908 | return switch (self.tag()) { | 4935 | if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4936 | .int_type => true, | ||
| 4937 | .simple_type => |s| return switch (s) { | ||
| 4938 | .f16, | ||
| 4939 | .f32, | ||
| 4940 | .f64, | ||
| 4941 | .f80, | ||
| 4942 | .f128, | ||
| 4943 | .c_longdouble, | ||
| 4944 | .comptime_int, | ||
| 4945 | .comptime_float, | ||
| 4946 | .usize, | ||
| 4947 | .isize, | ||
| 4948 | .c_char, | ||
| 4949 | .c_short, | ||
| 4950 | .c_ushort, | ||
| 4951 | .c_int, | ||
| 4952 | .c_uint, | ||
| 4953 | .c_long, | ||
| 4954 | .c_ulong, | ||
| 4955 | .c_longlong, | ||
| 4956 | .c_ulonglong, | ||
| 4957 | => true, | ||
| 4958 | |||
| 4959 | else => false, | ||
| 4960 | }, | ||
| 4961 | else => false, | ||
| 4962 | }; | ||
| 4963 | return switch (ty.tag()) { | ||
| 4909 | .f16, | 4964 | .f16, |
| 4910 | .f32, | 4965 | .f32, |
| 4911 | .f64, | 4966 | .f64, |
| ... | @@ -4937,8 +4992,6 @@ pub const Type = extern union { | ... | @@ -4937,8 +4992,6 @@ pub const Type = extern union { |
| 4937 | .c_ulong, | 4992 | .c_ulong, |
| 4938 | .c_longlong, | 4993 | .c_longlong, |
| 4939 | .c_ulonglong, | 4994 | .c_ulonglong, |
| 4940 | .int_unsigned, | ||
| 4941 | .int_signed, | ||
| 4942 | => true, | 4995 | => true, |
| 4943 | 4996 | ||
| 4944 | else => false, | 4997 | else => false, |
| ... | @@ -4947,8 +5000,30 @@ pub const Type = extern union { | ... | @@ -4947,8 +5000,30 @@ pub const Type = extern union { |
| 4947 | 5000 | ||
| 4948 | /// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which | 5001 | /// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which |
| 4949 | /// resolves field types rather than asserting they are already resolved. | 5002 | /// resolves field types rather than asserting they are already resolved. |
| 4950 | pub fn onePossibleValue(starting_type: Type) ?Value { | 5003 | pub fn onePossibleValue(starting_type: Type, mod: *const Module) ?Value { |
| 4951 | var ty = starting_type; | 5004 | var ty = starting_type; |
| 5005 | |||
| 5006 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 5007 | .int_type => |int_type| { | ||
| 5008 | if (int_type.bits == 0) { | ||
| 5009 | return Value.zero; | ||
| 5010 | } else { | ||
| 5011 | return null; | ||
| 5012 | } | ||
| 5013 | }, | ||
| 5014 | .ptr_type => @panic("TODO"), | ||
| 5015 | .array_type => @panic("TODO"), | ||
| 5016 | .vector_type => @panic("TODO"), | ||
| 5017 | .optional_type => @panic("TODO"), | ||
| 5018 | .error_union_type => @panic("TODO"), | ||
| 5019 | .simple_type => @panic("TODO"), | ||
| 5020 | .struct_type => @panic("TODO"), | ||
| 5021 | .simple_value => unreachable, | ||
| 5022 | .extern_func => unreachable, | ||
| 5023 | .int => unreachable, | ||
| 5024 | .enum_tag => unreachable, // it's a value, not a type | ||
| 5025 | }; | ||
| 5026 | |||
| 4952 | while (true) switch (ty.tag()) { | 5027 | while (true) switch (ty.tag()) { |
| 4953 | .f16, | 5028 | .f16, |
| 4954 | .f32, | 5029 | .f32, |
| ... | @@ -4988,10 +5063,6 @@ pub const Type = extern union { | ... | @@ -4988,10 +5063,6 @@ pub const Type = extern union { |
| 4988 | .error_set_single, | 5063 | .error_set_single, |
| 4989 | .error_set, | 5064 | .error_set, |
| 4990 | .error_set_merged, | 5065 | .error_set_merged, |
| 4991 | .fn_noreturn_no_args, | ||
| 4992 | .fn_void_no_args, | ||
| 4993 | .fn_naked_noreturn_no_args, | ||
| 4994 | .fn_ccc_void_no_args, | ||
| 4995 | .function, | 5066 | .function, |
| 4996 | .single_const_pointer_to_comptime_int, | 5067 | .single_const_pointer_to_comptime_int, |
| 4997 | .array_sentinel, | 5068 | .array_sentinel, |
| ... | @@ -5047,7 +5118,7 @@ pub const Type = extern union { | ... | @@ -5047,7 +5118,7 @@ pub const Type = extern union { |
| 5047 | assert(s.haveFieldTypes()); | 5118 | assert(s.haveFieldTypes()); |
| 5048 | for (s.fields.values()) |field| { | 5119 | for (s.fields.values()) |field| { |
| 5049 | if (field.is_comptime) continue; | 5120 | if (field.is_comptime) continue; |
| 5050 | if (field.ty.onePossibleValue() != null) continue; | 5121 | if (field.ty.onePossibleValue(mod) != null) continue; |
| 5051 | return null; | 5122 | return null; |
| 5052 | } | 5123 | } |
| 5053 | return Value.initTag(.empty_struct_value); | 5124 | return Value.initTag(.empty_struct_value); |
| ... | @@ -5058,7 +5129,7 @@ pub const Type = extern union { | ... | @@ -5058,7 +5129,7 @@ pub const Type = extern union { |
| 5058 | for (tuple.values, 0..) |val, i| { | 5129 | for (tuple.values, 0..) |val, i| { |
| 5059 | const is_comptime = val.tag() != .unreachable_value; | 5130 | const is_comptime = val.tag() != .unreachable_value; |
| 5060 | if (is_comptime) continue; | 5131 | if (is_comptime) continue; |
| 5061 | if (tuple.types[i].onePossibleValue() != null) continue; | 5132 | if (tuple.types[i].onePossibleValue(mod) != null) continue; |
| 5062 | return null; | 5133 | return null; |
| 5063 | } | 5134 | } |
| 5064 | return Value.initTag(.empty_struct_value); | 5135 | return Value.initTag(.empty_struct_value); |
| ... | @@ -5067,7 +5138,7 @@ pub const Type = extern union { | ... | @@ -5067,7 +5138,7 @@ pub const Type = extern union { |
| 5067 | .enum_numbered => { | 5138 | .enum_numbered => { |
| 5068 | const enum_numbered = ty.castTag(.enum_numbered).?.data; | 5139 | const enum_numbered = ty.castTag(.enum_numbered).?.data; |
| 5069 | // An explicit tag type is always provided for enum_numbered. | 5140 | // An explicit tag type is always provided for enum_numbered. |
| 5070 | if (enum_numbered.tag_ty.hasRuntimeBits()) { | 5141 | if (enum_numbered.tag_ty.hasRuntimeBits(mod)) { |
| 5071 | return null; | 5142 | return null; |
| 5072 | } | 5143 | } |
| 5073 | assert(enum_numbered.fields.count() == 1); | 5144 | assert(enum_numbered.fields.count() == 1); |
| ... | @@ -5075,7 +5146,7 @@ pub const Type = extern union { | ... | @@ -5075,7 +5146,7 @@ pub const Type = extern union { |
| 5075 | }, | 5146 | }, |
| 5076 | .enum_full => { | 5147 | .enum_full => { |
| 5077 | const enum_full = ty.castTag(.enum_full).?.data; | 5148 | const enum_full = ty.castTag(.enum_full).?.data; |
| 5078 | if (enum_full.tag_ty.hasRuntimeBits()) { | 5149 | if (enum_full.tag_ty.hasRuntimeBits(mod)) { |
| 5079 | return null; | 5150 | return null; |
| 5080 | } | 5151 | } |
| 5081 | switch (enum_full.fields.count()) { | 5152 | switch (enum_full.fields.count()) { |
| ... | @@ -5098,7 +5169,7 @@ pub const Type = extern union { | ... | @@ -5098,7 +5169,7 @@ pub const Type = extern union { |
| 5098 | }, | 5169 | }, |
| 5099 | .enum_nonexhaustive => { | 5170 | .enum_nonexhaustive => { |
| 5100 | const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty; | 5171 | const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty; |
| 5101 | if (!tag_ty.hasRuntimeBits()) { | 5172 | if (!tag_ty.hasRuntimeBits(mod)) { |
| 5102 | return Value.zero; | 5173 | return Value.zero; |
| 5103 | } else { | 5174 | } else { |
| 5104 | return null; | 5175 | return null; |
| ... | @@ -5106,10 +5177,10 @@ pub const Type = extern union { | ... | @@ -5106,10 +5177,10 @@ pub const Type = extern union { |
| 5106 | }, | 5177 | }, |
| 5107 | .@"union", .union_safety_tagged, .union_tagged => { | 5178 | .@"union", .union_safety_tagged, .union_tagged => { |
| 5108 | const union_obj = ty.cast(Payload.Union).?.data; | 5179 | const union_obj = ty.cast(Payload.Union).?.data; |
| 5109 | const tag_val = union_obj.tag_ty.onePossibleValue() orelse return null; | 5180 | const tag_val = union_obj.tag_ty.onePossibleValue(mod) orelse return null; |
| 5110 | if (union_obj.fields.count() == 0) return Value.initTag(.unreachable_value); | 5181 | if (union_obj.fields.count() == 0) return Value.initTag(.unreachable_value); |
| 5111 | const only_field = union_obj.fields.values()[0]; | 5182 | const only_field = union_obj.fields.values()[0]; |
| 5112 | const val_val = only_field.ty.onePossibleValue() orelse return null; | 5183 | const val_val = only_field.ty.onePossibleValue(mod) orelse return null; |
| 5113 | _ = tag_val; | 5184 | _ = tag_val; |
| 5114 | _ = val_val; | 5185 | _ = val_val; |
| 5115 | return Value.initTag(.empty_struct_value); | 5186 | return Value.initTag(.empty_struct_value); |
| ... | @@ -5121,17 +5192,10 @@ pub const Type = extern union { | ... | @@ -5121,17 +5192,10 @@ pub const Type = extern union { |
| 5121 | .null => return Value.initTag(.null_value), | 5192 | .null => return Value.initTag(.null_value), |
| 5122 | .undefined => return Value.initTag(.undef), | 5193 | .undefined => return Value.initTag(.undef), |
| 5123 | 5194 | ||
| 5124 | .int_unsigned, .int_signed => { | ||
| 5125 | if (ty.cast(Payload.Bits).?.data == 0) { | ||
| 5126 | return Value.zero; | ||
| 5127 | } else { | ||
| 5128 | return null; | ||
| 5129 | } | ||
| 5130 | }, | ||
| 5131 | .vector, .array, .array_u8 => { | 5195 | .vector, .array, .array_u8 => { |
| 5132 | if (ty.arrayLen() == 0) | 5196 | if (ty.arrayLen() == 0) |
| 5133 | return Value.initTag(.empty_array); | 5197 | return Value.initTag(.empty_array); |
| 5134 | if (ty.elemType().onePossibleValue() != null) | 5198 | if (ty.elemType().onePossibleValue(mod) != null) |
| 5135 | return Value.initTag(.the_only_possible_value); | 5199 | return Value.initTag(.the_only_possible_value); |
| 5136 | return null; | 5200 | return null; |
| 5137 | }, | 5201 | }, |
| ... | @@ -5146,7 +5210,22 @@ pub const Type = extern union { | ... | @@ -5146,7 +5210,22 @@ pub const Type = extern union { |
| 5146 | /// resolves field types rather than asserting they are already resolved. | 5210 | /// resolves field types rather than asserting they are already resolved. |
| 5147 | /// TODO merge these implementations together with the "advanced" pattern seen | 5211 | /// TODO merge these implementations together with the "advanced" pattern seen |
| 5148 | /// elsewhere in this file. | 5212 | /// elsewhere in this file. |
| 5149 | pub fn comptimeOnly(ty: Type) bool { | 5213 | pub fn comptimeOnly(ty: Type, mod: *const Module) bool { |
| 5214 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 5215 | .int_type => return false, | ||
| 5216 | .ptr_type => @panic("TODO"), | ||
| 5217 | .array_type => @panic("TODO"), | ||
| 5218 | .vector_type => @panic("TODO"), | ||
| 5219 | .optional_type => @panic("TODO"), | ||
| 5220 | .error_union_type => @panic("TODO"), | ||
| 5221 | .simple_type => @panic("TODO"), | ||
| 5222 | .struct_type => @panic("TODO"), | ||
| 5223 | .simple_value => unreachable, | ||
| 5224 | .extern_func => unreachable, | ||
| 5225 | .int => unreachable, | ||
| 5226 | .enum_tag => unreachable, // it's a value, not a type | ||
| 5227 | }; | ||
| 5228 | |||
| 5150 | return switch (ty.tag()) { | 5229 | return switch (ty.tag()) { |
| 5151 | .u1, | 5230 | .u1, |
| 5152 | .u8, | 5231 | .u8, |
| ... | @@ -5211,8 +5290,6 @@ pub const Type = extern union { | ... | @@ -5211,8 +5290,6 @@ pub const Type = extern union { |
| 5211 | .generic_poison, | 5290 | .generic_poison, |
| 5212 | .array_u8, | 5291 | .array_u8, |
| 5213 | .array_u8_sentinel_0, | 5292 | .array_u8_sentinel_0, |
| 5214 | .int_signed, | ||
| 5215 | .int_unsigned, | ||
| 5216 | .enum_simple, | 5293 | .enum_simple, |
| 5217 | => false, | 5294 | => false, |
| 5218 | 5295 | ||
| ... | @@ -5223,10 +5300,6 @@ pub const Type = extern union { | ... | @@ -5223,10 +5300,6 @@ pub const Type = extern union { |
| 5223 | .enum_literal, | 5300 | .enum_literal, |
| 5224 | .type_info, | 5301 | .type_info, |
| 5225 | // These are function bodies, not function pointers. | 5302 | // These are function bodies, not function pointers. |
| 5226 | .fn_noreturn_no_args, | ||
| 5227 | .fn_void_no_args, | ||
| 5228 | .fn_naked_noreturn_no_args, | ||
| 5229 | .fn_ccc_void_no_args, | ||
| 5230 | .function, | 5303 | .function, |
| 5231 | => true, | 5304 | => true, |
| 5232 | 5305 | ||
| ... | @@ -5236,7 +5309,7 @@ pub const Type = extern union { | ... | @@ -5236,7 +5309,7 @@ pub const Type = extern union { |
| 5236 | .array, | 5309 | .array, |
| 5237 | .array_sentinel, | 5310 | .array_sentinel, |
| 5238 | .vector, | 5311 | .vector, |
| 5239 | => return ty.childType().comptimeOnly(), | 5312 | => return ty.childType().comptimeOnly(mod), |
| 5240 | 5313 | ||
| 5241 | .pointer, | 5314 | .pointer, |
| 5242 | .single_const_pointer, | 5315 | .single_const_pointer, |
| ... | @@ -5249,10 +5322,10 @@ pub const Type = extern union { | ... | @@ -5249,10 +5322,10 @@ pub const Type = extern union { |
| 5249 | .mut_slice, | 5322 | .mut_slice, |
| 5250 | => { | 5323 | => { |
| 5251 | const child_ty = ty.childType(); | 5324 | const child_ty = ty.childType(); |
| 5252 | if (child_ty.zigTypeTag() == .Fn) { | 5325 | if (child_ty.zigTypeTag(mod) == .Fn) { |
| 5253 | return false; | 5326 | return false; |
| 5254 | } else { | 5327 | } else { |
| 5255 | return child_ty.comptimeOnly(); | 5328 | return child_ty.comptimeOnly(mod); |
| 5256 | } | 5329 | } |
| 5257 | }, | 5330 | }, |
| 5258 | 5331 | ||
| ... | @@ -5261,14 +5334,14 @@ pub const Type = extern union { | ... | @@ -5261,14 +5334,14 @@ pub const Type = extern union { |
| 5261 | .optional_single_const_pointer, | 5334 | .optional_single_const_pointer, |
| 5262 | => { | 5335 | => { |
| 5263 | var buf: Type.Payload.ElemType = undefined; | 5336 | var buf: Type.Payload.ElemType = undefined; |
| 5264 | return ty.optionalChild(&buf).comptimeOnly(); | 5337 | return ty.optionalChild(&buf).comptimeOnly(mod); |
| 5265 | }, | 5338 | }, |
| 5266 | 5339 | ||
| 5267 | .tuple, .anon_struct => { | 5340 | .tuple, .anon_struct => { |
| 5268 | const tuple = ty.tupleFields(); | 5341 | const tuple = ty.tupleFields(); |
| 5269 | for (tuple.types, 0..) |field_ty, i| { | 5342 | for (tuple.types, 0..) |field_ty, i| { |
| 5270 | const have_comptime_val = tuple.values[i].tag() != .unreachable_value; | 5343 | const have_comptime_val = tuple.values[i].tag() != .unreachable_value; |
| 5271 | if (!have_comptime_val and field_ty.comptimeOnly()) return true; | 5344 | if (!have_comptime_val and field_ty.comptimeOnly(mod)) return true; |
| 5272 | } | 5345 | } |
| 5273 | return false; | 5346 | return false; |
| 5274 | }, | 5347 | }, |
| ... | @@ -5301,48 +5374,48 @@ pub const Type = extern union { | ... | @@ -5301,48 +5374,48 @@ pub const Type = extern union { |
| 5301 | } | 5374 | } |
| 5302 | }, | 5375 | }, |
| 5303 | 5376 | ||
| 5304 | .error_union => return ty.errorUnionPayload().comptimeOnly(), | 5377 | .error_union => return ty.errorUnionPayload().comptimeOnly(mod), |
| 5305 | .anyframe_T => { | 5378 | .anyframe_T => { |
| 5306 | const child_ty = ty.castTag(.anyframe_T).?.data; | 5379 | const child_ty = ty.castTag(.anyframe_T).?.data; |
| 5307 | return child_ty.comptimeOnly(); | 5380 | return child_ty.comptimeOnly(mod); |
| 5308 | }, | 5381 | }, |
| 5309 | .enum_numbered => { | 5382 | .enum_numbered => { |
| 5310 | const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty; | 5383 | const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty; |
| 5311 | return tag_ty.comptimeOnly(); | 5384 | return tag_ty.comptimeOnly(mod); |
| 5312 | }, | 5385 | }, |
| 5313 | .enum_full, .enum_nonexhaustive => { | 5386 | .enum_full, .enum_nonexhaustive => { |
| 5314 | const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty; | 5387 | const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty; |
| 5315 | return tag_ty.comptimeOnly(); | 5388 | return tag_ty.comptimeOnly(mod); |
| 5316 | }, | 5389 | }, |
| 5317 | }; | 5390 | }; |
| 5318 | } | 5391 | } |
| 5319 | 5392 | ||
| 5320 | pub fn isArrayOrVector(ty: Type) bool { | 5393 | pub fn isArrayOrVector(ty: Type, mod: *const Module) bool { |
| 5321 | return switch (ty.zigTypeTag()) { | 5394 | return switch (ty.zigTypeTag(mod)) { |
| 5322 | .Array, .Vector => true, | 5395 | .Array, .Vector => true, |
| 5323 | else => false, | 5396 | else => false, |
| 5324 | }; | 5397 | }; |
| 5325 | } | 5398 | } |
| 5326 | 5399 | ||
| 5327 | pub fn isIndexable(ty: Type) bool { | 5400 | pub fn isIndexable(ty: Type, mod: *const Module) bool { |
| 5328 | return switch (ty.zigTypeTag()) { | 5401 | return switch (ty.zigTypeTag(mod)) { |
| 5329 | .Array, .Vector => true, | 5402 | .Array, .Vector => true, |
| 5330 | .Pointer => switch (ty.ptrSize()) { | 5403 | .Pointer => switch (ty.ptrSize()) { |
| 5331 | .Slice, .Many, .C => true, | 5404 | .Slice, .Many, .C => true, |
| 5332 | .One => ty.elemType().zigTypeTag() == .Array, | 5405 | .One => ty.elemType().zigTypeTag(mod) == .Array, |
| 5333 | }, | 5406 | }, |
| 5334 | .Struct => ty.isTuple(), | 5407 | .Struct => ty.isTuple(), |
| 5335 | else => false, | 5408 | else => false, |
| 5336 | }; | 5409 | }; |
| 5337 | } | 5410 | } |
| 5338 | 5411 | ||
| 5339 | pub fn indexableHasLen(ty: Type) bool { | 5412 | pub fn indexableHasLen(ty: Type, mod: *const Module) bool { |
| 5340 | return switch (ty.zigTypeTag()) { | 5413 | return switch (ty.zigTypeTag(mod)) { |
| 5341 | .Array, .Vector => true, | 5414 | .Array, .Vector => true, |
| 5342 | .Pointer => switch (ty.ptrSize()) { | 5415 | .Pointer => switch (ty.ptrSize()) { |
| 5343 | .Many, .C => false, | 5416 | .Many, .C => false, |
| 5344 | .Slice => true, | 5417 | .Slice => true, |
| 5345 | .One => ty.elemType().zigTypeTag() == .Array, | 5418 | .One => ty.elemType().zigTypeTag(mod) == .Array, |
| 5346 | }, | 5419 | }, |
| 5347 | .Struct => ty.isTuple(), | 5420 | .Struct => ty.isTuple(), |
| 5348 | else => false, | 5421 | else => false, |
| ... | @@ -5366,19 +5439,19 @@ pub const Type = extern union { | ... | @@ -5366,19 +5439,19 @@ pub const Type = extern union { |
| 5366 | } | 5439 | } |
| 5367 | 5440 | ||
| 5368 | // Works for vectors and vectors of integers. | 5441 | // Works for vectors and vectors of integers. |
| 5369 | pub fn minInt(ty: Type, arena: Allocator, target: Target) !Value { | 5442 | pub fn minInt(ty: Type, arena: Allocator, mod: *const Module) !Value { |
| 5370 | const scalar = try minIntScalar(ty.scalarType(), arena, target); | 5443 | const scalar = try minIntScalar(ty.scalarType(mod), arena, mod); |
| 5371 | if (ty.zigTypeTag() == .Vector and scalar.tag() != .the_only_possible_value) { | 5444 | if (ty.zigTypeTag(mod) == .Vector and scalar.tag() != .the_only_possible_value) { |
| 5372 | return Value.Tag.repeated.create(arena, scalar); | 5445 | return Value.Tag.repeated.create(arena, scalar); |
| 5373 | } else { | 5446 | } else { |
| 5374 | return scalar; | 5447 | return scalar; |
| 5375 | } | 5448 | } |
| 5376 | } | 5449 | } |
| 5377 | 5450 | ||
| 5378 | /// Asserts that self.zigTypeTag() == .Int. | 5451 | /// Asserts that self.zigTypeTag(mod) == .Int. |
| 5379 | pub fn minIntScalar(ty: Type, arena: Allocator, target: Target) !Value { | 5452 | pub fn minIntScalar(ty: Type, arena: Allocator, mod: *const Module) !Value { |
| 5380 | assert(ty.zigTypeTag() == .Int); | 5453 | assert(ty.zigTypeTag(mod) == .Int); |
| 5381 | const info = ty.intInfo(target); | 5454 | const info = ty.intInfo(mod); |
| 5382 | 5455 | ||
| 5383 | if (info.bits == 0) { | 5456 | if (info.bits == 0) { |
| 5384 | return Value.initTag(.the_only_possible_value); | 5457 | return Value.initTag(.the_only_possible_value); |
| ... | @@ -5405,9 +5478,9 @@ pub const Type = extern union { | ... | @@ -5405,9 +5478,9 @@ pub const Type = extern union { |
| 5405 | } | 5478 | } |
| 5406 | 5479 | ||
| 5407 | // Works for vectors and vectors of integers. | 5480 | // Works for vectors and vectors of integers. |
| 5408 | pub fn maxInt(ty: Type, arena: Allocator, target: Target) !Value { | 5481 | pub fn maxInt(ty: Type, arena: Allocator, mod: *const Module) !Value { |
| 5409 | const scalar = try maxIntScalar(ty.scalarType(), arena, target); | 5482 | const scalar = try maxIntScalar(ty.scalarType(mod), arena, mod); |
| 5410 | if (ty.zigTypeTag() == .Vector and scalar.tag() != .the_only_possible_value) { | 5483 | if (ty.zigTypeTag(mod) == .Vector and scalar.tag() != .the_only_possible_value) { |
| 5411 | return Value.Tag.repeated.create(arena, scalar); | 5484 | return Value.Tag.repeated.create(arena, scalar); |
| 5412 | } else { | 5485 | } else { |
| 5413 | return scalar; | 5486 | return scalar; |
| ... | @@ -5415,9 +5488,9 @@ pub const Type = extern union { | ... | @@ -5415,9 +5488,9 @@ pub const Type = extern union { |
| 5415 | } | 5488 | } |
| 5416 | 5489 | ||
| 5417 | /// Asserts that self.zigTypeTag() == .Int. | 5490 | /// Asserts that self.zigTypeTag() == .Int. |
| 5418 | pub fn maxIntScalar(self: Type, arena: Allocator, target: Target) !Value { | 5491 | pub fn maxIntScalar(self: Type, arena: Allocator, mod: *const Module) !Value { |
| 5419 | assert(self.zigTypeTag() == .Int); | 5492 | assert(self.zigTypeTag(mod) == .Int); |
| 5420 | const info = self.intInfo(target); | 5493 | const info = self.intInfo(mod); |
| 5421 | 5494 | ||
| 5422 | if (info.bits == 0) { | 5495 | if (info.bits == 0) { |
| 5423 | return Value.initTag(.the_only_possible_value); | 5496 | return Value.initTag(.the_only_possible_value); |
| ... | @@ -5452,21 +5525,25 @@ pub const Type = extern union { | ... | @@ -5452,21 +5525,25 @@ pub const Type = extern union { |
| 5452 | } | 5525 | } |
| 5453 | 5526 | ||
| 5454 | /// Asserts the type is an enum or a union. | 5527 | /// Asserts the type is an enum or a union. |
| 5455 | pub fn intTagType(ty: Type, buffer: *Payload.Bits) Type { | 5528 | pub fn intTagType(ty: Type) Type { |
| 5456 | switch (ty.tag()) { | 5529 | switch (ty.tag()) { |
| 5457 | .enum_full, .enum_nonexhaustive => return ty.cast(Payload.EnumFull).?.data.tag_ty, | 5530 | .enum_full, .enum_nonexhaustive => return ty.cast(Payload.EnumFull).?.data.tag_ty, |
| 5458 | .enum_numbered => return ty.castTag(.enum_numbered).?.data.tag_ty, | 5531 | .enum_numbered => return ty.castTag(.enum_numbered).?.data.tag_ty, |
| 5459 | .enum_simple => { | 5532 | .enum_simple => { |
| 5460 | const enum_simple = ty.castTag(.enum_simple).?.data; | 5533 | @panic("TODO move enum_simple to use the intern pool"); |
| 5461 | const field_count = enum_simple.fields.count(); | 5534 | //const enum_simple = ty.castTag(.enum_simple).?.data; |
| 5462 | const bits: u16 = if (field_count == 0) 0 else std.math.log2_int_ceil(usize, field_count); | 5535 | //const field_count = enum_simple.fields.count(); |
| 5463 | buffer.* = .{ | 5536 | //const bits: u16 = if (field_count == 0) 0 else std.math.log2_int_ceil(usize, field_count); |
| 5464 | .base = .{ .tag = .int_unsigned }, | 5537 | //buffer.* = .{ |
| 5465 | .data = bits, | 5538 | // .base = .{ .tag = .int_unsigned }, |
| 5466 | }; | 5539 | // .data = bits, |
| 5467 | return Type.initPayload(&buffer.base); | 5540 | //}; |
| 5541 | //return Type.initPayload(&buffer.base); | ||
| 5542 | }, | ||
| 5543 | .union_tagged => { | ||
| 5544 | @panic("TODO move union_tagged to use the intern pool"); | ||
| 5545 | //return ty.castTag(.union_tagged).?.data.tag_ty.intTagType(buffer), | ||
| 5468 | }, | 5546 | }, |
| 5469 | .union_tagged => return ty.castTag(.union_tagged).?.data.tag_ty.intTagType(buffer), | ||
| 5470 | else => unreachable, | 5547 | else => unreachable, |
| 5471 | } | 5548 | } |
| 5472 | } | 5549 | } |
| ... | @@ -5566,7 +5643,7 @@ pub const Type = extern union { | ... | @@ -5566,7 +5643,7 @@ pub const Type = extern union { |
| 5566 | }; | 5643 | }; |
| 5567 | const end_val = Value.initPayload(&end_payload.base); | 5644 | const end_val = Value.initPayload(&end_payload.base); |
| 5568 | if (int_val.compareAll(.gte, end_val, int_ty, m)) return null; | 5645 | if (int_val.compareAll(.gte, end_val, int_ty, m)) return null; |
| 5569 | return @intCast(usize, int_val.toUnsignedInt(m.getTarget())); | 5646 | return @intCast(usize, int_val.toUnsignedInt(m)); |
| 5570 | } | 5647 | } |
| 5571 | }; | 5648 | }; |
| 5572 | switch (ty.tag()) { | 5649 | switch (ty.tag()) { |
| ... | @@ -5598,11 +5675,7 @@ pub const Type = extern union { | ... | @@ -5598,11 +5675,7 @@ pub const Type = extern union { |
| 5598 | const enum_simple = ty.castTag(.enum_simple).?.data; | 5675 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 5599 | const fields_len = enum_simple.fields.count(); | 5676 | const fields_len = enum_simple.fields.count(); |
| 5600 | const bits = std.math.log2_int_ceil(usize, fields_len); | 5677 | const bits = std.math.log2_int_ceil(usize, fields_len); |
| 5601 | var buffer: Payload.Bits = .{ | 5678 | const tag_ty = mod.intType(.unsigned, bits) catch @panic("TODO: handle OOM here"); |
| 5602 | .base = .{ .tag = .int_unsigned }, | ||
| 5603 | .data = bits, | ||
| 5604 | }; | ||
| 5605 | const tag_ty = Type.initPayload(&buffer.base); | ||
| 5606 | return S.fieldWithRange(tag_ty, enum_tag, fields_len, mod); | 5679 | return S.fieldWithRange(tag_ty, enum_tag, fields_len, mod); |
| 5607 | }, | 5680 | }, |
| 5608 | .atomic_order, | 5681 | .atomic_order, |
| ... | @@ -5675,19 +5748,19 @@ pub const Type = extern union { | ... | @@ -5675,19 +5748,19 @@ pub const Type = extern union { |
| 5675 | } | 5748 | } |
| 5676 | } | 5749 | } |
| 5677 | 5750 | ||
| 5678 | pub fn structFieldAlign(ty: Type, index: usize, target: Target) u32 { | 5751 | pub fn structFieldAlign(ty: Type, index: usize, mod: *const Module) u32 { |
| 5679 | switch (ty.tag()) { | 5752 | switch (ty.tag()) { |
| 5680 | .@"struct" => { | 5753 | .@"struct" => { |
| 5681 | const struct_obj = ty.castTag(.@"struct").?.data; | 5754 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 5682 | assert(struct_obj.layout != .Packed); | 5755 | assert(struct_obj.layout != .Packed); |
| 5683 | return struct_obj.fields.values()[index].alignment(target, struct_obj.layout); | 5756 | return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout); |
| 5684 | }, | 5757 | }, |
| 5685 | .@"union", .union_safety_tagged, .union_tagged => { | 5758 | .@"union", .union_safety_tagged, .union_tagged => { |
| 5686 | const union_obj = ty.cast(Payload.Union).?.data; | 5759 | const union_obj = ty.cast(Payload.Union).?.data; |
| 5687 | return union_obj.fields.values()[index].normalAlignment(target); | 5760 | return union_obj.fields.values()[index].normalAlignment(mod); |
| 5688 | }, | 5761 | }, |
| 5689 | .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(target), | 5762 | .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(mod), |
| 5690 | .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(target), | 5763 | .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(mod), |
| 5691 | else => unreachable, | 5764 | else => unreachable, |
| 5692 | } | 5765 | } |
| 5693 | } | 5766 | } |
| ... | @@ -5710,7 +5783,7 @@ pub const Type = extern union { | ... | @@ -5710,7 +5783,7 @@ pub const Type = extern union { |
| 5710 | } | 5783 | } |
| 5711 | } | 5784 | } |
| 5712 | 5785 | ||
| 5713 | pub fn structFieldValueComptime(ty: Type, index: usize) ?Value { | 5786 | pub fn structFieldValueComptime(ty: Type, mod: *const Module, index: usize) ?Value { |
| 5714 | switch (ty.tag()) { | 5787 | switch (ty.tag()) { |
| 5715 | .@"struct" => { | 5788 | .@"struct" => { |
| 5716 | const struct_obj = ty.castTag(.@"struct").?.data; | 5789 | const struct_obj = ty.castTag(.@"struct").?.data; |
| ... | @@ -5718,14 +5791,14 @@ pub const Type = extern union { | ... | @@ -5718,14 +5791,14 @@ pub const Type = extern union { |
| 5718 | if (field.is_comptime) { | 5791 | if (field.is_comptime) { |
| 5719 | return field.default_val; | 5792 | return field.default_val; |
| 5720 | } else { | 5793 | } else { |
| 5721 | return field.ty.onePossibleValue(); | 5794 | return field.ty.onePossibleValue(mod); |
| 5722 | } | 5795 | } |
| 5723 | }, | 5796 | }, |
| 5724 | .tuple => { | 5797 | .tuple => { |
| 5725 | const tuple = ty.castTag(.tuple).?.data; | 5798 | const tuple = ty.castTag(.tuple).?.data; |
| 5726 | const val = tuple.values[index]; | 5799 | const val = tuple.values[index]; |
| 5727 | if (val.tag() == .unreachable_value) { | 5800 | if (val.tag() == .unreachable_value) { |
| 5728 | return tuple.types[index].onePossibleValue(); | 5801 | return tuple.types[index].onePossibleValue(mod); |
| 5729 | } else { | 5802 | } else { |
| 5730 | return val; | 5803 | return val; |
| 5731 | } | 5804 | } |
| ... | @@ -5734,7 +5807,7 @@ pub const Type = extern union { | ... | @@ -5734,7 +5807,7 @@ pub const Type = extern union { |
| 5734 | const anon_struct = ty.castTag(.anon_struct).?.data; | 5807 | const anon_struct = ty.castTag(.anon_struct).?.data; |
| 5735 | const val = anon_struct.values[index]; | 5808 | const val = anon_struct.values[index]; |
| 5736 | if (val.tag() == .unreachable_value) { | 5809 | if (val.tag() == .unreachable_value) { |
| 5737 | return anon_struct.types[index].onePossibleValue(); | 5810 | return anon_struct.types[index].onePossibleValue(mod); |
| 5738 | } else { | 5811 | } else { |
| 5739 | return val; | 5812 | return val; |
| 5740 | } | 5813 | } |
| ... | @@ -5765,7 +5838,7 @@ pub const Type = extern union { | ... | @@ -5765,7 +5838,7 @@ pub const Type = extern union { |
| 5765 | } | 5838 | } |
| 5766 | } | 5839 | } |
| 5767 | 5840 | ||
| 5768 | pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, target: Target) u32 { | 5841 | pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *const Module) u32 { |
| 5769 | const struct_obj = ty.castTag(.@"struct").?.data; | 5842 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 5770 | assert(struct_obj.layout == .Packed); | 5843 | assert(struct_obj.layout == .Packed); |
| 5771 | comptime assert(Type.packed_struct_layout_version == 2); | 5844 | comptime assert(Type.packed_struct_layout_version == 2); |
| ... | @@ -5774,9 +5847,9 @@ pub const Type = extern union { | ... | @@ -5774,9 +5847,9 @@ pub const Type = extern union { |
| 5774 | var elem_size_bits: u16 = undefined; | 5847 | var elem_size_bits: u16 = undefined; |
| 5775 | var running_bits: u16 = 0; | 5848 | var running_bits: u16 = 0; |
| 5776 | for (struct_obj.fields.values(), 0..) |f, i| { | 5849 | for (struct_obj.fields.values(), 0..) |f, i| { |
| 5777 | if (!f.ty.hasRuntimeBits()) continue; | 5850 | if (!f.ty.hasRuntimeBits(mod)) continue; |
| 5778 | 5851 | ||
| 5779 | const field_bits = @intCast(u16, f.ty.bitSize(target)); | 5852 | const field_bits = @intCast(u16, f.ty.bitSize(mod)); |
| 5780 | if (i == field_index) { | 5853 | if (i == field_index) { |
| 5781 | bit_offset = running_bits; | 5854 | bit_offset = running_bits; |
| 5782 | elem_size_bits = field_bits; | 5855 | elem_size_bits = field_bits; |
| ... | @@ -5797,9 +5870,10 @@ pub const Type = extern union { | ... | @@ -5797,9 +5870,10 @@ pub const Type = extern union { |
| 5797 | offset: u64 = 0, | 5870 | offset: u64 = 0, |
| 5798 | big_align: u32 = 0, | 5871 | big_align: u32 = 0, |
| 5799 | struct_obj: *Module.Struct, | 5872 | struct_obj: *Module.Struct, |
| 5800 | target: Target, | 5873 | module: *const Module, |
| 5801 | 5874 | ||
| 5802 | pub fn next(it: *StructOffsetIterator) ?FieldOffset { | 5875 | pub fn next(it: *StructOffsetIterator) ?FieldOffset { |
| 5876 | const mod = it.module; | ||
| 5803 | var i = it.field; | 5877 | var i = it.field; |
| 5804 | if (it.struct_obj.fields.count() <= i) | 5878 | if (it.struct_obj.fields.count() <= i) |
| 5805 | return null; | 5879 | return null; |
| ... | @@ -5811,35 +5885,35 @@ pub const Type = extern union { | ... | @@ -5811,35 +5885,35 @@ pub const Type = extern union { |
| 5811 | const field = it.struct_obj.fields.values()[i]; | 5885 | const field = it.struct_obj.fields.values()[i]; |
| 5812 | it.field += 1; | 5886 | it.field += 1; |
| 5813 | 5887 | ||
| 5814 | if (field.is_comptime or !field.ty.hasRuntimeBits()) { | 5888 | if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) { |
| 5815 | return FieldOffset{ .field = i, .offset = it.offset }; | 5889 | return FieldOffset{ .field = i, .offset = it.offset }; |
| 5816 | } | 5890 | } |
| 5817 | 5891 | ||
| 5818 | const field_align = field.alignment(it.target, it.struct_obj.layout); | 5892 | const field_align = field.alignment(mod, it.struct_obj.layout); |
| 5819 | it.big_align = @max(it.big_align, field_align); | 5893 | it.big_align = @max(it.big_align, field_align); |
| 5820 | const field_offset = std.mem.alignForwardGeneric(u64, it.offset, field_align); | 5894 | const field_offset = std.mem.alignForwardGeneric(u64, it.offset, field_align); |
| 5821 | it.offset = field_offset + field.ty.abiSize(it.target); | 5895 | it.offset = field_offset + field.ty.abiSize(mod); |
| 5822 | return FieldOffset{ .field = i, .offset = field_offset }; | 5896 | return FieldOffset{ .field = i, .offset = field_offset }; |
| 5823 | } | 5897 | } |
| 5824 | }; | 5898 | }; |
| 5825 | 5899 | ||
| 5826 | /// Get an iterator that iterates over all the struct field, returning the field and | 5900 | /// Get an iterator that iterates over all the struct field, returning the field and |
| 5827 | /// offset of that field. Asserts that the type is a non-packed struct. | 5901 | /// offset of that field. Asserts that the type is a non-packed struct. |
| 5828 | pub fn iterateStructOffsets(ty: Type, target: Target) StructOffsetIterator { | 5902 | pub fn iterateStructOffsets(ty: Type, mod: *const Module) StructOffsetIterator { |
| 5829 | const struct_obj = ty.castTag(.@"struct").?.data; | 5903 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 5830 | assert(struct_obj.haveLayout()); | 5904 | assert(struct_obj.haveLayout()); |
| 5831 | assert(struct_obj.layout != .Packed); | 5905 | assert(struct_obj.layout != .Packed); |
| 5832 | return .{ .struct_obj = struct_obj, .target = target }; | 5906 | return .{ .struct_obj = struct_obj, .module = mod }; |
| 5833 | } | 5907 | } |
| 5834 | 5908 | ||
| 5835 | /// Supports structs and unions. | 5909 | /// Supports structs and unions. |
| 5836 | pub fn structFieldOffset(ty: Type, index: usize, target: Target) u64 { | 5910 | pub fn structFieldOffset(ty: Type, index: usize, mod: *const Module) u64 { |
| 5837 | switch (ty.tag()) { | 5911 | switch (ty.tag()) { |
| 5838 | .@"struct" => { | 5912 | .@"struct" => { |
| 5839 | const struct_obj = ty.castTag(.@"struct").?.data; | 5913 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 5840 | assert(struct_obj.haveLayout()); | 5914 | assert(struct_obj.haveLayout()); |
| 5841 | assert(struct_obj.layout != .Packed); | 5915 | assert(struct_obj.layout != .Packed); |
| 5842 | var it = ty.iterateStructOffsets(target); | 5916 | var it = ty.iterateStructOffsets(mod); |
| 5843 | while (it.next()) |field_offset| { | 5917 | while (it.next()) |field_offset| { |
| 5844 | if (index == field_offset.field) | 5918 | if (index == field_offset.field) |
| 5845 | return field_offset.offset; | 5919 | return field_offset.offset; |
| ... | @@ -5856,17 +5930,17 @@ pub const Type = extern union { | ... | @@ -5856,17 +5930,17 @@ pub const Type = extern union { |
| 5856 | 5930 | ||
| 5857 | for (tuple.types, 0..) |field_ty, i| { | 5931 | for (tuple.types, 0..) |field_ty, i| { |
| 5858 | const field_val = tuple.values[i]; | 5932 | const field_val = tuple.values[i]; |
| 5859 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) { | 5933 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits(mod)) { |
| 5860 | // comptime field | 5934 | // comptime field |
| 5861 | if (i == index) return offset; | 5935 | if (i == index) return offset; |
| 5862 | continue; | 5936 | continue; |
| 5863 | } | 5937 | } |
| 5864 | 5938 | ||
| 5865 | const field_align = field_ty.abiAlignment(target); | 5939 | const field_align = field_ty.abiAlignment(mod); |
| 5866 | big_align = @max(big_align, field_align); | 5940 | big_align = @max(big_align, field_align); |
| 5867 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); | 5941 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| 5868 | if (i == index) return offset; | 5942 | if (i == index) return offset; |
| 5869 | offset += field_ty.abiSize(target); | 5943 | offset += field_ty.abiSize(mod); |
| 5870 | } | 5944 | } |
| 5871 | offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1)); | 5945 | offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1)); |
| 5872 | return offset; | 5946 | return offset; |
| ... | @@ -5875,7 +5949,7 @@ pub const Type = extern union { | ... | @@ -5875,7 +5949,7 @@ pub const Type = extern union { |
| 5875 | .@"union" => return 0, | 5949 | .@"union" => return 0, |
| 5876 | .union_safety_tagged, .union_tagged => { | 5950 | .union_safety_tagged, .union_tagged => { |
| 5877 | const union_obj = ty.cast(Payload.Union).?.data; | 5951 | const union_obj = ty.cast(Payload.Union).?.data; |
| 5878 | const layout = union_obj.getLayout(target, true); | 5952 | const layout = union_obj.getLayout(mod, true); |
| 5879 | if (layout.tag_align >= layout.payload_align) { | 5953 | if (layout.tag_align >= layout.payload_align) { |
| 5880 | // {Tag, Payload} | 5954 | // {Tag, Payload} |
| 5881 | return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align); | 5955 | return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align); |
| ... | @@ -6050,10 +6124,6 @@ pub const Type = extern union { | ... | @@ -6050,10 +6124,6 @@ pub const Type = extern union { |
| 6050 | manyptr_u8, | 6124 | manyptr_u8, |
| 6051 | manyptr_const_u8, | 6125 | manyptr_const_u8, |
| 6052 | manyptr_const_u8_sentinel_0, | 6126 | manyptr_const_u8_sentinel_0, |
| 6053 | fn_noreturn_no_args, | ||
| 6054 | fn_void_no_args, | ||
| 6055 | fn_naked_noreturn_no_args, | ||
| 6056 | fn_ccc_void_no_args, | ||
| 6057 | single_const_pointer_to_comptime_int, | 6127 | single_const_pointer_to_comptime_int, |
| 6058 | const_slice_u8, | 6128 | const_slice_u8, |
| 6059 | const_slice_u8_sentinel_0, | 6129 | const_slice_u8_sentinel_0, |
| ... | @@ -6087,8 +6157,6 @@ pub const Type = extern union { | ... | @@ -6087,8 +6157,6 @@ pub const Type = extern union { |
| 6087 | c_mut_pointer, | 6157 | c_mut_pointer, |
| 6088 | const_slice, | 6158 | const_slice, |
| 6089 | mut_slice, | 6159 | mut_slice, |
| 6090 | int_signed, | ||
| 6091 | int_unsigned, | ||
| 6092 | function, | 6160 | function, |
| 6093 | optional, | 6161 | optional, |
| 6094 | optional_single_mut_pointer, | 6162 | optional_single_mut_pointer, |
| ... | @@ -6157,10 +6225,6 @@ pub const Type = extern union { | ... | @@ -6157,10 +6225,6 @@ pub const Type = extern union { |
| 6157 | .enum_literal, | 6225 | .enum_literal, |
| 6158 | .null, | 6226 | .null, |
| 6159 | .undefined, | 6227 | .undefined, |
| 6160 | .fn_noreturn_no_args, | ||
| 6161 | .fn_void_no_args, | ||
| 6162 | .fn_naked_noreturn_no_args, | ||
| 6163 | .fn_ccc_void_no_args, | ||
| 6164 | .single_const_pointer_to_comptime_int, | 6228 | .single_const_pointer_to_comptime_int, |
| 6165 | .anyerror_void_error_union, | 6229 | .anyerror_void_error_union, |
| 6166 | .const_slice_u8, | 6230 | .const_slice_u8, |
| ... | @@ -6204,10 +6268,6 @@ pub const Type = extern union { | ... | @@ -6204,10 +6268,6 @@ pub const Type = extern union { |
| 6204 | .anyframe_T, | 6268 | .anyframe_T, |
| 6205 | => Payload.ElemType, | 6269 | => Payload.ElemType, |
| 6206 | 6270 | ||
| 6207 | .int_signed, | ||
| 6208 | .int_unsigned, | ||
| 6209 | => Payload.Bits, | ||
| 6210 | |||
| 6211 | .error_set => Payload.ErrorSet, | 6271 | .error_set => Payload.ErrorSet, |
| 6212 | .error_set_inferred => Payload.ErrorSetInferred, | 6272 | .error_set_inferred => Payload.ErrorSetInferred, |
| 6213 | .error_set_merged => Payload.ErrorSetMerged, | 6273 | .error_set_merged => Payload.ErrorSetMerged, |
| ... | @@ -6232,7 +6292,10 @@ pub const Type = extern union { | ... | @@ -6232,7 +6292,10 @@ pub const Type = extern union { |
| 6232 | 6292 | ||
| 6233 | pub fn init(comptime t: Tag) file_struct.Type { | 6293 | pub fn init(comptime t: Tag) file_struct.Type { |
| 6234 | comptime std.debug.assert(@enumToInt(t) < Tag.no_payload_count); | 6294 | comptime std.debug.assert(@enumToInt(t) < Tag.no_payload_count); |
| 6235 | return .{ .tag_if_small_enough = t }; | 6295 | return file_struct.Type{ |
| 6296 | .ip_index = .none, | ||
| 6297 | .legacy = .{ .tag_if_small_enough = t }, | ||
| 6298 | }; | ||
| 6236 | } | 6299 | } |
| 6237 | 6300 | ||
| 6238 | pub fn create(comptime t: Tag, ally: Allocator, data: Data(t)) error{OutOfMemory}!file_struct.Type { | 6301 | pub fn create(comptime t: Tag, ally: Allocator, data: Data(t)) error{OutOfMemory}!file_struct.Type { |
| ... | @@ -6241,7 +6304,10 @@ pub const Type = extern union { | ... | @@ -6241,7 +6304,10 @@ pub const Type = extern union { |
| 6241 | .base = .{ .tag = t }, | 6304 | .base = .{ .tag = t }, |
| 6242 | .data = data, | 6305 | .data = data, |
| 6243 | }; | 6306 | }; |
| 6244 | return file_struct.Type{ .ptr_otherwise = &p.base }; | 6307 | return file_struct.Type{ |
| 6308 | .ip_index = .none, | ||
| 6309 | .legacy = .{ .ptr_otherwise = &p.base }, | ||
| 6310 | }; | ||
| 6245 | } | 6311 | } |
| 6246 | 6312 | ||
| 6247 | pub fn Data(comptime t: Tag) type { | 6313 | pub fn Data(comptime t: Tag) type { |
| ... | @@ -6422,10 +6488,9 @@ pub const Type = extern union { | ... | @@ -6422,10 +6488,9 @@ pub const Type = extern union { |
| 6422 | runtime = std.math.maxInt(u32) - 1, | 6488 | runtime = std.math.maxInt(u32) - 1, |
| 6423 | _, | 6489 | _, |
| 6424 | }; | 6490 | }; |
| 6425 | 6491 | pub fn alignment(data: Data, mod: *const Module) u32 { | |
| 6426 | pub fn alignment(data: Data, target: Target) u32 { | ||
| 6427 | if (data.@"align" != 0) return data.@"align"; | 6492 | if (data.@"align" != 0) return data.@"align"; |
| 6428 | return abiAlignment(data.pointee_type, target); | 6493 | return abiAlignment(data.pointee_type, mod); |
| 6429 | } | 6494 | } |
| 6430 | }; | 6495 | }; |
| 6431 | }; | 6496 | }; |
| ... | @@ -6537,12 +6602,11 @@ pub const Type = extern union { | ... | @@ -6537,12 +6602,11 @@ pub const Type = extern union { |
| 6537 | pub const @"anyerror" = initTag(.anyerror); | 6602 | pub const @"anyerror" = initTag(.anyerror); |
| 6538 | pub const @"anyopaque" = initTag(.anyopaque); | 6603 | pub const @"anyopaque" = initTag(.anyopaque); |
| 6539 | pub const @"null" = initTag(.null); | 6604 | pub const @"null" = initTag(.null); |
| 6605 | pub const @"noreturn" = initTag(.noreturn); | ||
| 6540 | 6606 | ||
| 6541 | pub const err_int = Type.u16; | 6607 | pub const err_int = Type.u16; |
| 6542 | 6608 | ||
| 6543 | pub fn ptr(arena: Allocator, mod: *Module, data: Payload.Pointer.Data) !Type { | 6609 | pub fn ptr(arena: Allocator, mod: *Module, data: Payload.Pointer.Data) !Type { |
| 6544 | const target = mod.getTarget(); | ||
| 6545 | |||
| 6546 | var d = data; | 6610 | var d = data; |
| 6547 | 6611 | ||
| 6548 | if (d.size == .C) { | 6612 | if (d.size == .C) { |
| ... | @@ -6554,8 +6618,8 @@ pub const Type = extern union { | ... | @@ -6554,8 +6618,8 @@ pub const Type = extern union { |
| 6554 | // pointee type needs to be resolved more, that needs to be done before calling | 6618 | // pointee type needs to be resolved more, that needs to be done before calling |
| 6555 | // this ptr() function. | 6619 | // this ptr() function. |
| 6556 | if (d.@"align" != 0) canonicalize: { | 6620 | if (d.@"align" != 0) canonicalize: { |
| 6557 | if (!d.pointee_type.layoutIsResolved()) break :canonicalize; | 6621 | if (!d.pointee_type.layoutIsResolved(mod)) break :canonicalize; |
| 6558 | if (d.@"align" == d.pointee_type.abiAlignment(target)) { | 6622 | if (d.@"align" == d.pointee_type.abiAlignment(mod)) { |
| 6559 | d.@"align" = 0; | 6623 | d.@"align" = 0; |
| 6560 | } | 6624 | } |
| 6561 | } | 6625 | } |
| ... | @@ -6565,7 +6629,7 @@ pub const Type = extern union { | ... | @@ -6565,7 +6629,7 @@ pub const Type = extern union { |
| 6565 | // needs to be resolved before calling this ptr() function. | 6629 | // needs to be resolved before calling this ptr() function. |
| 6566 | if (d.host_size != 0) { | 6630 | if (d.host_size != 0) { |
| 6567 | assert(d.bit_offset < d.host_size * 8); | 6631 | assert(d.bit_offset < d.host_size * 8); |
| 6568 | if (d.host_size * 8 == d.pointee_type.bitSize(target)) { | 6632 | if (d.host_size * 8 == d.pointee_type.bitSize(mod)) { |
| 6569 | assert(d.bit_offset == 0); | 6633 | assert(d.bit_offset == 0); |
| 6570 | d.host_size = 0; | 6634 | d.host_size = 0; |
| 6571 | } | 6635 | } |
| ... | @@ -6676,7 +6740,7 @@ pub const Type = extern union { | ... | @@ -6676,7 +6740,7 @@ pub const Type = extern union { |
| 6676 | payload: Type, | 6740 | payload: Type, |
| 6677 | mod: *Module, | 6741 | mod: *Module, |
| 6678 | ) Allocator.Error!Type { | 6742 | ) Allocator.Error!Type { |
| 6679 | assert(error_set.zigTypeTag() == .ErrorSet); | 6743 | assert(error_set.zigTypeTag(mod) == .ErrorSet); |
| 6680 | if (error_set.eql(Type.anyerror, mod) and | 6744 | if (error_set.eql(Type.anyerror, mod) and |
| 6681 | payload.eql(Type.void, mod)) | 6745 | payload.eql(Type.void, mod)) |
| 6682 | { | 6746 | { |
| ... | @@ -6696,83 +6760,6 @@ pub const Type = extern union { | ... | @@ -6696,83 +6760,6 @@ pub const Type = extern union { |
| 6696 | return @intCast(u16, base + @boolToInt(upper < max)); | 6760 | return @intCast(u16, base + @boolToInt(upper < max)); |
| 6697 | } | 6761 | } |
| 6698 | 6762 | ||
| 6699 | pub fn smallestUnsignedInt(arena: Allocator, max: u64) !Type { | ||
| 6700 | const bits = smallestUnsignedBits(max); | ||
| 6701 | return intWithBits(arena, false, bits); | ||
| 6702 | } | ||
| 6703 | |||
| 6704 | pub fn intWithBits(arena: Allocator, sign: bool, bits: u16) !Type { | ||
| 6705 | return if (sign) switch (bits) { | ||
| 6706 | 8 => initTag(.i8), | ||
| 6707 | 16 => initTag(.i16), | ||
| 6708 | 32 => initTag(.i32), | ||
| 6709 | 64 => initTag(.i64), | ||
| 6710 | else => return Tag.int_signed.create(arena, bits), | ||
| 6711 | } else switch (bits) { | ||
| 6712 | 1 => initTag(.u1), | ||
| 6713 | 8 => initTag(.u8), | ||
| 6714 | 16 => initTag(.u16), | ||
| 6715 | 32 => initTag(.u32), | ||
| 6716 | 64 => initTag(.u64), | ||
| 6717 | else => return Tag.int_unsigned.create(arena, bits), | ||
| 6718 | }; | ||
| 6719 | } | ||
| 6720 | |||
| 6721 | /// Given a value representing an integer, returns the number of bits necessary to represent | ||
| 6722 | /// this value in an integer. If `sign` is true, returns the number of bits necessary in a | ||
| 6723 | /// twos-complement integer; otherwise in an unsigned integer. | ||
| 6724 | /// Asserts that `val` is not undef. If `val` is negative, asserts that `sign` is true. | ||
| 6725 | pub fn intBitsForValue(target: Target, val: Value, sign: bool) u16 { | ||
| 6726 | assert(!val.isUndef()); | ||
| 6727 | switch (val.tag()) { | ||
| 6728 | .int_big_positive => { | ||
| 6729 | const limbs = val.castTag(.int_big_positive).?.data; | ||
| 6730 | const big: std.math.big.int.Const = .{ .limbs = limbs, .positive = true }; | ||
| 6731 | return @intCast(u16, big.bitCountAbs() + @boolToInt(sign)); | ||
| 6732 | }, | ||
| 6733 | .int_big_negative => { | ||
| 6734 | const limbs = val.castTag(.int_big_negative).?.data; | ||
| 6735 | // Zero is still a possibility, in which case unsigned is fine | ||
| 6736 | for (limbs) |limb| { | ||
| 6737 | if (limb != 0) break; | ||
| 6738 | } else return 0; // val == 0 | ||
| 6739 | assert(sign); | ||
| 6740 | const big: std.math.big.int.Const = .{ .limbs = limbs, .positive = false }; | ||
| 6741 | return @intCast(u16, big.bitCountTwosComp()); | ||
| 6742 | }, | ||
| 6743 | .int_i64 => { | ||
| 6744 | const x = val.castTag(.int_i64).?.data; | ||
| 6745 | if (x >= 0) return smallestUnsignedBits(@intCast(u64, x)); | ||
| 6746 | assert(sign); | ||
| 6747 | return smallestUnsignedBits(@intCast(u64, -x - 1)) + 1; | ||
| 6748 | }, | ||
| 6749 | else => { | ||
| 6750 | const x = val.toUnsignedInt(target); | ||
| 6751 | return smallestUnsignedBits(x) + @boolToInt(sign); | ||
| 6752 | }, | ||
| 6753 | } | ||
| 6754 | } | ||
| 6755 | |||
| 6756 | /// Returns the smallest possible integer type containing both `min` and `max`. Asserts that neither | ||
| 6757 | /// value is undef. | ||
| 6758 | /// TODO: if #3806 is implemented, this becomes trivial | ||
| 6759 | pub fn intFittingRange(target: Target, arena: Allocator, min: Value, max: Value) !Type { | ||
| 6760 | assert(!min.isUndef()); | ||
| 6761 | assert(!max.isUndef()); | ||
| 6762 | |||
| 6763 | if (std.debug.runtime_safety) { | ||
| 6764 | assert(Value.order(min, max, target).compare(.lte)); | ||
| 6765 | } | ||
| 6766 | |||
| 6767 | const sign = min.orderAgainstZero() == .lt; | ||
| 6768 | |||
| 6769 | const min_val_bits = intBitsForValue(target, min, sign); | ||
| 6770 | const max_val_bits = intBitsForValue(target, max, sign); | ||
| 6771 | const bits = @max(min_val_bits, max_val_bits); | ||
| 6772 | |||
| 6773 | return intWithBits(arena, sign, bits); | ||
| 6774 | } | ||
| 6775 | |||
| 6776 | /// This is only used for comptime asserts. Bump this number when you make a change | 6763 | /// This is only used for comptime asserts. Bump this number when you make a change |
| 6777 | /// to packed struct layout to find out all the places in the codebase you need to edit! | 6764 | /// to packed struct layout to find out all the places in the codebase you need to edit! |
| 6778 | pub const packed_struct_layout_version = 2; | 6765 | pub const packed_struct_layout_version = 2; |
src/value.zig+441-439| ... | @@ -11,17 +11,24 @@ const Module = @import("Module.zig"); | ... | @@ -11,17 +11,24 @@ const Module = @import("Module.zig"); |
| 11 | const Air = @import("Air.zig"); | 11 | const Air = @import("Air.zig"); |
| 12 | const TypedValue = @import("TypedValue.zig"); | 12 | const TypedValue = @import("TypedValue.zig"); |
| 13 | const Sema = @import("Sema.zig"); | 13 | const Sema = @import("Sema.zig"); |
| 14 | 14 | const InternPool = @import("InternPool.zig"); | |
| 15 | /// This is the raw data, with no bookkeeping, no memory awareness, | 15 | |
| 16 | /// no de-duplication, and no type system awareness. | 16 | pub const Value = struct { |
| 17 | /// It's important for this type to be small. | 17 | /// We are migrating towards using this for every Value object. However, many |
| 18 | /// This union takes advantage of the fact that the first page of memory | 18 | /// values are still represented the legacy way. This is indicated by using |
| 19 | /// is unmapped, giving us 4096 possible enum tags that have no payload. | 19 | /// InternPool.Index.none. |
| 20 | pub const Value = extern union { | 20 | ip_index: InternPool.Index, |
| 21 | /// If the tag value is less than Tag.no_payload_count, then no pointer | 21 | |
| 22 | /// dereference is needed. | 22 | /// This is the raw data, with no bookkeeping, no memory awareness, |
| 23 | tag_if_small_enough: Tag, | 23 | /// no de-duplication, and no type system awareness. |
| 24 | ptr_otherwise: *Payload, | 24 | /// This union takes advantage of the fact that the first page of memory |
| 25 | /// is unmapped, giving us 4096 possible enum tags that have no payload. | ||
| 26 | legacy: extern union { | ||
| 27 | /// If the tag value is less than Tag.no_payload_count, then no pointer | ||
| 28 | /// dereference is needed. | ||
| 29 | tag_if_small_enough: Tag, | ||
| 30 | ptr_otherwise: *Payload, | ||
| 31 | }, | ||
| 25 | 32 | ||
| 26 | // Keep in sync with tools/stage2_pretty_printers_common.py | 33 | // Keep in sync with tools/stage2_pretty_printers_common.py |
| 27 | pub const Tag = enum(usize) { | 34 | pub const Tag = enum(usize) { |
| ... | @@ -81,10 +88,6 @@ pub const Value = extern union { | ... | @@ -81,10 +88,6 @@ pub const Value = extern union { |
| 81 | manyptr_u8_type, | 88 | manyptr_u8_type, |
| 82 | manyptr_const_u8_type, | 89 | manyptr_const_u8_type, |
| 83 | manyptr_const_u8_sentinel_0_type, | 90 | manyptr_const_u8_sentinel_0_type, |
| 84 | fn_noreturn_no_args_type, | ||
| 85 | fn_void_no_args_type, | ||
| 86 | fn_naked_noreturn_no_args_type, | ||
| 87 | fn_ccc_void_no_args_type, | ||
| 88 | single_const_pointer_to_comptime_int_type, | 91 | single_const_pointer_to_comptime_int_type, |
| 89 | const_slice_u8_type, | 92 | const_slice_u8_type, |
| 90 | const_slice_u8_sentinel_0_type, | 93 | const_slice_u8_sentinel_0_type, |
| ... | @@ -108,7 +111,6 @@ pub const Value = extern union { | ... | @@ -108,7 +111,6 @@ pub const Value = extern union { |
| 108 | // After this, the tag requires a payload. | 111 | // After this, the tag requires a payload. |
| 109 | 112 | ||
| 110 | ty, | 113 | ty, |
| 111 | int_type, | ||
| 112 | int_u64, | 114 | int_u64, |
| 113 | int_i64, | 115 | int_i64, |
| 114 | int_big_positive, | 116 | int_big_positive, |
| ... | @@ -232,10 +234,6 @@ pub const Value = extern union { | ... | @@ -232,10 +234,6 @@ pub const Value = extern union { |
| 232 | .noreturn_type, | 234 | .noreturn_type, |
| 233 | .null_type, | 235 | .null_type, |
| 234 | .undefined_type, | 236 | .undefined_type, |
| 235 | .fn_noreturn_no_args_type, | ||
| 236 | .fn_void_no_args_type, | ||
| 237 | .fn_naked_noreturn_no_args_type, | ||
| 238 | .fn_ccc_void_no_args_type, | ||
| 239 | .single_const_pointer_to_comptime_int_type, | 237 | .single_const_pointer_to_comptime_int_type, |
| 240 | .anyframe_type, | 238 | .anyframe_type, |
| 241 | .const_slice_u8_type, | 239 | .const_slice_u8_type, |
| ... | @@ -304,7 +302,6 @@ pub const Value = extern union { | ... | @@ -304,7 +302,6 @@ pub const Value = extern union { |
| 304 | .lazy_size, | 302 | .lazy_size, |
| 305 | => Payload.Ty, | 303 | => Payload.Ty, |
| 306 | 304 | ||
| 307 | .int_type => Payload.IntType, | ||
| 308 | .int_u64 => Payload.U64, | 305 | .int_u64 => Payload.U64, |
| 309 | .int_i64 => Payload.I64, | 306 | .int_i64 => Payload.I64, |
| 310 | .function => Payload.Function, | 307 | .function => Payload.Function, |
| ... | @@ -332,7 +329,10 @@ pub const Value = extern union { | ... | @@ -332,7 +329,10 @@ pub const Value = extern union { |
| 332 | .base = .{ .tag = t }, | 329 | .base = .{ .tag = t }, |
| 333 | .data = data, | 330 | .data = data, |
| 334 | }; | 331 | }; |
| 335 | return Value{ .ptr_otherwise = &ptr.base }; | 332 | return Value{ |
| 333 | .ip_index = .none, | ||
| 334 | .legacy = .{ .ptr_otherwise = &ptr.base }, | ||
| 335 | }; | ||
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | pub fn Data(comptime t: Tag) type { | 338 | pub fn Data(comptime t: Tag) type { |
| ... | @@ -342,37 +342,47 @@ pub const Value = extern union { | ... | @@ -342,37 +342,47 @@ pub const Value = extern union { |
| 342 | 342 | ||
| 343 | pub fn initTag(small_tag: Tag) Value { | 343 | pub fn initTag(small_tag: Tag) Value { |
| 344 | assert(@enumToInt(small_tag) < Tag.no_payload_count); | 344 | assert(@enumToInt(small_tag) < Tag.no_payload_count); |
| 345 | return .{ .tag_if_small_enough = small_tag }; | 345 | return Value{ |
| 346 | .ip_index = .none, | ||
| 347 | .legacy = .{ .tag_if_small_enough = small_tag }, | ||
| 348 | }; | ||
| 346 | } | 349 | } |
| 347 | 350 | ||
| 348 | pub fn initPayload(payload: *Payload) Value { | 351 | pub fn initPayload(payload: *Payload) Value { |
| 349 | assert(@enumToInt(payload.tag) >= Tag.no_payload_count); | 352 | assert(@enumToInt(payload.tag) >= Tag.no_payload_count); |
| 350 | return .{ .ptr_otherwise = payload }; | 353 | return Value{ |
| 354 | .ip_index = .none, | ||
| 355 | .legacy = .{ .ptr_otherwise = payload }, | ||
| 356 | }; | ||
| 351 | } | 357 | } |
| 352 | 358 | ||
| 353 | pub fn tag(self: Value) Tag { | 359 | pub fn tag(self: Value) Tag { |
| 354 | if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) { | 360 | assert(self.ip_index == .none); |
| 355 | return self.tag_if_small_enough; | 361 | if (@enumToInt(self.legacy.tag_if_small_enough) < Tag.no_payload_count) { |
| 362 | return self.legacy.tag_if_small_enough; | ||
| 356 | } else { | 363 | } else { |
| 357 | return self.ptr_otherwise.tag; | 364 | return self.legacy.ptr_otherwise.tag; |
| 358 | } | 365 | } |
| 359 | } | 366 | } |
| 360 | 367 | ||
| 361 | /// Prefer `castTag` to this. | 368 | /// Prefer `castTag` to this. |
| 362 | pub fn cast(self: Value, comptime T: type) ?*T { | 369 | pub fn cast(self: Value, comptime T: type) ?*T { |
| 370 | if (self.ip_index != .none) { | ||
| 371 | return null; | ||
| 372 | } | ||
| 363 | if (@hasField(T, "base_tag")) { | 373 | if (@hasField(T, "base_tag")) { |
| 364 | return self.castTag(T.base_tag); | 374 | return self.castTag(T.base_tag); |
| 365 | } | 375 | } |
| 366 | if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) { | 376 | if (@enumToInt(self.legacy.tag_if_small_enough) < Tag.no_payload_count) { |
| 367 | return null; | 377 | return null; |
| 368 | } | 378 | } |
| 369 | inline for (@typeInfo(Tag).Enum.fields) |field| { | 379 | inline for (@typeInfo(Tag).Enum.fields) |field| { |
| 370 | if (field.value < Tag.no_payload_count) | 380 | if (field.value < Tag.no_payload_count) |
| 371 | continue; | 381 | continue; |
| 372 | const t = @intToEnum(Tag, field.value); | 382 | const t = @intToEnum(Tag, field.value); |
| 373 | if (self.ptr_otherwise.tag == t) { | 383 | if (self.legacy.ptr_otherwise.tag == t) { |
| 374 | if (T == t.Type()) { | 384 | if (T == t.Type()) { |
| 375 | return @fieldParentPtr(T, "base", self.ptr_otherwise); | 385 | return @fieldParentPtr(T, "base", self.legacy.ptr_otherwise); |
| 376 | } | 386 | } |
| 377 | return null; | 387 | return null; |
| 378 | } | 388 | } |
| ... | @@ -381,11 +391,15 @@ pub const Value = extern union { | ... | @@ -381,11 +391,15 @@ pub const Value = extern union { |
| 381 | } | 391 | } |
| 382 | 392 | ||
| 383 | pub fn castTag(self: Value, comptime t: Tag) ?*t.Type() { | 393 | pub fn castTag(self: Value, comptime t: Tag) ?*t.Type() { |
| 384 | if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) | 394 | if (self.ip_index != .none) { |
| 395 | return null; | ||
| 396 | } | ||
| 397 | |||
| 398 | if (@enumToInt(self.legacy.tag_if_small_enough) < Tag.no_payload_count) | ||
| 385 | return null; | 399 | return null; |
| 386 | 400 | ||
| 387 | if (self.ptr_otherwise.tag == t) | 401 | if (self.legacy.ptr_otherwise.tag == t) |
| 388 | return @fieldParentPtr(t.Type(), "base", self.ptr_otherwise); | 402 | return @fieldParentPtr(t.Type(), "base", self.legacy.ptr_otherwise); |
| 389 | 403 | ||
| 390 | return null; | 404 | return null; |
| 391 | } | 405 | } |
| ... | @@ -393,9 +407,15 @@ pub const Value = extern union { | ... | @@ -393,9 +407,15 @@ pub const Value = extern union { |
| 393 | /// It's intentional that this function is not passed a corresponding Type, so that | 407 | /// It's intentional that this function is not passed a corresponding Type, so that |
| 394 | /// a Value can be copied from a Sema to a Decl prior to resolving struct/union field types. | 408 | /// a Value can be copied from a Sema to a Decl prior to resolving struct/union field types. |
| 395 | pub fn copy(self: Value, arena: Allocator) error{OutOfMemory}!Value { | 409 | pub fn copy(self: Value, arena: Allocator) error{OutOfMemory}!Value { |
| 396 | if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) { | 410 | if (self.ip_index != .none) { |
| 397 | return Value{ .tag_if_small_enough = self.tag_if_small_enough }; | 411 | return Value{ .ip_index = self.ip_index, .legacy = undefined }; |
| 398 | } else switch (self.ptr_otherwise.tag) { | 412 | } |
| 413 | if (@enumToInt(self.legacy.tag_if_small_enough) < Tag.no_payload_count) { | ||
| 414 | return Value{ | ||
| 415 | .ip_index = .none, | ||
| 416 | .legacy = .{ .tag_if_small_enough = self.legacy.tag_if_small_enough }, | ||
| 417 | }; | ||
| 418 | } else switch (self.legacy.ptr_otherwise.tag) { | ||
| 399 | .u1_type, | 419 | .u1_type, |
| 400 | .u8_type, | 420 | .u8_type, |
| 401 | .i8_type, | 421 | .i8_type, |
| ... | @@ -435,10 +455,6 @@ pub const Value = extern union { | ... | @@ -435,10 +455,6 @@ pub const Value = extern union { |
| 435 | .noreturn_type, | 455 | .noreturn_type, |
| 436 | .null_type, | 456 | .null_type, |
| 437 | .undefined_type, | 457 | .undefined_type, |
| 438 | .fn_noreturn_no_args_type, | ||
| 439 | .fn_void_no_args_type, | ||
| 440 | .fn_naked_noreturn_no_args_type, | ||
| 441 | .fn_ccc_void_no_args_type, | ||
| 442 | .single_const_pointer_to_comptime_int_type, | 458 | .single_const_pointer_to_comptime_int_type, |
| 443 | .anyframe_type, | 459 | .anyframe_type, |
| 444 | .const_slice_u8_type, | 460 | .const_slice_u8_type, |
| ... | @@ -481,19 +497,24 @@ pub const Value = extern union { | ... | @@ -481,19 +497,24 @@ pub const Value = extern union { |
| 481 | .base = payload.base, | 497 | .base = payload.base, |
| 482 | .data = try payload.data.copy(arena), | 498 | .data = try payload.data.copy(arena), |
| 483 | }; | 499 | }; |
| 484 | return Value{ .ptr_otherwise = &new_payload.base }; | 500 | return Value{ |
| 501 | .ip_index = .none, | ||
| 502 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 503 | }; | ||
| 485 | }, | 504 | }, |
| 486 | .int_type => return self.copyPayloadShallow(arena, Payload.IntType), | ||
| 487 | .int_u64 => return self.copyPayloadShallow(arena, Payload.U64), | 505 | .int_u64 => return self.copyPayloadShallow(arena, Payload.U64), |
| 488 | .int_i64 => return self.copyPayloadShallow(arena, Payload.I64), | 506 | .int_i64 => return self.copyPayloadShallow(arena, Payload.I64), |
| 489 | .int_big_positive, .int_big_negative => { | 507 | .int_big_positive, .int_big_negative => { |
| 490 | const old_payload = self.cast(Payload.BigInt).?; | 508 | const old_payload = self.cast(Payload.BigInt).?; |
| 491 | const new_payload = try arena.create(Payload.BigInt); | 509 | const new_payload = try arena.create(Payload.BigInt); |
| 492 | new_payload.* = .{ | 510 | new_payload.* = .{ |
| 493 | .base = .{ .tag = self.ptr_otherwise.tag }, | 511 | .base = .{ .tag = self.legacy.ptr_otherwise.tag }, |
| 494 | .data = try arena.dupe(std.math.big.Limb, old_payload.data), | 512 | .data = try arena.dupe(std.math.big.Limb, old_payload.data), |
| 495 | }; | 513 | }; |
| 496 | return Value{ .ptr_otherwise = &new_payload.base }; | 514 | return Value{ |
| 515 | .ip_index = .none, | ||
| 516 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 517 | }; | ||
| 497 | }, | 518 | }, |
| 498 | .function => return self.copyPayloadShallow(arena, Payload.Function), | 519 | .function => return self.copyPayloadShallow(arena, Payload.Function), |
| 499 | .extern_fn => return self.copyPayloadShallow(arena, Payload.ExternFn), | 520 | .extern_fn => return self.copyPayloadShallow(arena, Payload.ExternFn), |
| ... | @@ -512,7 +533,10 @@ pub const Value = extern union { | ... | @@ -512,7 +533,10 @@ pub const Value = extern union { |
| 512 | .container_ty = try payload.data.container_ty.copy(arena), | 533 | .container_ty = try payload.data.container_ty.copy(arena), |
| 513 | }, | 534 | }, |
| 514 | }; | 535 | }; |
| 515 | return Value{ .ptr_otherwise = &new_payload.base }; | 536 | return Value{ |
| 537 | .ip_index = .none, | ||
| 538 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 539 | }; | ||
| 516 | }, | 540 | }, |
| 517 | .comptime_field_ptr => { | 541 | .comptime_field_ptr => { |
| 518 | const payload = self.cast(Payload.ComptimeFieldPtr).?; | 542 | const payload = self.cast(Payload.ComptimeFieldPtr).?; |
| ... | @@ -524,7 +548,10 @@ pub const Value = extern union { | ... | @@ -524,7 +548,10 @@ pub const Value = extern union { |
| 524 | .field_ty = try payload.data.field_ty.copy(arena), | 548 | .field_ty = try payload.data.field_ty.copy(arena), |
| 525 | }, | 549 | }, |
| 526 | }; | 550 | }; |
| 527 | return Value{ .ptr_otherwise = &new_payload.base }; | 551 | return Value{ |
| 552 | .ip_index = .none, | ||
| 553 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 554 | }; | ||
| 528 | }, | 555 | }, |
| 529 | .elem_ptr => { | 556 | .elem_ptr => { |
| 530 | const payload = self.castTag(.elem_ptr).?; | 557 | const payload = self.castTag(.elem_ptr).?; |
| ... | @@ -537,7 +564,10 @@ pub const Value = extern union { | ... | @@ -537,7 +564,10 @@ pub const Value = extern union { |
| 537 | .index = payload.data.index, | 564 | .index = payload.data.index, |
| 538 | }, | 565 | }, |
| 539 | }; | 566 | }; |
| 540 | return Value{ .ptr_otherwise = &new_payload.base }; | 567 | return Value{ |
| 568 | .ip_index = .none, | ||
| 569 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 570 | }; | ||
| 541 | }, | 571 | }, |
| 542 | .field_ptr => { | 572 | .field_ptr => { |
| 543 | const payload = self.castTag(.field_ptr).?; | 573 | const payload = self.castTag(.field_ptr).?; |
| ... | @@ -550,7 +580,10 @@ pub const Value = extern union { | ... | @@ -550,7 +580,10 @@ pub const Value = extern union { |
| 550 | .field_index = payload.data.field_index, | 580 | .field_index = payload.data.field_index, |
| 551 | }, | 581 | }, |
| 552 | }; | 582 | }; |
| 553 | return Value{ .ptr_otherwise = &new_payload.base }; | 583 | return Value{ |
| 584 | .ip_index = .none, | ||
| 585 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 586 | }; | ||
| 554 | }, | 587 | }, |
| 555 | .bytes => { | 588 | .bytes => { |
| 556 | const bytes = self.castTag(.bytes).?.data; | 589 | const bytes = self.castTag(.bytes).?.data; |
| ... | @@ -559,7 +592,10 @@ pub const Value = extern union { | ... | @@ -559,7 +592,10 @@ pub const Value = extern union { |
| 559 | .base = .{ .tag = .bytes }, | 592 | .base = .{ .tag = .bytes }, |
| 560 | .data = try arena.dupe(u8, bytes), | 593 | .data = try arena.dupe(u8, bytes), |
| 561 | }; | 594 | }; |
| 562 | return Value{ .ptr_otherwise = &new_payload.base }; | 595 | return Value{ |
| 596 | .ip_index = .none, | ||
| 597 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 598 | }; | ||
| 563 | }, | 599 | }, |
| 564 | .str_lit => return self.copyPayloadShallow(arena, Payload.StrLit), | 600 | .str_lit => return self.copyPayloadShallow(arena, Payload.StrLit), |
| 565 | .repeated, | 601 | .repeated, |
| ... | @@ -574,7 +610,10 @@ pub const Value = extern union { | ... | @@ -574,7 +610,10 @@ pub const Value = extern union { |
| 574 | .base = payload.base, | 610 | .base = payload.base, |
| 575 | .data = try payload.data.copy(arena), | 611 | .data = try payload.data.copy(arena), |
| 576 | }; | 612 | }; |
| 577 | return Value{ .ptr_otherwise = &new_payload.base }; | 613 | return Value{ |
| 614 | .ip_index = .none, | ||
| 615 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 616 | }; | ||
| 578 | }, | 617 | }, |
| 579 | .slice => { | 618 | .slice => { |
| 580 | const payload = self.castTag(.slice).?; | 619 | const payload = self.castTag(.slice).?; |
| ... | @@ -586,7 +625,10 @@ pub const Value = extern union { | ... | @@ -586,7 +625,10 @@ pub const Value = extern union { |
| 586 | .len = try payload.data.len.copy(arena), | 625 | .len = try payload.data.len.copy(arena), |
| 587 | }, | 626 | }, |
| 588 | }; | 627 | }; |
| 589 | return Value{ .ptr_otherwise = &new_payload.base }; | 628 | return Value{ |
| 629 | .ip_index = .none, | ||
| 630 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 631 | }; | ||
| 590 | }, | 632 | }, |
| 591 | .float_16 => return self.copyPayloadShallow(arena, Payload.Float_16), | 633 | .float_16 => return self.copyPayloadShallow(arena, Payload.Float_16), |
| 592 | .float_32 => return self.copyPayloadShallow(arena, Payload.Float_32), | 634 | .float_32 => return self.copyPayloadShallow(arena, Payload.Float_32), |
| ... | @@ -600,7 +642,10 @@ pub const Value = extern union { | ... | @@ -600,7 +642,10 @@ pub const Value = extern union { |
| 600 | .base = payload.base, | 642 | .base = payload.base, |
| 601 | .data = try arena.dupe(u8, payload.data), | 643 | .data = try arena.dupe(u8, payload.data), |
| 602 | }; | 644 | }; |
| 603 | return Value{ .ptr_otherwise = &new_payload.base }; | 645 | return Value{ |
| 646 | .ip_index = .none, | ||
| 647 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 648 | }; | ||
| 604 | }, | 649 | }, |
| 605 | .enum_field_index => return self.copyPayloadShallow(arena, Payload.U32), | 650 | .enum_field_index => return self.copyPayloadShallow(arena, Payload.U32), |
| 606 | .@"error" => return self.copyPayloadShallow(arena, Payload.Error), | 651 | .@"error" => return self.copyPayloadShallow(arena, Payload.Error), |
| ... | @@ -615,7 +660,10 @@ pub const Value = extern union { | ... | @@ -615,7 +660,10 @@ pub const Value = extern union { |
| 615 | for (new_payload.data, 0..) |*elem, i| { | 660 | for (new_payload.data, 0..) |*elem, i| { |
| 616 | elem.* = try payload.data[i].copy(arena); | 661 | elem.* = try payload.data[i].copy(arena); |
| 617 | } | 662 | } |
| 618 | return Value{ .ptr_otherwise = &new_payload.base }; | 663 | return Value{ |
| 664 | .ip_index = .none, | ||
| 665 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 666 | }; | ||
| 619 | }, | 667 | }, |
| 620 | 668 | ||
| 621 | .@"union" => { | 669 | .@"union" => { |
| ... | @@ -628,7 +676,10 @@ pub const Value = extern union { | ... | @@ -628,7 +676,10 @@ pub const Value = extern union { |
| 628 | .val = try tag_and_val.val.copy(arena), | 676 | .val = try tag_and_val.val.copy(arena), |
| 629 | }, | 677 | }, |
| 630 | }; | 678 | }; |
| 631 | return Value{ .ptr_otherwise = &new_payload.base }; | 679 | return Value{ |
| 680 | .ip_index = .none, | ||
| 681 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 682 | }; | ||
| 632 | }, | 683 | }, |
| 633 | 684 | ||
| 634 | .inferred_alloc => unreachable, | 685 | .inferred_alloc => unreachable, |
| ... | @@ -640,7 +691,10 @@ pub const Value = extern union { | ... | @@ -640,7 +691,10 @@ pub const Value = extern union { |
| 640 | const payload = self.cast(T).?; | 691 | const payload = self.cast(T).?; |
| 641 | const new_payload = try arena.create(T); | 692 | const new_payload = try arena.create(T); |
| 642 | new_payload.* = payload.*; | 693 | new_payload.* = payload.*; |
| 643 | return Value{ .ptr_otherwise = &new_payload.base }; | 694 | return Value{ |
| 695 | .ip_index = .none, | ||
| 696 | .legacy = .{ .ptr_otherwise = &new_payload.base }, | ||
| 697 | }; | ||
| 644 | } | 698 | } |
| 645 | 699 | ||
| 646 | pub fn format(val: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | 700 | pub fn format(val: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| ... | @@ -660,6 +714,10 @@ pub const Value = extern union { | ... | @@ -660,6 +714,10 @@ pub const Value = extern union { |
| 660 | out_stream: anytype, | 714 | out_stream: anytype, |
| 661 | ) !void { | 715 | ) !void { |
| 662 | comptime assert(fmt.len == 0); | 716 | comptime assert(fmt.len == 0); |
| 717 | if (start_val.ip_index != .none) { | ||
| 718 | try out_stream.print("(interned {d})", .{@enumToInt(start_val.ip_index)}); | ||
| 719 | return; | ||
| 720 | } | ||
| 663 | var val = start_val; | 721 | var val = start_val; |
| 664 | while (true) switch (val.tag()) { | 722 | while (true) switch (val.tag()) { |
| 665 | .u1_type => return out_stream.writeAll("u1"), | 723 | .u1_type => return out_stream.writeAll("u1"), |
| ... | @@ -701,10 +759,6 @@ pub const Value = extern union { | ... | @@ -701,10 +759,6 @@ pub const Value = extern union { |
| 701 | .noreturn_type => return out_stream.writeAll("noreturn"), | 759 | .noreturn_type => return out_stream.writeAll("noreturn"), |
| 702 | .null_type => return out_stream.writeAll("@Type(.Null)"), | 760 | .null_type => return out_stream.writeAll("@Type(.Null)"), |
| 703 | .undefined_type => return out_stream.writeAll("@Type(.Undefined)"), | 761 | .undefined_type => return out_stream.writeAll("@Type(.Undefined)"), |
| 704 | .fn_noreturn_no_args_type => return out_stream.writeAll("fn() noreturn"), | ||
| 705 | .fn_void_no_args_type => return out_stream.writeAll("fn() void"), | ||
| 706 | .fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"), | ||
| 707 | .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"), | ||
| 708 | .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"), | 762 | .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"), |
| 709 | .anyframe_type => return out_stream.writeAll("anyframe"), | 763 | .anyframe_type => return out_stream.writeAll("anyframe"), |
| 710 | .const_slice_u8_type => return out_stream.writeAll("[]const u8"), | 764 | .const_slice_u8_type => return out_stream.writeAll("[]const u8"), |
| ... | @@ -755,13 +809,6 @@ pub const Value = extern union { | ... | @@ -755,13 +809,6 @@ pub const Value = extern union { |
| 755 | try val.castTag(.lazy_size).?.data.dump("", options, out_stream); | 809 | try val.castTag(.lazy_size).?.data.dump("", options, out_stream); |
| 756 | return try out_stream.writeAll(")"); | 810 | return try out_stream.writeAll(")"); |
| 757 | }, | 811 | }, |
| 758 | .int_type => { | ||
| 759 | const int_type = val.castTag(.int_type).?.data; | ||
| 760 | return out_stream.print("{s}{d}", .{ | ||
| 761 | if (int_type.signed) "s" else "u", | ||
| 762 | int_type.bits, | ||
| 763 | }); | ||
| 764 | }, | ||
| 765 | .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", options, out_stream), | 812 | .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", options, out_stream), |
| 766 | .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", options, out_stream), | 813 | .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", options, out_stream), |
| 767 | .int_big_positive => return out_stream.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}), | 814 | .int_big_positive => return out_stream.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}), |
| ... | @@ -848,7 +895,6 @@ pub const Value = extern union { | ... | @@ -848,7 +895,6 @@ pub const Value = extern union { |
| 848 | /// Asserts that the value is representable as an array of bytes. | 895 | /// Asserts that the value is representable as an array of bytes. |
| 849 | /// Copies the value into a freshly allocated slice of memory, which is owned by the caller. | 896 | /// Copies the value into a freshly allocated slice of memory, which is owned by the caller. |
| 850 | pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator, mod: *Module) ![]u8 { | 897 | pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator, mod: *Module) ![]u8 { |
| 851 | const target = mod.getTarget(); | ||
| 852 | switch (val.tag()) { | 898 | switch (val.tag()) { |
| 853 | .bytes => { | 899 | .bytes => { |
| 854 | const bytes = val.castTag(.bytes).?.data; | 900 | const bytes = val.castTag(.bytes).?.data; |
| ... | @@ -863,7 +909,7 @@ pub const Value = extern union { | ... | @@ -863,7 +909,7 @@ pub const Value = extern union { |
| 863 | }, | 909 | }, |
| 864 | .enum_literal => return allocator.dupe(u8, val.castTag(.enum_literal).?.data), | 910 | .enum_literal => return allocator.dupe(u8, val.castTag(.enum_literal).?.data), |
| 865 | .repeated => { | 911 | .repeated => { |
| 866 | const byte = @intCast(u8, val.castTag(.repeated).?.data.toUnsignedInt(target)); | 912 | const byte = @intCast(u8, val.castTag(.repeated).?.data.toUnsignedInt(mod)); |
| 867 | const result = try allocator.alloc(u8, @intCast(usize, ty.arrayLen())); | 913 | const result = try allocator.alloc(u8, @intCast(usize, ty.arrayLen())); |
| 868 | @memset(result, byte); | 914 | @memset(result, byte); |
| 869 | return result; | 915 | return result; |
| ... | @@ -877,7 +923,7 @@ pub const Value = extern union { | ... | @@ -877,7 +923,7 @@ pub const Value = extern union { |
| 877 | .the_only_possible_value => return &[_]u8{}, | 923 | .the_only_possible_value => return &[_]u8{}, |
| 878 | .slice => { | 924 | .slice => { |
| 879 | const slice = val.castTag(.slice).?.data; | 925 | const slice = val.castTag(.slice).?.data; |
| 880 | return arrayToAllocatedBytes(slice.ptr, slice.len.toUnsignedInt(target), allocator, mod); | 926 | return arrayToAllocatedBytes(slice.ptr, slice.len.toUnsignedInt(mod), allocator, mod); |
| 881 | }, | 927 | }, |
| 882 | else => return arrayToAllocatedBytes(val, ty.arrayLen(), allocator, mod), | 928 | else => return arrayToAllocatedBytes(val, ty.arrayLen(), allocator, mod), |
| 883 | } | 929 | } |
| ... | @@ -888,15 +934,19 @@ pub const Value = extern union { | ... | @@ -888,15 +934,19 @@ pub const Value = extern union { |
| 888 | var elem_value_buf: ElemValueBuffer = undefined; | 934 | var elem_value_buf: ElemValueBuffer = undefined; |
| 889 | for (result, 0..) |*elem, i| { | 935 | for (result, 0..) |*elem, i| { |
| 890 | const elem_val = val.elemValueBuffer(mod, i, &elem_value_buf); | 936 | const elem_val = val.elemValueBuffer(mod, i, &elem_value_buf); |
| 891 | elem.* = @intCast(u8, elem_val.toUnsignedInt(mod.getTarget())); | 937 | elem.* = @intCast(u8, elem_val.toUnsignedInt(mod)); |
| 892 | } | 938 | } |
| 893 | return result; | 939 | return result; |
| 894 | } | 940 | } |
| 895 | 941 | ||
| 896 | pub const ToTypeBuffer = Type.Payload.Bits; | ||
| 897 | |||
| 898 | /// Asserts that the value is representable as a type. | 942 | /// Asserts that the value is representable as a type. |
| 899 | pub fn toType(self: Value, buffer: *ToTypeBuffer) Type { | 943 | pub fn toType(self: Value) Type { |
| 944 | if (self.ip_index != .none) { | ||
| 945 | return .{ | ||
| 946 | .ip_index = self.ip_index, | ||
| 947 | .legacy = undefined, | ||
| 948 | }; | ||
| 949 | } | ||
| 900 | return switch (self.tag()) { | 950 | return switch (self.tag()) { |
| 901 | .ty => self.castTag(.ty).?.data, | 951 | .ty => self.castTag(.ty).?.data, |
| 902 | .u1_type => Type.initTag(.u1), | 952 | .u1_type => Type.initTag(.u1), |
| ... | @@ -938,10 +988,6 @@ pub const Value = extern union { | ... | @@ -938,10 +988,6 @@ pub const Value = extern union { |
| 938 | .noreturn_type => Type.initTag(.noreturn), | 988 | .noreturn_type => Type.initTag(.noreturn), |
| 939 | .null_type => Type.initTag(.null), | 989 | .null_type => Type.initTag(.null), |
| 940 | .undefined_type => Type.initTag(.undefined), | 990 | .undefined_type => Type.initTag(.undefined), |
| 941 | .fn_noreturn_no_args_type => Type.initTag(.fn_noreturn_no_args), | ||
| 942 | .fn_void_no_args_type => Type.initTag(.fn_void_no_args), | ||
| 943 | .fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args), | ||
| 944 | .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args), | ||
| 945 | .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int), | 991 | .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int), |
| 946 | .anyframe_type => Type.initTag(.@"anyframe"), | 992 | .anyframe_type => Type.initTag(.@"anyframe"), |
| 947 | .const_slice_u8_type => Type.initTag(.const_slice_u8), | 993 | .const_slice_u8_type => Type.initTag(.const_slice_u8), |
| ... | @@ -964,17 +1010,6 @@ pub const Value = extern union { | ... | @@ -964,17 +1010,6 @@ pub const Value = extern union { |
| 964 | .extern_options_type => Type.initTag(.extern_options), | 1010 | .extern_options_type => Type.initTag(.extern_options), |
| 965 | .type_info_type => Type.initTag(.type_info), | 1011 | .type_info_type => Type.initTag(.type_info), |
| 966 | 1012 | ||
| 967 | .int_type => { | ||
| 968 | const payload = self.castTag(.int_type).?.data; | ||
| 969 | buffer.* = .{ | ||
| 970 | .base = .{ | ||
| 971 | .tag = if (payload.signed) .int_signed else .int_unsigned, | ||
| 972 | }, | ||
| 973 | .data = payload.bits, | ||
| 974 | }; | ||
| 975 | return Type.initPayload(&buffer.base); | ||
| 976 | }, | ||
| 977 | |||
| 978 | else => unreachable, | 1013 | else => unreachable, |
| 979 | }; | 1014 | }; |
| 980 | } | 1015 | } |
| ... | @@ -1050,7 +1085,7 @@ pub const Value = extern union { | ... | @@ -1050,7 +1085,7 @@ pub const Value = extern union { |
| 1050 | } | 1085 | } |
| 1051 | 1086 | ||
| 1052 | pub fn tagName(val: Value, ty: Type, mod: *Module) []const u8 { | 1087 | pub fn tagName(val: Value, ty: Type, mod: *Module) []const u8 { |
| 1053 | if (ty.zigTypeTag() == .Union) return val.unionTag().tagName(ty.unionTagTypeHypothetical(), mod); | 1088 | if (ty.zigTypeTag(mod) == .Union) return val.unionTag().tagName(ty.unionTagTypeHypothetical(), mod); |
| 1054 | 1089 | ||
| 1055 | const field_index = switch (val.tag()) { | 1090 | const field_index = switch (val.tag()) { |
| 1056 | .enum_field_index => val.castTag(.enum_field_index).?.data, | 1091 | .enum_field_index => val.castTag(.enum_field_index).?.data, |
| ... | @@ -1068,10 +1103,9 @@ pub const Value = extern union { | ... | @@ -1068,10 +1103,9 @@ pub const Value = extern union { |
| 1068 | }; | 1103 | }; |
| 1069 | if (values.entries.len == 0) { | 1104 | if (values.entries.len == 0) { |
| 1070 | // auto-numbered enum | 1105 | // auto-numbered enum |
| 1071 | break :field_index @intCast(u32, val.toUnsignedInt(mod.getTarget())); | 1106 | break :field_index @intCast(u32, val.toUnsignedInt(mod)); |
| 1072 | } | 1107 | } |
| 1073 | var buffer: Type.Payload.Bits = undefined; | 1108 | const int_tag_ty = ty.intTagType(); |
| 1074 | const int_tag_ty = ty.intTagType(&buffer); | ||
| 1075 | break :field_index @intCast(u32, values.getIndexContext(val, .{ .ty = int_tag_ty, .mod = mod }).?); | 1109 | break :field_index @intCast(u32, values.getIndexContext(val, .{ .ty = int_tag_ty, .mod = mod }).?); |
| 1076 | }, | 1110 | }, |
| 1077 | }; | 1111 | }; |
| ... | @@ -1086,15 +1120,15 @@ pub const Value = extern union { | ... | @@ -1086,15 +1120,15 @@ pub const Value = extern union { |
| 1086 | } | 1120 | } |
| 1087 | 1121 | ||
| 1088 | /// Asserts the value is an integer. | 1122 | /// Asserts the value is an integer. |
| 1089 | pub fn toBigInt(val: Value, space: *BigIntSpace, target: Target) BigIntConst { | 1123 | pub fn toBigInt(val: Value, space: *BigIntSpace, mod: *const Module) BigIntConst { |
| 1090 | return val.toBigIntAdvanced(space, target, null) catch unreachable; | 1124 | return val.toBigIntAdvanced(space, mod, null) catch unreachable; |
| 1091 | } | 1125 | } |
| 1092 | 1126 | ||
| 1093 | /// Asserts the value is an integer. | 1127 | /// Asserts the value is an integer. |
| 1094 | pub fn toBigIntAdvanced( | 1128 | pub fn toBigIntAdvanced( |
| 1095 | val: Value, | 1129 | val: Value, |
| 1096 | space: *BigIntSpace, | 1130 | space: *BigIntSpace, |
| 1097 | target: Target, | 1131 | mod: *const Module, |
| 1098 | opt_sema: ?*Sema, | 1132 | opt_sema: ?*Sema, |
| 1099 | ) Module.CompileError!BigIntConst { | 1133 | ) Module.CompileError!BigIntConst { |
| 1100 | switch (val.tag()) { | 1134 | switch (val.tag()) { |
| ... | @@ -1114,7 +1148,7 @@ pub const Value = extern union { | ... | @@ -1114,7 +1148,7 @@ pub const Value = extern union { |
| 1114 | }, | 1148 | }, |
| 1115 | .runtime_value => { | 1149 | .runtime_value => { |
| 1116 | const sub_val = val.castTag(.runtime_value).?.data; | 1150 | const sub_val = val.castTag(.runtime_value).?.data; |
| 1117 | return sub_val.toBigIntAdvanced(space, target, opt_sema); | 1151 | return sub_val.toBigIntAdvanced(space, mod, opt_sema); |
| 1118 | }, | 1152 | }, |
| 1119 | .int_u64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_u64).?.data).toConst(), | 1153 | .int_u64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_u64).?.data).toConst(), |
| 1120 | .int_i64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_i64).?.data).toConst(), | 1154 | .int_i64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_i64).?.data).toConst(), |
| ... | @@ -1128,7 +1162,7 @@ pub const Value = extern union { | ... | @@ -1128,7 +1162,7 @@ pub const Value = extern union { |
| 1128 | if (opt_sema) |sema| { | 1162 | if (opt_sema) |sema| { |
| 1129 | try sema.resolveTypeLayout(ty); | 1163 | try sema.resolveTypeLayout(ty); |
| 1130 | } | 1164 | } |
| 1131 | const x = ty.abiAlignment(target); | 1165 | const x = ty.abiAlignment(mod); |
| 1132 | return BigIntMutable.init(&space.limbs, x).toConst(); | 1166 | return BigIntMutable.init(&space.limbs, x).toConst(); |
| 1133 | }, | 1167 | }, |
| 1134 | .lazy_size => { | 1168 | .lazy_size => { |
| ... | @@ -1136,14 +1170,14 @@ pub const Value = extern union { | ... | @@ -1136,14 +1170,14 @@ pub const Value = extern union { |
| 1136 | if (opt_sema) |sema| { | 1170 | if (opt_sema) |sema| { |
| 1137 | try sema.resolveTypeLayout(ty); | 1171 | try sema.resolveTypeLayout(ty); |
| 1138 | } | 1172 | } |
| 1139 | const x = ty.abiSize(target); | 1173 | const x = ty.abiSize(mod); |
| 1140 | return BigIntMutable.init(&space.limbs, x).toConst(); | 1174 | return BigIntMutable.init(&space.limbs, x).toConst(); |
| 1141 | }, | 1175 | }, |
| 1142 | 1176 | ||
| 1143 | .elem_ptr => { | 1177 | .elem_ptr => { |
| 1144 | const elem_ptr = val.castTag(.elem_ptr).?.data; | 1178 | const elem_ptr = val.castTag(.elem_ptr).?.data; |
| 1145 | const array_addr = (try elem_ptr.array_ptr.getUnsignedIntAdvanced(target, opt_sema)).?; | 1179 | const array_addr = (try elem_ptr.array_ptr.getUnsignedIntAdvanced(mod, opt_sema)).?; |
| 1146 | const elem_size = elem_ptr.elem_ty.abiSize(target); | 1180 | const elem_size = elem_ptr.elem_ty.abiSize(mod); |
| 1147 | const new_addr = array_addr + elem_size * elem_ptr.index; | 1181 | const new_addr = array_addr + elem_size * elem_ptr.index; |
| 1148 | return BigIntMutable.init(&space.limbs, new_addr).toConst(); | 1182 | return BigIntMutable.init(&space.limbs, new_addr).toConst(); |
| 1149 | }, | 1183 | }, |
| ... | @@ -1154,13 +1188,13 @@ pub const Value = extern union { | ... | @@ -1154,13 +1188,13 @@ pub const Value = extern union { |
| 1154 | 1188 | ||
| 1155 | /// If the value fits in a u64, return it, otherwise null. | 1189 | /// If the value fits in a u64, return it, otherwise null. |
| 1156 | /// Asserts not undefined. | 1190 | /// Asserts not undefined. |
| 1157 | pub fn getUnsignedInt(val: Value, target: Target) ?u64 { | 1191 | pub fn getUnsignedInt(val: Value, mod: *const Module) ?u64 { |
| 1158 | return getUnsignedIntAdvanced(val, target, null) catch unreachable; | 1192 | return getUnsignedIntAdvanced(val, mod, null) catch unreachable; |
| 1159 | } | 1193 | } |
| 1160 | 1194 | ||
| 1161 | /// If the value fits in a u64, return it, otherwise null. | 1195 | /// If the value fits in a u64, return it, otherwise null. |
| 1162 | /// Asserts not undefined. | 1196 | /// Asserts not undefined. |
| 1163 | pub fn getUnsignedIntAdvanced(val: Value, target: Target, opt_sema: ?*Sema) !?u64 { | 1197 | pub fn getUnsignedIntAdvanced(val: Value, mod: *const Module, opt_sema: ?*Sema) !?u64 { |
| 1164 | switch (val.tag()) { | 1198 | switch (val.tag()) { |
| 1165 | .zero, | 1199 | .zero, |
| 1166 | .bool_false, | 1200 | .bool_false, |
| ... | @@ -1181,17 +1215,17 @@ pub const Value = extern union { | ... | @@ -1181,17 +1215,17 @@ pub const Value = extern union { |
| 1181 | .lazy_align => { | 1215 | .lazy_align => { |
| 1182 | const ty = val.castTag(.lazy_align).?.data; | 1216 | const ty = val.castTag(.lazy_align).?.data; |
| 1183 | if (opt_sema) |sema| { | 1217 | if (opt_sema) |sema| { |
| 1184 | return (try ty.abiAlignmentAdvanced(target, .{ .sema = sema })).scalar; | 1218 | return (try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar; |
| 1185 | } else { | 1219 | } else { |
| 1186 | return ty.abiAlignment(target); | 1220 | return ty.abiAlignment(mod); |
| 1187 | } | 1221 | } |
| 1188 | }, | 1222 | }, |
| 1189 | .lazy_size => { | 1223 | .lazy_size => { |
| 1190 | const ty = val.castTag(.lazy_size).?.data; | 1224 | const ty = val.castTag(.lazy_size).?.data; |
| 1191 | if (opt_sema) |sema| { | 1225 | if (opt_sema) |sema| { |
| 1192 | return (try ty.abiSizeAdvanced(target, .{ .sema = sema })).scalar; | 1226 | return (try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar; |
| 1193 | } else { | 1227 | } else { |
| 1194 | return ty.abiSize(target); | 1228 | return ty.abiSize(mod); |
| 1195 | } | 1229 | } |
| 1196 | }, | 1230 | }, |
| 1197 | 1231 | ||
| ... | @@ -1200,12 +1234,12 @@ pub const Value = extern union { | ... | @@ -1200,12 +1234,12 @@ pub const Value = extern union { |
| 1200 | } | 1234 | } |
| 1201 | 1235 | ||
| 1202 | /// Asserts the value is an integer and it fits in a u64 | 1236 | /// Asserts the value is an integer and it fits in a u64 |
| 1203 | pub fn toUnsignedInt(val: Value, target: Target) u64 { | 1237 | pub fn toUnsignedInt(val: Value, mod: *const Module) u64 { |
| 1204 | return getUnsignedInt(val, target).?; | 1238 | return getUnsignedInt(val, mod).?; |
| 1205 | } | 1239 | } |
| 1206 | 1240 | ||
| 1207 | /// Asserts the value is an integer and it fits in a i64 | 1241 | /// Asserts the value is an integer and it fits in a i64 |
| 1208 | pub fn toSignedInt(val: Value, target: Target) i64 { | 1242 | pub fn toSignedInt(val: Value, mod: *const Module) i64 { |
| 1209 | switch (val.tag()) { | 1243 | switch (val.tag()) { |
| 1210 | .zero, | 1244 | .zero, |
| 1211 | .bool_false, | 1245 | .bool_false, |
| ... | @@ -1223,11 +1257,11 @@ pub const Value = extern union { | ... | @@ -1223,11 +1257,11 @@ pub const Value = extern union { |
| 1223 | 1257 | ||
| 1224 | .lazy_align => { | 1258 | .lazy_align => { |
| 1225 | const ty = val.castTag(.lazy_align).?.data; | 1259 | const ty = val.castTag(.lazy_align).?.data; |
| 1226 | return @intCast(i64, ty.abiAlignment(target)); | 1260 | return @intCast(i64, ty.abiAlignment(mod)); |
| 1227 | }, | 1261 | }, |
| 1228 | .lazy_size => { | 1262 | .lazy_size => { |
| 1229 | const ty = val.castTag(.lazy_size).?.data; | 1263 | const ty = val.castTag(.lazy_size).?.data; |
| 1230 | return @intCast(i64, ty.abiSize(target)); | 1264 | return @intCast(i64, ty.abiSize(mod)); |
| 1231 | }, | 1265 | }, |
| 1232 | 1266 | ||
| 1233 | .undef => unreachable, | 1267 | .undef => unreachable, |
| ... | @@ -1276,17 +1310,17 @@ pub const Value = extern union { | ... | @@ -1276,17 +1310,17 @@ pub const Value = extern union { |
| 1276 | const target = mod.getTarget(); | 1310 | const target = mod.getTarget(); |
| 1277 | const endian = target.cpu.arch.endian(); | 1311 | const endian = target.cpu.arch.endian(); |
| 1278 | if (val.isUndef()) { | 1312 | if (val.isUndef()) { |
| 1279 | const size = @intCast(usize, ty.abiSize(target)); | 1313 | const size = @intCast(usize, ty.abiSize(mod)); |
| 1280 | @memset(buffer[0..size], 0xaa); | 1314 | @memset(buffer[0..size], 0xaa); |
| 1281 | return; | 1315 | return; |
| 1282 | } | 1316 | } |
| 1283 | switch (ty.zigTypeTag()) { | 1317 | switch (ty.zigTypeTag(mod)) { |
| 1284 | .Void => {}, | 1318 | .Void => {}, |
| 1285 | .Bool => { | 1319 | .Bool => { |
| 1286 | buffer[0] = @boolToInt(val.toBool()); | 1320 | buffer[0] = @boolToInt(val.toBool()); |
| 1287 | }, | 1321 | }, |
| 1288 | .Int, .Enum => { | 1322 | .Int, .Enum => { |
| 1289 | const int_info = ty.intInfo(target); | 1323 | const int_info = ty.intInfo(mod); |
| 1290 | const bits = int_info.bits; | 1324 | const bits = int_info.bits; |
| 1291 | const byte_count = (bits + 7) / 8; | 1325 | const byte_count = (bits + 7) / 8; |
| 1292 | 1326 | ||
| ... | @@ -1307,7 +1341,7 @@ pub const Value = extern union { | ... | @@ -1307,7 +1341,7 @@ pub const Value = extern union { |
| 1307 | }; | 1341 | }; |
| 1308 | } else { | 1342 | } else { |
| 1309 | var bigint_buffer: BigIntSpace = undefined; | 1343 | var bigint_buffer: BigIntSpace = undefined; |
| 1310 | const bigint = int_val.toBigInt(&bigint_buffer, target); | 1344 | const bigint = int_val.toBigInt(&bigint_buffer, mod); |
| 1311 | bigint.writeTwosComplement(buffer[0..byte_count], endian); | 1345 | bigint.writeTwosComplement(buffer[0..byte_count], endian); |
| 1312 | } | 1346 | } |
| 1313 | }, | 1347 | }, |
| ... | @@ -1322,7 +1356,7 @@ pub const Value = extern union { | ... | @@ -1322,7 +1356,7 @@ pub const Value = extern union { |
| 1322 | .Array => { | 1356 | .Array => { |
| 1323 | const len = ty.arrayLen(); | 1357 | const len = ty.arrayLen(); |
| 1324 | const elem_ty = ty.childType(); | 1358 | const elem_ty = ty.childType(); |
| 1325 | const elem_size = @intCast(usize, elem_ty.abiSize(target)); | 1359 | const elem_size = @intCast(usize, elem_ty.abiSize(mod)); |
| 1326 | var elem_i: usize = 0; | 1360 | var elem_i: usize = 0; |
| 1327 | var elem_value_buf: ElemValueBuffer = undefined; | 1361 | var elem_value_buf: ElemValueBuffer = undefined; |
| 1328 | var buf_off: usize = 0; | 1362 | var buf_off: usize = 0; |
| ... | @@ -1335,7 +1369,7 @@ pub const Value = extern union { | ... | @@ -1335,7 +1369,7 @@ pub const Value = extern union { |
| 1335 | .Vector => { | 1369 | .Vector => { |
| 1336 | // We use byte_count instead of abi_size here, so that any padding bytes | 1370 | // We use byte_count instead of abi_size here, so that any padding bytes |
| 1337 | // follow the data bytes, on both big- and little-endian systems. | 1371 | // follow the data bytes, on both big- and little-endian systems. |
| 1338 | const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8; | 1372 | const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8; |
| 1339 | return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0); | 1373 | return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0); |
| 1340 | }, | 1374 | }, |
| 1341 | .Struct => switch (ty.containerLayout()) { | 1375 | .Struct => switch (ty.containerLayout()) { |
| ... | @@ -1344,12 +1378,12 @@ pub const Value = extern union { | ... | @@ -1344,12 +1378,12 @@ pub const Value = extern union { |
| 1344 | const fields = ty.structFields().values(); | 1378 | const fields = ty.structFields().values(); |
| 1345 | const field_vals = val.castTag(.aggregate).?.data; | 1379 | const field_vals = val.castTag(.aggregate).?.data; |
| 1346 | for (fields, 0..) |field, i| { | 1380 | for (fields, 0..) |field, i| { |
| 1347 | const off = @intCast(usize, ty.structFieldOffset(i, target)); | 1381 | const off = @intCast(usize, ty.structFieldOffset(i, mod)); |
| 1348 | try writeToMemory(field_vals[i], field.ty, mod, buffer[off..]); | 1382 | try writeToMemory(field_vals[i], field.ty, mod, buffer[off..]); |
| 1349 | } | 1383 | } |
| 1350 | }, | 1384 | }, |
| 1351 | .Packed => { | 1385 | .Packed => { |
| 1352 | const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8; | 1386 | const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8; |
| 1353 | return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0); | 1387 | return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0); |
| 1354 | }, | 1388 | }, |
| 1355 | }, | 1389 | }, |
| ... | @@ -1363,7 +1397,7 @@ pub const Value = extern union { | ... | @@ -1363,7 +1397,7 @@ pub const Value = extern union { |
| 1363 | .Auto => return error.IllDefinedMemoryLayout, | 1397 | .Auto => return error.IllDefinedMemoryLayout, |
| 1364 | .Extern => return error.Unimplemented, | 1398 | .Extern => return error.Unimplemented, |
| 1365 | .Packed => { | 1399 | .Packed => { |
| 1366 | const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8; | 1400 | const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8; |
| 1367 | return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0); | 1401 | return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0); |
| 1368 | }, | 1402 | }, |
| 1369 | }, | 1403 | }, |
| ... | @@ -1373,10 +1407,10 @@ pub const Value = extern union { | ... | @@ -1373,10 +1407,10 @@ pub const Value = extern union { |
| 1373 | return val.writeToMemory(Type.usize, mod, buffer); | 1407 | return val.writeToMemory(Type.usize, mod, buffer); |
| 1374 | }, | 1408 | }, |
| 1375 | .Optional => { | 1409 | .Optional => { |
| 1376 | if (!ty.isPtrLikeOptional()) return error.IllDefinedMemoryLayout; | 1410 | if (!ty.isPtrLikeOptional(mod)) return error.IllDefinedMemoryLayout; |
| 1377 | var buf: Type.Payload.ElemType = undefined; | 1411 | var buf: Type.Payload.ElemType = undefined; |
| 1378 | const child = ty.optionalChild(&buf); | 1412 | const child = ty.optionalChild(&buf); |
| 1379 | const opt_val = val.optionalValue(); | 1413 | const opt_val = val.optionalValue(mod); |
| 1380 | if (opt_val) |some| { | 1414 | if (opt_val) |some| { |
| 1381 | return some.writeToMemory(child, mod, buffer); | 1415 | return some.writeToMemory(child, mod, buffer); |
| 1382 | } else { | 1416 | } else { |
| ... | @@ -1395,11 +1429,11 @@ pub const Value = extern union { | ... | @@ -1395,11 +1429,11 @@ pub const Value = extern union { |
| 1395 | const target = mod.getTarget(); | 1429 | const target = mod.getTarget(); |
| 1396 | const endian = target.cpu.arch.endian(); | 1430 | const endian = target.cpu.arch.endian(); |
| 1397 | if (val.isUndef()) { | 1431 | if (val.isUndef()) { |
| 1398 | const bit_size = @intCast(usize, ty.bitSize(target)); | 1432 | const bit_size = @intCast(usize, ty.bitSize(mod)); |
| 1399 | std.mem.writeVarPackedInt(buffer, bit_offset, bit_size, @as(u1, 0), endian); | 1433 | std.mem.writeVarPackedInt(buffer, bit_offset, bit_size, @as(u1, 0), endian); |
| 1400 | return; | 1434 | return; |
| 1401 | } | 1435 | } |
| 1402 | switch (ty.zigTypeTag()) { | 1436 | switch (ty.zigTypeTag(mod)) { |
| 1403 | .Void => {}, | 1437 | .Void => {}, |
| 1404 | .Bool => { | 1438 | .Bool => { |
| 1405 | const byte_index = switch (endian) { | 1439 | const byte_index = switch (endian) { |
| ... | @@ -1413,8 +1447,8 @@ pub const Value = extern union { | ... | @@ -1413,8 +1447,8 @@ pub const Value = extern union { |
| 1413 | } | 1447 | } |
| 1414 | }, | 1448 | }, |
| 1415 | .Int, .Enum => { | 1449 | .Int, .Enum => { |
| 1416 | const bits = ty.intInfo(target).bits; | 1450 | const bits = ty.intInfo(mod).bits; |
| 1417 | const abi_size = @intCast(usize, ty.abiSize(target)); | 1451 | const abi_size = @intCast(usize, ty.abiSize(mod)); |
| 1418 | 1452 | ||
| 1419 | var enum_buffer: Payload.U64 = undefined; | 1453 | var enum_buffer: Payload.U64 = undefined; |
| 1420 | const int_val = val.enumToInt(ty, &enum_buffer); | 1454 | const int_val = val.enumToInt(ty, &enum_buffer); |
| ... | @@ -1431,7 +1465,7 @@ pub const Value = extern union { | ... | @@ -1431,7 +1465,7 @@ pub const Value = extern union { |
| 1431 | std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian); | 1465 | std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian); |
| 1432 | } else { | 1466 | } else { |
| 1433 | var bigint_buffer: BigIntSpace = undefined; | 1467 | var bigint_buffer: BigIntSpace = undefined; |
| 1434 | const bigint = int_val.toBigInt(&bigint_buffer, target); | 1468 | const bigint = int_val.toBigInt(&bigint_buffer, mod); |
| 1435 | bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian); | 1469 | bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian); |
| 1436 | } | 1470 | } |
| 1437 | }, | 1471 | }, |
| ... | @@ -1445,7 +1479,7 @@ pub const Value = extern union { | ... | @@ -1445,7 +1479,7 @@ pub const Value = extern union { |
| 1445 | }, | 1479 | }, |
| 1446 | .Vector => { | 1480 | .Vector => { |
| 1447 | const elem_ty = ty.childType(); | 1481 | const elem_ty = ty.childType(); |
| 1448 | const elem_bit_size = @intCast(u16, elem_ty.bitSize(target)); | 1482 | const elem_bit_size = @intCast(u16, elem_ty.bitSize(mod)); |
| 1449 | const len = @intCast(usize, ty.arrayLen()); | 1483 | const len = @intCast(usize, ty.arrayLen()); |
| 1450 | 1484 | ||
| 1451 | var bits: u16 = 0; | 1485 | var bits: u16 = 0; |
| ... | @@ -1467,7 +1501,7 @@ pub const Value = extern union { | ... | @@ -1467,7 +1501,7 @@ pub const Value = extern union { |
| 1467 | const fields = ty.structFields().values(); | 1501 | const fields = ty.structFields().values(); |
| 1468 | const field_vals = val.castTag(.aggregate).?.data; | 1502 | const field_vals = val.castTag(.aggregate).?.data; |
| 1469 | for (fields, 0..) |field, i| { | 1503 | for (fields, 0..) |field, i| { |
| 1470 | const field_bits = @intCast(u16, field.ty.bitSize(target)); | 1504 | const field_bits = @intCast(u16, field.ty.bitSize(mod)); |
| 1471 | try field_vals[i].writeToPackedMemory(field.ty, mod, buffer, bit_offset + bits); | 1505 | try field_vals[i].writeToPackedMemory(field.ty, mod, buffer, bit_offset + bits); |
| 1472 | bits += field_bits; | 1506 | bits += field_bits; |
| 1473 | } | 1507 | } |
| ... | @@ -1479,7 +1513,7 @@ pub const Value = extern union { | ... | @@ -1479,7 +1513,7 @@ pub const Value = extern union { |
| 1479 | .Packed => { | 1513 | .Packed => { |
| 1480 | const field_index = ty.unionTagFieldIndex(val.unionTag(), mod); | 1514 | const field_index = ty.unionTagFieldIndex(val.unionTag(), mod); |
| 1481 | const field_type = ty.unionFields().values()[field_index.?].ty; | 1515 | const field_type = ty.unionFields().values()[field_index.?].ty; |
| 1482 | const field_val = val.fieldValue(field_type, field_index.?); | 1516 | const field_val = val.fieldValue(field_type, mod, field_index.?); |
| 1483 | 1517 | ||
| 1484 | return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset); | 1518 | return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset); |
| 1485 | }, | 1519 | }, |
| ... | @@ -1490,10 +1524,10 @@ pub const Value = extern union { | ... | @@ -1490,10 +1524,10 @@ pub const Value = extern union { |
| 1490 | return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset); | 1524 | return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset); |
| 1491 | }, | 1525 | }, |
| 1492 | .Optional => { | 1526 | .Optional => { |
| 1493 | assert(ty.isPtrLikeOptional()); | 1527 | assert(ty.isPtrLikeOptional(mod)); |
| 1494 | var buf: Type.Payload.ElemType = undefined; | 1528 | var buf: Type.Payload.ElemType = undefined; |
| 1495 | const child = ty.optionalChild(&buf); | 1529 | const child = ty.optionalChild(&buf); |
| 1496 | const opt_val = val.optionalValue(); | 1530 | const opt_val = val.optionalValue(mod); |
| 1497 | if (opt_val) |some| { | 1531 | if (opt_val) |some| { |
| 1498 | return some.writeToPackedMemory(child, mod, buffer, bit_offset); | 1532 | return some.writeToPackedMemory(child, mod, buffer, bit_offset); |
| 1499 | } else { | 1533 | } else { |
| ... | @@ -1516,7 +1550,7 @@ pub const Value = extern union { | ... | @@ -1516,7 +1550,7 @@ pub const Value = extern union { |
| 1516 | ) Allocator.Error!Value { | 1550 | ) Allocator.Error!Value { |
| 1517 | const target = mod.getTarget(); | 1551 | const target = mod.getTarget(); |
| 1518 | const endian = target.cpu.arch.endian(); | 1552 | const endian = target.cpu.arch.endian(); |
| 1519 | switch (ty.zigTypeTag()) { | 1553 | switch (ty.zigTypeTag(mod)) { |
| 1520 | .Void => return Value.void, | 1554 | .Void => return Value.void, |
| 1521 | .Bool => { | 1555 | .Bool => { |
| 1522 | if (buffer[0] == 0) { | 1556 | if (buffer[0] == 0) { |
| ... | @@ -1526,7 +1560,7 @@ pub const Value = extern union { | ... | @@ -1526,7 +1560,7 @@ pub const Value = extern union { |
| 1526 | } | 1560 | } |
| 1527 | }, | 1561 | }, |
| 1528 | .Int, .Enum => { | 1562 | .Int, .Enum => { |
| 1529 | const int_info = ty.intInfo(target); | 1563 | const int_info = ty.intInfo(mod); |
| 1530 | const bits = int_info.bits; | 1564 | const bits = int_info.bits; |
| 1531 | const byte_count = (bits + 7) / 8; | 1565 | const byte_count = (bits + 7) / 8; |
| 1532 | if (bits == 0 or buffer.len == 0) return Value.zero; | 1566 | if (bits == 0 or buffer.len == 0) return Value.zero; |
| ... | @@ -1560,7 +1594,7 @@ pub const Value = extern union { | ... | @@ -1560,7 +1594,7 @@ pub const Value = extern union { |
| 1560 | }, | 1594 | }, |
| 1561 | .Array => { | 1595 | .Array => { |
| 1562 | const elem_ty = ty.childType(); | 1596 | const elem_ty = ty.childType(); |
| 1563 | const elem_size = elem_ty.abiSize(target); | 1597 | const elem_size = elem_ty.abiSize(mod); |
| 1564 | const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen())); | 1598 | const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen())); |
| 1565 | var offset: usize = 0; | 1599 | var offset: usize = 0; |
| 1566 | for (elems) |*elem| { | 1600 | for (elems) |*elem| { |
| ... | @@ -1572,7 +1606,7 @@ pub const Value = extern union { | ... | @@ -1572,7 +1606,7 @@ pub const Value = extern union { |
| 1572 | .Vector => { | 1606 | .Vector => { |
| 1573 | // We use byte_count instead of abi_size here, so that any padding bytes | 1607 | // We use byte_count instead of abi_size here, so that any padding bytes |
| 1574 | // follow the data bytes, on both big- and little-endian systems. | 1608 | // follow the data bytes, on both big- and little-endian systems. |
| 1575 | const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8; | 1609 | const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8; |
| 1576 | return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena); | 1610 | return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena); |
| 1577 | }, | 1611 | }, |
| 1578 | .Struct => switch (ty.containerLayout()) { | 1612 | .Struct => switch (ty.containerLayout()) { |
| ... | @@ -1581,14 +1615,14 @@ pub const Value = extern union { | ... | @@ -1581,14 +1615,14 @@ pub const Value = extern union { |
| 1581 | const fields = ty.structFields().values(); | 1615 | const fields = ty.structFields().values(); |
| 1582 | const field_vals = try arena.alloc(Value, fields.len); | 1616 | const field_vals = try arena.alloc(Value, fields.len); |
| 1583 | for (fields, 0..) |field, i| { | 1617 | for (fields, 0..) |field, i| { |
| 1584 | const off = @intCast(usize, ty.structFieldOffset(i, target)); | 1618 | const off = @intCast(usize, ty.structFieldOffset(i, mod)); |
| 1585 | const sz = @intCast(usize, ty.structFieldType(i).abiSize(target)); | 1619 | const sz = @intCast(usize, ty.structFieldType(i).abiSize(mod)); |
| 1586 | field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena); | 1620 | field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena); |
| 1587 | } | 1621 | } |
| 1588 | return Tag.aggregate.create(arena, field_vals); | 1622 | return Tag.aggregate.create(arena, field_vals); |
| 1589 | }, | 1623 | }, |
| 1590 | .Packed => { | 1624 | .Packed => { |
| 1591 | const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8; | 1625 | const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8; |
| 1592 | return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena); | 1626 | return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena); |
| 1593 | }, | 1627 | }, |
| 1594 | }, | 1628 | }, |
| ... | @@ -1609,7 +1643,7 @@ pub const Value = extern union { | ... | @@ -1609,7 +1643,7 @@ pub const Value = extern union { |
| 1609 | return readFromMemory(Type.usize, mod, buffer, arena); | 1643 | return readFromMemory(Type.usize, mod, buffer, arena); |
| 1610 | }, | 1644 | }, |
| 1611 | .Optional => { | 1645 | .Optional => { |
| 1612 | assert(ty.isPtrLikeOptional()); | 1646 | assert(ty.isPtrLikeOptional(mod)); |
| 1613 | var buf: Type.Payload.ElemType = undefined; | 1647 | var buf: Type.Payload.ElemType = undefined; |
| 1614 | const child = ty.optionalChild(&buf); | 1648 | const child = ty.optionalChild(&buf); |
| 1615 | return readFromMemory(child, mod, buffer, arena); | 1649 | return readFromMemory(child, mod, buffer, arena); |
| ... | @@ -1631,7 +1665,7 @@ pub const Value = extern union { | ... | @@ -1631,7 +1665,7 @@ pub const Value = extern union { |
| 1631 | ) Allocator.Error!Value { | 1665 | ) Allocator.Error!Value { |
| 1632 | const target = mod.getTarget(); | 1666 | const target = mod.getTarget(); |
| 1633 | const endian = target.cpu.arch.endian(); | 1667 | const endian = target.cpu.arch.endian(); |
| 1634 | switch (ty.zigTypeTag()) { | 1668 | switch (ty.zigTypeTag(mod)) { |
| 1635 | .Void => return Value.void, | 1669 | .Void => return Value.void, |
| 1636 | .Bool => { | 1670 | .Bool => { |
| 1637 | const byte = switch (endian) { | 1671 | const byte = switch (endian) { |
| ... | @@ -1646,8 +1680,8 @@ pub const Value = extern union { | ... | @@ -1646,8 +1680,8 @@ pub const Value = extern union { |
| 1646 | }, | 1680 | }, |
| 1647 | .Int, .Enum => { | 1681 | .Int, .Enum => { |
| 1648 | if (buffer.len == 0) return Value.zero; | 1682 | if (buffer.len == 0) return Value.zero; |
| 1649 | const int_info = ty.intInfo(target); | 1683 | const int_info = ty.intInfo(mod); |
| 1650 | const abi_size = @intCast(usize, ty.abiSize(target)); | 1684 | const abi_size = @intCast(usize, ty.abiSize(mod)); |
| 1651 | 1685 | ||
| 1652 | const bits = int_info.bits; | 1686 | const bits = int_info.bits; |
| 1653 | if (bits == 0) return Value.zero; | 1687 | if (bits == 0) return Value.zero; |
| ... | @@ -1677,7 +1711,7 @@ pub const Value = extern union { | ... | @@ -1677,7 +1711,7 @@ pub const Value = extern union { |
| 1677 | const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen())); | 1711 | const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen())); |
| 1678 | 1712 | ||
| 1679 | var bits: u16 = 0; | 1713 | var bits: u16 = 0; |
| 1680 | const elem_bit_size = @intCast(u16, elem_ty.bitSize(target)); | 1714 | const elem_bit_size = @intCast(u16, elem_ty.bitSize(mod)); |
| 1681 | for (elems, 0..) |_, i| { | 1715 | for (elems, 0..) |_, i| { |
| 1682 | // On big-endian systems, LLVM reverses the element order of vectors by default | 1716 | // On big-endian systems, LLVM reverses the element order of vectors by default |
| 1683 | const tgt_elem_i = if (endian == .Big) elems.len - i - 1 else i; | 1717 | const tgt_elem_i = if (endian == .Big) elems.len - i - 1 else i; |
| ... | @@ -1694,7 +1728,7 @@ pub const Value = extern union { | ... | @@ -1694,7 +1728,7 @@ pub const Value = extern union { |
| 1694 | const fields = ty.structFields().values(); | 1728 | const fields = ty.structFields().values(); |
| 1695 | const field_vals = try arena.alloc(Value, fields.len); | 1729 | const field_vals = try arena.alloc(Value, fields.len); |
| 1696 | for (fields, 0..) |field, i| { | 1730 | for (fields, 0..) |field, i| { |
| 1697 | const field_bits = @intCast(u16, field.ty.bitSize(target)); | 1731 | const field_bits = @intCast(u16, field.ty.bitSize(mod)); |
| 1698 | field_vals[i] = try readFromPackedMemory(field.ty, mod, buffer, bit_offset + bits, arena); | 1732 | field_vals[i] = try readFromPackedMemory(field.ty, mod, buffer, bit_offset + bits, arena); |
| 1699 | bits += field_bits; | 1733 | bits += field_bits; |
| 1700 | } | 1734 | } |
| ... | @@ -1706,7 +1740,7 @@ pub const Value = extern union { | ... | @@ -1706,7 +1740,7 @@ pub const Value = extern union { |
| 1706 | return readFromPackedMemory(Type.usize, mod, buffer, bit_offset, arena); | 1740 | return readFromPackedMemory(Type.usize, mod, buffer, bit_offset, arena); |
| 1707 | }, | 1741 | }, |
| 1708 | .Optional => { | 1742 | .Optional => { |
| 1709 | assert(ty.isPtrLikeOptional()); | 1743 | assert(ty.isPtrLikeOptional(mod)); |
| 1710 | var buf: Type.Payload.ElemType = undefined; | 1744 | var buf: Type.Payload.ElemType = undefined; |
| 1711 | const child = ty.optionalChild(&buf); | 1745 | const child = ty.optionalChild(&buf); |
| 1712 | return readFromPackedMemory(child, mod, buffer, bit_offset, arena); | 1746 | return readFromPackedMemory(child, mod, buffer, bit_offset, arena); |
| ... | @@ -1764,8 +1798,8 @@ pub const Value = extern union { | ... | @@ -1764,8 +1798,8 @@ pub const Value = extern union { |
| 1764 | } | 1798 | } |
| 1765 | } | 1799 | } |
| 1766 | 1800 | ||
| 1767 | pub fn clz(val: Value, ty: Type, target: Target) u64 { | 1801 | pub fn clz(val: Value, ty: Type, mod: *const Module) u64 { |
| 1768 | const ty_bits = ty.intInfo(target).bits; | 1802 | const ty_bits = ty.intInfo(mod).bits; |
| 1769 | switch (val.tag()) { | 1803 | switch (val.tag()) { |
| 1770 | .zero, .bool_false => return ty_bits, | 1804 | .zero, .bool_false => return ty_bits, |
| 1771 | .one, .bool_true => return ty_bits - 1, | 1805 | .one, .bool_true => return ty_bits - 1, |
| ... | @@ -1792,7 +1826,7 @@ pub const Value = extern union { | ... | @@ -1792,7 +1826,7 @@ pub const Value = extern union { |
| 1792 | 1826 | ||
| 1793 | .lazy_align, .lazy_size => { | 1827 | .lazy_align, .lazy_size => { |
| 1794 | var bigint_buf: BigIntSpace = undefined; | 1828 | var bigint_buf: BigIntSpace = undefined; |
| 1795 | const bigint = val.toBigIntAdvanced(&bigint_buf, target, null) catch unreachable; | 1829 | const bigint = val.toBigIntAdvanced(&bigint_buf, mod, null) catch unreachable; |
| 1796 | return bigint.clz(ty_bits); | 1830 | return bigint.clz(ty_bits); |
| 1797 | }, | 1831 | }, |
| 1798 | 1832 | ||
| ... | @@ -1800,8 +1834,8 @@ pub const Value = extern union { | ... | @@ -1800,8 +1834,8 @@ pub const Value = extern union { |
| 1800 | } | 1834 | } |
| 1801 | } | 1835 | } |
| 1802 | 1836 | ||
| 1803 | pub fn ctz(val: Value, ty: Type, target: Target) u64 { | 1837 | pub fn ctz(val: Value, ty: Type, mod: *const Module) u64 { |
| 1804 | const ty_bits = ty.intInfo(target).bits; | 1838 | const ty_bits = ty.intInfo(mod).bits; |
| 1805 | switch (val.tag()) { | 1839 | switch (val.tag()) { |
| 1806 | .zero, .bool_false => return ty_bits, | 1840 | .zero, .bool_false => return ty_bits, |
| 1807 | .one, .bool_true => return 0, | 1841 | .one, .bool_true => return 0, |
| ... | @@ -1828,7 +1862,7 @@ pub const Value = extern union { | ... | @@ -1828,7 +1862,7 @@ pub const Value = extern union { |
| 1828 | 1862 | ||
| 1829 | .lazy_align, .lazy_size => { | 1863 | .lazy_align, .lazy_size => { |
| 1830 | var bigint_buf: BigIntSpace = undefined; | 1864 | var bigint_buf: BigIntSpace = undefined; |
| 1831 | const bigint = val.toBigIntAdvanced(&bigint_buf, target, null) catch unreachable; | 1865 | const bigint = val.toBigIntAdvanced(&bigint_buf, mod, null) catch unreachable; |
| 1832 | return bigint.ctz(); | 1866 | return bigint.ctz(); |
| 1833 | }, | 1867 | }, |
| 1834 | 1868 | ||
| ... | @@ -1836,7 +1870,7 @@ pub const Value = extern union { | ... | @@ -1836,7 +1870,7 @@ pub const Value = extern union { |
| 1836 | } | 1870 | } |
| 1837 | } | 1871 | } |
| 1838 | 1872 | ||
| 1839 | pub fn popCount(val: Value, ty: Type, target: Target) u64 { | 1873 | pub fn popCount(val: Value, ty: Type, mod: *const Module) u64 { |
| 1840 | assert(!val.isUndef()); | 1874 | assert(!val.isUndef()); |
| 1841 | switch (val.tag()) { | 1875 | switch (val.tag()) { |
| 1842 | .zero, .bool_false => return 0, | 1876 | .zero, .bool_false => return 0, |
| ... | @@ -1845,22 +1879,22 @@ pub const Value = extern union { | ... | @@ -1845,22 +1879,22 @@ pub const Value = extern union { |
| 1845 | .int_u64 => return @popCount(val.castTag(.int_u64).?.data), | 1879 | .int_u64 => return @popCount(val.castTag(.int_u64).?.data), |
| 1846 | 1880 | ||
| 1847 | else => { | 1881 | else => { |
| 1848 | const info = ty.intInfo(target); | 1882 | const info = ty.intInfo(mod); |
| 1849 | 1883 | ||
| 1850 | var buffer: Value.BigIntSpace = undefined; | 1884 | var buffer: Value.BigIntSpace = undefined; |
| 1851 | const int = val.toBigInt(&buffer, target); | 1885 | const int = val.toBigInt(&buffer, mod); |
| 1852 | return @intCast(u64, int.popCount(info.bits)); | 1886 | return @intCast(u64, int.popCount(info.bits)); |
| 1853 | }, | 1887 | }, |
| 1854 | } | 1888 | } |
| 1855 | } | 1889 | } |
| 1856 | 1890 | ||
| 1857 | pub fn bitReverse(val: Value, ty: Type, target: Target, arena: Allocator) !Value { | 1891 | pub fn bitReverse(val: Value, ty: Type, mod: *const Module, arena: Allocator) !Value { |
| 1858 | assert(!val.isUndef()); | 1892 | assert(!val.isUndef()); |
| 1859 | 1893 | ||
| 1860 | const info = ty.intInfo(target); | 1894 | const info = ty.intInfo(mod); |
| 1861 | 1895 | ||
| 1862 | var buffer: Value.BigIntSpace = undefined; | 1896 | var buffer: Value.BigIntSpace = undefined; |
| 1863 | const operand_bigint = val.toBigInt(&buffer, target); | 1897 | const operand_bigint = val.toBigInt(&buffer, mod); |
| 1864 | 1898 | ||
| 1865 | const limbs = try arena.alloc( | 1899 | const limbs = try arena.alloc( |
| 1866 | std.math.big.Limb, | 1900 | std.math.big.Limb, |
| ... | @@ -1872,16 +1906,16 @@ pub const Value = extern union { | ... | @@ -1872,16 +1906,16 @@ pub const Value = extern union { |
| 1872 | return fromBigInt(arena, result_bigint.toConst()); | 1906 | return fromBigInt(arena, result_bigint.toConst()); |
| 1873 | } | 1907 | } |
| 1874 | 1908 | ||
| 1875 | pub fn byteSwap(val: Value, ty: Type, target: Target, arena: Allocator) !Value { | 1909 | pub fn byteSwap(val: Value, ty: Type, mod: *const Module, arena: Allocator) !Value { |
| 1876 | assert(!val.isUndef()); | 1910 | assert(!val.isUndef()); |
| 1877 | 1911 | ||
| 1878 | const info = ty.intInfo(target); | 1912 | const info = ty.intInfo(mod); |
| 1879 | 1913 | ||
| 1880 | // Bit count must be evenly divisible by 8 | 1914 | // Bit count must be evenly divisible by 8 |
| 1881 | assert(info.bits % 8 == 0); | 1915 | assert(info.bits % 8 == 0); |
| 1882 | 1916 | ||
| 1883 | var buffer: Value.BigIntSpace = undefined; | 1917 | var buffer: Value.BigIntSpace = undefined; |
| 1884 | const operand_bigint = val.toBigInt(&buffer, target); | 1918 | const operand_bigint = val.toBigInt(&buffer, mod); |
| 1885 | 1919 | ||
| 1886 | const limbs = try arena.alloc( | 1920 | const limbs = try arena.alloc( |
| 1887 | std.math.big.Limb, | 1921 | std.math.big.Limb, |
| ... | @@ -1895,7 +1929,8 @@ pub const Value = extern union { | ... | @@ -1895,7 +1929,8 @@ pub const Value = extern union { |
| 1895 | 1929 | ||
| 1896 | /// Asserts the value is an integer and not undefined. | 1930 | /// Asserts the value is an integer and not undefined. |
| 1897 | /// Returns the number of bits the value requires to represent stored in twos complement form. | 1931 | /// Returns the number of bits the value requires to represent stored in twos complement form. |
| 1898 | pub fn intBitCountTwosComp(self: Value, target: Target) usize { | 1932 | pub fn intBitCountTwosComp(self: Value, mod: *const Module) usize { |
| 1933 | const target = mod.getTarget(); | ||
| 1899 | switch (self.tag()) { | 1934 | switch (self.tag()) { |
| 1900 | .zero, | 1935 | .zero, |
| 1901 | .bool_false, | 1936 | .bool_false, |
| ... | @@ -1926,7 +1961,7 @@ pub const Value = extern union { | ... | @@ -1926,7 +1961,7 @@ pub const Value = extern union { |
| 1926 | 1961 | ||
| 1927 | else => { | 1962 | else => { |
| 1928 | var buffer: BigIntSpace = undefined; | 1963 | var buffer: BigIntSpace = undefined; |
| 1929 | return self.toBigInt(&buffer, target).bitCountTwosComp(); | 1964 | return self.toBigInt(&buffer, mod).bitCountTwosComp(); |
| 1930 | }, | 1965 | }, |
| 1931 | } | 1966 | } |
| 1932 | } | 1967 | } |
| ... | @@ -1962,12 +1997,13 @@ pub const Value = extern union { | ... | @@ -1962,12 +1997,13 @@ pub const Value = extern union { |
| 1962 | }; | 1997 | }; |
| 1963 | } | 1998 | } |
| 1964 | 1999 | ||
| 1965 | pub fn orderAgainstZero(lhs: Value) std.math.Order { | 2000 | pub fn orderAgainstZero(lhs: Value, mod: *const Module) std.math.Order { |
| 1966 | return orderAgainstZeroAdvanced(lhs, null) catch unreachable; | 2001 | return orderAgainstZeroAdvanced(lhs, mod, null) catch unreachable; |
| 1967 | } | 2002 | } |
| 1968 | 2003 | ||
| 1969 | pub fn orderAgainstZeroAdvanced( | 2004 | pub fn orderAgainstZeroAdvanced( |
| 1970 | lhs: Value, | 2005 | lhs: Value, |
| 2006 | mod: *const Module, | ||
| 1971 | opt_sema: ?*Sema, | 2007 | opt_sema: ?*Sema, |
| 1972 | ) Module.CompileError!std.math.Order { | 2008 | ) Module.CompileError!std.math.Order { |
| 1973 | return switch (lhs.tag()) { | 2009 | return switch (lhs.tag()) { |
| ... | @@ -1991,7 +2027,7 @@ pub const Value = extern union { | ... | @@ -1991,7 +2027,7 @@ pub const Value = extern union { |
| 1991 | // This is needed to correctly handle hashing the value. | 2027 | // This is needed to correctly handle hashing the value. |
| 1992 | // Checks in Sema should prevent direct comparisons from reaching here. | 2028 | // Checks in Sema should prevent direct comparisons from reaching here. |
| 1993 | const val = lhs.castTag(.runtime_value).?.data; | 2029 | const val = lhs.castTag(.runtime_value).?.data; |
| 1994 | return val.orderAgainstZeroAdvanced(opt_sema); | 2030 | return val.orderAgainstZeroAdvanced(mod, opt_sema); |
| 1995 | }, | 2031 | }, |
| 1996 | .int_u64 => std.math.order(lhs.castTag(.int_u64).?.data, 0), | 2032 | .int_u64 => std.math.order(lhs.castTag(.int_u64).?.data, 0), |
| 1997 | .int_i64 => std.math.order(lhs.castTag(.int_i64).?.data, 0), | 2033 | .int_i64 => std.math.order(lhs.castTag(.int_i64).?.data, 0), |
| ... | @@ -2001,7 +2037,7 @@ pub const Value = extern union { | ... | @@ -2001,7 +2037,7 @@ pub const Value = extern union { |
| 2001 | .lazy_align => { | 2037 | .lazy_align => { |
| 2002 | const ty = lhs.castTag(.lazy_align).?.data; | 2038 | const ty = lhs.castTag(.lazy_align).?.data; |
| 2003 | const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; | 2039 | const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; |
| 2004 | if (ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { | 2040 | if (ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { |
| 2005 | error.NeedLazy => unreachable, | 2041 | error.NeedLazy => unreachable, |
| 2006 | else => |e| return e, | 2042 | else => |e| return e, |
| 2007 | }) { | 2043 | }) { |
| ... | @@ -2013,7 +2049,7 @@ pub const Value = extern union { | ... | @@ -2013,7 +2049,7 @@ pub const Value = extern union { |
| 2013 | .lazy_size => { | 2049 | .lazy_size => { |
| 2014 | const ty = lhs.castTag(.lazy_size).?.data; | 2050 | const ty = lhs.castTag(.lazy_size).?.data; |
| 2015 | const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; | 2051 | const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; |
| 2016 | if (ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { | 2052 | if (ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { |
| 2017 | error.NeedLazy => unreachable, | 2053 | error.NeedLazy => unreachable, |
| 2018 | else => |e| return e, | 2054 | else => |e| return e, |
| 2019 | }) { | 2055 | }) { |
| ... | @@ -2031,7 +2067,7 @@ pub const Value = extern union { | ... | @@ -2031,7 +2067,7 @@ pub const Value = extern union { |
| 2031 | 2067 | ||
| 2032 | .elem_ptr => { | 2068 | .elem_ptr => { |
| 2033 | const elem_ptr = lhs.castTag(.elem_ptr).?.data; | 2069 | const elem_ptr = lhs.castTag(.elem_ptr).?.data; |
| 2034 | switch (try elem_ptr.array_ptr.orderAgainstZeroAdvanced(opt_sema)) { | 2070 | switch (try elem_ptr.array_ptr.orderAgainstZeroAdvanced(mod, opt_sema)) { |
| 2035 | .lt => unreachable, | 2071 | .lt => unreachable, |
| 2036 | .gt => return .gt, | 2072 | .gt => return .gt, |
| 2037 | .eq => { | 2073 | .eq => { |
| ... | @@ -2049,17 +2085,17 @@ pub const Value = extern union { | ... | @@ -2049,17 +2085,17 @@ pub const Value = extern union { |
| 2049 | } | 2085 | } |
| 2050 | 2086 | ||
| 2051 | /// Asserts the value is comparable. | 2087 | /// Asserts the value is comparable. |
| 2052 | pub fn order(lhs: Value, rhs: Value, target: Target) std.math.Order { | 2088 | pub fn order(lhs: Value, rhs: Value, mod: *const Module) std.math.Order { |
| 2053 | return orderAdvanced(lhs, rhs, target, null) catch unreachable; | 2089 | return orderAdvanced(lhs, rhs, mod, null) catch unreachable; |
| 2054 | } | 2090 | } |
| 2055 | 2091 | ||
| 2056 | /// Asserts the value is comparable. | 2092 | /// Asserts the value is comparable. |
| 2057 | /// If opt_sema is null then this function asserts things are resolved and cannot fail. | 2093 | /// If opt_sema is null then this function asserts things are resolved and cannot fail. |
| 2058 | pub fn orderAdvanced(lhs: Value, rhs: Value, target: Target, opt_sema: ?*Sema) !std.math.Order { | 2094 | pub fn orderAdvanced(lhs: Value, rhs: Value, mod: *const Module, opt_sema: ?*Sema) !std.math.Order { |
| 2059 | const lhs_tag = lhs.tag(); | 2095 | const lhs_tag = lhs.tag(); |
| 2060 | const rhs_tag = rhs.tag(); | 2096 | const rhs_tag = rhs.tag(); |
| 2061 | const lhs_against_zero = try lhs.orderAgainstZeroAdvanced(opt_sema); | 2097 | const lhs_against_zero = try lhs.orderAgainstZeroAdvanced(mod, opt_sema); |
| 2062 | const rhs_against_zero = try rhs.orderAgainstZeroAdvanced(opt_sema); | 2098 | const rhs_against_zero = try rhs.orderAgainstZeroAdvanced(mod, opt_sema); |
| 2063 | switch (lhs_against_zero) { | 2099 | switch (lhs_against_zero) { |
| 2064 | .lt => if (rhs_against_zero != .lt) return .lt, | 2100 | .lt => if (rhs_against_zero != .lt) return .lt, |
| 2065 | .eq => return rhs_against_zero.invert(), | 2101 | .eq => return rhs_against_zero.invert(), |
| ... | @@ -2093,22 +2129,22 @@ pub const Value = extern union { | ... | @@ -2093,22 +2129,22 @@ pub const Value = extern union { |
| 2093 | 2129 | ||
| 2094 | var lhs_bigint_space: BigIntSpace = undefined; | 2130 | var lhs_bigint_space: BigIntSpace = undefined; |
| 2095 | var rhs_bigint_space: BigIntSpace = undefined; | 2131 | var rhs_bigint_space: BigIntSpace = undefined; |
| 2096 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_bigint_space, target, opt_sema); | 2132 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_bigint_space, mod, opt_sema); |
| 2097 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_bigint_space, target, opt_sema); | 2133 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_bigint_space, mod, opt_sema); |
| 2098 | return lhs_bigint.order(rhs_bigint); | 2134 | return lhs_bigint.order(rhs_bigint); |
| 2099 | } | 2135 | } |
| 2100 | 2136 | ||
| 2101 | /// Asserts the value is comparable. Does not take a type parameter because it supports | 2137 | /// Asserts the value is comparable. Does not take a type parameter because it supports |
| 2102 | /// comparisons between heterogeneous types. | 2138 | /// comparisons between heterogeneous types. |
| 2103 | pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, target: Target) bool { | 2139 | pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, mod: *const Module) bool { |
| 2104 | return compareHeteroAdvanced(lhs, op, rhs, target, null) catch unreachable; | 2140 | return compareHeteroAdvanced(lhs, op, rhs, mod, null) catch unreachable; |
| 2105 | } | 2141 | } |
| 2106 | 2142 | ||
| 2107 | pub fn compareHeteroAdvanced( | 2143 | pub fn compareHeteroAdvanced( |
| 2108 | lhs: Value, | 2144 | lhs: Value, |
| 2109 | op: std.math.CompareOperator, | 2145 | op: std.math.CompareOperator, |
| 2110 | rhs: Value, | 2146 | rhs: Value, |
| 2111 | target: Target, | 2147 | mod: *const Module, |
| 2112 | opt_sema: ?*Sema, | 2148 | opt_sema: ?*Sema, |
| 2113 | ) !bool { | 2149 | ) !bool { |
| 2114 | if (lhs.pointerDecl()) |lhs_decl| { | 2150 | if (lhs.pointerDecl()) |lhs_decl| { |
| ... | @@ -2132,20 +2168,20 @@ pub const Value = extern union { | ... | @@ -2132,20 +2168,20 @@ pub const Value = extern union { |
| 2132 | else => {}, | 2168 | else => {}, |
| 2133 | } | 2169 | } |
| 2134 | } | 2170 | } |
| 2135 | return (try orderAdvanced(lhs, rhs, target, opt_sema)).compare(op); | 2171 | return (try orderAdvanced(lhs, rhs, mod, opt_sema)).compare(op); |
| 2136 | } | 2172 | } |
| 2137 | 2173 | ||
| 2138 | /// Asserts the values are comparable. Both operands have type `ty`. | 2174 | /// Asserts the values are comparable. Both operands have type `ty`. |
| 2139 | /// For vectors, returns true if comparison is true for ALL elements. | 2175 | /// For vectors, returns true if comparison is true for ALL elements. |
| 2140 | pub fn compareAll(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) bool { | 2176 | pub fn compareAll(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) bool { |
| 2141 | if (ty.zigTypeTag() == .Vector) { | 2177 | if (ty.zigTypeTag(mod) == .Vector) { |
| 2142 | var i: usize = 0; | 2178 | var i: usize = 0; |
| 2143 | while (i < ty.vectorLen()) : (i += 1) { | 2179 | while (i < ty.vectorLen()) : (i += 1) { |
| 2144 | var lhs_buf: Value.ElemValueBuffer = undefined; | 2180 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 2145 | var rhs_buf: Value.ElemValueBuffer = undefined; | 2181 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 2146 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 2182 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 2147 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 2183 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 2148 | if (!compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(), mod)) { | 2184 | if (!compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(mod), mod)) { |
| 2149 | return false; | 2185 | return false; |
| 2150 | } | 2186 | } |
| 2151 | } | 2187 | } |
| ... | @@ -2165,7 +2201,7 @@ pub const Value = extern union { | ... | @@ -2165,7 +2201,7 @@ pub const Value = extern union { |
| 2165 | return switch (op) { | 2201 | return switch (op) { |
| 2166 | .eq => lhs.eql(rhs, ty, mod), | 2202 | .eq => lhs.eql(rhs, ty, mod), |
| 2167 | .neq => !lhs.eql(rhs, ty, mod), | 2203 | .neq => !lhs.eql(rhs, ty, mod), |
| 2168 | else => compareHetero(lhs, op, rhs, mod.getTarget()), | 2204 | else => compareHetero(lhs, op, rhs, mod), |
| 2169 | }; | 2205 | }; |
| 2170 | } | 2206 | } |
| 2171 | 2207 | ||
| ... | @@ -2231,7 +2267,7 @@ pub const Value = extern union { | ... | @@ -2231,7 +2267,7 @@ pub const Value = extern union { |
| 2231 | .float_128 => if (std.math.isNan(lhs.castTag(.float_128).?.data)) return op == .neq, | 2267 | .float_128 => if (std.math.isNan(lhs.castTag(.float_128).?.data)) return op == .neq, |
| 2232 | else => {}, | 2268 | else => {}, |
| 2233 | } | 2269 | } |
| 2234 | return (try orderAgainstZeroAdvanced(lhs, opt_sema)).compare(op); | 2270 | return (try orderAgainstZeroAdvanced(lhs, mod, opt_sema)).compare(op); |
| 2235 | } | 2271 | } |
| 2236 | 2272 | ||
| 2237 | pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool { | 2273 | pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool { |
| ... | @@ -2346,7 +2382,7 @@ pub const Value = extern union { | ... | @@ -2346,7 +2382,7 @@ pub const Value = extern union { |
| 2346 | return true; | 2382 | return true; |
| 2347 | } | 2383 | } |
| 2348 | 2384 | ||
| 2349 | if (ty.zigTypeTag() == .Struct) { | 2385 | if (ty.zigTypeTag(mod) == .Struct) { |
| 2350 | const fields = ty.structFields().values(); | 2386 | const fields = ty.structFields().values(); |
| 2351 | assert(fields.len == a_field_vals.len); | 2387 | assert(fields.len == a_field_vals.len); |
| 2352 | for (fields, 0..) |field, i| { | 2388 | for (fields, 0..) |field, i| { |
| ... | @@ -2406,12 +2442,10 @@ pub const Value = extern union { | ... | @@ -2406,12 +2442,10 @@ pub const Value = extern union { |
| 2406 | return false; | 2442 | return false; |
| 2407 | } | 2443 | } |
| 2408 | 2444 | ||
| 2409 | switch (ty.zigTypeTag()) { | 2445 | switch (ty.zigTypeTag(mod)) { |
| 2410 | .Type => { | 2446 | .Type => { |
| 2411 | var buf_a: ToTypeBuffer = undefined; | 2447 | const a_type = a.toType(); |
| 2412 | var buf_b: ToTypeBuffer = undefined; | 2448 | const b_type = b.toType(); |
| 2413 | const a_type = a.toType(&buf_a); | ||
| 2414 | const b_type = b.toType(&buf_b); | ||
| 2415 | return a_type.eql(b_type, mod); | 2449 | return a_type.eql(b_type, mod); |
| 2416 | }, | 2450 | }, |
| 2417 | .Enum => { | 2451 | .Enum => { |
| ... | @@ -2419,8 +2453,7 @@ pub const Value = extern union { | ... | @@ -2419,8 +2453,7 @@ pub const Value = extern union { |
| 2419 | var buf_b: Payload.U64 = undefined; | 2453 | var buf_b: Payload.U64 = undefined; |
| 2420 | const a_val = a.enumToInt(ty, &buf_a); | 2454 | const a_val = a.enumToInt(ty, &buf_a); |
| 2421 | const b_val = b.enumToInt(ty, &buf_b); | 2455 | const b_val = b.enumToInt(ty, &buf_b); |
| 2422 | var buf_ty: Type.Payload.Bits = undefined; | 2456 | const int_ty = ty.intTagType(); |
| 2423 | const int_ty = ty.intTagType(&buf_ty); | ||
| 2424 | return eqlAdvanced(a_val, int_ty, b_val, int_ty, mod, opt_sema); | 2457 | return eqlAdvanced(a_val, int_ty, b_val, int_ty, mod, opt_sema); |
| 2425 | }, | 2458 | }, |
| 2426 | .Array, .Vector => { | 2459 | .Array, .Vector => { |
| ... | @@ -2466,11 +2499,11 @@ pub const Value = extern union { | ... | @@ -2466,11 +2499,11 @@ pub const Value = extern union { |
| 2466 | // .the_one_possible_value, | 2499 | // .the_one_possible_value, |
| 2467 | // .aggregate, | 2500 | // .aggregate, |
| 2468 | // Note that we already checked above for matching tags, e.g. both .aggregate. | 2501 | // Note that we already checked above for matching tags, e.g. both .aggregate. |
| 2469 | return ty.onePossibleValue() != null; | 2502 | return ty.onePossibleValue(mod) != null; |
| 2470 | }, | 2503 | }, |
| 2471 | .Union => { | 2504 | .Union => { |
| 2472 | // Here we have to check for value equality, as-if `a` has been coerced to `ty`. | 2505 | // Here we have to check for value equality, as-if `a` has been coerced to `ty`. |
| 2473 | if (ty.onePossibleValue() != null) { | 2506 | if (ty.onePossibleValue(mod) != null) { |
| 2474 | return true; | 2507 | return true; |
| 2475 | } | 2508 | } |
| 2476 | if (a_ty.castTag(.anon_struct)) |payload| { | 2509 | if (a_ty.castTag(.anon_struct)) |payload| { |
| ... | @@ -2533,13 +2566,13 @@ pub const Value = extern union { | ... | @@ -2533,13 +2566,13 @@ pub const Value = extern union { |
| 2533 | else => {}, | 2566 | else => {}, |
| 2534 | } | 2567 | } |
| 2535 | if (a_tag == .null_value or a_tag == .@"error") return false; | 2568 | if (a_tag == .null_value or a_tag == .@"error") return false; |
| 2536 | return (try orderAdvanced(a, b, target, opt_sema)).compare(.eq); | 2569 | return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq); |
| 2537 | } | 2570 | } |
| 2538 | 2571 | ||
| 2539 | /// This function is used by hash maps and so treats floating-point NaNs as equal | 2572 | /// This function is used by hash maps and so treats floating-point NaNs as equal |
| 2540 | /// to each other, and not equal to other floating-point values. | 2573 | /// to each other, and not equal to other floating-point values. |
| 2541 | pub fn hash(val: Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void { | 2574 | pub fn hash(val: Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void { |
| 2542 | const zig_ty_tag = ty.zigTypeTag(); | 2575 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 2543 | std.hash.autoHash(hasher, zig_ty_tag); | 2576 | std.hash.autoHash(hasher, zig_ty_tag); |
| 2544 | if (val.isUndef()) return; | 2577 | if (val.isUndef()) return; |
| 2545 | // The value is runtime-known and shouldn't affect the hash. | 2578 | // The value is runtime-known and shouldn't affect the hash. |
| ... | @@ -2555,8 +2588,7 @@ pub const Value = extern union { | ... | @@ -2555,8 +2588,7 @@ pub const Value = extern union { |
| 2555 | => {}, | 2588 | => {}, |
| 2556 | 2589 | ||
| 2557 | .Type => { | 2590 | .Type => { |
| 2558 | var buf: ToTypeBuffer = undefined; | 2591 | return val.toType().hashWithHasher(hasher, mod); |
| 2559 | return val.toType(&buf).hashWithHasher(hasher, mod); | ||
| 2560 | }, | 2592 | }, |
| 2561 | .Float => { | 2593 | .Float => { |
| 2562 | // For hash/eql purposes, we treat floats as their IEEE integer representation. | 2594 | // For hash/eql purposes, we treat floats as their IEEE integer representation. |
| ... | @@ -2588,7 +2620,7 @@ pub const Value = extern union { | ... | @@ -2588,7 +2620,7 @@ pub const Value = extern union { |
| 2588 | hash(slice.len, Type.usize, hasher, mod); | 2620 | hash(slice.len, Type.usize, hasher, mod); |
| 2589 | }, | 2621 | }, |
| 2590 | 2622 | ||
| 2591 | else => return hashPtr(val, hasher, mod.getTarget()), | 2623 | else => return hashPtr(val, hasher, mod), |
| 2592 | }, | 2624 | }, |
| 2593 | .Array, .Vector => { | 2625 | .Array, .Vector => { |
| 2594 | const len = ty.arrayLen(); | 2626 | const len = ty.arrayLen(); |
| ... | @@ -2648,7 +2680,7 @@ pub const Value = extern union { | ... | @@ -2648,7 +2680,7 @@ pub const Value = extern union { |
| 2648 | .Enum => { | 2680 | .Enum => { |
| 2649 | var enum_space: Payload.U64 = undefined; | 2681 | var enum_space: Payload.U64 = undefined; |
| 2650 | const int_val = val.enumToInt(ty, &enum_space); | 2682 | const int_val = val.enumToInt(ty, &enum_space); |
| 2651 | hashInt(int_val, hasher, mod.getTarget()); | 2683 | hashInt(int_val, hasher, mod); |
| 2652 | }, | 2684 | }, |
| 2653 | .Union => { | 2685 | .Union => { |
| 2654 | const union_obj = val.cast(Payload.Union).?.data; | 2686 | const union_obj = val.cast(Payload.Union).?.data; |
| ... | @@ -2691,7 +2723,7 @@ pub const Value = extern union { | ... | @@ -2691,7 +2723,7 @@ pub const Value = extern union { |
| 2691 | // The value is runtime-known and shouldn't affect the hash. | 2723 | // The value is runtime-known and shouldn't affect the hash. |
| 2692 | if (val.tag() == .runtime_value) return; | 2724 | if (val.tag() == .runtime_value) return; |
| 2693 | 2725 | ||
| 2694 | switch (ty.zigTypeTag()) { | 2726 | switch (ty.zigTypeTag(mod)) { |
| 2695 | .Opaque => unreachable, // Cannot hash opaque types | 2727 | .Opaque => unreachable, // Cannot hash opaque types |
| 2696 | .Void, | 2728 | .Void, |
| 2697 | .NoReturn, | 2729 | .NoReturn, |
| ... | @@ -2700,8 +2732,7 @@ pub const Value = extern union { | ... | @@ -2700,8 +2732,7 @@ pub const Value = extern union { |
| 2700 | .Struct, // It sure would be nice to do something clever with structs. | 2732 | .Struct, // It sure would be nice to do something clever with structs. |
| 2701 | => |zig_type_tag| std.hash.autoHash(hasher, zig_type_tag), | 2733 | => |zig_type_tag| std.hash.autoHash(hasher, zig_type_tag), |
| 2702 | .Type => { | 2734 | .Type => { |
| 2703 | var buf: ToTypeBuffer = undefined; | 2735 | val.toType().hashWithHasher(hasher, mod); |
| 2704 | val.toType(&buf).hashWithHasher(hasher, mod); | ||
| 2705 | }, | 2736 | }, |
| 2706 | .Float, .ComptimeFloat => std.hash.autoHash(hasher, @bitCast(u128, val.toFloat(f128))), | 2737 | .Float, .ComptimeFloat => std.hash.autoHash(hasher, @bitCast(u128, val.toFloat(f128))), |
| 2707 | .Bool, .Int, .ComptimeInt, .Pointer, .Fn => switch (val.tag()) { | 2738 | .Bool, .Int, .ComptimeInt, .Pointer, .Fn => switch (val.tag()) { |
| ... | @@ -2711,7 +2742,7 @@ pub const Value = extern union { | ... | @@ -2711,7 +2742,7 @@ pub const Value = extern union { |
| 2711 | const ptr_ty = ty.slicePtrFieldType(&ptr_buf); | 2742 | const ptr_ty = ty.slicePtrFieldType(&ptr_buf); |
| 2712 | slice.ptr.hashUncoerced(ptr_ty, hasher, mod); | 2743 | slice.ptr.hashUncoerced(ptr_ty, hasher, mod); |
| 2713 | }, | 2744 | }, |
| 2714 | else => val.hashPtr(hasher, mod.getTarget()), | 2745 | else => val.hashPtr(hasher, mod), |
| 2715 | }, | 2746 | }, |
| 2716 | .Array, .Vector => { | 2747 | .Array, .Vector => { |
| 2717 | const len = ty.arrayLen(); | 2748 | const len = ty.arrayLen(); |
| ... | @@ -2821,16 +2852,16 @@ pub const Value = extern union { | ... | @@ -2821,16 +2852,16 @@ pub const Value = extern union { |
| 2821 | }; | 2852 | }; |
| 2822 | } | 2853 | } |
| 2823 | 2854 | ||
| 2824 | fn hashInt(int_val: Value, hasher: *std.hash.Wyhash, target: Target) void { | 2855 | fn hashInt(int_val: Value, hasher: *std.hash.Wyhash, mod: *const Module) void { |
| 2825 | var buffer: BigIntSpace = undefined; | 2856 | var buffer: BigIntSpace = undefined; |
| 2826 | const big = int_val.toBigInt(&buffer, target); | 2857 | const big = int_val.toBigInt(&buffer, mod); |
| 2827 | std.hash.autoHash(hasher, big.positive); | 2858 | std.hash.autoHash(hasher, big.positive); |
| 2828 | for (big.limbs) |limb| { | 2859 | for (big.limbs) |limb| { |
| 2829 | std.hash.autoHash(hasher, limb); | 2860 | std.hash.autoHash(hasher, limb); |
| 2830 | } | 2861 | } |
| 2831 | } | 2862 | } |
| 2832 | 2863 | ||
| 2833 | fn hashPtr(ptr_val: Value, hasher: *std.hash.Wyhash, target: Target) void { | 2864 | fn hashPtr(ptr_val: Value, hasher: *std.hash.Wyhash, mod: *const Module) void { |
| 2834 | switch (ptr_val.tag()) { | 2865 | switch (ptr_val.tag()) { |
| 2835 | .decl_ref, | 2866 | .decl_ref, |
| 2836 | .decl_ref_mut, | 2867 | .decl_ref_mut, |
| ... | @@ -2847,25 +2878,25 @@ pub const Value = extern union { | ... | @@ -2847,25 +2878,25 @@ pub const Value = extern union { |
| 2847 | 2878 | ||
| 2848 | .elem_ptr => { | 2879 | .elem_ptr => { |
| 2849 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; | 2880 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; |
| 2850 | hashPtr(elem_ptr.array_ptr, hasher, target); | 2881 | hashPtr(elem_ptr.array_ptr, hasher, mod); |
| 2851 | std.hash.autoHash(hasher, Value.Tag.elem_ptr); | 2882 | std.hash.autoHash(hasher, Value.Tag.elem_ptr); |
| 2852 | std.hash.autoHash(hasher, elem_ptr.index); | 2883 | std.hash.autoHash(hasher, elem_ptr.index); |
| 2853 | }, | 2884 | }, |
| 2854 | .field_ptr => { | 2885 | .field_ptr => { |
| 2855 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; | 2886 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| 2856 | std.hash.autoHash(hasher, Value.Tag.field_ptr); | 2887 | std.hash.autoHash(hasher, Value.Tag.field_ptr); |
| 2857 | hashPtr(field_ptr.container_ptr, hasher, target); | 2888 | hashPtr(field_ptr.container_ptr, hasher, mod); |
| 2858 | std.hash.autoHash(hasher, field_ptr.field_index); | 2889 | std.hash.autoHash(hasher, field_ptr.field_index); |
| 2859 | }, | 2890 | }, |
| 2860 | .eu_payload_ptr => { | 2891 | .eu_payload_ptr => { |
| 2861 | const err_union_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; | 2892 | const err_union_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; |
| 2862 | std.hash.autoHash(hasher, Value.Tag.eu_payload_ptr); | 2893 | std.hash.autoHash(hasher, Value.Tag.eu_payload_ptr); |
| 2863 | hashPtr(err_union_ptr.container_ptr, hasher, target); | 2894 | hashPtr(err_union_ptr.container_ptr, hasher, mod); |
| 2864 | }, | 2895 | }, |
| 2865 | .opt_payload_ptr => { | 2896 | .opt_payload_ptr => { |
| 2866 | const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; | 2897 | const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; |
| 2867 | std.hash.autoHash(hasher, Value.Tag.opt_payload_ptr); | 2898 | std.hash.autoHash(hasher, Value.Tag.opt_payload_ptr); |
| 2868 | hashPtr(opt_ptr.container_ptr, hasher, target); | 2899 | hashPtr(opt_ptr.container_ptr, hasher, mod); |
| 2869 | }, | 2900 | }, |
| 2870 | 2901 | ||
| 2871 | .zero, | 2902 | .zero, |
| ... | @@ -2880,7 +2911,7 @@ pub const Value = extern union { | ... | @@ -2880,7 +2911,7 @@ pub const Value = extern union { |
| 2880 | .the_only_possible_value, | 2911 | .the_only_possible_value, |
| 2881 | .lazy_align, | 2912 | .lazy_align, |
| 2882 | .lazy_size, | 2913 | .lazy_size, |
| 2883 | => return hashInt(ptr_val, hasher, target), | 2914 | => return hashInt(ptr_val, hasher, mod), |
| 2884 | 2915 | ||
| 2885 | else => unreachable, | 2916 | else => unreachable, |
| 2886 | } | 2917 | } |
| ... | @@ -2897,11 +2928,11 @@ pub const Value = extern union { | ... | @@ -2897,11 +2928,11 @@ pub const Value = extern union { |
| 2897 | 2928 | ||
| 2898 | pub fn sliceLen(val: Value, mod: *Module) u64 { | 2929 | pub fn sliceLen(val: Value, mod: *Module) u64 { |
| 2899 | return switch (val.tag()) { | 2930 | return switch (val.tag()) { |
| 2900 | .slice => val.castTag(.slice).?.data.len.toUnsignedInt(mod.getTarget()), | 2931 | .slice => val.castTag(.slice).?.data.len.toUnsignedInt(mod), |
| 2901 | .decl_ref => { | 2932 | .decl_ref => { |
| 2902 | const decl_index = val.castTag(.decl_ref).?.data; | 2933 | const decl_index = val.castTag(.decl_ref).?.data; |
| 2903 | const decl = mod.declPtr(decl_index); | 2934 | const decl = mod.declPtr(decl_index); |
| 2904 | if (decl.ty.zigTypeTag() == .Array) { | 2935 | if (decl.ty.zigTypeTag(mod) == .Array) { |
| 2905 | return decl.ty.arrayLen(); | 2936 | return decl.ty.arrayLen(); |
| 2906 | } else { | 2937 | } else { |
| 2907 | return 1; | 2938 | return 1; |
| ... | @@ -2910,7 +2941,7 @@ pub const Value = extern union { | ... | @@ -2910,7 +2941,7 @@ pub const Value = extern union { |
| 2910 | .decl_ref_mut => { | 2941 | .decl_ref_mut => { |
| 2911 | const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index; | 2942 | const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index; |
| 2912 | const decl = mod.declPtr(decl_index); | 2943 | const decl = mod.declPtr(decl_index); |
| 2913 | if (decl.ty.zigTypeTag() == .Array) { | 2944 | if (decl.ty.zigTypeTag(mod) == .Array) { |
| 2914 | return decl.ty.arrayLen(); | 2945 | return decl.ty.arrayLen(); |
| 2915 | } else { | 2946 | } else { |
| 2916 | return 1; | 2947 | return 1; |
| ... | @@ -2918,7 +2949,7 @@ pub const Value = extern union { | ... | @@ -2918,7 +2949,7 @@ pub const Value = extern union { |
| 2918 | }, | 2949 | }, |
| 2919 | .comptime_field_ptr => { | 2950 | .comptime_field_ptr => { |
| 2920 | const payload = val.castTag(.comptime_field_ptr).?.data; | 2951 | const payload = val.castTag(.comptime_field_ptr).?.data; |
| 2921 | if (payload.field_ty.zigTypeTag() == .Array) { | 2952 | if (payload.field_ty.zigTypeTag(mod) == .Array) { |
| 2922 | return payload.field_ty.arrayLen(); | 2953 | return payload.field_ty.arrayLen(); |
| 2923 | } else { | 2954 | } else { |
| 2924 | return 1; | 2955 | return 1; |
| ... | @@ -3003,7 +3034,7 @@ pub const Value = extern union { | ... | @@ -3003,7 +3034,7 @@ pub const Value = extern union { |
| 3003 | if (data.container_ptr.pointerDecl()) |decl_index| { | 3034 | if (data.container_ptr.pointerDecl()) |decl_index| { |
| 3004 | const container_decl = mod.declPtr(decl_index); | 3035 | const container_decl = mod.declPtr(decl_index); |
| 3005 | const field_type = data.container_ty.structFieldType(data.field_index); | 3036 | const field_type = data.container_ty.structFieldType(data.field_index); |
| 3006 | const field_val = container_decl.val.fieldValue(field_type, data.field_index); | 3037 | const field_val = container_decl.val.fieldValue(field_type, mod, data.field_index); |
| 3007 | return field_val.elemValueAdvanced(mod, index, arena, buffer); | 3038 | return field_val.elemValueAdvanced(mod, index, arena, buffer); |
| 3008 | } else unreachable; | 3039 | } else unreachable; |
| 3009 | }, | 3040 | }, |
| ... | @@ -3032,10 +3063,7 @@ pub const Value = extern union { | ... | @@ -3032,10 +3063,7 @@ pub const Value = extern union { |
| 3032 | } | 3063 | } |
| 3033 | 3064 | ||
| 3034 | /// Returns true if a Value is backed by a variable | 3065 | /// Returns true if a Value is backed by a variable |
| 3035 | pub fn isVariable( | 3066 | pub fn isVariable(val: Value, mod: *Module) bool { |
| 3036 | val: Value, | ||
| 3037 | mod: *Module, | ||
| 3038 | ) bool { | ||
| 3039 | return switch (val.tag()) { | 3067 | return switch (val.tag()) { |
| 3040 | .slice => val.castTag(.slice).?.data.ptr.isVariable(mod), | 3068 | .slice => val.castTag(.slice).?.data.ptr.isVariable(mod), |
| 3041 | .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod), | 3069 | .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod), |
| ... | @@ -3119,7 +3147,7 @@ pub const Value = extern union { | ... | @@ -3119,7 +3147,7 @@ pub const Value = extern union { |
| 3119 | }; | 3147 | }; |
| 3120 | } | 3148 | } |
| 3121 | 3149 | ||
| 3122 | pub fn fieldValue(val: Value, ty: Type, index: usize) Value { | 3150 | pub fn fieldValue(val: Value, ty: Type, mod: *const Module, index: usize) Value { |
| 3123 | switch (val.tag()) { | 3151 | switch (val.tag()) { |
| 3124 | .aggregate => { | 3152 | .aggregate => { |
| 3125 | const field_values = val.castTag(.aggregate).?.data; | 3153 | const field_values = val.castTag(.aggregate).?.data; |
| ... | @@ -3131,14 +3159,14 @@ pub const Value = extern union { | ... | @@ -3131,14 +3159,14 @@ pub const Value = extern union { |
| 3131 | return payload.val; | 3159 | return payload.val; |
| 3132 | }, | 3160 | }, |
| 3133 | 3161 | ||
| 3134 | .the_only_possible_value => return ty.onePossibleValue().?, | 3162 | .the_only_possible_value => return ty.onePossibleValue(mod).?, |
| 3135 | 3163 | ||
| 3136 | .empty_struct_value => { | 3164 | .empty_struct_value => { |
| 3137 | if (ty.isSimpleTupleOrAnonStruct()) { | 3165 | if (ty.isSimpleTupleOrAnonStruct()) { |
| 3138 | const tuple = ty.tupleFields(); | 3166 | const tuple = ty.tupleFields(); |
| 3139 | return tuple.values[index]; | 3167 | return tuple.values[index]; |
| 3140 | } | 3168 | } |
| 3141 | if (ty.structFieldValueComptime(index)) |some| { | 3169 | if (ty.structFieldValueComptime(mod, index)) |some| { |
| 3142 | return some; | 3170 | return some; |
| 3143 | } | 3171 | } |
| 3144 | unreachable; | 3172 | unreachable; |
| ... | @@ -3165,7 +3193,7 @@ pub const Value = extern union { | ... | @@ -3165,7 +3193,7 @@ pub const Value = extern union { |
| 3165 | index: usize, | 3193 | index: usize, |
| 3166 | mod: *Module, | 3194 | mod: *Module, |
| 3167 | ) Allocator.Error!Value { | 3195 | ) Allocator.Error!Value { |
| 3168 | const elem_ty = ty.elemType2(); | 3196 | const elem_ty = ty.elemType2(mod); |
| 3169 | const ptr_val = switch (val.tag()) { | 3197 | const ptr_val = switch (val.tag()) { |
| 3170 | .slice => val.castTag(.slice).?.data.ptr, | 3198 | .slice => val.castTag(.slice).?.data.ptr, |
| 3171 | else => val, | 3199 | else => val, |
| ... | @@ -3207,7 +3235,7 @@ pub const Value = extern union { | ... | @@ -3207,7 +3235,7 @@ pub const Value = extern union { |
| 3207 | switch (self.tag()) { | 3235 | switch (self.tag()) { |
| 3208 | .slice => { | 3236 | .slice => { |
| 3209 | const payload = self.castTag(.slice).?; | 3237 | const payload = self.castTag(.slice).?; |
| 3210 | const len = payload.data.len.toUnsignedInt(mod.getTarget()); | 3238 | const len = payload.data.len.toUnsignedInt(mod); |
| 3211 | 3239 | ||
| 3212 | var elem_value_buf: ElemValueBuffer = undefined; | 3240 | var elem_value_buf: ElemValueBuffer = undefined; |
| 3213 | var i: usize = 0; | 3241 | var i: usize = 0; |
| ... | @@ -3233,7 +3261,7 @@ pub const Value = extern union { | ... | @@ -3233,7 +3261,7 @@ pub const Value = extern union { |
| 3233 | 3261 | ||
| 3234 | /// Asserts the value is not undefined and not unreachable. | 3262 | /// Asserts the value is not undefined and not unreachable. |
| 3235 | /// Integer value 0 is considered null because of C pointers. | 3263 | /// Integer value 0 is considered null because of C pointers. |
| 3236 | pub fn isNull(self: Value) bool { | 3264 | pub fn isNull(self: Value, mod: *const Module) bool { |
| 3237 | return switch (self.tag()) { | 3265 | return switch (self.tag()) { |
| 3238 | .null_value => true, | 3266 | .null_value => true, |
| 3239 | .opt_payload => false, | 3267 | .opt_payload => false, |
| ... | @@ -3254,7 +3282,7 @@ pub const Value = extern union { | ... | @@ -3254,7 +3282,7 @@ pub const Value = extern union { |
| 3254 | .int_i64, | 3282 | .int_i64, |
| 3255 | .int_big_positive, | 3283 | .int_big_positive, |
| 3256 | .int_big_negative, | 3284 | .int_big_negative, |
| 3257 | => self.orderAgainstZero().compare(.eq), | 3285 | => self.orderAgainstZero(mod).compare(.eq), |
| 3258 | 3286 | ||
| 3259 | .undef => unreachable, | 3287 | .undef => unreachable, |
| 3260 | .unreachable_value => unreachable, | 3288 | .unreachable_value => unreachable, |
| ... | @@ -3300,8 +3328,8 @@ pub const Value = extern union { | ... | @@ -3300,8 +3328,8 @@ pub const Value = extern union { |
| 3300 | } | 3328 | } |
| 3301 | 3329 | ||
| 3302 | /// Value of the optional, null if optional has no payload. | 3330 | /// Value of the optional, null if optional has no payload. |
| 3303 | pub fn optionalValue(val: Value) ?Value { | 3331 | pub fn optionalValue(val: Value, mod: *const Module) ?Value { |
| 3304 | if (val.isNull()) return null; | 3332 | if (val.isNull(mod)) return null; |
| 3305 | 3333 | ||
| 3306 | // Valid for optional representation to be the direct value | 3334 | // Valid for optional representation to be the direct value |
| 3307 | // and not use opt_payload. | 3335 | // and not use opt_payload. |
| ... | @@ -3333,20 +3361,20 @@ pub const Value = extern union { | ... | @@ -3333,20 +3361,20 @@ pub const Value = extern union { |
| 3333 | } | 3361 | } |
| 3334 | 3362 | ||
| 3335 | pub fn intToFloatAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value { | 3363 | pub fn intToFloatAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value { |
| 3336 | const target = mod.getTarget(); | 3364 | if (int_ty.zigTypeTag(mod) == .Vector) { |
| 3337 | if (int_ty.zigTypeTag() == .Vector) { | ||
| 3338 | const result_data = try arena.alloc(Value, int_ty.vectorLen()); | 3365 | const result_data = try arena.alloc(Value, int_ty.vectorLen()); |
| 3339 | for (result_data, 0..) |*scalar, i| { | 3366 | for (result_data, 0..) |*scalar, i| { |
| 3340 | var buf: Value.ElemValueBuffer = undefined; | 3367 | var buf: Value.ElemValueBuffer = undefined; |
| 3341 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 3368 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 3342 | scalar.* = try intToFloatScalar(elem_val, arena, float_ty.scalarType(), target, opt_sema); | 3369 | scalar.* = try intToFloatScalar(elem_val, arena, float_ty.scalarType(mod), mod, opt_sema); |
| 3343 | } | 3370 | } |
| 3344 | return Value.Tag.aggregate.create(arena, result_data); | 3371 | return Value.Tag.aggregate.create(arena, result_data); |
| 3345 | } | 3372 | } |
| 3346 | return intToFloatScalar(val, arena, float_ty, target, opt_sema); | 3373 | return intToFloatScalar(val, arena, float_ty, mod, opt_sema); |
| 3347 | } | 3374 | } |
| 3348 | 3375 | ||
| 3349 | pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, target: Target, opt_sema: ?*Sema) !Value { | 3376 | pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value { |
| 3377 | const target = mod.getTarget(); | ||
| 3350 | switch (val.tag()) { | 3378 | switch (val.tag()) { |
| 3351 | .undef, .zero, .one => return val, | 3379 | .undef, .zero, .one => return val, |
| 3352 | .the_only_possible_value => return Value.initTag(.zero), // for i0, u0 | 3380 | .the_only_possible_value => return Value.initTag(.zero), // for i0, u0 |
| ... | @@ -3369,17 +3397,17 @@ pub const Value = extern union { | ... | @@ -3369,17 +3397,17 @@ pub const Value = extern union { |
| 3369 | .lazy_align => { | 3397 | .lazy_align => { |
| 3370 | const ty = val.castTag(.lazy_align).?.data; | 3398 | const ty = val.castTag(.lazy_align).?.data; |
| 3371 | if (opt_sema) |sema| { | 3399 | if (opt_sema) |sema| { |
| 3372 | return intToFloatInner((try ty.abiAlignmentAdvanced(target, .{ .sema = sema })).scalar, arena, float_ty, target); | 3400 | return intToFloatInner((try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target); |
| 3373 | } else { | 3401 | } else { |
| 3374 | return intToFloatInner(ty.abiAlignment(target), arena, float_ty, target); | 3402 | return intToFloatInner(ty.abiAlignment(mod), arena, float_ty, target); |
| 3375 | } | 3403 | } |
| 3376 | }, | 3404 | }, |
| 3377 | .lazy_size => { | 3405 | .lazy_size => { |
| 3378 | const ty = val.castTag(.lazy_size).?.data; | 3406 | const ty = val.castTag(.lazy_size).?.data; |
| 3379 | if (opt_sema) |sema| { | 3407 | if (opt_sema) |sema| { |
| 3380 | return intToFloatInner((try ty.abiSizeAdvanced(target, .{ .sema = sema })).scalar, arena, float_ty, target); | 3408 | return intToFloatInner((try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target); |
| 3381 | } else { | 3409 | } else { |
| 3382 | return intToFloatInner(ty.abiSize(target), arena, float_ty, target); | 3410 | return intToFloatInner(ty.abiSize(mod), arena, float_ty, target); |
| 3383 | } | 3411 | } |
| 3384 | }, | 3412 | }, |
| 3385 | else => unreachable, | 3413 | else => unreachable, |
| ... | @@ -3446,19 +3474,18 @@ pub const Value = extern union { | ... | @@ -3446,19 +3474,18 @@ pub const Value = extern union { |
| 3446 | arena: Allocator, | 3474 | arena: Allocator, |
| 3447 | mod: *Module, | 3475 | mod: *Module, |
| 3448 | ) !Value { | 3476 | ) !Value { |
| 3449 | const target = mod.getTarget(); | 3477 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3450 | if (ty.zigTypeTag() == .Vector) { | ||
| 3451 | const result_data = try arena.alloc(Value, ty.vectorLen()); | 3478 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| 3452 | for (result_data, 0..) |*scalar, i| { | 3479 | for (result_data, 0..) |*scalar, i| { |
| 3453 | var lhs_buf: Value.ElemValueBuffer = undefined; | 3480 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 3454 | var rhs_buf: Value.ElemValueBuffer = undefined; | 3481 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3455 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 3482 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3456 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 3483 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3457 | scalar.* = try intAddSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target); | 3484 | scalar.* = try intAddSatScalar(lhs_elem, rhs_elem, ty.scalarType(mod), arena, mod); |
| 3458 | } | 3485 | } |
| 3459 | return Value.Tag.aggregate.create(arena, result_data); | 3486 | return Value.Tag.aggregate.create(arena, result_data); |
| 3460 | } | 3487 | } |
| 3461 | return intAddSatScalar(lhs, rhs, ty, arena, target); | 3488 | return intAddSatScalar(lhs, rhs, ty, arena, mod); |
| 3462 | } | 3489 | } |
| 3463 | 3490 | ||
| 3464 | /// Supports integers only; asserts neither operand is undefined. | 3491 | /// Supports integers only; asserts neither operand is undefined. |
| ... | @@ -3467,17 +3494,17 @@ pub const Value = extern union { | ... | @@ -3467,17 +3494,17 @@ pub const Value = extern union { |
| 3467 | rhs: Value, | 3494 | rhs: Value, |
| 3468 | ty: Type, | 3495 | ty: Type, |
| 3469 | arena: Allocator, | 3496 | arena: Allocator, |
| 3470 | target: Target, | 3497 | mod: *Module, |
| 3471 | ) !Value { | 3498 | ) !Value { |
| 3472 | assert(!lhs.isUndef()); | 3499 | assert(!lhs.isUndef()); |
| 3473 | assert(!rhs.isUndef()); | 3500 | assert(!rhs.isUndef()); |
| 3474 | 3501 | ||
| 3475 | const info = ty.intInfo(target); | 3502 | const info = ty.intInfo(mod); |
| 3476 | 3503 | ||
| 3477 | var lhs_space: Value.BigIntSpace = undefined; | 3504 | var lhs_space: Value.BigIntSpace = undefined; |
| 3478 | var rhs_space: Value.BigIntSpace = undefined; | 3505 | var rhs_space: Value.BigIntSpace = undefined; |
| 3479 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 3506 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 3480 | const rhs_bigint = rhs.toBigInt(&rhs_space, target); | 3507 | const rhs_bigint = rhs.toBigInt(&rhs_space, mod); |
| 3481 | const limbs = try arena.alloc( | 3508 | const limbs = try arena.alloc( |
| 3482 | std.math.big.Limb, | 3509 | std.math.big.Limb, |
| 3483 | std.math.big.int.calcTwosCompLimbCount(info.bits), | 3510 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| ... | @@ -3495,19 +3522,18 @@ pub const Value = extern union { | ... | @@ -3495,19 +3522,18 @@ pub const Value = extern union { |
| 3495 | arena: Allocator, | 3522 | arena: Allocator, |
| 3496 | mod: *Module, | 3523 | mod: *Module, |
| 3497 | ) !Value { | 3524 | ) !Value { |
| 3498 | const target = mod.getTarget(); | 3525 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3499 | if (ty.zigTypeTag() == .Vector) { | ||
| 3500 | const result_data = try arena.alloc(Value, ty.vectorLen()); | 3526 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| 3501 | for (result_data, 0..) |*scalar, i| { | 3527 | for (result_data, 0..) |*scalar, i| { |
| 3502 | var lhs_buf: Value.ElemValueBuffer = undefined; | 3528 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 3503 | var rhs_buf: Value.ElemValueBuffer = undefined; | 3529 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3504 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 3530 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3505 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 3531 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3506 | scalar.* = try intSubSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target); | 3532 | scalar.* = try intSubSatScalar(lhs_elem, rhs_elem, ty.scalarType(mod), arena, mod); |
| 3507 | } | 3533 | } |
| 3508 | return Value.Tag.aggregate.create(arena, result_data); | 3534 | return Value.Tag.aggregate.create(arena, result_data); |
| 3509 | } | 3535 | } |
| 3510 | return intSubSatScalar(lhs, rhs, ty, arena, target); | 3536 | return intSubSatScalar(lhs, rhs, ty, arena, mod); |
| 3511 | } | 3537 | } |
| 3512 | 3538 | ||
| 3513 | /// Supports integers only; asserts neither operand is undefined. | 3539 | /// Supports integers only; asserts neither operand is undefined. |
| ... | @@ -3516,17 +3542,17 @@ pub const Value = extern union { | ... | @@ -3516,17 +3542,17 @@ pub const Value = extern union { |
| 3516 | rhs: Value, | 3542 | rhs: Value, |
| 3517 | ty: Type, | 3543 | ty: Type, |
| 3518 | arena: Allocator, | 3544 | arena: Allocator, |
| 3519 | target: Target, | 3545 | mod: *Module, |
| 3520 | ) !Value { | 3546 | ) !Value { |
| 3521 | assert(!lhs.isUndef()); | 3547 | assert(!lhs.isUndef()); |
| 3522 | assert(!rhs.isUndef()); | 3548 | assert(!rhs.isUndef()); |
| 3523 | 3549 | ||
| 3524 | const info = ty.intInfo(target); | 3550 | const info = ty.intInfo(mod); |
| 3525 | 3551 | ||
| 3526 | var lhs_space: Value.BigIntSpace = undefined; | 3552 | var lhs_space: Value.BigIntSpace = undefined; |
| 3527 | var rhs_space: Value.BigIntSpace = undefined; | 3553 | var rhs_space: Value.BigIntSpace = undefined; |
| 3528 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 3554 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 3529 | const rhs_bigint = rhs.toBigInt(&rhs_space, target); | 3555 | const rhs_bigint = rhs.toBigInt(&rhs_space, mod); |
| 3530 | const limbs = try arena.alloc( | 3556 | const limbs = try arena.alloc( |
| 3531 | std.math.big.Limb, | 3557 | std.math.big.Limb, |
| 3532 | std.math.big.int.calcTwosCompLimbCount(info.bits), | 3558 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| ... | @@ -3543,8 +3569,7 @@ pub const Value = extern union { | ... | @@ -3543,8 +3569,7 @@ pub const Value = extern union { |
| 3543 | arena: Allocator, | 3569 | arena: Allocator, |
| 3544 | mod: *Module, | 3570 | mod: *Module, |
| 3545 | ) !OverflowArithmeticResult { | 3571 | ) !OverflowArithmeticResult { |
| 3546 | const target = mod.getTarget(); | 3572 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3547 | if (ty.zigTypeTag() == .Vector) { | ||
| 3548 | const overflowed_data = try arena.alloc(Value, ty.vectorLen()); | 3573 | const overflowed_data = try arena.alloc(Value, ty.vectorLen()); |
| 3549 | const result_data = try arena.alloc(Value, ty.vectorLen()); | 3574 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| 3550 | for (result_data, 0..) |*scalar, i| { | 3575 | for (result_data, 0..) |*scalar, i| { |
| ... | @@ -3552,7 +3577,7 @@ pub const Value = extern union { | ... | @@ -3552,7 +3577,7 @@ pub const Value = extern union { |
| 3552 | var rhs_buf: Value.ElemValueBuffer = undefined; | 3577 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3553 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 3578 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3554 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 3579 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3555 | const of_math_result = try intMulWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target); | 3580 | const of_math_result = try intMulWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(mod), arena, mod); |
| 3556 | overflowed_data[i] = of_math_result.overflow_bit; | 3581 | overflowed_data[i] = of_math_result.overflow_bit; |
| 3557 | scalar.* = of_math_result.wrapped_result; | 3582 | scalar.* = of_math_result.wrapped_result; |
| 3558 | } | 3583 | } |
| ... | @@ -3561,7 +3586,7 @@ pub const Value = extern union { | ... | @@ -3561,7 +3586,7 @@ pub const Value = extern union { |
| 3561 | .wrapped_result = try Value.Tag.aggregate.create(arena, result_data), | 3586 | .wrapped_result = try Value.Tag.aggregate.create(arena, result_data), |
| 3562 | }; | 3587 | }; |
| 3563 | } | 3588 | } |
| 3564 | return intMulWithOverflowScalar(lhs, rhs, ty, arena, target); | 3589 | return intMulWithOverflowScalar(lhs, rhs, ty, arena, mod); |
| 3565 | } | 3590 | } |
| 3566 | 3591 | ||
| 3567 | pub fn intMulWithOverflowScalar( | 3592 | pub fn intMulWithOverflowScalar( |
| ... | @@ -3569,14 +3594,14 @@ pub const Value = extern union { | ... | @@ -3569,14 +3594,14 @@ pub const Value = extern union { |
| 3569 | rhs: Value, | 3594 | rhs: Value, |
| 3570 | ty: Type, | 3595 | ty: Type, |
| 3571 | arena: Allocator, | 3596 | arena: Allocator, |
| 3572 | target: Target, | 3597 | mod: *Module, |
| 3573 | ) !OverflowArithmeticResult { | 3598 | ) !OverflowArithmeticResult { |
| 3574 | const info = ty.intInfo(target); | 3599 | const info = ty.intInfo(mod); |
| 3575 | 3600 | ||
| 3576 | var lhs_space: Value.BigIntSpace = undefined; | 3601 | var lhs_space: Value.BigIntSpace = undefined; |
| 3577 | var rhs_space: Value.BigIntSpace = undefined; | 3602 | var rhs_space: Value.BigIntSpace = undefined; |
| 3578 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 3603 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 3579 | const rhs_bigint = rhs.toBigInt(&rhs_space, target); | 3604 | const rhs_bigint = rhs.toBigInt(&rhs_space, mod); |
| 3580 | const limbs = try arena.alloc( | 3605 | const limbs = try arena.alloc( |
| 3581 | std.math.big.Limb, | 3606 | std.math.big.Limb, |
| 3582 | lhs_bigint.limbs.len + rhs_bigint.limbs.len, | 3607 | lhs_bigint.limbs.len + rhs_bigint.limbs.len, |
| ... | @@ -3607,14 +3632,14 @@ pub const Value = extern union { | ... | @@ -3607,14 +3632,14 @@ pub const Value = extern union { |
| 3607 | arena: Allocator, | 3632 | arena: Allocator, |
| 3608 | mod: *Module, | 3633 | mod: *Module, |
| 3609 | ) !Value { | 3634 | ) !Value { |
| 3610 | if (ty.zigTypeTag() == .Vector) { | 3635 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3611 | const result_data = try arena.alloc(Value, ty.vectorLen()); | 3636 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| 3612 | for (result_data, 0..) |*scalar, i| { | 3637 | for (result_data, 0..) |*scalar, i| { |
| 3613 | var lhs_buf: Value.ElemValueBuffer = undefined; | 3638 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 3614 | var rhs_buf: Value.ElemValueBuffer = undefined; | 3639 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3615 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 3640 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3616 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 3641 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3617 | scalar.* = try numberMulWrapScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, mod); | 3642 | scalar.* = try numberMulWrapScalar(lhs_elem, rhs_elem, ty.scalarType(mod), arena, mod); |
| 3618 | } | 3643 | } |
| 3619 | return Value.Tag.aggregate.create(arena, result_data); | 3644 | return Value.Tag.aggregate.create(arena, result_data); |
| 3620 | } | 3645 | } |
| ... | @@ -3631,7 +3656,7 @@ pub const Value = extern union { | ... | @@ -3631,7 +3656,7 @@ pub const Value = extern union { |
| 3631 | ) !Value { | 3656 | ) !Value { |
| 3632 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 3657 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 3633 | 3658 | ||
| 3634 | if (ty.zigTypeTag() == .ComptimeInt) { | 3659 | if (ty.zigTypeTag(mod) == .ComptimeInt) { |
| 3635 | return intMul(lhs, rhs, ty, arena, mod); | 3660 | return intMul(lhs, rhs, ty, arena, mod); |
| 3636 | } | 3661 | } |
| 3637 | 3662 | ||
| ... | @@ -3651,19 +3676,18 @@ pub const Value = extern union { | ... | @@ -3651,19 +3676,18 @@ pub const Value = extern union { |
| 3651 | arena: Allocator, | 3676 | arena: Allocator, |
| 3652 | mod: *Module, | 3677 | mod: *Module, |
| 3653 | ) !Value { | 3678 | ) !Value { |
| 3654 | const target = mod.getTarget(); | 3679 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3655 | if (ty.zigTypeTag() == .Vector) { | ||
| 3656 | const result_data = try arena.alloc(Value, ty.vectorLen()); | 3680 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| 3657 | for (result_data, 0..) |*scalar, i| { | 3681 | for (result_data, 0..) |*scalar, i| { |
| 3658 | var lhs_buf: Value.ElemValueBuffer = undefined; | 3682 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 3659 | var rhs_buf: Value.ElemValueBuffer = undefined; | 3683 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3660 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 3684 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3661 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 3685 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3662 | scalar.* = try intMulSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target); | 3686 | scalar.* = try intMulSatScalar(lhs_elem, rhs_elem, ty.scalarType(mod), arena, mod); |
| 3663 | } | 3687 | } |
| 3664 | return Value.Tag.aggregate.create(arena, result_data); | 3688 | return Value.Tag.aggregate.create(arena, result_data); |
| 3665 | } | 3689 | } |
| 3666 | return intMulSatScalar(lhs, rhs, ty, arena, target); | 3690 | return intMulSatScalar(lhs, rhs, ty, arena, mod); |
| 3667 | } | 3691 | } |
| 3668 | 3692 | ||
| 3669 | /// Supports (vectors of) integers only; asserts neither operand is undefined. | 3693 | /// Supports (vectors of) integers only; asserts neither operand is undefined. |
| ... | @@ -3672,17 +3696,17 @@ pub const Value = extern union { | ... | @@ -3672,17 +3696,17 @@ pub const Value = extern union { |
| 3672 | rhs: Value, | 3696 | rhs: Value, |
| 3673 | ty: Type, | 3697 | ty: Type, |
| 3674 | arena: Allocator, | 3698 | arena: Allocator, |
| 3675 | target: Target, | 3699 | mod: *Module, |
| 3676 | ) !Value { | 3700 | ) !Value { |
| 3677 | assert(!lhs.isUndef()); | 3701 | assert(!lhs.isUndef()); |
| 3678 | assert(!rhs.isUndef()); | 3702 | assert(!rhs.isUndef()); |
| 3679 | 3703 | ||
| 3680 | const info = ty.intInfo(target); | 3704 | const info = ty.intInfo(mod); |
| 3681 | 3705 | ||
| 3682 | var lhs_space: Value.BigIntSpace = undefined; | 3706 | var lhs_space: Value.BigIntSpace = undefined; |
| 3683 | var rhs_space: Value.BigIntSpace = undefined; | 3707 | var rhs_space: Value.BigIntSpace = undefined; |
| 3684 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 3708 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 3685 | const rhs_bigint = rhs.toBigInt(&rhs_space, target); | 3709 | const rhs_bigint = rhs.toBigInt(&rhs_space, mod); |
| 3686 | const limbs = try arena.alloc( | 3710 | const limbs = try arena.alloc( |
| 3687 | std.math.big.Limb, | 3711 | std.math.big.Limb, |
| 3688 | std.math.max( | 3712 | std.math.max( |
| ... | @@ -3702,24 +3726,24 @@ pub const Value = extern union { | ... | @@ -3702,24 +3726,24 @@ pub const Value = extern union { |
| 3702 | } | 3726 | } |
| 3703 | 3727 | ||
| 3704 | /// Supports both floats and ints; handles undefined. | 3728 | /// Supports both floats and ints; handles undefined. |
| 3705 | pub fn numberMax(lhs: Value, rhs: Value, target: Target) Value { | 3729 | pub fn numberMax(lhs: Value, rhs: Value, mod: *Module) Value { |
| 3706 | if (lhs.isUndef() or rhs.isUndef()) return undef; | 3730 | if (lhs.isUndef() or rhs.isUndef()) return undef; |
| 3707 | if (lhs.isNan()) return rhs; | 3731 | if (lhs.isNan()) return rhs; |
| 3708 | if (rhs.isNan()) return lhs; | 3732 | if (rhs.isNan()) return lhs; |
| 3709 | 3733 | ||
| 3710 | return switch (order(lhs, rhs, target)) { | 3734 | return switch (order(lhs, rhs, mod)) { |
| 3711 | .lt => rhs, | 3735 | .lt => rhs, |
| 3712 | .gt, .eq => lhs, | 3736 | .gt, .eq => lhs, |
| 3713 | }; | 3737 | }; |
| 3714 | } | 3738 | } |
| 3715 | 3739 | ||
| 3716 | /// Supports both floats and ints; handles undefined. | 3740 | /// Supports both floats and ints; handles undefined. |
| 3717 | pub fn numberMin(lhs: Value, rhs: Value, target: Target) Value { | 3741 | pub fn numberMin(lhs: Value, rhs: Value, mod: *Module) Value { |
| 3718 | if (lhs.isUndef() or rhs.isUndef()) return undef; | 3742 | if (lhs.isUndef() or rhs.isUndef()) return undef; |
| 3719 | if (lhs.isNan()) return rhs; | 3743 | if (lhs.isNan()) return rhs; |
| 3720 | if (rhs.isNan()) return lhs; | 3744 | if (rhs.isNan()) return lhs; |
| 3721 | 3745 | ||
| 3722 | return switch (order(lhs, rhs, target)) { | 3746 | return switch (order(lhs, rhs, mod)) { |
| 3723 | .lt => lhs, | 3747 | .lt => lhs, |
| 3724 | .gt, .eq => rhs, | 3748 | .gt, .eq => rhs, |
| 3725 | }; | 3749 | }; |
| ... | @@ -3727,24 +3751,23 @@ pub const Value = extern union { | ... | @@ -3727,24 +3751,23 @@ pub const Value = extern union { |
| 3727 | 3751 | ||
| 3728 | /// operands must be (vectors of) integers; handles undefined scalars. | 3752 | /// operands must be (vectors of) integers; handles undefined scalars. |
| 3729 | pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value { | 3753 | pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value { |
| 3730 | const target = mod.getTarget(); | 3754 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3731 | if (ty.zigTypeTag() == .Vector) { | ||
| 3732 | const result_data = try arena.alloc(Value, ty.vectorLen()); | 3755 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| 3733 | for (result_data, 0..) |*scalar, i| { | 3756 | for (result_data, 0..) |*scalar, i| { |
| 3734 | var buf: Value.ElemValueBuffer = undefined; | 3757 | var buf: Value.ElemValueBuffer = undefined; |
| 3735 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 3758 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 3736 | scalar.* = try bitwiseNotScalar(elem_val, ty.scalarType(), arena, target); | 3759 | scalar.* = try bitwiseNotScalar(elem_val, ty.scalarType(mod), arena, mod); |
| 3737 | } | 3760 | } |
| 3738 | return Value.Tag.aggregate.create(arena, result_data); | 3761 | return Value.Tag.aggregate.create(arena, result_data); |
| 3739 | } | 3762 | } |
| 3740 | return bitwiseNotScalar(val, ty, arena, target); | 3763 | return bitwiseNotScalar(val, ty, arena, mod); |
| 3741 | } | 3764 | } |
| 3742 | 3765 | ||
| 3743 | /// operands must be integers; handles undefined. | 3766 | /// operands must be integers; handles undefined. |
| 3744 | pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, target: Target) !Value { | 3767 | pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value { |
| 3745 | if (val.isUndef()) return Value.initTag(.undef); | 3768 | if (val.isUndef()) return Value.initTag(.undef); |
| 3746 | 3769 | ||
| 3747 | const info = ty.intInfo(target); | 3770 | const info = ty.intInfo(mod); |
| 3748 | 3771 | ||
| 3749 | if (info.bits == 0) { | 3772 | if (info.bits == 0) { |
| 3750 | return val; | 3773 | return val; |
| ... | @@ -3753,7 +3776,7 @@ pub const Value = extern union { | ... | @@ -3753,7 +3776,7 @@ pub const Value = extern union { |
| 3753 | // TODO is this a performance issue? maybe we should try the operation without | 3776 | // TODO is this a performance issue? maybe we should try the operation without |
| 3754 | // resorting to BigInt first. | 3777 | // resorting to BigInt first. |
| 3755 | var val_space: Value.BigIntSpace = undefined; | 3778 | var val_space: Value.BigIntSpace = undefined; |
| 3756 | const val_bigint = val.toBigInt(&val_space, target); | 3779 | const val_bigint = val.toBigInt(&val_space, mod); |
| 3757 | const limbs = try arena.alloc( | 3780 | const limbs = try arena.alloc( |
| 3758 | std.math.big.Limb, | 3781 | std.math.big.Limb, |
| 3759 | std.math.big.int.calcTwosCompLimbCount(info.bits), | 3782 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| ... | @@ -3766,31 +3789,30 @@ pub const Value = extern union { | ... | @@ -3766,31 +3789,30 @@ pub const Value = extern union { |
| 3766 | 3789 | ||
| 3767 | /// operands must be (vectors of) integers; handles undefined scalars. | 3790 | /// operands must be (vectors of) integers; handles undefined scalars. |
| 3768 | pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { | 3791 | pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { |
| 3769 | const target = mod.getTarget(); | 3792 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3770 | if (ty.zigTypeTag() == .Vector) { | ||
| 3771 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 3793 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 3772 | for (result_data, 0..) |*scalar, i| { | 3794 | for (result_data, 0..) |*scalar, i| { |
| 3773 | var lhs_buf: Value.ElemValueBuffer = undefined; | 3795 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 3774 | var rhs_buf: Value.ElemValueBuffer = undefined; | 3796 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3775 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 3797 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3776 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 3798 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3777 | scalar.* = try bitwiseAndScalar(lhs_elem, rhs_elem, allocator, target); | 3799 | scalar.* = try bitwiseAndScalar(lhs_elem, rhs_elem, allocator, mod); |
| 3778 | } | 3800 | } |
| 3779 | return Value.Tag.aggregate.create(allocator, result_data); | 3801 | return Value.Tag.aggregate.create(allocator, result_data); |
| 3780 | } | 3802 | } |
| 3781 | return bitwiseAndScalar(lhs, rhs, allocator, target); | 3803 | return bitwiseAndScalar(lhs, rhs, allocator, mod); |
| 3782 | } | 3804 | } |
| 3783 | 3805 | ||
| 3784 | /// operands must be integers; handles undefined. | 3806 | /// operands must be integers; handles undefined. |
| 3785 | pub fn bitwiseAndScalar(lhs: Value, rhs: Value, arena: Allocator, target: Target) !Value { | 3807 | pub fn bitwiseAndScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value { |
| 3786 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 3808 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 3787 | 3809 | ||
| 3788 | // TODO is this a performance issue? maybe we should try the operation without | 3810 | // TODO is this a performance issue? maybe we should try the operation without |
| 3789 | // resorting to BigInt first. | 3811 | // resorting to BigInt first. |
| 3790 | var lhs_space: Value.BigIntSpace = undefined; | 3812 | var lhs_space: Value.BigIntSpace = undefined; |
| 3791 | var rhs_space: Value.BigIntSpace = undefined; | 3813 | var rhs_space: Value.BigIntSpace = undefined; |
| 3792 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 3814 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 3793 | const rhs_bigint = rhs.toBigInt(&rhs_space, target); | 3815 | const rhs_bigint = rhs.toBigInt(&rhs_space, mod); |
| 3794 | const limbs = try arena.alloc( | 3816 | const limbs = try arena.alloc( |
| 3795 | std.math.big.Limb, | 3817 | std.math.big.Limb, |
| 3796 | // + 1 for negatives | 3818 | // + 1 for negatives |
| ... | @@ -3803,14 +3825,14 @@ pub const Value = extern union { | ... | @@ -3803,14 +3825,14 @@ pub const Value = extern union { |
| 3803 | 3825 | ||
| 3804 | /// operands must be (vectors of) integers; handles undefined scalars. | 3826 | /// operands must be (vectors of) integers; handles undefined scalars. |
| 3805 | pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value { | 3827 | pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value { |
| 3806 | if (ty.zigTypeTag() == .Vector) { | 3828 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3807 | const result_data = try arena.alloc(Value, ty.vectorLen()); | 3829 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| 3808 | for (result_data, 0..) |*scalar, i| { | 3830 | for (result_data, 0..) |*scalar, i| { |
| 3809 | var lhs_buf: Value.ElemValueBuffer = undefined; | 3831 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 3810 | var rhs_buf: Value.ElemValueBuffer = undefined; | 3832 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3811 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 3833 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3812 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 3834 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3813 | scalar.* = try bitwiseNandScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, mod); | 3835 | scalar.* = try bitwiseNandScalar(lhs_elem, rhs_elem, ty.scalarType(mod), arena, mod); |
| 3814 | } | 3836 | } |
| 3815 | return Value.Tag.aggregate.create(arena, result_data); | 3837 | return Value.Tag.aggregate.create(arena, result_data); |
| 3816 | } | 3838 | } |
| ... | @@ -3823,41 +3845,40 @@ pub const Value = extern union { | ... | @@ -3823,41 +3845,40 @@ pub const Value = extern union { |
| 3823 | 3845 | ||
| 3824 | const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod); | 3846 | const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod); |
| 3825 | 3847 | ||
| 3826 | const all_ones = if (ty.isSignedInt()) | 3848 | const all_ones = if (ty.isSignedInt(mod)) |
| 3827 | try Value.Tag.int_i64.create(arena, -1) | 3849 | try Value.Tag.int_i64.create(arena, -1) |
| 3828 | else | 3850 | else |
| 3829 | try ty.maxInt(arena, mod.getTarget()); | 3851 | try ty.maxInt(arena, mod); |
| 3830 | 3852 | ||
| 3831 | return bitwiseXor(anded, all_ones, ty, arena, mod); | 3853 | return bitwiseXor(anded, all_ones, ty, arena, mod); |
| 3832 | } | 3854 | } |
| 3833 | 3855 | ||
| 3834 | /// operands must be (vectors of) integers; handles undefined scalars. | 3856 | /// operands must be (vectors of) integers; handles undefined scalars. |
| 3835 | pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { | 3857 | pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { |
| 3836 | const target = mod.getTarget(); | 3858 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3837 | if (ty.zigTypeTag() == .Vector) { | ||
| 3838 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 3859 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 3839 | for (result_data, 0..) |*scalar, i| { | 3860 | for (result_data, 0..) |*scalar, i| { |
| 3840 | var lhs_buf: Value.ElemValueBuffer = undefined; | 3861 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 3841 | var rhs_buf: Value.ElemValueBuffer = undefined; | 3862 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3842 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 3863 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3843 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 3864 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3844 | scalar.* = try bitwiseOrScalar(lhs_elem, rhs_elem, allocator, target); | 3865 | scalar.* = try bitwiseOrScalar(lhs_elem, rhs_elem, allocator, mod); |
| 3845 | } | 3866 | } |
| 3846 | return Value.Tag.aggregate.create(allocator, result_data); | 3867 | return Value.Tag.aggregate.create(allocator, result_data); |
| 3847 | } | 3868 | } |
| 3848 | return bitwiseOrScalar(lhs, rhs, allocator, target); | 3869 | return bitwiseOrScalar(lhs, rhs, allocator, mod); |
| 3849 | } | 3870 | } |
| 3850 | 3871 | ||
| 3851 | /// operands must be integers; handles undefined. | 3872 | /// operands must be integers; handles undefined. |
| 3852 | pub fn bitwiseOrScalar(lhs: Value, rhs: Value, arena: Allocator, target: Target) !Value { | 3873 | pub fn bitwiseOrScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value { |
| 3853 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 3874 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 3854 | 3875 | ||
| 3855 | // TODO is this a performance issue? maybe we should try the operation without | 3876 | // TODO is this a performance issue? maybe we should try the operation without |
| 3856 | // resorting to BigInt first. | 3877 | // resorting to BigInt first. |
| 3857 | var lhs_space: Value.BigIntSpace = undefined; | 3878 | var lhs_space: Value.BigIntSpace = undefined; |
| 3858 | var rhs_space: Value.BigIntSpace = undefined; | 3879 | var rhs_space: Value.BigIntSpace = undefined; |
| 3859 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 3880 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 3860 | const rhs_bigint = rhs.toBigInt(&rhs_space, target); | 3881 | const rhs_bigint = rhs.toBigInt(&rhs_space, mod); |
| 3861 | const limbs = try arena.alloc( | 3882 | const limbs = try arena.alloc( |
| 3862 | std.math.big.Limb, | 3883 | std.math.big.Limb, |
| 3863 | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len), | 3884 | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len), |
| ... | @@ -3869,31 +3890,30 @@ pub const Value = extern union { | ... | @@ -3869,31 +3890,30 @@ pub const Value = extern union { |
| 3869 | 3890 | ||
| 3870 | /// operands must be (vectors of) integers; handles undefined scalars. | 3891 | /// operands must be (vectors of) integers; handles undefined scalars. |
| 3871 | pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { | 3892 | pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { |
| 3872 | const target = mod.getTarget(); | 3893 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3873 | if (ty.zigTypeTag() == .Vector) { | ||
| 3874 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 3894 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 3875 | for (result_data, 0..) |*scalar, i| { | 3895 | for (result_data, 0..) |*scalar, i| { |
| 3876 | var lhs_buf: Value.ElemValueBuffer = undefined; | 3896 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 3877 | var rhs_buf: Value.ElemValueBuffer = undefined; | 3897 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3878 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 3898 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3879 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 3899 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3880 | scalar.* = try bitwiseXorScalar(lhs_elem, rhs_elem, allocator, target); | 3900 | scalar.* = try bitwiseXorScalar(lhs_elem, rhs_elem, allocator, mod); |
| 3881 | } | 3901 | } |
| 3882 | return Value.Tag.aggregate.create(allocator, result_data); | 3902 | return Value.Tag.aggregate.create(allocator, result_data); |
| 3883 | } | 3903 | } |
| 3884 | return bitwiseXorScalar(lhs, rhs, allocator, target); | 3904 | return bitwiseXorScalar(lhs, rhs, allocator, mod); |
| 3885 | } | 3905 | } |
| 3886 | 3906 | ||
| 3887 | /// operands must be integers; handles undefined. | 3907 | /// operands must be integers; handles undefined. |
| 3888 | pub fn bitwiseXorScalar(lhs: Value, rhs: Value, arena: Allocator, target: Target) !Value { | 3908 | pub fn bitwiseXorScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value { |
| 3889 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); | 3909 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 3890 | 3910 | ||
| 3891 | // TODO is this a performance issue? maybe we should try the operation without | 3911 | // TODO is this a performance issue? maybe we should try the operation without |
| 3892 | // resorting to BigInt first. | 3912 | // resorting to BigInt first. |
| 3893 | var lhs_space: Value.BigIntSpace = undefined; | 3913 | var lhs_space: Value.BigIntSpace = undefined; |
| 3894 | var rhs_space: Value.BigIntSpace = undefined; | 3914 | var rhs_space: Value.BigIntSpace = undefined; |
| 3895 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 3915 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 3896 | const rhs_bigint = rhs.toBigInt(&rhs_space, target); | 3916 | const rhs_bigint = rhs.toBigInt(&rhs_space, mod); |
| 3897 | const limbs = try arena.alloc( | 3917 | const limbs = try arena.alloc( |
| 3898 | std.math.big.Limb, | 3918 | std.math.big.Limb, |
| 3899 | // + 1 for negatives | 3919 | // + 1 for negatives |
| ... | @@ -3905,28 +3925,27 @@ pub const Value = extern union { | ... | @@ -3905,28 +3925,27 @@ pub const Value = extern union { |
| 3905 | } | 3925 | } |
| 3906 | 3926 | ||
| 3907 | pub fn intDiv(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { | 3927 | pub fn intDiv(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { |
| 3908 | const target = mod.getTarget(); | 3928 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3909 | if (ty.zigTypeTag() == .Vector) { | ||
| 3910 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 3929 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 3911 | for (result_data, 0..) |*scalar, i| { | 3930 | for (result_data, 0..) |*scalar, i| { |
| 3912 | var lhs_buf: Value.ElemValueBuffer = undefined; | 3931 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 3913 | var rhs_buf: Value.ElemValueBuffer = undefined; | 3932 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3914 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 3933 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3915 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 3934 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3916 | scalar.* = try intDivScalar(lhs_elem, rhs_elem, allocator, target); | 3935 | scalar.* = try intDivScalar(lhs_elem, rhs_elem, allocator, mod); |
| 3917 | } | 3936 | } |
| 3918 | return Value.Tag.aggregate.create(allocator, result_data); | 3937 | return Value.Tag.aggregate.create(allocator, result_data); |
| 3919 | } | 3938 | } |
| 3920 | return intDivScalar(lhs, rhs, allocator, target); | 3939 | return intDivScalar(lhs, rhs, allocator, mod); |
| 3921 | } | 3940 | } |
| 3922 | 3941 | ||
| 3923 | pub fn intDivScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value { | 3942 | pub fn intDivScalar(lhs: Value, rhs: Value, allocator: Allocator, mod: *Module) !Value { |
| 3924 | // TODO is this a performance issue? maybe we should try the operation without | 3943 | // TODO is this a performance issue? maybe we should try the operation without |
| 3925 | // resorting to BigInt first. | 3944 | // resorting to BigInt first. |
| 3926 | var lhs_space: Value.BigIntSpace = undefined; | 3945 | var lhs_space: Value.BigIntSpace = undefined; |
| 3927 | var rhs_space: Value.BigIntSpace = undefined; | 3946 | var rhs_space: Value.BigIntSpace = undefined; |
| 3928 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 3947 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 3929 | const rhs_bigint = rhs.toBigInt(&rhs_space, target); | 3948 | const rhs_bigint = rhs.toBigInt(&rhs_space, mod); |
| 3930 | const limbs_q = try allocator.alloc( | 3949 | const limbs_q = try allocator.alloc( |
| 3931 | std.math.big.Limb, | 3950 | std.math.big.Limb, |
| 3932 | lhs_bigint.limbs.len, | 3951 | lhs_bigint.limbs.len, |
| ... | @@ -3946,28 +3965,27 @@ pub const Value = extern union { | ... | @@ -3946,28 +3965,27 @@ pub const Value = extern union { |
| 3946 | } | 3965 | } |
| 3947 | 3966 | ||
| 3948 | pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { | 3967 | pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { |
| 3949 | const target = mod.getTarget(); | 3968 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3950 | if (ty.zigTypeTag() == .Vector) { | ||
| 3951 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 3969 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 3952 | for (result_data, 0..) |*scalar, i| { | 3970 | for (result_data, 0..) |*scalar, i| { |
| 3953 | var lhs_buf: Value.ElemValueBuffer = undefined; | 3971 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 3954 | var rhs_buf: Value.ElemValueBuffer = undefined; | 3972 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3955 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 3973 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3956 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 3974 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3957 | scalar.* = try intDivFloorScalar(lhs_elem, rhs_elem, allocator, target); | 3975 | scalar.* = try intDivFloorScalar(lhs_elem, rhs_elem, allocator, mod); |
| 3958 | } | 3976 | } |
| 3959 | return Value.Tag.aggregate.create(allocator, result_data); | 3977 | return Value.Tag.aggregate.create(allocator, result_data); |
| 3960 | } | 3978 | } |
| 3961 | return intDivFloorScalar(lhs, rhs, allocator, target); | 3979 | return intDivFloorScalar(lhs, rhs, allocator, mod); |
| 3962 | } | 3980 | } |
| 3963 | 3981 | ||
| 3964 | pub fn intDivFloorScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value { | 3982 | pub fn intDivFloorScalar(lhs: Value, rhs: Value, allocator: Allocator, mod: *Module) !Value { |
| 3965 | // TODO is this a performance issue? maybe we should try the operation without | 3983 | // TODO is this a performance issue? maybe we should try the operation without |
| 3966 | // resorting to BigInt first. | 3984 | // resorting to BigInt first. |
| 3967 | var lhs_space: Value.BigIntSpace = undefined; | 3985 | var lhs_space: Value.BigIntSpace = undefined; |
| 3968 | var rhs_space: Value.BigIntSpace = undefined; | 3986 | var rhs_space: Value.BigIntSpace = undefined; |
| 3969 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 3987 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 3970 | const rhs_bigint = rhs.toBigInt(&rhs_space, target); | 3988 | const rhs_bigint = rhs.toBigInt(&rhs_space, mod); |
| 3971 | const limbs_q = try allocator.alloc( | 3989 | const limbs_q = try allocator.alloc( |
| 3972 | std.math.big.Limb, | 3990 | std.math.big.Limb, |
| 3973 | lhs_bigint.limbs.len, | 3991 | lhs_bigint.limbs.len, |
| ... | @@ -3987,28 +4005,27 @@ pub const Value = extern union { | ... | @@ -3987,28 +4005,27 @@ pub const Value = extern union { |
| 3987 | } | 4005 | } |
| 3988 | 4006 | ||
| 3989 | pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { | 4007 | pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { |
| 3990 | const target = mod.getTarget(); | 4008 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3991 | if (ty.zigTypeTag() == .Vector) { | ||
| 3992 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 4009 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 3993 | for (result_data, 0..) |*scalar, i| { | 4010 | for (result_data, 0..) |*scalar, i| { |
| 3994 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4011 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 3995 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4012 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 3996 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4013 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 3997 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4014 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 3998 | scalar.* = try intModScalar(lhs_elem, rhs_elem, allocator, target); | 4015 | scalar.* = try intModScalar(lhs_elem, rhs_elem, allocator, mod); |
| 3999 | } | 4016 | } |
| 4000 | return Value.Tag.aggregate.create(allocator, result_data); | 4017 | return Value.Tag.aggregate.create(allocator, result_data); |
| 4001 | } | 4018 | } |
| 4002 | return intModScalar(lhs, rhs, allocator, target); | 4019 | return intModScalar(lhs, rhs, allocator, mod); |
| 4003 | } | 4020 | } |
| 4004 | 4021 | ||
| 4005 | pub fn intModScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value { | 4022 | pub fn intModScalar(lhs: Value, rhs: Value, allocator: Allocator, mod: *Module) !Value { |
| 4006 | // TODO is this a performance issue? maybe we should try the operation without | 4023 | // TODO is this a performance issue? maybe we should try the operation without |
| 4007 | // resorting to BigInt first. | 4024 | // resorting to BigInt first. |
| 4008 | var lhs_space: Value.BigIntSpace = undefined; | 4025 | var lhs_space: Value.BigIntSpace = undefined; |
| 4009 | var rhs_space: Value.BigIntSpace = undefined; | 4026 | var rhs_space: Value.BigIntSpace = undefined; |
| 4010 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 4027 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 4011 | const rhs_bigint = rhs.toBigInt(&rhs_space, target); | 4028 | const rhs_bigint = rhs.toBigInt(&rhs_space, mod); |
| 4012 | const limbs_q = try allocator.alloc( | 4029 | const limbs_q = try allocator.alloc( |
| 4013 | std.math.big.Limb, | 4030 | std.math.big.Limb, |
| 4014 | lhs_bigint.limbs.len, | 4031 | lhs_bigint.limbs.len, |
| ... | @@ -4064,14 +4081,14 @@ pub const Value = extern union { | ... | @@ -4064,14 +4081,14 @@ pub const Value = extern union { |
| 4064 | 4081 | ||
| 4065 | pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 4082 | pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 4066 | const target = mod.getTarget(); | 4083 | const target = mod.getTarget(); |
| 4067 | if (float_type.zigTypeTag() == .Vector) { | 4084 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4068 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4085 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4069 | for (result_data, 0..) |*scalar, i| { | 4086 | for (result_data, 0..) |*scalar, i| { |
| 4070 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4087 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 4071 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4088 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4072 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4089 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4073 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4090 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4074 | scalar.* = try floatRemScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target); | 4091 | scalar.* = try floatRemScalar(lhs_elem, rhs_elem, float_type.scalarType(mod), arena, target); |
| 4075 | } | 4092 | } |
| 4076 | return Value.Tag.aggregate.create(arena, result_data); | 4093 | return Value.Tag.aggregate.create(arena, result_data); |
| 4077 | } | 4094 | } |
| ... | @@ -4111,14 +4128,14 @@ pub const Value = extern union { | ... | @@ -4111,14 +4128,14 @@ pub const Value = extern union { |
| 4111 | 4128 | ||
| 4112 | pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 4129 | pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 4113 | const target = mod.getTarget(); | 4130 | const target = mod.getTarget(); |
| 4114 | if (float_type.zigTypeTag() == .Vector) { | 4131 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4115 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4132 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4116 | for (result_data, 0..) |*scalar, i| { | 4133 | for (result_data, 0..) |*scalar, i| { |
| 4117 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4134 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 4118 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4135 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4119 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4136 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4120 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4137 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4121 | scalar.* = try floatModScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target); | 4138 | scalar.* = try floatModScalar(lhs_elem, rhs_elem, float_type.scalarType(mod), arena, target); |
| 4122 | } | 4139 | } |
| 4123 | return Value.Tag.aggregate.create(arena, result_data); | 4140 | return Value.Tag.aggregate.create(arena, result_data); |
| 4124 | } | 4141 | } |
| ... | @@ -4157,28 +4174,27 @@ pub const Value = extern union { | ... | @@ -4157,28 +4174,27 @@ pub const Value = extern union { |
| 4157 | } | 4174 | } |
| 4158 | 4175 | ||
| 4159 | pub fn intMul(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { | 4176 | pub fn intMul(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { |
| 4160 | const target = mod.getTarget(); | 4177 | if (ty.zigTypeTag(mod) == .Vector) { |
| 4161 | if (ty.zigTypeTag() == .Vector) { | ||
| 4162 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 4178 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 4163 | for (result_data, 0..) |*scalar, i| { | 4179 | for (result_data, 0..) |*scalar, i| { |
| 4164 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4180 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 4165 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4181 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4166 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4182 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4167 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4183 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4168 | scalar.* = try intMulScalar(lhs_elem, rhs_elem, allocator, target); | 4184 | scalar.* = try intMulScalar(lhs_elem, rhs_elem, allocator, mod); |
| 4169 | } | 4185 | } |
| 4170 | return Value.Tag.aggregate.create(allocator, result_data); | 4186 | return Value.Tag.aggregate.create(allocator, result_data); |
| 4171 | } | 4187 | } |
| 4172 | return intMulScalar(lhs, rhs, allocator, target); | 4188 | return intMulScalar(lhs, rhs, allocator, mod); |
| 4173 | } | 4189 | } |
| 4174 | 4190 | ||
| 4175 | pub fn intMulScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value { | 4191 | pub fn intMulScalar(lhs: Value, rhs: Value, allocator: Allocator, mod: *Module) !Value { |
| 4176 | // TODO is this a performance issue? maybe we should try the operation without | 4192 | // TODO is this a performance issue? maybe we should try the operation without |
| 4177 | // resorting to BigInt first. | 4193 | // resorting to BigInt first. |
| 4178 | var lhs_space: Value.BigIntSpace = undefined; | 4194 | var lhs_space: Value.BigIntSpace = undefined; |
| 4179 | var rhs_space: Value.BigIntSpace = undefined; | 4195 | var rhs_space: Value.BigIntSpace = undefined; |
| 4180 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 4196 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 4181 | const rhs_bigint = rhs.toBigInt(&rhs_space, target); | 4197 | const rhs_bigint = rhs.toBigInt(&rhs_space, mod); |
| 4182 | const limbs = try allocator.alloc( | 4198 | const limbs = try allocator.alloc( |
| 4183 | std.math.big.Limb, | 4199 | std.math.big.Limb, |
| 4184 | lhs_bigint.limbs.len + rhs_bigint.limbs.len, | 4200 | lhs_bigint.limbs.len + rhs_bigint.limbs.len, |
| ... | @@ -4194,17 +4210,16 @@ pub const Value = extern union { | ... | @@ -4194,17 +4210,16 @@ pub const Value = extern union { |
| 4194 | } | 4210 | } |
| 4195 | 4211 | ||
| 4196 | pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16, mod: *Module) !Value { | 4212 | pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16, mod: *Module) !Value { |
| 4197 | const target = mod.getTarget(); | 4213 | if (ty.zigTypeTag(mod) == .Vector) { |
| 4198 | if (ty.zigTypeTag() == .Vector) { | ||
| 4199 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 4214 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 4200 | for (result_data, 0..) |*scalar, i| { | 4215 | for (result_data, 0..) |*scalar, i| { |
| 4201 | var buf: Value.ElemValueBuffer = undefined; | 4216 | var buf: Value.ElemValueBuffer = undefined; |
| 4202 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 4217 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 4203 | scalar.* = try intTruncScalar(elem_val, allocator, signedness, bits, target); | 4218 | scalar.* = try intTruncScalar(elem_val, allocator, signedness, bits, mod); |
| 4204 | } | 4219 | } |
| 4205 | return Value.Tag.aggregate.create(allocator, result_data); | 4220 | return Value.Tag.aggregate.create(allocator, result_data); |
| 4206 | } | 4221 | } |
| 4207 | return intTruncScalar(val, allocator, signedness, bits, target); | 4222 | return intTruncScalar(val, allocator, signedness, bits, mod); |
| 4208 | } | 4223 | } |
| 4209 | 4224 | ||
| 4210 | /// This variant may vectorize on `bits`. Asserts that `bits` is a (vector of) `u16`. | 4225 | /// This variant may vectorize on `bits`. Asserts that `bits` is a (vector of) `u16`. |
| ... | @@ -4216,26 +4231,25 @@ pub const Value = extern union { | ... | @@ -4216,26 +4231,25 @@ pub const Value = extern union { |
| 4216 | bits: Value, | 4231 | bits: Value, |
| 4217 | mod: *Module, | 4232 | mod: *Module, |
| 4218 | ) !Value { | 4233 | ) !Value { |
| 4219 | const target = mod.getTarget(); | 4234 | if (ty.zigTypeTag(mod) == .Vector) { |
| 4220 | if (ty.zigTypeTag() == .Vector) { | ||
| 4221 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 4235 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 4222 | for (result_data, 0..) |*scalar, i| { | 4236 | for (result_data, 0..) |*scalar, i| { |
| 4223 | var buf: Value.ElemValueBuffer = undefined; | 4237 | var buf: Value.ElemValueBuffer = undefined; |
| 4224 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 4238 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 4225 | var bits_buf: Value.ElemValueBuffer = undefined; | 4239 | var bits_buf: Value.ElemValueBuffer = undefined; |
| 4226 | const bits_elem = bits.elemValueBuffer(mod, i, &bits_buf); | 4240 | const bits_elem = bits.elemValueBuffer(mod, i, &bits_buf); |
| 4227 | scalar.* = try intTruncScalar(elem_val, allocator, signedness, @intCast(u16, bits_elem.toUnsignedInt(target)), target); | 4241 | scalar.* = try intTruncScalar(elem_val, allocator, signedness, @intCast(u16, bits_elem.toUnsignedInt(mod)), mod); |
| 4228 | } | 4242 | } |
| 4229 | return Value.Tag.aggregate.create(allocator, result_data); | 4243 | return Value.Tag.aggregate.create(allocator, result_data); |
| 4230 | } | 4244 | } |
| 4231 | return intTruncScalar(val, allocator, signedness, @intCast(u16, bits.toUnsignedInt(target)), target); | 4245 | return intTruncScalar(val, allocator, signedness, @intCast(u16, bits.toUnsignedInt(mod)), mod); |
| 4232 | } | 4246 | } |
| 4233 | 4247 | ||
| 4234 | pub fn intTruncScalar(val: Value, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16, target: Target) !Value { | 4248 | pub fn intTruncScalar(val: Value, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16, mod: *Module) !Value { |
| 4235 | if (bits == 0) return Value.zero; | 4249 | if (bits == 0) return Value.zero; |
| 4236 | 4250 | ||
| 4237 | var val_space: Value.BigIntSpace = undefined; | 4251 | var val_space: Value.BigIntSpace = undefined; |
| 4238 | const val_bigint = val.toBigInt(&val_space, target); | 4252 | const val_bigint = val.toBigInt(&val_space, mod); |
| 4239 | 4253 | ||
| 4240 | const limbs = try allocator.alloc( | 4254 | const limbs = try allocator.alloc( |
| 4241 | std.math.big.Limb, | 4255 | std.math.big.Limb, |
| ... | @@ -4248,27 +4262,26 @@ pub const Value = extern union { | ... | @@ -4248,27 +4262,26 @@ pub const Value = extern union { |
| 4248 | } | 4262 | } |
| 4249 | 4263 | ||
| 4250 | pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { | 4264 | pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { |
| 4251 | const target = mod.getTarget(); | 4265 | if (ty.zigTypeTag(mod) == .Vector) { |
| 4252 | if (ty.zigTypeTag() == .Vector) { | ||
| 4253 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 4266 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 4254 | for (result_data, 0..) |*scalar, i| { | 4267 | for (result_data, 0..) |*scalar, i| { |
| 4255 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4268 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 4256 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4269 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4257 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4270 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4258 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4271 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4259 | scalar.* = try shlScalar(lhs_elem, rhs_elem, allocator, target); | 4272 | scalar.* = try shlScalar(lhs_elem, rhs_elem, allocator, mod); |
| 4260 | } | 4273 | } |
| 4261 | return Value.Tag.aggregate.create(allocator, result_data); | 4274 | return Value.Tag.aggregate.create(allocator, result_data); |
| 4262 | } | 4275 | } |
| 4263 | return shlScalar(lhs, rhs, allocator, target); | 4276 | return shlScalar(lhs, rhs, allocator, mod); |
| 4264 | } | 4277 | } |
| 4265 | 4278 | ||
| 4266 | pub fn shlScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value { | 4279 | pub fn shlScalar(lhs: Value, rhs: Value, allocator: Allocator, mod: *Module) !Value { |
| 4267 | // TODO is this a performance issue? maybe we should try the operation without | 4280 | // TODO is this a performance issue? maybe we should try the operation without |
| 4268 | // resorting to BigInt first. | 4281 | // resorting to BigInt first. |
| 4269 | var lhs_space: Value.BigIntSpace = undefined; | 4282 | var lhs_space: Value.BigIntSpace = undefined; |
| 4270 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 4283 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 4271 | const shift = @intCast(usize, rhs.toUnsignedInt(target)); | 4284 | const shift = @intCast(usize, rhs.toUnsignedInt(mod)); |
| 4272 | const limbs = try allocator.alloc( | 4285 | const limbs = try allocator.alloc( |
| 4273 | std.math.big.Limb, | 4286 | std.math.big.Limb, |
| 4274 | lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1, | 4287 | lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1, |
| ... | @@ -4289,8 +4302,7 @@ pub const Value = extern union { | ... | @@ -4289,8 +4302,7 @@ pub const Value = extern union { |
| 4289 | allocator: Allocator, | 4302 | allocator: Allocator, |
| 4290 | mod: *Module, | 4303 | mod: *Module, |
| 4291 | ) !OverflowArithmeticResult { | 4304 | ) !OverflowArithmeticResult { |
| 4292 | const target = mod.getTarget(); | 4305 | if (ty.zigTypeTag(mod) == .Vector) { |
| 4293 | if (ty.zigTypeTag() == .Vector) { | ||
| 4294 | const overflowed_data = try allocator.alloc(Value, ty.vectorLen()); | 4306 | const overflowed_data = try allocator.alloc(Value, ty.vectorLen()); |
| 4295 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 4307 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 4296 | for (result_data, 0..) |*scalar, i| { | 4308 | for (result_data, 0..) |*scalar, i| { |
| ... | @@ -4298,7 +4310,7 @@ pub const Value = extern union { | ... | @@ -4298,7 +4310,7 @@ pub const Value = extern union { |
| 4298 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4310 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4299 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4311 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4300 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4312 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4301 | const of_math_result = try shlWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(), allocator, target); | 4313 | const of_math_result = try shlWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(mod), allocator, mod); |
| 4302 | overflowed_data[i] = of_math_result.overflow_bit; | 4314 | overflowed_data[i] = of_math_result.overflow_bit; |
| 4303 | scalar.* = of_math_result.wrapped_result; | 4315 | scalar.* = of_math_result.wrapped_result; |
| 4304 | } | 4316 | } |
| ... | @@ -4307,7 +4319,7 @@ pub const Value = extern union { | ... | @@ -4307,7 +4319,7 @@ pub const Value = extern union { |
| 4307 | .wrapped_result = try Value.Tag.aggregate.create(allocator, result_data), | 4319 | .wrapped_result = try Value.Tag.aggregate.create(allocator, result_data), |
| 4308 | }; | 4320 | }; |
| 4309 | } | 4321 | } |
| 4310 | return shlWithOverflowScalar(lhs, rhs, ty, allocator, target); | 4322 | return shlWithOverflowScalar(lhs, rhs, ty, allocator, mod); |
| 4311 | } | 4323 | } |
| 4312 | 4324 | ||
| 4313 | pub fn shlWithOverflowScalar( | 4325 | pub fn shlWithOverflowScalar( |
| ... | @@ -4315,12 +4327,12 @@ pub const Value = extern union { | ... | @@ -4315,12 +4327,12 @@ pub const Value = extern union { |
| 4315 | rhs: Value, | 4327 | rhs: Value, |
| 4316 | ty: Type, | 4328 | ty: Type, |
| 4317 | allocator: Allocator, | 4329 | allocator: Allocator, |
| 4318 | target: Target, | 4330 | mod: *Module, |
| 4319 | ) !OverflowArithmeticResult { | 4331 | ) !OverflowArithmeticResult { |
| 4320 | const info = ty.intInfo(target); | 4332 | const info = ty.intInfo(mod); |
| 4321 | var lhs_space: Value.BigIntSpace = undefined; | 4333 | var lhs_space: Value.BigIntSpace = undefined; |
| 4322 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 4334 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 4323 | const shift = @intCast(usize, rhs.toUnsignedInt(target)); | 4335 | const shift = @intCast(usize, rhs.toUnsignedInt(mod)); |
| 4324 | const limbs = try allocator.alloc( | 4336 | const limbs = try allocator.alloc( |
| 4325 | std.math.big.Limb, | 4337 | std.math.big.Limb, |
| 4326 | lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1, | 4338 | lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1, |
| ... | @@ -4348,19 +4360,18 @@ pub const Value = extern union { | ... | @@ -4348,19 +4360,18 @@ pub const Value = extern union { |
| 4348 | arena: Allocator, | 4360 | arena: Allocator, |
| 4349 | mod: *Module, | 4361 | mod: *Module, |
| 4350 | ) !Value { | 4362 | ) !Value { |
| 4351 | const target = mod.getTarget(); | 4363 | if (ty.zigTypeTag(mod) == .Vector) { |
| 4352 | if (ty.zigTypeTag() == .Vector) { | ||
| 4353 | const result_data = try arena.alloc(Value, ty.vectorLen()); | 4364 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| 4354 | for (result_data, 0..) |*scalar, i| { | 4365 | for (result_data, 0..) |*scalar, i| { |
| 4355 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4366 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 4356 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4367 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4357 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4368 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4358 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4369 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4359 | scalar.* = try shlSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target); | 4370 | scalar.* = try shlSatScalar(lhs_elem, rhs_elem, ty.scalarType(mod), arena, mod); |
| 4360 | } | 4371 | } |
| 4361 | return Value.Tag.aggregate.create(arena, result_data); | 4372 | return Value.Tag.aggregate.create(arena, result_data); |
| 4362 | } | 4373 | } |
| 4363 | return shlSatScalar(lhs, rhs, ty, arena, target); | 4374 | return shlSatScalar(lhs, rhs, ty, arena, mod); |
| 4364 | } | 4375 | } |
| 4365 | 4376 | ||
| 4366 | pub fn shlSatScalar( | 4377 | pub fn shlSatScalar( |
| ... | @@ -4368,15 +4379,15 @@ pub const Value = extern union { | ... | @@ -4368,15 +4379,15 @@ pub const Value = extern union { |
| 4368 | rhs: Value, | 4379 | rhs: Value, |
| 4369 | ty: Type, | 4380 | ty: Type, |
| 4370 | arena: Allocator, | 4381 | arena: Allocator, |
| 4371 | target: Target, | 4382 | mod: *Module, |
| 4372 | ) !Value { | 4383 | ) !Value { |
| 4373 | // TODO is this a performance issue? maybe we should try the operation without | 4384 | // TODO is this a performance issue? maybe we should try the operation without |
| 4374 | // resorting to BigInt first. | 4385 | // resorting to BigInt first. |
| 4375 | const info = ty.intInfo(target); | 4386 | const info = ty.intInfo(mod); |
| 4376 | 4387 | ||
| 4377 | var lhs_space: Value.BigIntSpace = undefined; | 4388 | var lhs_space: Value.BigIntSpace = undefined; |
| 4378 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 4389 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 4379 | const shift = @intCast(usize, rhs.toUnsignedInt(target)); | 4390 | const shift = @intCast(usize, rhs.toUnsignedInt(mod)); |
| 4380 | const limbs = try arena.alloc( | 4391 | const limbs = try arena.alloc( |
| 4381 | std.math.big.Limb, | 4392 | std.math.big.Limb, |
| 4382 | std.math.big.int.calcTwosCompLimbCount(info.bits) + 1, | 4393 | std.math.big.int.calcTwosCompLimbCount(info.bits) + 1, |
| ... | @@ -4397,14 +4408,14 @@ pub const Value = extern union { | ... | @@ -4397,14 +4408,14 @@ pub const Value = extern union { |
| 4397 | arena: Allocator, | 4408 | arena: Allocator, |
| 4398 | mod: *Module, | 4409 | mod: *Module, |
| 4399 | ) !Value { | 4410 | ) !Value { |
| 4400 | if (ty.zigTypeTag() == .Vector) { | 4411 | if (ty.zigTypeTag(mod) == .Vector) { |
| 4401 | const result_data = try arena.alloc(Value, ty.vectorLen()); | 4412 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| 4402 | for (result_data, 0..) |*scalar, i| { | 4413 | for (result_data, 0..) |*scalar, i| { |
| 4403 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4414 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 4404 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4415 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4405 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4416 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4406 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4417 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4407 | scalar.* = try shlTruncScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, mod); | 4418 | scalar.* = try shlTruncScalar(lhs_elem, rhs_elem, ty.scalarType(mod), arena, mod); |
| 4408 | } | 4419 | } |
| 4409 | return Value.Tag.aggregate.create(arena, result_data); | 4420 | return Value.Tag.aggregate.create(arena, result_data); |
| 4410 | } | 4421 | } |
| ... | @@ -4419,33 +4430,32 @@ pub const Value = extern union { | ... | @@ -4419,33 +4430,32 @@ pub const Value = extern union { |
| 4419 | mod: *Module, | 4430 | mod: *Module, |
| 4420 | ) !Value { | 4431 | ) !Value { |
| 4421 | const shifted = try lhs.shl(rhs, ty, arena, mod); | 4432 | const shifted = try lhs.shl(rhs, ty, arena, mod); |
| 4422 | const int_info = ty.intInfo(mod.getTarget()); | 4433 | const int_info = ty.intInfo(mod); |
| 4423 | const truncated = try shifted.intTrunc(ty, arena, int_info.signedness, int_info.bits, mod); | 4434 | const truncated = try shifted.intTrunc(ty, arena, int_info.signedness, int_info.bits, mod); |
| 4424 | return truncated; | 4435 | return truncated; |
| 4425 | } | 4436 | } |
| 4426 | 4437 | ||
| 4427 | pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { | 4438 | pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value { |
| 4428 | const target = mod.getTarget(); | 4439 | if (ty.zigTypeTag(mod) == .Vector) { |
| 4429 | if (ty.zigTypeTag() == .Vector) { | ||
| 4430 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | 4440 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 4431 | for (result_data, 0..) |*scalar, i| { | 4441 | for (result_data, 0..) |*scalar, i| { |
| 4432 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4442 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 4433 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4443 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4434 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4444 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4435 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4445 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4436 | scalar.* = try shrScalar(lhs_elem, rhs_elem, allocator, target); | 4446 | scalar.* = try shrScalar(lhs_elem, rhs_elem, allocator, mod); |
| 4437 | } | 4447 | } |
| 4438 | return Value.Tag.aggregate.create(allocator, result_data); | 4448 | return Value.Tag.aggregate.create(allocator, result_data); |
| 4439 | } | 4449 | } |
| 4440 | return shrScalar(lhs, rhs, allocator, target); | 4450 | return shrScalar(lhs, rhs, allocator, mod); |
| 4441 | } | 4451 | } |
| 4442 | 4452 | ||
| 4443 | pub fn shrScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value { | 4453 | pub fn shrScalar(lhs: Value, rhs: Value, allocator: Allocator, mod: *Module) !Value { |
| 4444 | // TODO is this a performance issue? maybe we should try the operation without | 4454 | // TODO is this a performance issue? maybe we should try the operation without |
| 4445 | // resorting to BigInt first. | 4455 | // resorting to BigInt first. |
| 4446 | var lhs_space: Value.BigIntSpace = undefined; | 4456 | var lhs_space: Value.BigIntSpace = undefined; |
| 4447 | const lhs_bigint = lhs.toBigInt(&lhs_space, target); | 4457 | const lhs_bigint = lhs.toBigInt(&lhs_space, mod); |
| 4448 | const shift = @intCast(usize, rhs.toUnsignedInt(target)); | 4458 | const shift = @intCast(usize, rhs.toUnsignedInt(mod)); |
| 4449 | 4459 | ||
| 4450 | const result_limbs = lhs_bigint.limbs.len -| (shift / (@sizeOf(std.math.big.Limb) * 8)); | 4460 | const result_limbs = lhs_bigint.limbs.len -| (shift / (@sizeOf(std.math.big.Limb) * 8)); |
| 4451 | if (result_limbs == 0) { | 4461 | if (result_limbs == 0) { |
| ... | @@ -4478,12 +4488,12 @@ pub const Value = extern union { | ... | @@ -4478,12 +4488,12 @@ pub const Value = extern union { |
| 4478 | mod: *Module, | 4488 | mod: *Module, |
| 4479 | ) !Value { | 4489 | ) !Value { |
| 4480 | const target = mod.getTarget(); | 4490 | const target = mod.getTarget(); |
| 4481 | if (float_type.zigTypeTag() == .Vector) { | 4491 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4482 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4492 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4483 | for (result_data, 0..) |*scalar, i| { | 4493 | for (result_data, 0..) |*scalar, i| { |
| 4484 | var buf: Value.ElemValueBuffer = undefined; | 4494 | var buf: Value.ElemValueBuffer = undefined; |
| 4485 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 4495 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 4486 | scalar.* = try floatNegScalar(elem_val, float_type.scalarType(), arena, target); | 4496 | scalar.* = try floatNegScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 4487 | } | 4497 | } |
| 4488 | return Value.Tag.aggregate.create(arena, result_data); | 4498 | return Value.Tag.aggregate.create(arena, result_data); |
| 4489 | } | 4499 | } |
| ... | @@ -4514,14 +4524,14 @@ pub const Value = extern union { | ... | @@ -4514,14 +4524,14 @@ pub const Value = extern union { |
| 4514 | mod: *Module, | 4524 | mod: *Module, |
| 4515 | ) !Value { | 4525 | ) !Value { |
| 4516 | const target = mod.getTarget(); | 4526 | const target = mod.getTarget(); |
| 4517 | if (float_type.zigTypeTag() == .Vector) { | 4527 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4518 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4528 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4519 | for (result_data, 0..) |*scalar, i| { | 4529 | for (result_data, 0..) |*scalar, i| { |
| 4520 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4530 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 4521 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4531 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4522 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4532 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4523 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4533 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4524 | scalar.* = try floatDivScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target); | 4534 | scalar.* = try floatDivScalar(lhs_elem, rhs_elem, float_type.scalarType(mod), arena, target); |
| 4525 | } | 4535 | } |
| 4526 | return Value.Tag.aggregate.create(arena, result_data); | 4536 | return Value.Tag.aggregate.create(arena, result_data); |
| 4527 | } | 4537 | } |
| ... | @@ -4573,14 +4583,14 @@ pub const Value = extern union { | ... | @@ -4573,14 +4583,14 @@ pub const Value = extern union { |
| 4573 | mod: *Module, | 4583 | mod: *Module, |
| 4574 | ) !Value { | 4584 | ) !Value { |
| 4575 | const target = mod.getTarget(); | 4585 | const target = mod.getTarget(); |
| 4576 | if (float_type.zigTypeTag() == .Vector) { | 4586 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4577 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4587 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4578 | for (result_data, 0..) |*scalar, i| { | 4588 | for (result_data, 0..) |*scalar, i| { |
| 4579 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4589 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 4580 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4590 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4581 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4591 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4582 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4592 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4583 | scalar.* = try floatDivFloorScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target); | 4593 | scalar.* = try floatDivFloorScalar(lhs_elem, rhs_elem, float_type.scalarType(mod), arena, target); |
| 4584 | } | 4594 | } |
| 4585 | return Value.Tag.aggregate.create(arena, result_data); | 4595 | return Value.Tag.aggregate.create(arena, result_data); |
| 4586 | } | 4596 | } |
| ... | @@ -4632,14 +4642,14 @@ pub const Value = extern union { | ... | @@ -4632,14 +4642,14 @@ pub const Value = extern union { |
| 4632 | mod: *Module, | 4642 | mod: *Module, |
| 4633 | ) !Value { | 4643 | ) !Value { |
| 4634 | const target = mod.getTarget(); | 4644 | const target = mod.getTarget(); |
| 4635 | if (float_type.zigTypeTag() == .Vector) { | 4645 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4636 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4646 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4637 | for (result_data, 0..) |*scalar, i| { | 4647 | for (result_data, 0..) |*scalar, i| { |
| 4638 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4648 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 4639 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4649 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4640 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4650 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4641 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4651 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4642 | scalar.* = try floatDivTruncScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target); | 4652 | scalar.* = try floatDivTruncScalar(lhs_elem, rhs_elem, float_type.scalarType(mod), arena, target); |
| 4643 | } | 4653 | } |
| 4644 | return Value.Tag.aggregate.create(arena, result_data); | 4654 | return Value.Tag.aggregate.create(arena, result_data); |
| 4645 | } | 4655 | } |
| ... | @@ -4691,14 +4701,14 @@ pub const Value = extern union { | ... | @@ -4691,14 +4701,14 @@ pub const Value = extern union { |
| 4691 | mod: *Module, | 4701 | mod: *Module, |
| 4692 | ) !Value { | 4702 | ) !Value { |
| 4693 | const target = mod.getTarget(); | 4703 | const target = mod.getTarget(); |
| 4694 | if (float_type.zigTypeTag() == .Vector) { | 4704 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4695 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4705 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4696 | for (result_data, 0..) |*scalar, i| { | 4706 | for (result_data, 0..) |*scalar, i| { |
| 4697 | var lhs_buf: Value.ElemValueBuffer = undefined; | 4707 | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 4698 | var rhs_buf: Value.ElemValueBuffer = undefined; | 4708 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 4699 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); | 4709 | const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf); |
| 4700 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); | 4710 | const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf); |
| 4701 | scalar.* = try floatMulScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target); | 4711 | scalar.* = try floatMulScalar(lhs_elem, rhs_elem, float_type.scalarType(mod), arena, target); |
| 4702 | } | 4712 | } |
| 4703 | return Value.Tag.aggregate.create(arena, result_data); | 4713 | return Value.Tag.aggregate.create(arena, result_data); |
| 4704 | } | 4714 | } |
| ... | @@ -4744,12 +4754,12 @@ pub const Value = extern union { | ... | @@ -4744,12 +4754,12 @@ pub const Value = extern union { |
| 4744 | 4754 | ||
| 4745 | pub fn sqrt(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 4755 | pub fn sqrt(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 4746 | const target = mod.getTarget(); | 4756 | const target = mod.getTarget(); |
| 4747 | if (float_type.zigTypeTag() == .Vector) { | 4757 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4748 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4758 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4749 | for (result_data, 0..) |*scalar, i| { | 4759 | for (result_data, 0..) |*scalar, i| { |
| 4750 | var buf: Value.ElemValueBuffer = undefined; | 4760 | var buf: Value.ElemValueBuffer = undefined; |
| 4751 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 4761 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 4752 | scalar.* = try sqrtScalar(elem_val, float_type.scalarType(), arena, target); | 4762 | scalar.* = try sqrtScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 4753 | } | 4763 | } |
| 4754 | return Value.Tag.aggregate.create(arena, result_data); | 4764 | return Value.Tag.aggregate.create(arena, result_data); |
| 4755 | } | 4765 | } |
| ... | @@ -4784,12 +4794,12 @@ pub const Value = extern union { | ... | @@ -4784,12 +4794,12 @@ pub const Value = extern union { |
| 4784 | 4794 | ||
| 4785 | pub fn sin(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 4795 | pub fn sin(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 4786 | const target = mod.getTarget(); | 4796 | const target = mod.getTarget(); |
| 4787 | if (float_type.zigTypeTag() == .Vector) { | 4797 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4788 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4798 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4789 | for (result_data, 0..) |*scalar, i| { | 4799 | for (result_data, 0..) |*scalar, i| { |
| 4790 | var buf: Value.ElemValueBuffer = undefined; | 4800 | var buf: Value.ElemValueBuffer = undefined; |
| 4791 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 4801 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 4792 | scalar.* = try sinScalar(elem_val, float_type.scalarType(), arena, target); | 4802 | scalar.* = try sinScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 4793 | } | 4803 | } |
| 4794 | return Value.Tag.aggregate.create(arena, result_data); | 4804 | return Value.Tag.aggregate.create(arena, result_data); |
| 4795 | } | 4805 | } |
| ... | @@ -4824,12 +4834,12 @@ pub const Value = extern union { | ... | @@ -4824,12 +4834,12 @@ pub const Value = extern union { |
| 4824 | 4834 | ||
| 4825 | pub fn cos(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 4835 | pub fn cos(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 4826 | const target = mod.getTarget(); | 4836 | const target = mod.getTarget(); |
| 4827 | if (float_type.zigTypeTag() == .Vector) { | 4837 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4828 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4838 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4829 | for (result_data, 0..) |*scalar, i| { | 4839 | for (result_data, 0..) |*scalar, i| { |
| 4830 | var buf: Value.ElemValueBuffer = undefined; | 4840 | var buf: Value.ElemValueBuffer = undefined; |
| 4831 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 4841 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 4832 | scalar.* = try cosScalar(elem_val, float_type.scalarType(), arena, target); | 4842 | scalar.* = try cosScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 4833 | } | 4843 | } |
| 4834 | return Value.Tag.aggregate.create(arena, result_data); | 4844 | return Value.Tag.aggregate.create(arena, result_data); |
| 4835 | } | 4845 | } |
| ... | @@ -4864,12 +4874,12 @@ pub const Value = extern union { | ... | @@ -4864,12 +4874,12 @@ pub const Value = extern union { |
| 4864 | 4874 | ||
| 4865 | pub fn tan(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 4875 | pub fn tan(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 4866 | const target = mod.getTarget(); | 4876 | const target = mod.getTarget(); |
| 4867 | if (float_type.zigTypeTag() == .Vector) { | 4877 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4868 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4878 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4869 | for (result_data, 0..) |*scalar, i| { | 4879 | for (result_data, 0..) |*scalar, i| { |
| 4870 | var buf: Value.ElemValueBuffer = undefined; | 4880 | var buf: Value.ElemValueBuffer = undefined; |
| 4871 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 4881 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 4872 | scalar.* = try tanScalar(elem_val, float_type.scalarType(), arena, target); | 4882 | scalar.* = try tanScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 4873 | } | 4883 | } |
| 4874 | return Value.Tag.aggregate.create(arena, result_data); | 4884 | return Value.Tag.aggregate.create(arena, result_data); |
| 4875 | } | 4885 | } |
| ... | @@ -4904,12 +4914,12 @@ pub const Value = extern union { | ... | @@ -4904,12 +4914,12 @@ pub const Value = extern union { |
| 4904 | 4914 | ||
| 4905 | pub fn exp(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 4915 | pub fn exp(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 4906 | const target = mod.getTarget(); | 4916 | const target = mod.getTarget(); |
| 4907 | if (float_type.zigTypeTag() == .Vector) { | 4917 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4908 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4918 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4909 | for (result_data, 0..) |*scalar, i| { | 4919 | for (result_data, 0..) |*scalar, i| { |
| 4910 | var buf: Value.ElemValueBuffer = undefined; | 4920 | var buf: Value.ElemValueBuffer = undefined; |
| 4911 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 4921 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 4912 | scalar.* = try expScalar(elem_val, float_type.scalarType(), arena, target); | 4922 | scalar.* = try expScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 4913 | } | 4923 | } |
| 4914 | return Value.Tag.aggregate.create(arena, result_data); | 4924 | return Value.Tag.aggregate.create(arena, result_data); |
| 4915 | } | 4925 | } |
| ... | @@ -4944,12 +4954,12 @@ pub const Value = extern union { | ... | @@ -4944,12 +4954,12 @@ pub const Value = extern union { |
| 4944 | 4954 | ||
| 4945 | pub fn exp2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 4955 | pub fn exp2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 4946 | const target = mod.getTarget(); | 4956 | const target = mod.getTarget(); |
| 4947 | if (float_type.zigTypeTag() == .Vector) { | 4957 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4948 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4958 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4949 | for (result_data, 0..) |*scalar, i| { | 4959 | for (result_data, 0..) |*scalar, i| { |
| 4950 | var buf: Value.ElemValueBuffer = undefined; | 4960 | var buf: Value.ElemValueBuffer = undefined; |
| 4951 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 4961 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 4952 | scalar.* = try exp2Scalar(elem_val, float_type.scalarType(), arena, target); | 4962 | scalar.* = try exp2Scalar(elem_val, float_type.scalarType(mod), arena, target); |
| 4953 | } | 4963 | } |
| 4954 | return Value.Tag.aggregate.create(arena, result_data); | 4964 | return Value.Tag.aggregate.create(arena, result_data); |
| 4955 | } | 4965 | } |
| ... | @@ -4984,12 +4994,12 @@ pub const Value = extern union { | ... | @@ -4984,12 +4994,12 @@ pub const Value = extern union { |
| 4984 | 4994 | ||
| 4985 | pub fn log(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 4995 | pub fn log(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 4986 | const target = mod.getTarget(); | 4996 | const target = mod.getTarget(); |
| 4987 | if (float_type.zigTypeTag() == .Vector) { | 4997 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 4988 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 4998 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 4989 | for (result_data, 0..) |*scalar, i| { | 4999 | for (result_data, 0..) |*scalar, i| { |
| 4990 | var buf: Value.ElemValueBuffer = undefined; | 5000 | var buf: Value.ElemValueBuffer = undefined; |
| 4991 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 5001 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 4992 | scalar.* = try logScalar(elem_val, float_type.scalarType(), arena, target); | 5002 | scalar.* = try logScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 4993 | } | 5003 | } |
| 4994 | return Value.Tag.aggregate.create(arena, result_data); | 5004 | return Value.Tag.aggregate.create(arena, result_data); |
| 4995 | } | 5005 | } |
| ... | @@ -5024,12 +5034,12 @@ pub const Value = extern union { | ... | @@ -5024,12 +5034,12 @@ pub const Value = extern union { |
| 5024 | 5034 | ||
| 5025 | pub fn log2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 5035 | pub fn log2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 5026 | const target = mod.getTarget(); | 5036 | const target = mod.getTarget(); |
| 5027 | if (float_type.zigTypeTag() == .Vector) { | 5037 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 5028 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 5038 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 5029 | for (result_data, 0..) |*scalar, i| { | 5039 | for (result_data, 0..) |*scalar, i| { |
| 5030 | var buf: Value.ElemValueBuffer = undefined; | 5040 | var buf: Value.ElemValueBuffer = undefined; |
| 5031 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 5041 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 5032 | scalar.* = try log2Scalar(elem_val, float_type.scalarType(), arena, target); | 5042 | scalar.* = try log2Scalar(elem_val, float_type.scalarType(mod), arena, target); |
| 5033 | } | 5043 | } |
| 5034 | return Value.Tag.aggregate.create(arena, result_data); | 5044 | return Value.Tag.aggregate.create(arena, result_data); |
| 5035 | } | 5045 | } |
| ... | @@ -5064,12 +5074,12 @@ pub const Value = extern union { | ... | @@ -5064,12 +5074,12 @@ pub const Value = extern union { |
| 5064 | 5074 | ||
| 5065 | pub fn log10(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 5075 | pub fn log10(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 5066 | const target = mod.getTarget(); | 5076 | const target = mod.getTarget(); |
| 5067 | if (float_type.zigTypeTag() == .Vector) { | 5077 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 5068 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 5078 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 5069 | for (result_data, 0..) |*scalar, i| { | 5079 | for (result_data, 0..) |*scalar, i| { |
| 5070 | var buf: Value.ElemValueBuffer = undefined; | 5080 | var buf: Value.ElemValueBuffer = undefined; |
| 5071 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 5081 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 5072 | scalar.* = try log10Scalar(elem_val, float_type.scalarType(), arena, target); | 5082 | scalar.* = try log10Scalar(elem_val, float_type.scalarType(mod), arena, target); |
| 5073 | } | 5083 | } |
| 5074 | return Value.Tag.aggregate.create(arena, result_data); | 5084 | return Value.Tag.aggregate.create(arena, result_data); |
| 5075 | } | 5085 | } |
| ... | @@ -5104,12 +5114,12 @@ pub const Value = extern union { | ... | @@ -5104,12 +5114,12 @@ pub const Value = extern union { |
| 5104 | 5114 | ||
| 5105 | pub fn fabs(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 5115 | pub fn fabs(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 5106 | const target = mod.getTarget(); | 5116 | const target = mod.getTarget(); |
| 5107 | if (float_type.zigTypeTag() == .Vector) { | 5117 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 5108 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 5118 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 5109 | for (result_data, 0..) |*scalar, i| { | 5119 | for (result_data, 0..) |*scalar, i| { |
| 5110 | var buf: Value.ElemValueBuffer = undefined; | 5120 | var buf: Value.ElemValueBuffer = undefined; |
| 5111 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 5121 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 5112 | scalar.* = try fabsScalar(elem_val, float_type.scalarType(), arena, target); | 5122 | scalar.* = try fabsScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 5113 | } | 5123 | } |
| 5114 | return Value.Tag.aggregate.create(arena, result_data); | 5124 | return Value.Tag.aggregate.create(arena, result_data); |
| 5115 | } | 5125 | } |
| ... | @@ -5144,12 +5154,12 @@ pub const Value = extern union { | ... | @@ -5144,12 +5154,12 @@ pub const Value = extern union { |
| 5144 | 5154 | ||
| 5145 | pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 5155 | pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 5146 | const target = mod.getTarget(); | 5156 | const target = mod.getTarget(); |
| 5147 | if (float_type.zigTypeTag() == .Vector) { | 5157 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 5148 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 5158 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 5149 | for (result_data, 0..) |*scalar, i| { | 5159 | for (result_data, 0..) |*scalar, i| { |
| 5150 | var buf: Value.ElemValueBuffer = undefined; | 5160 | var buf: Value.ElemValueBuffer = undefined; |
| 5151 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 5161 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 5152 | scalar.* = try floorScalar(elem_val, float_type.scalarType(), arena, target); | 5162 | scalar.* = try floorScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 5153 | } | 5163 | } |
| 5154 | return Value.Tag.aggregate.create(arena, result_data); | 5164 | return Value.Tag.aggregate.create(arena, result_data); |
| 5155 | } | 5165 | } |
| ... | @@ -5184,12 +5194,12 @@ pub const Value = extern union { | ... | @@ -5184,12 +5194,12 @@ pub const Value = extern union { |
| 5184 | 5194 | ||
| 5185 | pub fn ceil(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 5195 | pub fn ceil(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 5186 | const target = mod.getTarget(); | 5196 | const target = mod.getTarget(); |
| 5187 | if (float_type.zigTypeTag() == .Vector) { | 5197 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 5188 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 5198 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 5189 | for (result_data, 0..) |*scalar, i| { | 5199 | for (result_data, 0..) |*scalar, i| { |
| 5190 | var buf: Value.ElemValueBuffer = undefined; | 5200 | var buf: Value.ElemValueBuffer = undefined; |
| 5191 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 5201 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 5192 | scalar.* = try ceilScalar(elem_val, float_type.scalarType(), arena, target); | 5202 | scalar.* = try ceilScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 5193 | } | 5203 | } |
| 5194 | return Value.Tag.aggregate.create(arena, result_data); | 5204 | return Value.Tag.aggregate.create(arena, result_data); |
| 5195 | } | 5205 | } |
| ... | @@ -5224,12 +5234,12 @@ pub const Value = extern union { | ... | @@ -5224,12 +5234,12 @@ pub const Value = extern union { |
| 5224 | 5234 | ||
| 5225 | pub fn round(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 5235 | pub fn round(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 5226 | const target = mod.getTarget(); | 5236 | const target = mod.getTarget(); |
| 5227 | if (float_type.zigTypeTag() == .Vector) { | 5237 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 5228 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 5238 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 5229 | for (result_data, 0..) |*scalar, i| { | 5239 | for (result_data, 0..) |*scalar, i| { |
| 5230 | var buf: Value.ElemValueBuffer = undefined; | 5240 | var buf: Value.ElemValueBuffer = undefined; |
| 5231 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 5241 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 5232 | scalar.* = try roundScalar(elem_val, float_type.scalarType(), arena, target); | 5242 | scalar.* = try roundScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 5233 | } | 5243 | } |
| 5234 | return Value.Tag.aggregate.create(arena, result_data); | 5244 | return Value.Tag.aggregate.create(arena, result_data); |
| 5235 | } | 5245 | } |
| ... | @@ -5264,12 +5274,12 @@ pub const Value = extern union { | ... | @@ -5264,12 +5274,12 @@ pub const Value = extern union { |
| 5264 | 5274 | ||
| 5265 | pub fn trunc(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 5275 | pub fn trunc(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
| 5266 | const target = mod.getTarget(); | 5276 | const target = mod.getTarget(); |
| 5267 | if (float_type.zigTypeTag() == .Vector) { | 5277 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 5268 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 5278 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 5269 | for (result_data, 0..) |*scalar, i| { | 5279 | for (result_data, 0..) |*scalar, i| { |
| 5270 | var buf: Value.ElemValueBuffer = undefined; | 5280 | var buf: Value.ElemValueBuffer = undefined; |
| 5271 | const elem_val = val.elemValueBuffer(mod, i, &buf); | 5281 | const elem_val = val.elemValueBuffer(mod, i, &buf); |
| 5272 | scalar.* = try truncScalar(elem_val, float_type.scalarType(), arena, target); | 5282 | scalar.* = try truncScalar(elem_val, float_type.scalarType(mod), arena, target); |
| 5273 | } | 5283 | } |
| 5274 | return Value.Tag.aggregate.create(arena, result_data); | 5284 | return Value.Tag.aggregate.create(arena, result_data); |
| 5275 | } | 5285 | } |
| ... | @@ -5311,7 +5321,7 @@ pub const Value = extern union { | ... | @@ -5311,7 +5321,7 @@ pub const Value = extern union { |
| 5311 | mod: *Module, | 5321 | mod: *Module, |
| 5312 | ) !Value { | 5322 | ) !Value { |
| 5313 | const target = mod.getTarget(); | 5323 | const target = mod.getTarget(); |
| 5314 | if (float_type.zigTypeTag() == .Vector) { | 5324 | if (float_type.zigTypeTag(mod) == .Vector) { |
| 5315 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | 5325 | const result_data = try arena.alloc(Value, float_type.vectorLen()); |
| 5316 | for (result_data, 0..) |*scalar, i| { | 5326 | for (result_data, 0..) |*scalar, i| { |
| 5317 | var mulend1_buf: Value.ElemValueBuffer = undefined; | 5327 | var mulend1_buf: Value.ElemValueBuffer = undefined; |
| ... | @@ -5321,7 +5331,7 @@ pub const Value = extern union { | ... | @@ -5321,7 +5331,7 @@ pub const Value = extern union { |
| 5321 | var addend_buf: Value.ElemValueBuffer = undefined; | 5331 | var addend_buf: Value.ElemValueBuffer = undefined; |
| 5322 | const addend_elem = addend.elemValueBuffer(mod, i, &addend_buf); | 5332 | const addend_elem = addend.elemValueBuffer(mod, i, &addend_buf); |
| 5323 | scalar.* = try mulAddScalar( | 5333 | scalar.* = try mulAddScalar( |
| 5324 | float_type.scalarType(), | 5334 | float_type.scalarType(mod), |
| 5325 | mulend1_elem, | 5335 | mulend1_elem, |
| 5326 | mulend2_elem, | 5336 | mulend2_elem, |
| 5327 | addend_elem, | 5337 | addend_elem, |
| ... | @@ -5380,8 +5390,7 @@ pub const Value = extern union { | ... | @@ -5380,8 +5390,7 @@ pub const Value = extern union { |
| 5380 | /// If the value is represented in-memory as a series of bytes that all | 5390 | /// If the value is represented in-memory as a series of bytes that all |
| 5381 | /// have the same value, return that byte value, otherwise null. | 5391 | /// have the same value, return that byte value, otherwise null. |
| 5382 | pub fn hasRepeatedByteRepr(val: Value, ty: Type, mod: *Module, value_buffer: *Payload.U64) !?Value { | 5392 | pub fn hasRepeatedByteRepr(val: Value, ty: Type, mod: *Module, value_buffer: *Payload.U64) !?Value { |
| 5383 | const target = mod.getTarget(); | 5393 | const abi_size = std.math.cast(usize, ty.abiSize(mod)) orelse return null; |
| 5384 | const abi_size = std.math.cast(usize, ty.abiSize(target)) orelse return null; | ||
| 5385 | assert(abi_size >= 1); | 5394 | assert(abi_size >= 1); |
| 5386 | const byte_buffer = try mod.gpa.alloc(u8, abi_size); | 5395 | const byte_buffer = try mod.gpa.alloc(u8, abi_size); |
| 5387 | defer mod.gpa.free(byte_buffer); | 5396 | defer mod.gpa.free(byte_buffer); |
| ... | @@ -5549,16 +5558,6 @@ pub const Value = extern union { | ... | @@ -5549,16 +5558,6 @@ pub const Value = extern union { |
| 5549 | data: Type, | 5558 | data: Type, |
| 5550 | }; | 5559 | }; |
| 5551 | 5560 | ||
| 5552 | pub const IntType = struct { | ||
| 5553 | pub const base_tag = Tag.int_type; | ||
| 5554 | |||
| 5555 | base: Payload = Payload{ .tag = base_tag }, | ||
| 5556 | data: struct { | ||
| 5557 | bits: u16, | ||
| 5558 | signed: bool, | ||
| 5559 | }, | ||
| 5560 | }; | ||
| 5561 | |||
| 5562 | pub const Float_16 = struct { | 5561 | pub const Float_16 = struct { |
| 5563 | pub const base_tag = Tag.float_16; | 5562 | pub const base_tag = Tag.float_16; |
| 5564 | 5563 | ||
| ... | @@ -5659,7 +5658,10 @@ pub const Value = extern union { | ... | @@ -5659,7 +5658,10 @@ pub const Value = extern union { |
| 5659 | 5658 | ||
| 5660 | pub const zero = initTag(.zero); | 5659 | pub const zero = initTag(.zero); |
| 5661 | pub const one = initTag(.one); | 5660 | pub const one = initTag(.one); |
| 5662 | pub const negative_one: Value = .{ .ptr_otherwise = &negative_one_payload.base }; | 5661 | pub const negative_one: Value = .{ |
| 5662 | .ip_index = .none, | ||
| 5663 | .legacy = .{ .ptr_otherwise = &negative_one_payload.base }, | ||
| 5664 | }; | ||
| 5663 | pub const undef = initTag(.undef); | 5665 | pub const undef = initTag(.undef); |
| 5664 | pub const @"void" = initTag(.void_value); | 5666 | pub const @"void" = initTag(.void_value); |
| 5665 | pub const @"null" = initTag(.null_value); | 5667 | pub const @"null" = initTag(.null_value); |