From 897c0b35a92dba851edd2ce49314468d3e1fcaff Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sun, 28 Jun 2026 15:19:23 -0400 Subject: [PATCH 01/22] Revert "cbe: improve struct/union defs on 32-bit targets" This reverts commit 5434f85c47f6412a8d5faf681419c15533bb388c, which was just hacking around other bugs. --- src/Type.zig | 2 +- src/codegen/c/type/render_defs.zig | 88 ++++++++++-------------------- 2 files changed, 29 insertions(+), 61 deletions(-) diff --git a/src/Type.zig b/src/Type.zig index e60726ced3ff48df988eff1505786071c596ff2a..32e49a05c26a8ee5459164c02f987c92704f0f65 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -962,7 +962,7 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { const bytes = ((elem_bits * vector_type.len) + 7) / 8; return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes)); }, - .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).defaultStructFieldAlignment(.auto, zcu), + .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).abiAlignment(zcu), .stage2_x86_64 => { if (vector_type.child == .bool_type) { if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .@"64"; diff --git a/src/codegen/c/type/render_defs.zig b/src/codegen/c/type/render_defs.zig index 03aae41ee0ec47cca9b560bd358263a5b0cb2352..866ea38cc44be5a44e0dba9aa6c75cf989cb664b 100644 --- a/src/codegen/c/type/render_defs.zig +++ b/src/codegen/c/type/render_defs.zig @@ -284,9 +284,8 @@ pub fn defineComplete( }, }, .array => if (ty.hasRuntimeBits(zcu)) { - const elem_ty = ty.childType(zcu); const name_cty: CType = .{ .arr = ty }; - const elem_cty: CType = try .lower(elem_ty, deps, arena, zcu); + const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu); const array_cty: CType = .{ .array = .{ .len = ty.arrayLenIncludingSentinel(zcu), .elem_ty = &elem_cty, @@ -296,28 +295,17 @@ pub fn defineComplete( break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu); }, } }; - if (elem_ty.defaultStructFieldAlignment(.auto, zcu) == elem_ty.abiAlignment(zcu)) { - try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ - name_cty.fmtTypeName(zcu), - array_cty.fmtDeclaratorPrefix(zcu), - array_cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), - }); - } else { - try w.print("zig_packed({f} {{ zig_under_align({d}) {f}array{f}; }}); /* {f} */\n", .{ - name_cty.fmtTypeName(zcu), - elem_ty.abiAlignment(zcu).toByteUnits().?, - array_cty.fmtDeclaratorPrefix(zcu), - array_cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), - }); - } + try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ + name_cty.fmtTypeName(zcu), + array_cty.fmtDeclaratorPrefix(zcu), + array_cty.fmtDeclaratorSuffix(zcu), + ty.fmt(pt), + }); try writeStaticAssertLayout(ty, name_cty, w, zcu); }, .vector => if (ty.hasRuntimeBits(zcu)) { - const elem_ty = ty.childType(zcu); const name_cty: CType = .{ .vec = ty }; - const elem_cty: CType = try .lower(elem_ty, deps, arena, zcu); + const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu); const array_cty: CType = .{ .array = .{ .len = ty.arrayLenIncludingSentinel(zcu), .elem_ty = &elem_cty, @@ -363,39 +351,21 @@ fn defineTuple( const ip = &zcu.intern_pool; const tuple = ip.indexToKey(ty.toIntern()).tuple_type; + // Fields cannot be underaligned, because tuple fields cannot have specified alignments. + // However, overaligned fields are possible thanks to intermediate zero-bit fields. + const tuple_align = ty.abiAlignment(zcu); - // If there are any underaligned fields, we need to byte-pack the tuple. - const pack: bool = pack: { - var offset: u64 = 0; - for (tuple.types.get(ip)) |field_ty_ip| { - const field_ty: Type = .fromInterned(field_ty_ip); - if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); - const natural_offset = natural_align.forward(offset); - offset = field_ty.abiAlignment(zcu).forward(offset); - if (offset < natural_offset) break :pack true; - // Also pack if any field is more aligned than the tuple should be. - if (natural_align.compareStrict(.gt, tuple_align)) break :pack true; - offset += field_ty.abiSize(zcu); - } - break :pack false; - }; - // If the alignment of other fields would not give the tuple sufficient alignment, we // need to align the first field (which does not affect its offset, because 0 is always // well-aligned) to indirectly specify the tuple alignment. - const overalign: bool = switch (pack) { - true => tuple_align.compareStrict(.gt, .@"1"), - false => for (tuple.types.get(ip)) |field_ty_ip| { - const field_ty: Type = .fromInterned(field_ty_ip); - if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); - if (natural_align.compareStrict(.gte, tuple_align)) break false; - } else true, - }; + const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); + if (natural_align.compareStrict(.gte, tuple_align)) break false; + } else true; - if (pack) try w.writeAll("zig_packed("); const name_cty: CType = .{ .@"struct" = ty }; try w.print("{f} {{ /* {f} */\n", .{ name_cty.fmtTypeName(zcu), @@ -406,18 +376,18 @@ fn defineTuple( for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| { if (field_val_ip != .none) continue; // `comptime` field const field_ty: Type = .fromInterned(field_ty_ip); - zig_offset = field_ty.abiAlignment(zcu).forward(zig_offset); + const field_align = field_ty.abiAlignment(zcu); + zig_offset = field_align.forward(zig_offset); if (!field_ty.hasRuntimeBits(zcu)) continue; - if (!pack) c_offset = field_ty.defaultStructFieldAlignment(.auto, zcu).forward(c_offset); + c_offset = field_align.forward(c_offset); try w.writeByte(' '); if (zig_offset == 0 and overalign) { // This is the first field; specify its alignment to align the tuple. try writeFieldAlign(field_ty, tuple_align, w, zcu); } else if (zig_offset > c_offset) { - // This field needs to be underaligned or overaligned compared to what its - // offset would otherwise be. + // This field needs to be overaligned compared to what its offset would otherwise be. const need_align: Alignment = .minStrict( - tuple_align, // don't make the tuple more aligned than it should be + tuple_align, // don't make the struct more aligned than it should be .fromLog2Units(@ctz(zig_offset)), ); try writeFieldAlign(field_ty, need_align, w, zcu); @@ -433,9 +403,7 @@ fn defineTuple( zig_offset += field_size; c_offset += field_size; } - try w.writeByte('}'); - if (pack) try w.writeByte(')'); - try w.writeAll(";\n"); + try w.writeAll("};\n"); try writeStaticAssertLayout(ty, name_cty, w, zcu); } @@ -553,7 +521,7 @@ fn defineUnionAuto( const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| { const field_ty: Type = .fromInterned(field_ty_ip); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gt, union_type.alignment)) break true; // The tag will immediately follow the payload. This layout may put the tag in what would // otherwise be padding on the payload union, because if the most-aligned union field is not @@ -571,7 +539,7 @@ fn defineUnionAuto( false => for (union_type.field_types.get(ip)) |field_ty_ip| { const field_ty: Type = .fromInterned(field_ty_ip); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gte, union_type.alignment)) break false; } else overalign: { if (union_type.has_runtime_tag) { @@ -642,7 +610,7 @@ fn defineUnionExtern( const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| { const field_ty: Type = .fromInterned(field_ty_ip); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gt, union_type.alignment)) break true; } else false; @@ -654,7 +622,7 @@ fn defineUnionExtern( false => for (union_type.field_types.get(ip)) |field_ty_ip| { const field_ty: Type = .fromInterned(field_ty_ip); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gte, union_type.alignment)) break false; } else overalign: { if (union_type.has_runtime_tag) { @@ -704,7 +672,7 @@ fn writeFieldAlign( w: *Writer, zcu: *const Zcu, ) Writer.Error!void { - if (alignment.compareStrict(.lt, ty.defaultStructFieldAlignment(.auto, zcu))) { + if (alignment.compareStrict(.lt, ty.abiAlignment(zcu))) { try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}); } else { try w.print("zig_align({d}) ", .{alignment.toByteUnits().?}); -- 2.54.0 From 409c89ee2161c071ca713b5b69e8707b0e538aab Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 27 Jun 2026 08:09:40 -0400 Subject: [PATCH 02/22] Compilation: avoid illegal behavior during create --- src/Compilation.zig | 3 +++ src/Zcu.zig | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/Compilation.zig b/src/Compilation.zig index d62856b0111be20def4ebf322ee0f58831995161..df6fc7b06b192553ca5faed923c4a9b4406814f5 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2134,6 +2134,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, comp.config.any_fuzz = any_fuzz; if (opt_zcu) |zcu| { + // Finish initializing the `zcu` after the fields on `comp` have been initialized. + zcu.initAfterCompilation(); + // Populate `zcu.module_roots`. const active = zcu.acquire(); defer active.release(); diff --git a/src/Zcu.zig b/src/Zcu.zig index d3c180b63eb8854ec8598cdb3099bba7a41fb2b3..d71d8ecf80ef074a1800c9d637744a023523fede 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -2825,6 +2825,11 @@ pub const CompileError = error{ pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void { try zcu.intern_pool.init(gpa, io, thread_count); +} + +/// It is valid to not call this function before `deinit` in error paths. +/// Requires the fields on `zcu.comp` to already be initialized. +pub fn initAfterCompilation(zcu: *Zcu) void { zcu.initTracyPlots(); } -- 2.54.0 From e26a70cb96bbdeb633314dec8afa9daf3029b894 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 27 Jun 2026 04:19:58 -0400 Subject: [PATCH 03/22] main: minor improvement to testing with cbe --- src/main.zig | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main.zig b/src/main.zig index 94011c81f9215df1da00328f221c41e42b9bc214..a7b8ddb6d08cac1dfd2b882f4dda65ec03c181d1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3835,11 +3835,17 @@ fn buildOutputType( var prev_has_cflags = false; var prev_has_rcflags = false; - if (dirs.zig_lib.path) |zig_lib_path| { - try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" }); - prev_has_cflags = true; + { + if (dirs.zig_lib.path) |zig_lib_path| { + try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" }); + prev_has_cflags = true; + } + const emit_ext: Compilation.FileExt = .c; + const need_lang = if (comp.emit_bin) |comp_emit_bin| Compilation.classifyFileExt(comp_emit_bin) != emit_ext else true; + if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", emit_ext.toLang() }); + try test_exec_args.append(arena, null); + if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", "none" }); } - try test_exec_args.append(arena, null); for (create_module.modules.keys(), create_module.modules.values()) |mod_name, mod| { for (create_module.c_source_files.items[mod.c_source_files_start..mod.c_source_files_end]) |c_source_file| { const cflags_len = c_source_file.extra_flags.len + c_source_file.cache_exempt_flags.len; -- 2.54.0 From 9e7f40db3a83242e12db853431cea0701446f5fb Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Tue, 23 Jun 2026 09:09:43 -0400 Subject: [PATCH 04/22] InternPool: update `Tag.encodings` to fix lldb pretty printing --- lib/std/hash_map.zig | 2 +- lib/std/multi_array_list.zig | 4 +-- src/InternPool.zig | 54 ++++++++++++++++++------------------ 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig index a6562bc5ea1ab479963b308beae24fb303d98c6d..b11f7e4a0dee9413d8ca5a798492c48f0ba5dde1 100644 --- a/lib/std/hash_map.zig +++ b/lib/std/hash_map.zig @@ -1518,7 +1518,7 @@ fn Custom( self.available = 0; } - /// This function is used in the debugger pretty formatters in tools/ to fetch the + /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the /// header type to facilitate fancy debug printing for this type. fn dbHelper(self: *Self, hdr: *Header, entry: *Entry) void { _ = self; diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig index a10f261e31ef8d4f47a976eebb3f637c199f835f..ce6265655eb690499577bc7fbd29c19eab375854 100644 --- a/lib/std/multi_array_list.zig +++ b/lib/std/multi_array_list.zig @@ -163,7 +163,7 @@ pub fn MultiArrayList(comptime T: type) type { }; } - /// This function is used in the debugger pretty formatters in tools/ to fetch the + /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the /// child field order and entry type to facilitate fancy debug printing for this type. fn dbHelper(self: *Slice, child: *Elem, field: *Field, entry: *Entry) void { _ = self; @@ -681,7 +681,7 @@ pub fn MultiArrayList(comptime T: type) type { } break :entry @Struct(.@"extern", null, &entry_field_names, &entry_field_types, &entry_field_attrs); }; - /// This function is used in the debugger pretty formatters in tools/ to fetch the + /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the /// child field order and entry type to facilitate fancy debug printing for this type. fn dbHelper(self: *Self, child: *Elem, field: *Field, entry: *Entry) void { _ = self; diff --git a/src/InternPool.zig b/src/InternPool.zig index 5a28a997418a52a40a06c324d610348ab5c17800..8502055c372f2fb915be32133ee6a8be60916e4b 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -4193,7 +4193,7 @@ pub const Index = enum(u32) { }; } - /// This function is used in the debugger pretty formatters in tools/ to fetch the + /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the /// Tag to encoding mapping to facilitate fancy debug printing for this type. fn dbHelper(self: *Index, tag_to_encoding_map: *struct { const DataIsIndex = struct { data: Index }; @@ -4219,26 +4219,17 @@ pub const Index = enum(u32) { type_inferred_error_set: DataIsIndex, simple_type: void, type_function: struct { - const @"data.flags.has_comptime_bits" = opaque {}; - const @"data.flags.has_noalias_bits" = opaque {}; - const @"data.flags.cc.extraLen()" = opaque {}; const @"data.params_len" = opaque {}; data: *Tag.TypeFunction, - @"trailing.comptime_bits.len": *@"data.flags.has_comptime_bits", - @"trailing.noalias_bits.len": *@"data.flags.has_noalias_bits", - @"trailing.cc_bits.len": *@"data.flags.cc.extraLen()", @"trailing.param_types.len": *@"data.params_len", - trailing: struct { comptime_bits: []u32, noalias_bits: []u32, cc_bits: []u32, param_types: []Index }, + trailing: struct { param_types: []Index }, }, type_tuple: struct { const @"data.fields_len" = opaque {}; data: *TypeTuple, @"trailing.types.len": *@"data.fields_len", @"trailing.values.len": *@"data.fields_len", - trailing: struct { - types: []Index, - values: []Index, - }, + trailing: struct { types: []Index, values: []Index }, }, type_struct: struct { data: *Tag.TypeStruct }, @@ -4350,7 +4341,7 @@ pub const Index = enum(u32) { const encoding = @field(Tag.encodings, tag_name); if (@hasField(@TypeOf(encoding), "trailing")) { const trailing_info = @typeInfo(encoding.trailing).@"struct"; - for (trailing_info.field_names, trailing_info.field_types) |field_name, field_type| { + for (trailing_info.field_names, trailing_info.field_types) |trailing_field_name, trailing_field_type| { struct { fn checkConfig(name: []const u8) void { if (!@hasField(@TypeOf(encoding.config), name)) @compileError("missing field: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ ".config.@\"" ++ name ++ "\""); @@ -4359,22 +4350,30 @@ pub const Index = enum(u32) { } fn checkField(name: []const u8, Type: type) void { switch (@typeInfo(Type)) { - .int => {}, - .@"enum" => {}, - .@"struct" => |info| assert(info.layout == .@"packed"), + .int, .@"enum" => return, + .@"struct" => |info| switch (info.layout) { + .auto => unreachable, + .@"extern" => { + for (info.field_names, info.field_types) |field_name, field_type| checkField(name ++ "." ++ field_name, field_type); + return; + }, + .@"packed" => return, + }, .optional => |info| { checkConfig(name ++ ".?"); checkField(name ++ ".?", info.child); + return; }, - .pointer => |info| { - assert(info.size == .slice); + .pointer => |info| if (info.size == .slice) { checkConfig(name ++ ".len"); checkField(name ++ "[0]", info.child); + return; }, - else => @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ "." ++ name ++ ": " ++ @typeName(Type)), + else => {}, } + @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ "." ++ name ++ ": " ++ @typeName(Type)); } - }.checkField("trailing." ++ field_name, field_type); + }.checkField("trailing." ++ trailing_field_name, trailing_field_type); } } }, @@ -5186,17 +5185,18 @@ pub const Tag = enum(u8) { .trailing = struct { param_comptime_bits: ?[]u32, param_noalias_bits: ?[]u32, - param_cc_bits: ?[]u32, - param_type: []Index, + spirv_kernel_options: ?extern struct { x: u32, y: u32, z: u32 }, + spirv_mesh_options: ?extern struct { max_primitives: u32, max_vertices: u32 }, + param_types: []Index, }, .config = .{ .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits", .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32", .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits", .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32", - .@"trailing.param_cc_bits.?" = .@"payload.flags.cc.extraLen() != 0", - .@"trailing.param_cc_bits.?.len" = .@"payload.flags.cc.extraLen()", - .@"trailing.param_type.len" = .@"payload.params_len", + .@"trailing.spirv_kernel_options.?" = .@"payload.flags.cc.tag == .spirv_kernel or payload.flags.cc.tag == .spirv_task", + .@"trailing.spirv_mesh_options.?" = .@"payload.flags.cc.tag == .spirv_mesh", + .@"trailing.param_types.len" = .@"payload.params_len", }, }, @@ -5225,7 +5225,7 @@ pub const Tag = enum(u8) { .@"trailing.field_defaults.?" = .@"payload.flags.any_field_defaults", .@"trailing.field_defaults.?.len" = .@"payload.fields_len", .@"trailing.field_aligns.?" = .@"payload.flags.any_field_aligns", - .@"trailing.field_aligns.?.len" = .@"payload.fields_len", + .@"trailing.field_aligns.?.len" = .@"(payload.fields_len + 3) / 4", .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields", .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32", .@"trailing.field_runtime_order.?" = .@"payload.flags.layout == .auto", @@ -5254,7 +5254,7 @@ pub const Tag = enum(u8) { .@"trailing.captures.?.len" = .@"trailing.captures_len.?", .@"trailing.field_types.len" = .@"payload.fields_len", .@"trailing.field_aligns.?" = .@"payloads.flags.any_field_aligns", - .@"trailing.field_aligns.?.len" = .@"payload.fields_len", + .@"trailing.field_aligns.?.len" = .@"(payload.fields_len + 3) / 4", }, }, .type_union_packed_auto = union_packed_encoding, -- 2.54.0 From c6ab46cc3effecd18db8b8469de965eafd02e1fd Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 26 Jun 2026 01:52:10 -0400 Subject: [PATCH 05/22] llvm: `TypeRepr.by_value` -> `TypeRepr.as_value` Otherwise, I constantly get it confused with `by_val` and `byval`. --- src/codegen/llvm.zig | 40 +++--- src/codegen/llvm/FuncGen.zig | 234 +++++++++++++++++------------------ 2 files changed, 137 insertions(+), 137 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 12422f9f6f8ba5609730e1f38e37960951409174..6d200cacafc52cc7067eefe18f07c1d1a9580768 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2848,7 +2848,7 @@ pub const Object = struct { pub const TypeRepr = enum { /// The representation of the type when it is being manipulated as a value in a function. /// e.g. Zig `u5` -> LLVM `i5` - by_value, + as_value, /// The representation of the type when it is stored in memory. /// e.g. Zig `u5` -> LLVM `i8` in_memory, @@ -2856,7 +2856,7 @@ pub const Object = struct { pub fn errorIntType(o: *Object, repr: TypeRepr) Allocator.Error!Builder.Type { return o.builder.intType(switch (repr) { - .by_value => o.zcu.errorSetBits(), + .as_value => o.zcu.errorSetBits(), .in_memory => @intCast(Type.anyerror.abiSize(o.zcu) * 8), }); } @@ -2866,7 +2866,7 @@ pub const Object = struct { const target = zcu.getTarget(); const ip = &zcu.intern_pool; - if (repr == .by_value) { + if (repr == .as_value) { assert(!isByRef(t, zcu)); // by-ref types must only be manipulated in memory } @@ -2886,7 +2886,7 @@ pub const Object = struct { .u128_type, .i128_type, => |tag| switch (repr) { - .by_value => @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]), + .as_value => @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]), .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)), }, .usize_type, .isize_type => try o.builder.intType(target.ptrBitWidth()), @@ -2973,7 +2973,7 @@ pub const Object = struct { => unreachable, else => switch (ip.indexToKey(t.toIntern())) { .int_type => |int_type| switch (repr) { - .by_value => try o.builder.intType(int_type.bits), + .as_value => try o.builder.intType(int_type.bits), .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)), }, .ptr_type => |ptr_type| type: { @@ -2995,7 +2995,7 @@ pub const Object = struct { .vector_type => |vector_type| o.builder.vectorType( .normal, vector_type.len, - try o.lowerType(.fromInterned(vector_type.child), .by_value), + try o.lowerType(.fromInterned(vector_type.child), .as_value), ), .opt_type => |child_ty| { // Must stay in sync with `opt_payload` logic in `lowerPtr`. @@ -3310,7 +3310,7 @@ pub const Object = struct { .no_bits => continue, .byval => { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .by_value)); + try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .as_value)); }, .byref, .byref_mut => { try llvm_params.append(o.gpa, .ptr); @@ -3325,7 +3325,7 @@ pub const Object = struct { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); try llvm_params.appendSlice(o.gpa, &.{ try o.builder.ptrType(toLlvmAddressSpace(param_ty.ptrAddressSpace(zcu), target)), - try o.lowerType(.usize, .by_value), + try o.lowerType(.usize, .as_value), }); }, .multiple_llvm_types => { @@ -3347,7 +3347,7 @@ pub const Object = struct { const llvm_ret_ty: Builder.Type = switch (ret_strat) { .void, .sret => .void, - .by_val => try o.lowerType(.fromInterned(fn_info.return_type), .by_value), + .by_val => try o.lowerType(.fromInterned(fn_info.return_type), .as_value), .mem_cast => |llvm_ret_ty| llvm_ret_ty, }; const llvm_fn_kind: Builder.Type.Function.Kind = switch (fn_info.is_var_args) { @@ -3604,7 +3604,7 @@ pub const Object = struct { result_val.* = try o.builder.intConst(.i8, byte); }, .elems => |elems| for (vals, elems) |*result_val, elem| { - result_val.* = try o.lowerValue(elem, .by_value); + result_val.* = try o.lowerValue(elem, .as_value); }, .repeated_elem => unreachable, } @@ -3612,7 +3612,7 @@ pub const Object = struct { }, .repeated_elem => |elem| return o.builder.splatConst( vector_ty, - try o.lowerValue(elem, .by_value), + try o.lowerValue(elem, .as_value), ), } }, @@ -3869,8 +3869,8 @@ pub const Object = struct { }, .int => try o.builder.castConst( .inttoptr, - try o.builder.intConst(try o.lowerType(.usize, .by_value), offset), - try o.lowerType(.fromInterned(ptr.ty), .by_value), + try o.builder.intConst(try o.lowerType(.usize, .as_value), offset), + try o.lowerType(.fromInterned(ptr.ty), .as_value), ), .eu_payload => |eu_ptr| try o.lowerPtr( eu_ptr, @@ -3917,7 +3917,7 @@ pub const Object = struct { @"addrspace": std.lang.AddressSpace, ) Allocator.Error!Builder.Constant { const addr: u64 = @"align".toByteUnits().?; - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); const llvm_addr = try o.builder.intConst(llvm_usize, addr); const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(@"addrspace", o.zcu.getTarget())); return o.builder.castConst(.inttoptr, llvm_addr, llvm_ptr_ty); @@ -4132,9 +4132,9 @@ pub const Object = struct { const ip = &zcu.intern_pool; const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); - const llvm_usize_ty = try o.lowerType(.usize, .by_value); - const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .by_value); - const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); + const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .as_value); + const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value); function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = try o.builder.fnType(llvm_ret_ty, &.{llvm_int_ty}, .normal); @@ -4183,7 +4183,7 @@ pub const Object = struct { const return_block = try wip.block(1, "Name"); const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, field_index)) { .none => try o.builder.intConst(llvm_int_ty, field_index), // auto-numbered - else => |tag_val_ip| try o.lowerValue(tag_val_ip, .by_value), + else => |tag_val_ip| try o.lowerValue(tag_val_ip, .as_value), }; try wip_switch.addCase(llvm_tag_val, return_block, &wip); @@ -4229,7 +4229,7 @@ pub const Object = struct { const ip = &zcu.intern_pool; const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); - const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value); + const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value); function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = try o.builder.fnType(.i1, &.{llvm_int_ty}, .normal); @@ -4256,7 +4256,7 @@ pub const Object = struct { if (loaded_enum.field_values.len > 0) { for (loaded_enum.field_values.get(ip)) |tag_val_ip| { - const llvm_tag_val = try o.lowerValue(tag_val_ip, .by_value); + const llvm_tag_val = try o.lowerValue(tag_val_ip, .as_value); try wip_switch.addCase(llvm_tag_val, named_block, &wip); } } else { diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 6e2d71994a6f67a10a9aa7723071c419cd1815e4..5e05a779220d002a88fd128d5057f5eef70e1a4a 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -164,7 +164,7 @@ fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant { const zcu = o.zcu; const ty = val.typeOf(zcu); if (!isByRef(ty, zcu)) { - return o.lowerValue(val.toIntern(), .by_value); + return o.lowerValue(val.toIntern(), .as_value); } else { // We need a pointer to a global constant, i.e. a UAV. return o.lowerUavRef( @@ -264,7 +264,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); assert(!isByRef(param_ty, zcu)); const slice_val = try fg.wip.buildAggregate( - try o.lowerType(param_ty, .by_value), + try o.lowerType(param_ty, .as_value), &.{ fg.wip.arg(it.llvm_index - 2), fg.wip.arg(it.llvm_index - 1) }, "", ); @@ -998,7 +998,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier }, cc_info.llvm_cc, try attributes.finish(&o.builder), - try o.lowerType(zig_fn_ty, .by_value), + try o.lowerType(zig_fn_ty, .as_value), llvm_fn, llvm_args.items, "", @@ -1038,7 +1038,7 @@ fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) Allocator.Error!v const target = zcu.getTarget(); const panic_func = zcu.funcInfo(zcu.std_lang_decl_values.get(panic_id.toStdLangDecl())); const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?; - const llvm_panic_fn_ty = try o.lowerType(.fromInterned(panic_func.ty), .by_value); + const llvm_panic_fn_ty = try o.lowerType(.fromInterned(panic_func.ty), .as_value); const llvm_panic_fn_ref = try o.lowerNavRef(panic_func.owner_nav); @@ -1076,7 +1076,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo .none => try self.buildZigAlloca(ret_ty, .none), else => |rp| rp, }; - const len = try o.builder.intValue(try o.lowerType(.usize, .by_value), ret_ty.abiSize(zcu)); + const len = try o.builder.intValue(try o.lowerType(.usize, .as_value), ret_ty.abiSize(zcu)); _ = try self.wip.callMemSet( rp, ret_ty_align.toLlvm(), @@ -1165,7 +1165,7 @@ fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const list = try self.resolveInst(ty_op.operand); const arg_ty = ty_op.ty.toType(); - const llvm_arg_ty = try self.object.lowerType(arg_ty, .by_value); + const llvm_arg_ty = try self.object.lowerType(arg_ty, .as_value); return self.wip.vaArg(list, llvm_arg_ty, ""); } @@ -1378,7 +1378,7 @@ fn lowerBlock( if (have_block_result) { const llvm_ty: Builder.Type = switch (isByRef(inst_ty, zcu)) { true => .ptr, - false => try o.lowerType(inst_ty, .by_value), + false => try o.lowerType(inst_ty, .as_value), }; parent_bb.ptr(&self.wip).incoming = @intCast(breaks.list.len); const phi = try self.wip.phi(llvm_ty, ""); @@ -1485,7 +1485,7 @@ fn lowerSwitchDispatch( const table_index = try self.wip.conv( .unsigned, try self.wip.bin(.@"sub nuw", cond, jmp_table.min.toValue(), ""), - try o.lowerType(.usize, .by_value), + try o.lowerType(.usize, .as_value), "", ); const target_ptr_ptr = try self.ptraddScaled( @@ -1510,7 +1510,7 @@ fn lowerSwitchDispatch( // The switch prongs will correspond to our scalar cases. Ranges will // be handled by conditional branches in the `else` prong. - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); const cond_int = if (cond_ty.zigTypeTag(zcu) == .pointer) try self.wip.cast(.ptrtoint, cond, llvm_usize, "") else @@ -1725,7 +1725,7 @@ fn lowerTry( if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal, ); }; - const zero = try o.builder.intValue(try o.errorIntType(.by_value), 0); + const zero = try o.builder.intValue(try o.errorIntType(.as_value), 0); const is_err = try fg.wip.icmp(.ne, loaded, zero, ""); const return_block = try fg.wip.block(1, "TryRet"); @@ -1862,8 +1862,8 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod const table_includes_else = item_count != table_len; break :jmp_table .{ - .min = try o.lowerValue(min.toIntern(), .by_value), - .max = try o.lowerValue(max.toIntern(), .by_value), + .min = try o.lowerValue(min.toIntern(), .as_value), + .max = try o.lowerValue(max.toIntern(), .as_value), .in_bounds_hint = if (table_includes_else) .none else switch (switch_br.getElseHint()) { .none, .cold => .none, .unpredictable => .unpredictable, @@ -2021,9 +2021,9 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const operand_ty = self.typeOf(ty_op.operand); const array_ty = operand_ty.childType(zcu); - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu)); - const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst), .by_value); + const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst), .as_value); const operand = try self.resolveInst(ty_op.operand); return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, ""); } @@ -2040,7 +2040,7 @@ fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value const dest_ty = self.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); - const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); + const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const target = zcu.getTarget(); if (intrinsicsAllowed(dest_scalar_ty, target)) return self.wip.conv( @@ -2108,7 +2108,7 @@ fn airIntFromFloat( const dest_ty = self.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); - const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); + const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); if (intrinsicsAllowed(operand_scalar_ty, target)) { // TODO set fast math flag @@ -2142,7 +2142,7 @@ fn airIntFromFloat( compiler_rt_dest_abbrev, }); - const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); + const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); var result = try self.wip.call( .normal, @@ -2167,7 +2167,7 @@ fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!B fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value { const o = fg.object; const zcu = o.zcu; - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); switch (ty.ptrSize(zcu)) { .slice => { const len = try fg.wip.extractValue(ptr, &.{1}, ""); @@ -2365,7 +2365,7 @@ fn airAggFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder. }, .float => { // bitcast int->float - return self.wip.cast(.bitcast, field_int_val, try o.lowerType(field_ty, .by_value), ""); + return self.wip.cast(.bitcast, field_int_val, try o.lowerType(field_ty, .as_value), ""); }, } } @@ -2395,8 +2395,8 @@ fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu); if (field_offset == 0) return field_ptr; - const res_ty = try o.lowerType(ty_pl.ty.toType(), .by_value); - const llvm_usize = try o.lowerType(.usize, .by_value); + const res_ty = try o.lowerType(ty_pl.ty.toType(), .as_value); + const llvm_usize = try o.lowerType(.usize, .as_value); const field_ptr_int = try self.wip.cast(.ptrtoint, field_ptr, llvm_usize, ""); const base_ptr_int = try self.wip.bin( @@ -2612,7 +2612,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { const output_inst = try self.resolveInst(output.operand); const output_ty = self.typeOf(output.operand); assert(output_ty.zigTypeTag(zcu) == .pointer); - const elem_llvm_ty = try o.lowerType(output_ty.childType(zcu), .by_value); + const elem_llvm_ty = try o.lowerType(output_ty.childType(zcu), .as_value); switch (constraint[0]) { '=' => {}, @@ -2650,7 +2650,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { llvm_ret_indirect[output.index] = false; const ret_ty = self.typeOfIndex(inst); - llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty, .by_value); + llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty, .as_value); llvm_ret_i += 1; } @@ -2689,7 +2689,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { llvm_param_types[llvm_param_i] = arg_llvm_value.typeOfWip(&self.wip); } else { const alignment = arg_ty.abiAlignment(zcu).toLlvm(); - const arg_llvm_ty = try o.lowerType(arg_ty, .by_value); + const arg_llvm_ty = try o.lowerType(arg_ty, .as_value); const load_inst = try self.wip.load(.normal, arg_llvm_ty, arg_llvm_value, alignment, ""); llvm_param_values[llvm_param_i] = load_inst; llvm_param_types[llvm_param_i] = arg_llvm_ty; @@ -2729,7 +2729,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: { if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu)); - break :blk try o.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu), .by_value); + break :blk try o.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu), .as_value); } else .none; llvm_param_i += 1; @@ -2743,7 +2743,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { if (constraint[0] != '+') continue; const rw_ty = self.typeOf(output.operand); - const llvm_elem_ty = try o.lowerType(rw_ty.childType(zcu), .by_value); + const llvm_elem_ty = try o.lowerType(rw_ty.childType(zcu), .as_value); if (llvm_ret_indirect[output.index]) { llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index]; llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip); @@ -2957,7 +2957,7 @@ fn airIsNonNull( )); return self.wip.icmp(cond, slice_ptr, try o.builder.nullValue(ptr_ty), ""); } - return self.wip.icmp(cond, loaded, try o.builder.zeroInitValue(try o.lowerType(optional_ty, .by_value)), ""); + return self.wip.icmp(cond, loaded, try o.builder.zeroInitValue(try o.lowerType(optional_ty, .as_value)), ""); } comptime assert(optional_layout_version == 3); @@ -2986,7 +2986,7 @@ fn airIsErr( const operand_ty = self.typeOf(un_op); const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty; const payload_ty = err_union_ty.errorUnionPayload(zcu); - const zero_err = try o.builder.intValue(try o.errorIntType(.by_value), 0); + const zero_err = try o.builder.intValue(try o.errorIntType(.as_value), 0); const access_kind: Builder.MemoryAccessKind = if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; @@ -3156,7 +3156,7 @@ fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu); const payload_ty = err_union_ty.errorUnionPayload(zcu); - const non_error_val = try o.builder.intValue(try o.errorIntType(.by_value), 0); + const non_error_val = try o.builder.intValue(try o.errorIntType(.as_value), 0); const access_kind: Builder.MemoryAccessKind = if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; @@ -3234,7 +3234,7 @@ fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error! const payload_ty = self.typeOf(ty_op.operand); assert(payload_ty.hasRuntimeBits(zcu)); assert(isByRef(err_un_ty, zcu)); // error unions with runtime bits are always by-ref - const ok_err_code = try o.builder.intValue(try o.errorIntType(.by_value), 0); + const ok_err_code = try o.builder.intValue(try o.errorIntType(.as_value), 0); const result_ptr = try self.buildZigAlloca(err_un_ty, .none); @@ -3273,7 +3273,7 @@ fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const o = self.object; const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op; const index = pl_op.payload; - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{llvm_usize}, &.{ try o.builder.intValue(.i32, index), }, ""); @@ -3283,7 +3283,7 @@ fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const o = self.object; const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op; const index = pl_op.payload; - const llvm_isize = try o.lowerType(.isize, .by_value); + const llvm_isize = try o.lowerType(.isize, .as_value); return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{llvm_isize}, &.{ try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand), }, ""); @@ -3310,7 +3310,7 @@ fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { .normal, .none, if (scalar_ty.isSignedInt(zcu)) .smin else .umin, - &.{try o.lowerType(inst_ty, .by_value)}, + &.{try o.lowerType(inst_ty, .as_value)}, &.{ lhs, rhs }, "", ); @@ -3330,7 +3330,7 @@ fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { .normal, .none, if (scalar_ty.isSignedInt(zcu)) .smax else .umax, - &.{try o.lowerType(inst_ty, .by_value)}, + &.{try o.lowerType(inst_ty, .as_value)}, &.{ lhs, rhs }, "", ); @@ -3342,7 +3342,7 @@ fn airSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ptr = try self.resolveInst(bin_op.lhs); const len = try self.resolveInst(bin_op.rhs); const inst_ty = self.typeOfIndex(inst); - return self.wip.buildAggregate(try self.object.lowerType(inst_ty, .by_value), &.{ ptr, len }, ""); + return self.wip.buildAggregate(try self.object.lowerType(inst_ty, .as_value), &.{ ptr, len }, ""); } fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { @@ -3373,7 +3373,7 @@ fn airSafeArithmetic( const scalar_ty = inst_ty.scalarType(zcu); const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic; - const llvm_inst_ty = try o.lowerType(inst_ty, .by_value); + const llvm_inst_ty = try o.lowerType(inst_ty, .as_value); const results = try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, ""); @@ -3423,7 +3423,7 @@ fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"sadd.sat" else .@"uadd.sat", - &.{try o.lowerType(inst_ty, .by_value)}, + &.{try o.lowerType(inst_ty, .as_value)}, &.{ lhs, rhs }, "", ); @@ -3462,7 +3462,7 @@ fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"ssub.sat" else .@"usub.sat", - &.{try o.lowerType(inst_ty, .by_value)}, + &.{try o.lowerType(inst_ty, .as_value)}, &.{ lhs, rhs }, "", ); @@ -3501,7 +3501,7 @@ fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"smul.fix.sat" else .@"umul.fix.sat", - &.{try o.lowerType(inst_ty, .by_value)}, + &.{try o.lowerType(inst_ty, .as_value)}, &.{ lhs, rhs, .@"0" }, "", ); @@ -3545,8 +3545,8 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result}); } if (scalar_ty.isSignedInt(zcu)) { - const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); - const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); + const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); + const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb; var bfa_buf: ExpectedContents = undefined; @@ -3594,8 +3594,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) return self.buildFloatOp(.ceil, fast, inst_ty, 1, .{result}); } if (scalar_ty.isSignedInt(zcu)) { - const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); - const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); + const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); + const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb; var bfa_buf: ExpectedContents = undefined; @@ -3634,8 +3634,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) const correction = try self.wip.cast(.zext, need_correction, inst_llvm_ty, "divCeil.correction"); return self.wip.bin(.@"add nsw", div, correction, "divCeil"); } else { - const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); - const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); + const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); + const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const zero = try o.builder.splatValue( inst_llvm_ty, @@ -3692,7 +3692,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); const inst_ty = self.typeOfIndex(inst); - const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); + const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const scalar_ty = inst_ty.scalarType(zcu); if (scalar_ty.isRuntimeFloat()) { @@ -3721,7 +3721,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo defer allocator.free(smin_big_int.limbs); smin_big_int.setTwosCompIntLimit(.min, .signed, scalar_bits); const smin = try o.builder.splatValue(inst_llvm_ty, try o.builder.bigIntConst( - try o.lowerType(scalar_ty, .by_value), + try o.lowerType(scalar_ty, .as_value), smin_big_int.toConst(), )); @@ -3757,7 +3757,7 @@ fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_or_slice = try self.resolveInst(bin_op.lhs); - const llvm_usize_ty = try o.lowerType(.usize, .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); const ptr_ty = self.typeOf(bin_op.lhs); const elem_ty = ptr_ty.indexableElem(zcu); const ptr = switch (ptr_ty.ptrSize(zcu)) { @@ -3790,7 +3790,7 @@ fn airOverflow( assert(isByRef(inst_ty, zcu)); // auto structs are by-ref const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic; - const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value); + const llvm_lhs_ty = try o.lowerType(lhs_ty, .as_value); const results = try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, ""); @@ -3863,7 +3863,7 @@ fn buildFloatCmp( const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); + const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); if (intrinsicsAllowed(scalar_ty, target)) { const cond: Builder.FloatCondition = switch (pred) { @@ -3969,7 +3969,7 @@ fn buildFloatOp( const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const llvm_ty = try o.lowerType(ty, .by_value); + const llvm_ty = try o.lowerType(ty, .as_value); if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) { // Some operations are dedicated LLVM instructions, not available as intrinsics @@ -4074,7 +4074,7 @@ fn buildFloatOp( }), }; - const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); + const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); const libc_fn = try o.getLibcFunction( fn_name, @as([3]Builder.Type, @splat(scalar_llvm_ty))[0..params.len], @@ -4129,7 +4129,7 @@ fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil const dest_ty = self.typeOfIndex(inst); assert(isByRef(dest_ty, zcu)); // auto structs are by-ref - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), ""); const result = try self.wip.bin(.shl, lhs, casted_rhs, ""); const reconstructed = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu)) @@ -4196,7 +4196,7 @@ fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val } const lhs_scalar_ty = lhs_ty.scalarType(zcu); - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), ""); return self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu)) .@"shl nsw" else @@ -4217,7 +4217,7 @@ fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { // features which we do not use. Therefore this branch is currently impossible. unreachable; } - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), ""); return self.wip.bin(.shl, lhs, casted_rhs, ""); } @@ -4231,8 +4231,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const lhs_ty = self.typeOf(bin_op.lhs); const lhs_info = lhs_ty.intInfo(zcu); - const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value); - const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .by_value); + const llvm_lhs_ty = try o.lowerType(lhs_ty, .as_value); + const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .as_value); const rhs_ty = self.typeOf(bin_op.rhs); if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) { @@ -4242,8 +4242,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } const rhs_info = rhs_ty.intInfo(zcu); assert(rhs_info.signedness == .unsigned); - const llvm_rhs_ty = try o.lowerType(rhs_ty, .by_value); - const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .by_value); + const llvm_rhs_ty = try o.lowerType(rhs_ty, .as_value); + const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .as_value); const result = try self.wip.callIntrinsic( .normal, @@ -4319,7 +4319,7 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error! } const lhs_scalar_ty = lhs_ty.scalarType(zcu); - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), ""); const is_signed_int = lhs_scalar_ty.isSignedInt(zcu); return self.wip.bin(if (is_exact) @@ -4340,7 +4340,7 @@ fn airAbs(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { .normal, .none, .abs, - &.{try o.lowerType(operand_ty, .by_value)}, + &.{try o.lowerType(operand_ty, .as_value)}, &.{ operand, .false }, "", ), @@ -4354,7 +4354,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! const zcu = o.zcu; const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op; const dest_ty = fg.typeOfIndex(inst); - const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); + const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const operand = try fg.resolveInst(ty_op.operand); const operand_ty = fg.typeOf(ty_op.operand); const operand_info = operand_ty.intInfo(zcu); @@ -4382,8 +4382,8 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! if (!have_min_check and !have_max_check) break :bounds_check; - const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); - const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .by_value); + const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); + const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .as_value); const is_vector = operand_ty.zigTypeTag(zcu) == .vector; assert(is_vector == (dest_ty.zigTypeTag(zcu) == .vector)); @@ -4461,7 +4461,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); - const dest_llvm_ty = try self.object.lowerType(self.typeOfIndex(inst), .by_value); + const dest_llvm_ty = try self.object.lowerType(self.typeOfIndex(inst), .as_value); return self.wip.cast(.trunc, operand, dest_llvm_ty, ""); } @@ -4475,10 +4475,10 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu const target = zcu.getTarget(); if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { - return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .by_value), ""); + return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .as_value), ""); } else { - const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); - const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); + const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); + const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const dest_bits = dest_ty.floatBits(target); const src_bits = operand_ty.floatBits(target); @@ -4509,10 +4509,10 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const target = zcu.getTarget(); if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { - return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .by_value), ""); + return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .as_value), ""); } else { - const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); - const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); + const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); + const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const dest_bits = dest_ty.scalarType(zcu).floatBits(target); const src_bits = operand_ty.scalarType(zcu).floatBits(target); @@ -4563,7 +4563,7 @@ fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! assert(!isByRef(operand_ty, zcu)); assert(!isByRef(dest_ty, zcu)); - const llvm_dest_ty = try o.lowerType(dest_ty, .by_value); + const llvm_dest_ty = try o.lowerType(dest_ty, .as_value); const result = try fg.wip.cast(.bitcast, operand, llvm_dest_ty, ""); if (safety and dest_ty.zigTypeTag(zcu) == .@"enum" and !dest_ty.isNonexhaustiveEnum(zcu)) { const llvm_fn = try o.getIsNamedEnumValueFunction(dest_ty); @@ -4606,7 +4606,7 @@ fn airPtrFromInt(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val assert(dest_ty.scalarType(zcu).isPtrAtRuntime(zcu)); const operand = try fg.resolveInst(ty_op.operand); - const llvm_dest_ty = try o.lowerType(dest_ty, .by_value); + const llvm_dest_ty = try o.lowerType(dest_ty, .as_value); return fg.wip.cast(.inttoptr, operand, llvm_dest_ty, ""); } @@ -4620,7 +4620,7 @@ fn airIntFromPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val assert(dest_ty.scalarType(zcu).toIntern() == .usize_type); const operand = try fg.resolveInst(ty_op.operand); - const llvm_dest_ty = try o.lowerType(dest_ty, .by_value); + const llvm_dest_ty = try o.lowerType(dest_ty, .as_value); return fg.wip.cast(.ptrtoint, operand, llvm_dest_ty, ""); } @@ -4832,7 +4832,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu return .none; } - const len = try o.builder.intValue(try o.lowerType(.usize, .by_value), elem_ty.abiSize(zcu)); + const len = try o.builder.intValue(try o.lowerType(.usize, .as_value), elem_ty.abiSize(zcu)); _ = try fg.wip.callMemSet( ptr, ptr_alignment.toLlvm(), @@ -4867,7 +4867,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu if (ptr_info.packed_offset.host_size != 0) { // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8)); - const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .by_value); + const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .as_value); const backing_int_val = try fg.load(ptr, ptr_alignment, backing_int_ty, access_kind); @@ -4945,14 +4945,14 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8)); - const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .by_value); + const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .as_value); const backing_int_val = try fg.load(ptr, ptr_align, backing_int_ty, .normal); const elem_bits = ptr_ty.childType(zcu).bitSize(zcu); const shift_amt = try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset); const shifted_value = try fg.wip.bin(.lshr, backing_int_val, shift_amt, ""); - const elem_llvm_ty = try o.lowerType(elem_ty, .by_value); + const elem_llvm_ty = try o.lowerType(elem_ty, .as_value); if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) { const same_size_int = try o.builder.intType(@intCast(elem_bits)); @@ -5002,7 +5002,7 @@ fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = inst; const o = self.object; - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); if (!target_util.supportsReturnAddress(self.object.zcu.getTarget(), self.ownerModule().optimize_mode)) { // https://github.com/ziglang/zig/issues/11946 return o.builder.intValue(llvm_usize, 0); @@ -5014,7 +5014,7 @@ fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = inst; const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{.@"0"}, ""); - return self.wip.cast(.ptrtoint, result, try self.object.lowerType(.usize, .by_value), ""); + return self.wip.cast(.ptrtoint, result, try self.object.lowerType(.usize, .as_value), ""); } fn airCmpxchg( @@ -5031,7 +5031,7 @@ fn airCmpxchg( var expected_value = try self.resolveInst(extra.expected_value); var new_value = try self.resolveInst(extra.new_value); const operand_ty = ptr_ty.childType(zcu); - const llvm_operand_ty = try o.lowerType(operand_ty, .by_value); + const llvm_operand_ty = try o.lowerType(operand_ty, .as_value); const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, false); if (llvm_abi_ty != .none) { // operand needs widening and truncating @@ -5101,7 +5101,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float); const ordering = toLlvmAtomicOrdering(extra.ordering()); const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, op == .xchg); - const llvm_operand_ty = try o.lowerType(operand_ty, .by_value); + const llvm_operand_ty = try o.lowerType(operand_ty, .as_value); const access_kind: Builder.MemoryAccessKind = if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; @@ -5130,7 +5130,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va // If we are storing a pointer we need to convert to and from a plain old integer. const non_ptr_operand = switch (operand_ty.zigTypeTag(zcu)) { - .pointer => try self.wip.cast(.ptrtoint, operand, try o.lowerType(.usize, .by_value), ""), + .pointer => try self.wip.cast(.ptrtoint, operand, try o.lowerType(.usize, .as_value), ""), else => operand, }; @@ -5169,7 +5169,7 @@ fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V Type.fromInterned(info.child).abiAlignment(zcu)).toLlvm(); const access_kind: Builder.MemoryAccessKind = if (info.flags.is_volatile) .@"volatile" else .normal; - const elem_llvm_ty = try o.lowerType(elem_ty, .by_value); + const elem_llvm_ty = try o.lowerType(elem_ty, .as_value); self.maybeMarkAllowZeroAccess(info); @@ -5503,11 +5503,11 @@ fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) .normal, .none, intrinsic, - &.{try o.lowerType(operand_ty, .by_value)}, + &.{try o.lowerType(operand_ty, .as_value)}, &.{ operand, .false }, "", ); - return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), ""); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), ""); } fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) Allocator.Error!Builder.Value { @@ -5521,11 +5521,11 @@ fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) .normal, .none, intrinsic, - &.{try o.lowerType(operand_ty, .by_value)}, + &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, "", ); - return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), ""); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), ""); } fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -5538,7 +5538,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const inst_ty = self.typeOfIndex(inst); var operand = try self.resolveInst(ty_op.operand); - var llvm_operand_ty = try o.lowerType(operand_ty, .by_value); + var llvm_operand_ty = try o.lowerType(operand_ty, .as_value); if (bits % 16 == 8) { // If not an even byte-multiple, we need zero-extend + shift-left 1 byte @@ -5559,7 +5559,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const result = try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, ""); - return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), ""); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), ""); } fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -5579,7 +5579,7 @@ fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Bui for (0..names.len) |name_index| { const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?; - const this_tag_int_value = try o.builder.intConst(try o.errorIntType(.by_value), err_int); + const this_tag_int_value = try o.builder.intConst(try o.errorIntType(.as_value), err_int); try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip); } self.wip.cursor = .{ .block = valid_block }; @@ -5638,7 +5638,7 @@ fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va const slice_ty = self.typeOfIndex(inst); // If operand is small (e.g. `u8`), then signedness becomes a problem -- GEP always treats the index as signed. - const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(.usize, .by_value), ""); + const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(.usize, .as_value), ""); const error_name_table_ptr = try o.getErrorNameTable(); const error_name_ptr = try self.ptraddScaled(error_name_table_ptr.toValue(&o.builder), operand_usize, slice_ty.abiSize(zcu)); @@ -5649,7 +5649,7 @@ fn airSplat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const scalar = try self.resolveInst(ty_op.operand); const vector_ty = self.typeOfIndex(inst); - return self.wip.splatVector(try self.object.lowerType(vector_ty, .by_value), scalar, ""); + return self.wip.splatVector(try self.object.lowerType(vector_ty, .as_value), scalar, ""); } fn airSelect(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -5672,9 +5672,9 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const operand = try fg.resolveInst(unwrapped.operand); const mask = unwrapped.mask; const operand_ty = fg.typeOf(unwrapped.operand); - const llvm_operand_ty = try o.lowerType(operand_ty, .by_value); - const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .by_value); - const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value); + const llvm_operand_ty = try o.lowerType(operand_ty, .as_value); + const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .as_value); + const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .as_value); const llvm_poison_elem = try o.builder.poisonConst(llvm_elem_ty); const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32); @@ -5704,7 +5704,7 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val .elem => llvm_poison_elem, .value => |val| if (!Value.fromInterned(val).isUndef(zcu)) elem: { any_defined_comptime_value = true; - break :elem try o.lowerValue(val, .by_value); + break :elem try o.lowerValue(val, .as_value); } else llvm_poison_elem, }; } @@ -5776,7 +5776,7 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst); const mask = unwrapped.mask; - const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value); + const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .as_value); const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32); const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); @@ -5866,7 +5866,7 @@ fn buildReducedCall( accum_init: Builder.Value, ) Allocator.Error!Builder.Value { const o = self.object; - const llvm_usize_ty = try o.lowerType(.usize, .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); const llvm_vector_len = try o.builder.intValue(llvm_usize_ty, vector_len); const llvm_result_ty = accum_init.typeOfWip(&self.wip); @@ -5924,9 +5924,9 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A const reduce = self.air.instructions.items(.data)[@backingInt(inst)].reduce; const operand = try self.resolveInst(reduce.operand); const operand_ty = self.typeOf(reduce.operand); - const llvm_operand_ty = try o.lowerType(operand_ty, .by_value); + const llvm_operand_ty = try o.lowerType(operand_ty, .as_value); const scalar_ty = self.typeOfIndex(inst); - const llvm_scalar_ty = try o.lowerType(scalar_ty, .by_value); + const llvm_scalar_ty = try o.lowerType(scalar_ty, .as_value); switch (reduce.operation) { .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { @@ -6036,7 +6036,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde switch (result_ty.zigTypeTag(zcu)) { .vector => { - const llvm_result_ty = try o.lowerType(result_ty, .by_value); + const llvm_result_ty = try o.lowerType(result_ty, .as_value); var vector = try o.builder.poisonValue(llvm_result_ty); for (elements, 0..) |elem, i| { const index_u32 = try o.builder.intValue(.i32, i); @@ -6153,10 +6153,10 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va const loaded_enum = ip.loadEnumType(tag_ty.toIntern()); const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, extra.field_index)) { .none => try o.builder.intConst( - try o.lowerType(.fromInterned(union_obj.enum_tag_type), .by_value), + try o.lowerType(.fromInterned(union_obj.enum_tag_type), .as_value), extra.field_index, // auto-numbered ), - else => |tag_val_ip| try o.lowerValue(tag_val_ip, .by_value), + else => |tag_val_ip| try o.lowerValue(tag_val_ip, .as_value), }; const tag_ptr = try self.ptraddConst(result_ptr, layout.tagOffset()); try self.store(tag_ptr, layout.tag_align, llvm_tag_val.toValue(), tag_ty, .normal); @@ -6218,7 +6218,7 @@ fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const inst_ty = self.typeOfIndex(inst); const operand = try self.resolveInst(ty_op.operand); - return self.wip.cast(.addrspacecast, operand, try self.object.lowerType(inst_ty, .by_value), ""); + return self.wip.cast(.addrspacecast, operand, try self.object.lowerType(inst_ty, .as_value), ""); } fn workIntrinsic( @@ -6370,7 +6370,7 @@ fn load( }; if (isByRef(load_ty, zcu)) { - const llvm_usize_ty = try o.lowerType(.usize, .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); const result_ptr = try fg.buildZigAlloca(load_ty, .none); _ = try fg.wip.callMemCpy( result_ptr, @@ -6385,7 +6385,7 @@ fn load( } const llvm_memory_ty = try o.lowerType(load_ty, .in_memory); - const llvm_value_ty = try o.lowerType(load_ty, .by_value); + const llvm_value_ty = try o.lowerType(load_ty, .as_value); if (llvm_memory_ty != llvm_value_ty) { assert(load_ty.isAbiInt(zcu)); @@ -6443,7 +6443,7 @@ fn store( }; if (isByRef(elem_ty, zcu)) { - const llvm_usize_ty = try o.lowerType(.usize, .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); _ = try fg.wip.callMemCpy( ptr, llvm_ptr_align, @@ -6456,10 +6456,10 @@ fn store( return; } - assert(elem.typeOfWip(&fg.wip) == try o.lowerType(elem_ty, .by_value)); + assert(elem.typeOfWip(&fg.wip) == try o.lowerType(elem_ty, .as_value)); const llvm_memory_ty = try o.lowerType(elem_ty, .in_memory); - const llvm_value_ty = try o.lowerType(elem_ty, .by_value); + const llvm_value_ty = try o.lowerType(elem_ty, .as_value); if (llvm_memory_ty != llvm_value_ty) { assert(elem_ty.isAbiInt(zcu)); @@ -6494,7 +6494,7 @@ fn store( fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void { const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; const o = fg.object; - const usize_ty = try o.lowerType(.usize, .by_value); + const usize_ty = try o.lowerType(.usize, .as_value); const zero = try o.builder.intValue(usize_ty, 0); const req = try o.builder.intValue(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED); const ptr_as_usize = try fg.wip.cast(.ptrtoint, ptr, usize_ty, ""); @@ -6516,7 +6516,7 @@ fn valgrindClientRequest( const target = zcu.getTarget(); if (!target_util.hasValgrindSupport(target, .stage2_llvm)) return default_value; - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); const usize_align = Type.usize.abiAlignment(zcu).toLlvm(); const array_llvm_ty = try o.builder.arrayType(6, llvm_usize); @@ -6798,7 +6798,7 @@ const ParamTypeIterator = struct { while (field_it.next()) |field_index| { const field_ty = ty.fieldType(field_index, zcu); if (!field_ty.hasRuntimeBits(zcu)) continue; - it.types_buffer[it.types_len] = try it.object.lowerType(field_ty, .by_value); + it.types_buffer[it.types_len] = try it.object.lowerType(field_ty, .as_value); it.offsets_buffer[it.types_len] = ty.structFieldOffset(field_index, zcu); it.types_len += 1; } @@ -6815,7 +6815,7 @@ const ParamTypeIterator = struct { it.llvm_index += 1; return .byval; } else { - it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .by_value)}; + it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .as_value)}; it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) }; it.types_len = 1; it.llvm_index += 1; @@ -7080,7 +7080,7 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err for (0..ret_ty.structFieldCount(zcu)) |field_index| { const field_ty = ret_ty.fieldType(field_index, zcu); if (!field_ty.hasRuntimeBits(zcu)) continue; - types[types_len] = try o.lowerType(field_ty, .by_value); + types[types_len] = try o.lowerType(field_ty, .as_value); types_len += 1; } return .{ .mem_cast = try o.builder.structType(.normal, types[0..types_len]) }; @@ -7091,7 +7091,7 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err assert(!isByRef(ret_ty, zcu)); return .by_val; } else { - return .{ .mem_cast = try o.lowerType(scalar_ty, .by_value) }; + return .{ .mem_cast = try o.lowerType(scalar_ty, .as_value) }; }, .indirect => return .sret, }, @@ -7392,7 +7392,7 @@ fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.E fn ptraddConst(fg: *FuncGen, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value { if (offset == 0) return ptr; const o = fg.object; - const llvm_usize_ty = try o.lowerType(.usize, .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); const offset_val = try o.builder.intValue(llvm_usize_ty, offset); return fg.wip.gep(.inbounds, .i8, ptr, &.{offset_val}, ""); } -- 2.54.0 From 1e4b0e0022fcbda51032fe555d948ae59db3f640 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 24 Jun 2026 00:39:25 -0400 Subject: [PATCH 06/22] llvm: update attributes and intrinsics --- lib/std/zig/llvm/Builder.zig | 1211 +++++++++++++++++++++------------- 1 file changed, 758 insertions(+), 453 deletions(-) diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index d0e86c80ac3baa8c9504095b8200b546789a39b2..48ae8216b9026099894b01f95ca9505215bef869 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -142,8 +142,8 @@ pub const String = enum(u32) { } fn fromIndex(index: ?usize) String { - return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) + - @backingInt(String.empty))))); + return @fromBackingInt(@as(u32, @intCast((index orelse return .none) + + @backingInt(String.empty)))); } fn toIndex(self: String) ?usize { @@ -937,6 +937,7 @@ pub const Attribute = union(Kind) { // Parameter Attributes zeroext, signext, + noext, inreg, byval: Type, byref: Type, @@ -947,6 +948,7 @@ pub const Attribute = union(Kind) { @"align": Alignment.Lazy, @"noalias", nocapture, + captures: Captures, nofree, nest, returned, @@ -965,6 +967,11 @@ pub const Attribute = union(Kind) { readnone, readonly, writeonly, + writable, + initializes: []const [2]u64, + dead_on_unwind, + dead_on_return: ?u32, + range: [2]Constant, // Function Attributes //alignstack: Alignment.Lazy, @@ -974,7 +981,7 @@ pub const Attribute = union(Kind) { builtin, cold, convergent, - disable_sanitizer_information, + disable_sanitizer_instrumentation, fn_ret_thunk_extern, hot, inlinehint, @@ -984,6 +991,7 @@ pub const Attribute = union(Kind) { naked, nobuiltin, nocallback, + nodivergencesource, noduplicate, //nofree, noimplicitfloat, @@ -1001,6 +1009,7 @@ pub const Attribute = union(Kind) { nosanitize_bounds, nosanitize_coverage, null_pointer_is_valid, + optdebug, optforfuzzing, optnone, optsize, @@ -1012,23 +1021,23 @@ pub const Attribute = union(Kind) { sanitize_thread, sanitize_hwaddress, sanitize_memtag, + sanitize_realtime, + sanitize_realtime_blocking, + sanitize_alloc_token, speculative_load_hardening, speculatable, ssp, sspstrong, sspreq, strictfp, + denormal_fpenv, uwtable: UwTable, nocf_check, shadowcallstack, mustprogress, vscale_range: VScaleRange, - - // Global Attributes - no_sanitize_address, - no_sanitize_hwaddress, - //sanitize_memtag, - sanitize_address_dyninit, + nooutline, + nocreateundeforpoison, string: struct { kind: String, value: String }, none: noreturn, @@ -1045,100 +1054,11 @@ pub const Attribute = union(Kind) { const storage = self.toStorage(builder); if (storage.kind.toString()) |kind| return .{ .string = .{ .kind = kind, - .value = @fromBackingInt(@intCast(storage.value)), + .value = @fromBackingInt(storage.value), } } else return switch (storage.kind) { - inline .zeroext, - .signext, - .inreg, - .byval, - .byref, - .preallocated, - .inalloca, - .sret, - .elementtype, - .@"align", - .@"noalias", - .nocapture, - .nofree, - .nest, - .returned, - .nonnull, - .dereferenceable, - .dereferenceable_or_null, - .swiftself, - .swiftasync, - .swifterror, - .immarg, - .noundef, - .nofpclass, - .alignstack, - .allocalign, - .allocptr, - .readnone, - .readonly, - .writeonly, - //.alignstack, - .allockind, - .allocsize, - .alwaysinline, - .builtin, - .cold, - .convergent, - .disable_sanitizer_information, - .fn_ret_thunk_extern, - .hot, - .inlinehint, - .jumptable, - .memory, - .minsize, - .naked, - .nobuiltin, - .nocallback, - .noduplicate, - //.nofree, - .noimplicitfloat, - .@"noinline", - .nomerge, - .nonlazybind, - .noprofile, - .skipprofile, - .noredzone, - .noreturn, - .norecurse, - .willreturn, - .nosync, - .nounwind, - .nosanitize_bounds, - .nosanitize_coverage, - .null_pointer_is_valid, - .optforfuzzing, - .optnone, - .optsize, - //.preallocated, - .returns_twice, - .safestack, - .sanitize_address, - .sanitize_memory, - .sanitize_thread, - .sanitize_hwaddress, - .sanitize_memtag, - .speculative_load_hardening, - .speculatable, - .ssp, - .sspstrong, - .sspreq, - .strictfp, - .uwtable, - .nocf_check, - .shadowcallstack, - .mustprogress, - .vscale_range, - .no_sanitize_address, - .no_sanitize_hwaddress, - .sanitize_address_dyninit, - => |kind| { + inline else => |kind| { const field_name, const field_type = comptime blk: { - @setEvalBranchQuota(10_000); + @setEvalBranchQuota(12_000); const info = @typeInfo(Attribute).@"union"; for (info.field_names, info.field_types) |field_name, field_type| { if (std.mem.eql(u8, field_name, @tagName(kind))) break :blk .{ field_name, field_type }; @@ -1149,14 +1069,17 @@ pub const Attribute = union(Kind) { return @unionInit(Attribute, field_name, switch (field_type) { void => {}, u32 => storage.value, - Alignment.Lazy, String, Type, UwTable => @fromBackingInt(@intCast(storage.value)), - AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value), + Alignment.Lazy, String, Type, UwTable => @fromBackingInt(storage.value), + AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(storage.value), else => @compileError("bad payload type: " ++ field_name ++ ": " ++ @typeName(field_type)), }); }, - .string, .none => unreachable, - _ => unreachable, + .initializes, + .dead_on_return, + .range, + => @panic("TODO"), + .string, .none, _ => unreachable, }; } @@ -1174,6 +1097,7 @@ pub const Attribute = union(Kind) { switch (attribute) { .zeroext, .signext, + .noext, .inreg, .@"noalias", .nocapture, @@ -1191,11 +1115,13 @@ pub const Attribute = union(Kind) { .readnone, .readonly, .writeonly, + .writable, + .dead_on_unwind, .alwaysinline, .builtin, .cold, .convergent, - .disable_sanitizer_information, + .disable_sanitizer_instrumentation, .fn_ret_thunk_extern, .hot, .inlinehint, @@ -1204,6 +1130,7 @@ pub const Attribute = union(Kind) { .naked, .nobuiltin, .nocallback, + .nodivergencesource, .noduplicate, .noimplicitfloat, .@"noinline", @@ -1220,6 +1147,7 @@ pub const Attribute = union(Kind) { .nosanitize_bounds, .nosanitize_coverage, .null_pointer_is_valid, + .optdebug, .optforfuzzing, .optnone, .optsize, @@ -1230,18 +1158,21 @@ pub const Attribute = union(Kind) { .sanitize_thread, .sanitize_hwaddress, .sanitize_memtag, + .sanitize_realtime, + .sanitize_realtime_blocking, + .sanitize_alloc_token, .speculative_load_hardening, .speculatable, .ssp, .sspstrong, .sspreq, .strictfp, + .denormal_fpenv, .nocf_check, .shadowcallstack, .mustprogress, - .no_sanitize_address, - .no_sanitize_hwaddress, - .sanitize_address_dyninit, + .nooutline, + .nocreateundeforpoison, => try w.print(" {s}", .{@tagName(attribute)}), .byval, .byref, @@ -1254,6 +1185,45 @@ pub const Attribute = union(Kind) { .dereferenceable, .dereferenceable_or_null, => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }), + .captures => |captures| { + try w.print(" {s}(", .{@tagName(attribute)}); + var need_comma = false; + if (captures == Captures.none) { + if (need_comma) try w.writeAll(", "); + try w.writeAll("none"); + need_comma = true; + } + inline for (@typeInfo(Captures).@"struct".field_names) |field_name| { + if (comptime std.mem.eql(u8, field_name, "_")) continue; + const components = @field(captures, field_name); + if (components != Captures.Components.none) { + if (!comptime std.mem.eql(u8, field_name, "other")) { + if (need_comma) try w.writeAll(", "); + try w.writeAll(field_name ++ ": "); + need_comma = false; + } + if (components.address) { + if (need_comma) try w.writeAll(", "); + try w.writeAll("address"); + need_comma = true; + } else if (components.address_is_null) { + if (need_comma) try w.writeAll(", "); + try w.writeAll("address_is_null"); + need_comma = true; + } + if (components.provenance) { + if (need_comma) try w.writeAll(", "); + try w.writeAll("provenance"); + need_comma = true; + } else if (components.read_provenance) { + if (need_comma) try w.writeAll(", "); + try w.writeAll("read_provenance"); + need_comma = true; + } + } + } + try w.writeByte(')'); + }, .nofpclass => |fpclass| { const Int = @typeInfo(FpClass).@"struct".backing_integer.?; try w.print(" {s}(", .{@tagName(attribute)}); @@ -1281,6 +1251,9 @@ pub const Attribute = union(Kind) { try w.print("({d})", .{alignment_bytes}); } }, + .initializes => @panic("TODO"), + .dead_on_return => @panic("TODO"), + .range => @panic("TODO"), .allockind => |allockind| { try w.print(" {t}(\"", .{attribute}); var any = false; @@ -1344,100 +1317,109 @@ pub const Attribute = union(Kind) { pub const Kind = enum(u32) { // Parameter Attributes - zeroext = 34, - signext = 24, - inreg = 5, - byval = 3, - byref = 69, - preallocated = 65, - inalloca = 38, - sret = 29, // TODO: ? - elementtype = 77, - @"align" = 1, - @"noalias" = 9, - nocapture = 11, - nofree = 62, - nest = 8, - returned = 22, - nonnull = 39, - dereferenceable = 41, - dereferenceable_or_null = 42, - swiftself = 46, - swiftasync = 75, - swifterror = 47, - immarg = 60, - noundef = 68, - nofpclass = 87, - alignstack = 25, - allocalign = 80, - allocptr = 81, - readnone = 20, - readonly = 21, - writeonly = 52, + zeroext = @backingInt(ATTR_KIND.Z_EXT), + signext = @backingInt(ATTR_KIND.S_EXT), + noext = @backingInt(ATTR_KIND.NO_EXT), + inreg = @backingInt(ATTR_KIND.IN_REG), + byval = @backingInt(ATTR_KIND.BY_VAL), + byref = @backingInt(ATTR_KIND.BYREF), + preallocated = @backingInt(ATTR_KIND.PREALLOCATED), + inalloca = @backingInt(ATTR_KIND.IN_ALLOCA), + sret = @backingInt(ATTR_KIND.STRUCT_RET), + elementtype = @backingInt(ATTR_KIND.ELEMENTTYPE), + @"align" = @backingInt(ATTR_KIND.ALIGNMENT), + @"noalias" = @backingInt(ATTR_KIND.NO_ALIAS), + nocapture = @backingInt(ATTR_KIND.NO_CAPTURE), + captures = @backingInt(ATTR_KIND.CAPTURES), + nofree = @backingInt(ATTR_KIND.NOFREE), + nest = @backingInt(ATTR_KIND.NEST), + returned = @backingInt(ATTR_KIND.RETURNED), + nonnull = @backingInt(ATTR_KIND.NON_NULL), + dereferenceable = @backingInt(ATTR_KIND.DEREFERENCEABLE), + dereferenceable_or_null = @backingInt(ATTR_KIND.DEREFERENCEABLE_OR_NULL), + swiftself = @backingInt(ATTR_KIND.SWIFT_SELF), + swiftasync = @backingInt(ATTR_KIND.SWIFT_ASYNC), + swifterror = @backingInt(ATTR_KIND.SWIFT_ERROR), + immarg = @backingInt(ATTR_KIND.IMMARG), + noundef = @backingInt(ATTR_KIND.NOUNDEF), + nofpclass = @backingInt(ATTR_KIND.NOFPCLASS), + alignstack = @backingInt(ATTR_KIND.STACK_ALIGNMENT), + allocalign = @backingInt(ATTR_KIND.ALLOC_ALIGN), + allocptr = @backingInt(ATTR_KIND.ALLOCATED_POINTER), + readnone = @backingInt(ATTR_KIND.READ_NONE), + readonly = @backingInt(ATTR_KIND.READ_ONLY), + writeonly = @backingInt(ATTR_KIND.WRITEONLY), + writable = @backingInt(ATTR_KIND.WRITABLE), + initializes = @backingInt(ATTR_KIND.INITIALIZES), + dead_on_unwind = @backingInt(ATTR_KIND.DEAD_ON_UNWIND), + dead_on_return = @backingInt(ATTR_KIND.DEAD_ON_RETURN), + range = @backingInt(ATTR_KIND.RANGE), // Function Attributes - //alignstack, - allockind = 82, - allocsize = 51, - alwaysinline = 2, - builtin = 35, - cold = 36, - convergent = 43, - disable_sanitizer_information = 78, - fn_ret_thunk_extern = 84, - hot = 72, - inlinehint = 4, - jumptable = 40, - memory = 86, - minsize = 6, - naked = 7, - nobuiltin = 10, - nocallback = 71, - noduplicate = 12, - //nofree, - noimplicitfloat = 13, - @"noinline" = 14, - nomerge = 66, - nonlazybind = 15, - noprofile = 73, - skipprofile = 85, - noredzone = 16, - noreturn = 17, - norecurse = 48, - willreturn = 61, - nosync = 63, - nounwind = 18, - nosanitize_bounds = 79, - nosanitize_coverage = 76, - null_pointer_is_valid = 67, - optforfuzzing = 57, - optnone = 37, - optsize = 19, - //preallocated, - returns_twice = 23, - safestack = 44, - sanitize_address = 30, - sanitize_memory = 32, - sanitize_thread = 31, - sanitize_hwaddress = 55, - sanitize_memtag = 64, - speculative_load_hardening = 59, - speculatable = 53, - ssp = 26, - sspstrong = 28, - sspreq = 27, - strictfp = 54, - uwtable = 33, - nocf_check = 56, - shadowcallstack = 58, - mustprogress = 70, - vscale_range = 74, - - // Global Attributes - no_sanitize_address = 100, - no_sanitize_hwaddress = 101, - //sanitize_memtag, - sanitize_address_dyninit = 102, + //alignstack = @intFromEnum(ATTR_KIND.STACK_ALIGNMENT), + allockind = @backingInt(ATTR_KIND.ALLOC_KIND), + allocsize = @backingInt(ATTR_KIND.ALLOC_SIZE), + alwaysinline = @backingInt(ATTR_KIND.ALWAYS_INLINE), + builtin = @backingInt(ATTR_KIND.BUILTIN), + cold = @backingInt(ATTR_KIND.COLD), + convergent = @backingInt(ATTR_KIND.CONVERGENT), + disable_sanitizer_instrumentation = @backingInt(ATTR_KIND.DISABLE_SANITIZER_INSTRUMENTATION), + fn_ret_thunk_extern = @backingInt(ATTR_KIND.FNRETTHUNK_EXTERN), + hot = @backingInt(ATTR_KIND.HOT), + inlinehint = @backingInt(ATTR_KIND.INLINE_HINT), + jumptable = @backingInt(ATTR_KIND.JUMP_TABLE), + memory = @backingInt(ATTR_KIND.MEMORY), + minsize = @backingInt(ATTR_KIND.MIN_SIZE), + naked = @backingInt(ATTR_KIND.NAKED), + nobuiltin = @backingInt(ATTR_KIND.NO_BUILTIN), + nocallback = @backingInt(ATTR_KIND.NO_CALLBACK), + nodivergencesource = @backingInt(ATTR_KIND.NO_DIVERGENCE_SOURCE), + noduplicate = @backingInt(ATTR_KIND.NO_DUPLICATE), + //nofree = @intFromEnum(ATTR_KIND.NOFREE), + noimplicitfloat = @backingInt(ATTR_KIND.NO_IMPLICIT_FLOAT), + @"noinline" = @backingInt(ATTR_KIND.NO_INLINE), + nomerge = @backingInt(ATTR_KIND.NO_MERGE), + nonlazybind = @backingInt(ATTR_KIND.NON_LAZY_BIND), + noprofile = @backingInt(ATTR_KIND.NO_PROFILE), + skipprofile = @backingInt(ATTR_KIND.SKIP_PROFILE), + noredzone = @backingInt(ATTR_KIND.NO_RED_ZONE), + noreturn = @backingInt(ATTR_KIND.NO_RETURN), + norecurse = @backingInt(ATTR_KIND.NO_RECURSE), + willreturn = @backingInt(ATTR_KIND.WILLRETURN), + nosync = @backingInt(ATTR_KIND.NOSYNC), + nounwind = @backingInt(ATTR_KIND.NO_UNWIND), + nosanitize_bounds = @backingInt(ATTR_KIND.NO_SANITIZE_BOUNDS), + nosanitize_coverage = @backingInt(ATTR_KIND.NO_SANITIZE_COVERAGE), + null_pointer_is_valid = @backingInt(ATTR_KIND.NULL_POINTER_IS_VALID), + optdebug = @backingInt(ATTR_KIND.OPTIMIZE_FOR_DEBUGGING), + optforfuzzing = @backingInt(ATTR_KIND.OPT_FOR_FUZZING), + optnone = @backingInt(ATTR_KIND.OPTIMIZE_NONE), + optsize = @backingInt(ATTR_KIND.OPTIMIZE_FOR_SIZE), + //preallocated = @intFromEnum(ATTR_KIND.PREALLOCATED), + returns_twice = @backingInt(ATTR_KIND.RETURNS_TWICE), + safestack = @backingInt(ATTR_KIND.SAFESTACK), + sanitize_address = @backingInt(ATTR_KIND.SANITIZE_ADDRESS), + sanitize_memory = @backingInt(ATTR_KIND.SANITIZE_MEMORY), + sanitize_thread = @backingInt(ATTR_KIND.SANITIZE_THREAD), + sanitize_hwaddress = @backingInt(ATTR_KIND.SANITIZE_HWADDRESS), + sanitize_memtag = @backingInt(ATTR_KIND.SANITIZE_MEMTAG), + sanitize_realtime = @backingInt(ATTR_KIND.SANITIZE_REALTIME), + sanitize_realtime_blocking = @backingInt(ATTR_KIND.SANITIZE_REALTIME_BLOCKING), + sanitize_alloc_token = @backingInt(ATTR_KIND.SANITIZE_ALLOC_TOKEN), + speculative_load_hardening = @backingInt(ATTR_KIND.SPECULATIVE_LOAD_HARDENING), + speculatable = @backingInt(ATTR_KIND.SPECULATABLE), + ssp = @backingInt(ATTR_KIND.STACK_PROTECT), + sspstrong = @backingInt(ATTR_KIND.STACK_PROTECT_STRONG), + sspreq = @backingInt(ATTR_KIND.STACK_PROTECT_REQ), + strictfp = @backingInt(ATTR_KIND.STRICT_FP), + denormal_fpenv = @backingInt(ATTR_KIND.DENORMAL_FPENV), + uwtable = @backingInt(ATTR_KIND.UW_TABLE), + nocf_check = @backingInt(ATTR_KIND.NOCF_CHECK), + shadowcallstack = @backingInt(ATTR_KIND.SHADOWCALLSTACK), + mustprogress = @backingInt(ATTR_KIND.MUSTPROGRESS), + vscale_range = @backingInt(ATTR_KIND.VSCALE_RANGE), + nooutline = @backingInt(ATTR_KIND.NOOUTLINE), + nocreateundeforpoison = @backingInt(ATTR_KIND.NO_CREATE_UNDEF_OR_POISON), string = maxInt(u31), none = maxInt(u32), @@ -1447,16 +1429,128 @@ pub const Attribute = union(Kind) { pub fn fromString(str: String) Kind { assert(!str.isAnon()); - const kind: Kind = @fromBackingInt(@intCast(@backingInt(str))); + const kind: Kind = @fromBackingInt(@backingInt(str)); assert(kind != .none); return kind; } fn toString(self: Kind) ?String { assert(self != .none); - const str: String = @fromBackingInt(@intCast(@backingInt(self))); + const str: String = @fromBackingInt(@backingInt(self)); return if (str.isAnon()) null else str; } + + /// enum AttributeKindCodes + const ATTR_KIND = enum(u32) { + ALIGNMENT = 1, + ALWAYS_INLINE = 2, + BY_VAL = 3, + INLINE_HINT = 4, + IN_REG = 5, + MIN_SIZE = 6, + NAKED = 7, + NEST = 8, + NO_ALIAS = 9, + NO_BUILTIN = 10, + NO_CAPTURE = 11, + NO_DUPLICATE = 12, + NO_IMPLICIT_FLOAT = 13, + NO_INLINE = 14, + NON_LAZY_BIND = 15, + NO_RED_ZONE = 16, + NO_RETURN = 17, + NO_UNWIND = 18, + OPTIMIZE_FOR_SIZE = 19, + READ_NONE = 20, + READ_ONLY = 21, + RETURNED = 22, + RETURNS_TWICE = 23, + S_EXT = 24, + STACK_ALIGNMENT = 25, + STACK_PROTECT = 26, + STACK_PROTECT_REQ = 27, + STACK_PROTECT_STRONG = 28, + STRUCT_RET = 29, + SANITIZE_ADDRESS = 30, + SANITIZE_THREAD = 31, + SANITIZE_MEMORY = 32, + UW_TABLE = 33, + Z_EXT = 34, + BUILTIN = 35, + COLD = 36, + OPTIMIZE_NONE = 37, + IN_ALLOCA = 38, + NON_NULL = 39, + JUMP_TABLE = 40, + DEREFERENCEABLE = 41, + DEREFERENCEABLE_OR_NULL = 42, + CONVERGENT = 43, + SAFESTACK = 44, + ARGMEMONLY = 45, + SWIFT_SELF = 46, + SWIFT_ERROR = 47, + NO_RECURSE = 48, + INACCESSIBLEMEM_ONLY = 49, + INACCESSIBLEMEM_OR_ARGMEMONLY = 50, + ALLOC_SIZE = 51, + WRITEONLY = 52, + SPECULATABLE = 53, + STRICT_FP = 54, + SANITIZE_HWADDRESS = 55, + NOCF_CHECK = 56, + OPT_FOR_FUZZING = 57, + SHADOWCALLSTACK = 58, + SPECULATIVE_LOAD_HARDENING = 59, + IMMARG = 60, + WILLRETURN = 61, + NOFREE = 62, + NOSYNC = 63, + SANITIZE_MEMTAG = 64, + PREALLOCATED = 65, + NO_MERGE = 66, + NULL_POINTER_IS_VALID = 67, + NOUNDEF = 68, + BYREF = 69, + MUSTPROGRESS = 70, + NO_CALLBACK = 71, + HOT = 72, + NO_PROFILE = 73, + VSCALE_RANGE = 74, + SWIFT_ASYNC = 75, + NO_SANITIZE_COVERAGE = 76, + ELEMENTTYPE = 77, + DISABLE_SANITIZER_INSTRUMENTATION = 78, + NO_SANITIZE_BOUNDS = 79, + ALLOC_ALIGN = 80, + ALLOCATED_POINTER = 81, + ALLOC_KIND = 82, + PRESPLIT_COROUTINE = 83, + FNRETTHUNK_EXTERN = 84, + SKIP_PROFILE = 85, + MEMORY = 86, + NOFPCLASS = 87, + OPTIMIZE_FOR_DEBUGGING = 88, + WRITABLE = 89, + CORO_ONLY_DESTROY_WHEN_COMPLETE = 90, + DEAD_ON_UNWIND = 91, + RANGE = 92, + SANITIZE_NUMERICAL_STABILITY = 93, + INITIALIZES = 94, + HYBRID_PATCHABLE = 95, + SANITIZE_REALTIME = 96, + SANITIZE_REALTIME_BLOCKING = 97, + CORO_ELIDE_SAFE = 98, + NO_EXT = 99, + NO_DIVERGENCE_SOURCE = 100, + SANITIZE_TYPE = 101, + CAPTURES = 102, + DEAD_ON_RETURN = 103, + SANITIZE_ALLOC_TOKEN = 104, + NO_CREATE_UNDEF_OR_POISON = 105, + DENORMAL_FPENV = 106, + NOOUTLINE = 107, + FLATTEN = 108, + }; }; pub const FpClass = packed struct(u32) { @@ -1506,6 +1600,29 @@ pub const Attribute = union(Kind) { pub const pnorm = FpClass{ .positive_normal = true }; }; + pub const Captures = packed struct(u32) { + other: Components = .none, + ret: Components = .none, + _: u24 = 0, + + pub const none: Captures = .{}; + + pub const Components = packed struct(u4) { + address_is_null: bool = false, + address: bool = false, + read_provenance: bool = false, + provenance: bool = false, + + pub const none: Components = .{}; + pub const all: Components = .{ + .address_is_null = true, + .address = true, + .read_provenance = true, + .provenance = true, + }; + }; + }; + pub const AllocKind = packed struct(u32) { alloc: bool, realloc: bool, @@ -1582,9 +1699,13 @@ pub const Attribute = union(Kind) { void => 0, u32 => value, Alignment.Lazy, String, Type, UwTable => @backingInt(value), - AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value), - else => @compileError("bad payload type: " ++ @tagName(tag) ++ @typeName(@TypeOf(value))), + AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(value), + else => @compileError("bad payload type: " ++ @tagName(tag) ++ ": " ++ @typeName(@TypeOf(value))), } }, + .initializes, + .dead_on_return, + .range, + => @panic("TODO"), .string => |string_attr| .{ .kind = Kind.fromString(string_attr.kind), .value = @backingInt(string_attr.value), @@ -1907,87 +2028,87 @@ pub const AddrSpace = enum(u24) { // See llvm/lib/Target/X86/X86.h pub const x86 = struct { - pub const gs: AddrSpace = @fromBackingInt(@intCast(256)); - pub const fs: AddrSpace = @fromBackingInt(@intCast(257)); - pub const ss: AddrSpace = @fromBackingInt(@intCast(258)); + pub const gs: AddrSpace = @fromBackingInt(256); + pub const fs: AddrSpace = @fromBackingInt(257); + pub const ss: AddrSpace = @fromBackingInt(258); - pub const ptr32_sptr: AddrSpace = @fromBackingInt(@intCast(270)); - pub const ptr32_uptr: AddrSpace = @fromBackingInt(@intCast(271)); - pub const ptr64: AddrSpace = @fromBackingInt(@intCast(272)); + pub const ptr32_sptr: AddrSpace = @fromBackingInt(270); + pub const ptr32_uptr: AddrSpace = @fromBackingInt(271); + pub const ptr64: AddrSpace = @fromBackingInt(272); }; pub const x86_64 = x86; // See llvm/lib/Target/AVR/AVR.h pub const avr = struct { - pub const data: AddrSpace = @fromBackingInt(@intCast(0)); - pub const program: AddrSpace = @fromBackingInt(@intCast(1)); - pub const program1: AddrSpace = @fromBackingInt(@intCast(2)); - pub const program2: AddrSpace = @fromBackingInt(@intCast(3)); - pub const program3: AddrSpace = @fromBackingInt(@intCast(4)); - pub const program4: AddrSpace = @fromBackingInt(@intCast(5)); - pub const program5: AddrSpace = @fromBackingInt(@intCast(6)); + pub const data: AddrSpace = @fromBackingInt(0); + pub const program: AddrSpace = @fromBackingInt(1); + pub const program1: AddrSpace = @fromBackingInt(2); + pub const program2: AddrSpace = @fromBackingInt(3); + pub const program3: AddrSpace = @fromBackingInt(4); + pub const program4: AddrSpace = @fromBackingInt(5); + pub const program5: AddrSpace = @fromBackingInt(6); }; // See llvm/lib/Target/NVPTX/NVPTX.h pub const nvptx = struct { - pub const generic: AddrSpace = @fromBackingInt(@intCast(0)); - pub const global: AddrSpace = @fromBackingInt(@intCast(1)); - pub const constant: AddrSpace = @fromBackingInt(@intCast(2)); - pub const shared: AddrSpace = @fromBackingInt(@intCast(3)); - pub const param: AddrSpace = @fromBackingInt(@intCast(4)); - pub const local: AddrSpace = @fromBackingInt(@intCast(5)); + pub const generic: AddrSpace = @fromBackingInt(0); + pub const global: AddrSpace = @fromBackingInt(1); + pub const constant: AddrSpace = @fromBackingInt(2); + pub const shared: AddrSpace = @fromBackingInt(3); + pub const param: AddrSpace = @fromBackingInt(4); + pub const local: AddrSpace = @fromBackingInt(5); }; // See llvm/lib/Target/AMDGPU/AMDGPU.h pub const amdgpu = struct { - pub const flat: AddrSpace = @fromBackingInt(@intCast(0)); - pub const global: AddrSpace = @fromBackingInt(@intCast(1)); - pub const region: AddrSpace = @fromBackingInt(@intCast(2)); - pub const local: AddrSpace = @fromBackingInt(@intCast(3)); - pub const constant: AddrSpace = @fromBackingInt(@intCast(4)); - pub const private: AddrSpace = @fromBackingInt(@intCast(5)); - pub const constant_32bit: AddrSpace = @fromBackingInt(@intCast(6)); - pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(@intCast(7)); - pub const buffer_resource: AddrSpace = @fromBackingInt(@intCast(8)); - pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(@intCast(9)); - pub const param_d: AddrSpace = @fromBackingInt(@intCast(6)); - pub const param_i: AddrSpace = @fromBackingInt(@intCast(7)); - pub const constant_buffer_0: AddrSpace = @fromBackingInt(@intCast(8)); - pub const constant_buffer_1: AddrSpace = @fromBackingInt(@intCast(9)); - pub const constant_buffer_2: AddrSpace = @fromBackingInt(@intCast(10)); - pub const constant_buffer_3: AddrSpace = @fromBackingInt(@intCast(11)); - pub const constant_buffer_4: AddrSpace = @fromBackingInt(@intCast(12)); - pub const constant_buffer_5: AddrSpace = @fromBackingInt(@intCast(13)); - pub const constant_buffer_6: AddrSpace = @fromBackingInt(@intCast(14)); - pub const constant_buffer_7: AddrSpace = @fromBackingInt(@intCast(15)); - pub const constant_buffer_8: AddrSpace = @fromBackingInt(@intCast(16)); - pub const constant_buffer_9: AddrSpace = @fromBackingInt(@intCast(17)); - pub const constant_buffer_10: AddrSpace = @fromBackingInt(@intCast(18)); - pub const constant_buffer_11: AddrSpace = @fromBackingInt(@intCast(19)); - pub const constant_buffer_12: AddrSpace = @fromBackingInt(@intCast(20)); - pub const constant_buffer_13: AddrSpace = @fromBackingInt(@intCast(21)); - pub const constant_buffer_14: AddrSpace = @fromBackingInt(@intCast(22)); - pub const constant_buffer_15: AddrSpace = @fromBackingInt(@intCast(23)); - pub const streamout_register: AddrSpace = @fromBackingInt(@intCast(128)); + pub const flat: AddrSpace = @fromBackingInt(0); + pub const global: AddrSpace = @fromBackingInt(1); + pub const region: AddrSpace = @fromBackingInt(2); + pub const local: AddrSpace = @fromBackingInt(3); + pub const constant: AddrSpace = @fromBackingInt(4); + pub const private: AddrSpace = @fromBackingInt(5); + pub const constant_32bit: AddrSpace = @fromBackingInt(6); + pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(7); + pub const buffer_resource: AddrSpace = @fromBackingInt(8); + pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(9); + pub const param_d: AddrSpace = @fromBackingInt(6); + pub const param_i: AddrSpace = @fromBackingInt(7); + pub const constant_buffer_0: AddrSpace = @fromBackingInt(8); + pub const constant_buffer_1: AddrSpace = @fromBackingInt(9); + pub const constant_buffer_2: AddrSpace = @fromBackingInt(10); + pub const constant_buffer_3: AddrSpace = @fromBackingInt(11); + pub const constant_buffer_4: AddrSpace = @fromBackingInt(12); + pub const constant_buffer_5: AddrSpace = @fromBackingInt(13); + pub const constant_buffer_6: AddrSpace = @fromBackingInt(14); + pub const constant_buffer_7: AddrSpace = @fromBackingInt(15); + pub const constant_buffer_8: AddrSpace = @fromBackingInt(16); + pub const constant_buffer_9: AddrSpace = @fromBackingInt(17); + pub const constant_buffer_10: AddrSpace = @fromBackingInt(18); + pub const constant_buffer_11: AddrSpace = @fromBackingInt(19); + pub const constant_buffer_12: AddrSpace = @fromBackingInt(20); + pub const constant_buffer_13: AddrSpace = @fromBackingInt(21); + pub const constant_buffer_14: AddrSpace = @fromBackingInt(22); + pub const constant_buffer_15: AddrSpace = @fromBackingInt(23); + pub const streamout_register: AddrSpace = @fromBackingInt(128); }; pub const spirv = struct { - pub const function: AddrSpace = @fromBackingInt(@intCast(0)); - pub const cross_workgroup: AddrSpace = @fromBackingInt(@intCast(1)); - pub const uniform_constant: AddrSpace = @fromBackingInt(@intCast(2)); - pub const workgroup: AddrSpace = @fromBackingInt(@intCast(3)); - pub const generic: AddrSpace = @fromBackingInt(@intCast(4)); - pub const device_only_intel: AddrSpace = @fromBackingInt(@intCast(5)); - pub const host_only_intel: AddrSpace = @fromBackingInt(@intCast(6)); - pub const input: AddrSpace = @fromBackingInt(@intCast(7)); + pub const function: AddrSpace = @fromBackingInt(0); + pub const cross_workgroup: AddrSpace = @fromBackingInt(1); + pub const uniform_constant: AddrSpace = @fromBackingInt(2); + pub const workgroup: AddrSpace = @fromBackingInt(3); + pub const generic: AddrSpace = @fromBackingInt(4); + pub const device_only_intel: AddrSpace = @fromBackingInt(5); + pub const host_only_intel: AddrSpace = @fromBackingInt(6); + pub const input: AddrSpace = @fromBackingInt(7); }; // See llvm/include/llvm/CodeGen/WasmAddressSpaces.h pub const wasm = struct { - pub const default: AddrSpace = @fromBackingInt(@intCast(0)); - pub const variable: AddrSpace = @fromBackingInt(@intCast(1)); - pub const externref: AddrSpace = @fromBackingInt(@intCast(10)); - pub const funcref: AddrSpace = @fromBackingInt(@intCast(20)); + pub const default: AddrSpace = @fromBackingInt(0); + pub const variable: AddrSpace = @fromBackingInt(1); + pub const externref: AddrSpace = @fromBackingInt(10); + pub const funcref: AddrSpace = @fromBackingInt(20); }; pub fn format(addr_space: AddrSpace, w: *Writer) Writer.Error!void { @@ -2030,7 +2151,7 @@ pub const Alignment = enum(u6) { _, pub fn wrap(a: Alignment) Lazy { - return @fromBackingInt(@intCast(@backingInt(a))); + return @fromBackingInt(@backingInt(a)); } pub fn resolve(l: Lazy, b: *const Builder) Alignment { return switch (@backingInt(l)) { @@ -2261,8 +2382,7 @@ pub const StrtabString = enum(u32) { } fn fromIndex(index: ?usize) StrtabString { - return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) + - @backingInt(StrtabString.empty))))); + return @fromBackingInt(@intCast((index orelse return .none) + @backingInt(StrtabString.empty))); } fn toIndex(self: StrtabString) ?usize { @@ -2398,7 +2518,7 @@ pub const Global = struct { } pub fn toConst(global: Index) Constant { - return @fromBackingInt(@intCast(@backingInt(Constant.first_global) + @backingInt(global))); + return @fromBackingInt(@backingInt(Constant.first_global) + @backingInt(global)); } pub fn toValue(global: Index) Value { @@ -2526,7 +2646,7 @@ pub const Global = struct { _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]); builder.globals.swapRemoveAt(index); if (!old_name.isAnon()) return; - builder.next_unnamed_global = @fromBackingInt(@intCast(@backingInt(builder.next_unnamed_global) - 1)); + builder.next_unnamed_global = @fromBackingInt(@backingInt(builder.next_unnamed_global) - 1); if (builder.next_unnamed_global == old_name) return; builder.getGlobal(builder.next_unnamed_global).?.renameAssumeCapacity(old_name, builder); } @@ -2539,7 +2659,7 @@ pub const Global = struct { fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void { if (self.eql(other, builder)) return; - builder.next_replaced_global = @fromBackingInt(@intCast(@backingInt(builder.next_replaced_global) - 1)); + builder.next_replaced_global = @fromBackingInt(@backingInt(builder.next_replaced_global) - 1); self.renameAssumeCapacity(builder.next_replaced_global, builder); self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) }; } @@ -2699,6 +2819,8 @@ pub const Intrinsic = enum { smin, umax, umin, + scmp, + ucmp, memcpy, @"memcpy.inline", memmove, @@ -2708,10 +2830,21 @@ pub const Intrinsic = enum { powi, sin, cos, + tan, + asin, + acos, + atan, + atan2, + sinh, + cosh, + tanh, + sincos, + sincospi, + modf, pow, exp, - exp10, exp2, + exp10, ldexp, frexp, log, @@ -2723,6 +2856,8 @@ pub const Intrinsic = enum { maxnum, minimum, maximum, + minimumnum, + maximumnum, copysign, floor, ceil, @@ -2744,6 +2879,7 @@ pub const Intrinsic = enum { cttz, fshl, fshr, + clmul, // Arithmetic with Overflow @"sadd.with.overflow", @@ -2904,21 +3040,21 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .ptr } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .addressofreturnaddress = .{ .ret_len = 1, .params = &.{ .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .sponentry = .{ .ret_len = 1, .params = &.{ .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .frameaddress = .{ .ret_len = 1, @@ -2926,7 +3062,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .prefetch = .{ .ret_len = 0, @@ -2936,14 +3072,14 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.readwrite) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.readwrite) } }, }, .@"thread.pointer" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .ptr } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .abs = .{ @@ -2953,7 +3089,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .smax = .{ .ret_len = 1, @@ -2962,7 +3098,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .smin = .{ .ret_len = 1, @@ -2971,7 +3107,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .umax = .{ .ret_len = 1, @@ -2980,7 +3116,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .umin = .{ .ret_len = 1, @@ -2989,7 +3125,25 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .scmp = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 1 } }, + }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .ucmp = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 1 } }, + }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .memcpy = .{ .ret_len = 0, @@ -3047,7 +3201,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .powi = .{ .ret_len = 1, @@ -3056,7 +3210,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .sin = .{ .ret_len = 1, @@ -3064,7 +3218,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .cos = .{ .ret_len = 1, @@ -3072,7 +3226,99 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .tan = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .asin = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .acos = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .atan = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .atan2 = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .sinh = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .cosh = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .tanh = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .sincos = .{ + .ret_len = 2, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .sincospi = .{ + .ret_len = 2, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .modf = .{ + .ret_len = 2, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .pow = .{ .ret_len = 1, @@ -3081,7 +3327,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .exp = .{ .ret_len = 1, @@ -3089,7 +3335,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .exp2 = .{ .ret_len = 1, @@ -3097,7 +3343,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .exp10 = .{ .ret_len = 1, @@ -3105,7 +3351,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .ldexp = .{ .ret_len = 1, @@ -3114,7 +3360,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .frexp = .{ .ret_len = 2, @@ -3123,7 +3369,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .log = .{ .ret_len = 1, @@ -3131,7 +3377,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .log10 = .{ .ret_len = 1, @@ -3139,7 +3385,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .log2 = .{ .ret_len = 1, @@ -3147,7 +3393,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .fma = .{ .ret_len = 1, @@ -3157,7 +3403,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .fabs = .{ .ret_len = 1, @@ -3165,7 +3411,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .minnum = .{ .ret_len = 1, @@ -3174,7 +3420,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .maxnum = .{ .ret_len = 1, @@ -3183,7 +3429,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .minimum = .{ .ret_len = 1, @@ -3192,7 +3438,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .maximum = .{ .ret_len = 1, @@ -3201,7 +3447,25 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .minimumnum = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .maximumnum = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .copysign = .{ .ret_len = 1, @@ -3210,7 +3474,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .floor = .{ .ret_len = 1, @@ -3218,7 +3482,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .ceil = .{ .ret_len = 1, @@ -3226,7 +3490,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .trunc = .{ .ret_len = 1, @@ -3234,7 +3498,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .rint = .{ .ret_len = 1, @@ -3242,7 +3506,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .nearbyint = .{ .ret_len = 1, @@ -3250,7 +3514,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .round = .{ .ret_len = 1, @@ -3258,7 +3522,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .roundeven = .{ .ret_len = 1, @@ -3266,7 +3530,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .lround = .{ .ret_len = 1, @@ -3274,7 +3538,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .llround = .{ .ret_len = 1, @@ -3282,7 +3546,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .lrint = .{ .ret_len = 1, @@ -3290,7 +3554,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .llrint = .{ .ret_len = 1, @@ -3298,7 +3562,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .bitreverse = .{ @@ -3307,7 +3571,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .bswap = .{ .ret_len = 1, @@ -3315,7 +3579,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .ctpop = .{ .ret_len = 1, @@ -3323,7 +3587,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .ctlz = .{ .ret_len = 1, @@ -3332,7 +3596,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .cttz = .{ .ret_len = 1, @@ -3341,7 +3605,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .fshl = .{ .ret_len = 1, @@ -3351,7 +3615,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .fshr = .{ .ret_len = 1, @@ -3361,7 +3625,16 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .clmul = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"sadd.with.overflow" = .{ @@ -3372,7 +3645,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"uadd.with.overflow" = .{ .ret_len = 2, @@ -3382,7 +3655,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"ssub.with.overflow" = .{ .ret_len = 2, @@ -3392,7 +3665,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"usub.with.overflow" = .{ .ret_len = 2, @@ -3402,7 +3675,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"smul.with.overflow" = .{ .ret_len = 2, @@ -3412,7 +3685,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"umul.with.overflow" = .{ .ret_len = 2, @@ -3422,7 +3695,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"sadd.sat" = .{ @@ -3432,7 +3705,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"uadd.sat" = .{ .ret_len = 1, @@ -3441,7 +3714,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"ssub.sat" = .{ .ret_len = 1, @@ -3450,7 +3723,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"usub.sat" = .{ .ret_len = 1, @@ -3459,7 +3732,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"sshl.sat" = .{ .ret_len = 1, @@ -3468,7 +3741,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"ushl.sat" = .{ .ret_len = 1, @@ -3477,7 +3750,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"smul.fix" = .{ @@ -3488,7 +3761,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"umul.fix" = .{ .ret_len = 1, @@ -3498,7 +3771,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"smul.fix.sat" = .{ .ret_len = 1, @@ -3508,7 +3781,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"umul.fix.sat" = .{ .ret_len = 1, @@ -3518,7 +3791,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"sdiv.fix" = .{ .ret_len = 1, @@ -3528,7 +3801,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"udiv.fix" = .{ .ret_len = 1, @@ -3538,7 +3811,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"sdiv.fix.sat" = .{ .ret_len = 1, @@ -3548,7 +3821,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"udiv.fix.sat" = .{ .ret_len = 1, @@ -3558,7 +3831,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .canonicalize = .{ @@ -3567,7 +3840,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .fmuladd = .{ .ret_len = 1, @@ -3577,7 +3850,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.add" = .{ @@ -3586,7 +3859,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fadd" = .{ .ret_len = 1, @@ -3595,7 +3868,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 2 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.mul" = .{ .ret_len = 1, @@ -3603,7 +3876,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fmul" = .{ .ret_len = 1, @@ -3612,7 +3885,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 2 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.and" = .{ .ret_len = 1, @@ -3620,7 +3893,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.or" = .{ .ret_len = 1, @@ -3628,7 +3901,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.xor" = .{ .ret_len = 1, @@ -3636,7 +3909,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.smax" = .{ .ret_len = 1, @@ -3644,7 +3917,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.smin" = .{ .ret_len = 1, @@ -3652,7 +3925,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.umax" = .{ .ret_len = 1, @@ -3660,7 +3933,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.umin" = .{ .ret_len = 1, @@ -3668,7 +3941,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fmax" = .{ .ret_len = 1, @@ -3676,7 +3949,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fmin" = .{ .ret_len = 1, @@ -3684,7 +3957,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fmaximum" = .{ .ret_len = 1, @@ -3692,7 +3965,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fminimum" = .{ .ret_len = 1, @@ -3700,7 +3973,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.insert" = .{ .ret_len = 1, @@ -3710,7 +3983,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .type = .i64 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.extract" = .{ .ret_len = 1, @@ -3719,7 +3992,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .type = .i64 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"is.fpclass" = .{ @@ -3729,7 +4002,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"var.annotation" = .{ @@ -3814,7 +4087,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .expect = .{ .ret_len = 1, @@ -3823,7 +4096,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"expect.with.probability" = .{ .ret_len = 1, @@ -3833,7 +4106,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .double }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .assume = .{ .ret_len = 0, @@ -3848,7 +4121,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 }, .attrs = &.{.returned} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"type.test" = .{ .ret_len = 1, @@ -3857,7 +4130,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .ptr } }, .{ .kind = .{ .type = .metadata } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"type.checked.load" = .{ .ret_len = 2, @@ -3868,7 +4141,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .i32 } }, .{ .kind = .{ .type = .metadata } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"type.checked.load.relative" = .{ .ret_len = 2, @@ -3879,7 +4152,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .i32 } }, .{ .kind = .{ .type = .metadata } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"arithmetic.fence" = .{ .ret_len = 1, @@ -3887,12 +4160,12 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .donothing = .{ .ret_len = 0, .params = &.{}, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"load.relative" = .{ .ret_len = 1, @@ -3914,7 +4187,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .i1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .ptrmask = .{ .ret_len = 1, @@ -3923,7 +4196,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"threadlocal.address" = .{ .ret_len = 1, @@ -3931,14 +4204,14 @@ pub const Intrinsic = enum { .{ .kind = .overloaded, .attrs = &.{.nonnull} }, .{ .kind = .{ .matches = 0 }, .attrs = &.{.nonnull} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .vscale = .{ .ret_len = 1, .params = &.{ .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"dbg.declare" = .{ @@ -3948,7 +4221,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .metadata } }, .{ .kind = .{ .type = .metadata } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"dbg.value" = .{ .ret_len = 0, @@ -3957,7 +4230,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .metadata } }, .{ .kind = .{ .type = .metadata } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workitem.id.x" = .{ @@ -3965,42 +4238,42 @@ pub const Intrinsic = enum { .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workitem.id.y" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workitem.id.z" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workgroup.id.x" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workgroup.id.y" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workgroup.id.z" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.dispatch.ptr" = .{ .ret_len = 1, @@ -4010,7 +4283,7 @@ pub const Intrinsic = enum { .attrs = &.{.{ .@"align" = .wrap(.fromByteUnits(4)) }}, }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"nvvm.read.ptx.sreg.tid.x" = .{ @@ -4085,7 +4358,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"wasm.memory.grow" = .{ .ret_len = 1, @@ -4166,6 +4439,10 @@ pub const Function = struct { self.ptr(builder).attributes = new_function_attributes; } + pub fn getAttributes(self: Index, builder: *Builder) FunctionAttributes { + return self.ptr(builder).attributes; + } + pub fn setSection(self: Index, section: String, builder: *Builder) void { self.ptr(builder).section = section; } @@ -4487,7 +4764,7 @@ pub const Function = struct { } pub fn toValue(self: Instruction.Index) Value { - return @fromBackingInt(@intCast(@backingInt(self))); + return @fromBackingInt(@backingInt(self)); } pub fn isTerminatorWip(self: Instruction.Index, wip: *const WipFunction) bool { @@ -4679,7 +4956,7 @@ pub const Function = struct { .changeScalarAssumeCapacity(.i1, wip.builder), .fneg, .@"fneg fast", - => @as(Value, @fromBackingInt(@intCast(instruction.data))).typeOfWip(wip), + => @as(Value, @fromBackingInt(instruction.data)).typeOfWip(wip), .getelementptr, .@"getelementptr inbounds", => { @@ -4871,7 +5148,7 @@ pub const Function = struct { .changeScalarAssumeCapacity(.i1, builder), .fneg, .@"fneg fast", - => @as(Value, @fromBackingInt(@intCast(instruction.data))).typeOf(function_index, builder), + => @as(Value, @fromBackingInt(instruction.data)).typeOf(function_index, builder), .getelementptr, .@"getelementptr inbounds", => { @@ -4963,7 +5240,7 @@ pub const Function = struct { pub fn fromMetadata(metadata: Metadata) Weights { assert(metadata.kind == .node); - return @fromBackingInt(@intCast(metadata.index)); + return @fromBackingInt(metadata.index); } pub fn toMetadata(weights: Weights) Metadata { @@ -5156,7 +5433,7 @@ pub const Function = struct { assert(argument.tag == .arg); assert(argument.data == index); - const argument_index: Instruction.Index = @fromBackingInt(@intCast(index)); + const argument_index: Instruction.Index = @fromBackingInt(index); return argument_index.toValue(); } @@ -5202,7 +5479,7 @@ pub const Function = struct { Type, Value, Instruction.BrCond.Weights, - => @fromBackingInt(@intCast(value)), + => @fromBackingInt(value), MemoryAccessInfo, Instruction.Alloca.Info, Instruction.Call.Info, @@ -5327,7 +5604,7 @@ pub const WipFunction = struct { assert(argument.tag == .arg); assert(argument.data == index); - const argument_index: Instruction.Index = @fromBackingInt(@intCast(index)); + const argument_index: Instruction.Index = @fromBackingInt(index); return argument_index.toValue(); } @@ -6414,24 +6691,24 @@ pub const WipFunction = struct { errdefer function.instructions.shrinkRetainingCapacity(0); { - var final_instruction_index: Instruction.Index = @fromBackingInt(@intCast(0)); + var final_instruction_index: Instruction.Index = @fromBackingInt(0); for (0..params_len) |param_index| { instructions.items[param_index] = final_instruction_index; - final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1)); + final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1); } for (blocks, self.blocks.items) |*final_block, current_block| { assert(current_block.incoming == current_block.branches); final_block.instruction = final_instruction_index; - final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1)); + final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1); for (current_block.instructions.items) |instruction| { instructions.items[@backingInt(instruction)] = final_instruction_index; - final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1)); + final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1); } } } var wip_name: struct { - next_name: String = @fromBackingInt(@intCast(0)), + next_name: String = @fromBackingInt(0), next_unique_name: std.AutoHashMap(String, String), builder: *Builder, @@ -6440,19 +6717,19 @@ pub const WipFunction = struct { .none => return .none, .empty => { assert(wip_name.next_name != .none); - defer wip_name.next_name = @fromBackingInt(@intCast(@backingInt(wip_name.next_name) + 1)); + defer wip_name.next_name = @fromBackingInt(@backingInt(wip_name.next_name) + 1); return wip_name.next_name; }, _ => { assert(!name.isAnon()); const gop = try wip_name.next_unique_name.getOrPut(name); if (!gop.found_existing) { - gop.value_ptr.* = @fromBackingInt(@intCast(0)); + gop.value_ptr.* = @fromBackingInt(0); return name; } while (true) { - gop.value_ptr.* = @fromBackingInt(@intCast(@backingInt(gop.value_ptr.*) + 1)); + gop.value_ptr.* = @fromBackingInt(@backingInt(gop.value_ptr.*) + 1); const unique_name = try wip_name.builder.fmt("{f}{s}{f}", .{ name.fmtRaw(wip_name.builder), sep, @@ -6460,7 +6737,7 @@ pub const WipFunction = struct { }); const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name); if (!unique_gop.found_existing) { - unique_gop.value_ptr.* = @fromBackingInt(@intCast(0)); + unique_gop.value_ptr.* = @fromBackingInt(0); return unique_name; } } @@ -6702,7 +6979,7 @@ pub const WipFunction = struct { .fneg, .@"fneg fast", .ret, - => instruction.data = @backingInt(instructions.map(@fromBackingInt(@intCast(instruction.data)))), + => instruction.data = @backingInt(instructions.map(@fromBackingInt(instruction.data))), .getelementptr, .@"getelementptr inbounds", => { @@ -7079,7 +7356,7 @@ pub const WipFunction = struct { Type, Value, Instruction.BrCond.Weights, - => @fromBackingInt(@intCast(value)), + => @fromBackingInt(value), MemoryAccessInfo, Instruction.Alloca.Info, Instruction.Call.Info, @@ -7268,7 +7545,7 @@ pub const Constant = enum(u32) { no_init = (1 << 30) - 1, _, - const first_global: Constant = @fromBackingInt(@intCast(1 << 29)); + const first_global: Constant = @fromBackingInt(1 << 29); pub const Tag = enum(u7) { positive_integer, @@ -7405,7 +7682,18 @@ pub const Constant = enum(u32) { val: Constant, type: Type, - pub const Signedness = enum { unsigned, signed, unneeded }; + pub const Signedness = enum { + unsigned, + signed, + unneeded, + + pub fn fromStdLang(signedness: std.lang.Signedness) Signedness { + return switch (signedness) { + .unsigned => .unsigned, + .signed => .signed, + }; + } + }; }; pub const GetElementPtr = struct { @@ -7444,11 +7732,11 @@ pub const Constant = enum(u32) { return if (@backingInt(self) < @backingInt(first_global)) .{ .constant = @intCast(@backingInt(self)) } else - .{ .global = @fromBackingInt(@intCast(@backingInt(self) - @backingInt(first_global))) }; + .{ .global = @fromBackingInt(@backingInt(self) - @backingInt(first_global)) }; } pub fn toValue(self: Constant) Value { - return @fromBackingInt(@intCast(Value.first_constant + @backingInt(self))); + return @fromBackingInt(Value.first_constant + @backingInt(self)); } pub fn typeOf(self: Constant, builder: *Builder) Type { @@ -7474,7 +7762,7 @@ pub const Constant = enum(u32) { .zeroinitializer, .undef, .poison, - => @fromBackingInt(@intCast(item.data)), + => @fromBackingInt(item.data), .structure, .packed_structure, .array, @@ -7482,7 +7770,7 @@ pub const Constant = enum(u32) { => builder.constantExtraData(Aggregate, item.data).type, .splat => builder.constantExtraData(Splat, item.data).type, .string => builder.arrayTypeAssumeCapacity( - @as(String, @fromBackingInt(@intCast(item.data))).slice(builder).?.len, + @as(String, @fromBackingInt(item.data)).slice(builder).?.len, .i8, ), .blockaddress => builder.ptrTypeAssumeCapacity( @@ -7491,7 +7779,7 @@ pub const Constant = enum(u32) { ), .dso_local_equivalent, .no_cfi, - => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(@intCast(item.data))) + => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(item.data)) .ptrConst(builder).global.ptrConst(builder).addr_space), .trunc, .ptrtoint, @@ -7802,7 +8090,7 @@ pub const Constant = enum(u32) { try w.writeByte('>'); }, .string => try w.print("c{f}", .{ - @as(String, @fromBackingInt(@intCast(item.data))).fmtQ(data.builder), + @as(String, @fromBackingInt(item.data)).fmtQ(data.builder), }), .blockaddress => |tag| { const extra = data.builder.constantExtraData(BlockAddress, item.data); @@ -7816,7 +8104,7 @@ pub const Constant = enum(u32) { .dso_local_equivalent, .no_cfi, => |tag| { - const function: Function.Index = @fromBackingInt(@intCast(item.data)); + const function: Function.Index = @fromBackingInt(item.data); try w.print("{s} {f}", .{ @tagName(tag), function.ptrConst(data.builder).global.fmt(data.builder), @@ -7920,9 +8208,9 @@ pub const Value = enum(u32) { metadata: Metadata, } { return if (@backingInt(self) < first_constant) - .{ .instruction = @fromBackingInt(@intCast(@backingInt(self))) } + .{ .instruction = @fromBackingInt(@backingInt(self)) } else if (@backingInt(self) < first_metadata) - .{ .constant = @fromBackingInt(@intCast(@backingInt(self) - first_constant)) } + .{ .constant = @fromBackingInt(@backingInt(self) - first_constant) } else .{ .metadata = @bitCast(@backingInt(self) - first_metadata) }; } @@ -8016,7 +8304,7 @@ pub const Metadata = packed struct(u32) { return .{ .index = metadata.index, .kind = metadata.kind, .is_none = false }; } pub fn toValue(metadata: Metadata) Value { - return @fromBackingInt(@intCast(Value.first_metadata + @as(u32, @bitCast(metadata)))); + return @fromBackingInt(Value.first_metadata + @as(u32, @bitCast(metadata))); } pub const String = enum(u32) { @@ -8032,7 +8320,7 @@ pub const Metadata = packed struct(u32) { pub fn unwrap(metadata: Metadata.String.Optional) ?Metadata.String { return switch (metadata) { .none => null, - else => @fromBackingInt(@intCast(@backingInt(metadata))), + else => @fromBackingInt(@backingInt(metadata)), }; } pub fn toMetadata(metadata: Metadata.String.Optional) Metadata.Optional { @@ -8040,7 +8328,7 @@ pub const Metadata = packed struct(u32) { } }; pub fn toOptional(metadata: Metadata.String) Metadata.String.Optional { - return @fromBackingInt(@intCast(@backingInt(metadata))); + return @fromBackingInt(@backingInt(metadata)); } pub fn toMetadata(metadata: Metadata.String) Metadata { return .{ .index = @intCast(@backingInt(metadata)), .kind = .string }; @@ -8077,7 +8365,7 @@ pub const Metadata = packed struct(u32) { }; pub fn toString(metadata: Metadata) Metadata.String { assert(metadata.kind == .string); - return @fromBackingInt(@intCast(metadata.index)); + return @fromBackingInt(metadata.index); } pub const Tag = enum(u6) { @@ -8542,7 +8830,7 @@ pub const Metadata = packed struct(u32) { try w.writeByte(')'); }, .constant => try Constant.format(.{ - .constant = @fromBackingInt(@intCast(node_item.data)), + .constant = @fromBackingInt(node_item.data), .builder = builder, .flags = data.specialized orelse .{}, }, w), @@ -8744,7 +9032,7 @@ pub fn init(options: Options) Allocator.Error!Builder { .string_bytes = .empty, .types = .empty, - .next_unnamed_type = @fromBackingInt(@intCast(0)), + .next_unnamed_type = @fromBackingInt(0), .next_unique_type_id = .empty, .type_map = .empty, .type_items = .empty, @@ -8758,7 +9046,7 @@ pub fn init(options: Options) Allocator.Error!Builder { .function_attributes_set = .empty, .globals = .empty, - .next_unnamed_global = @fromBackingInt(@intCast(0)), + .next_unnamed_global = @fromBackingInt(0), .next_replaced_global = .none, .next_unique_global_id = .empty, .aliases = .empty, @@ -8815,7 +9103,7 @@ pub fn init(options: Options) Allocator.Error!Builder { assert(self.intTypeAssumeCapacity(bits) == @field(Type, std.fmt.comptimePrint("i{d}", .{bits}))); inline for (.{ 0, 4 }) |addr_space_index| { - const addr_space: AddrSpace = @fromBackingInt(@intCast(addr_space_index)); + const addr_space: AddrSpace = @fromBackingInt(addr_space_index); assert(self.ptrTypeAssumeCapacity(addr_space) == @field(Type, std.fmt.comptimePrint("ptr{f}", .{addr_space.fmt(" ")}))); } @@ -9092,17 +9380,17 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr return @backingInt(lhs_kind) < @backingInt(rhs_kind); } }.lessThan); - return @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast(attributes)))); + return @fromBackingInt(try self.attrGeneric(@ptrCast(attributes))); } pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes { try self.function_attributes_set.ensureUnusedCapacity(self.gpa, 1); - const function_attributes: FunctionAttributes = @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast( + const function_attributes: FunctionAttributes = @fromBackingInt(try self.attrGeneric(@ptrCast( fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last| last + 1 else 0], - )))); + ))); _ = self.function_attributes_set.getOrPutAssumeCapacity(function_attributes); return function_attributes; @@ -9121,7 +9409,7 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: StrtabString, global: Globa if (name == .empty) { id = self.next_unnamed_global; assert(id != self.next_replaced_global); - self.next_unnamed_global = @fromBackingInt(@intCast(@backingInt(id) + 1)); + self.next_unnamed_global = @fromBackingInt(@backingInt(id) + 1); } while (true) { const global_gop = self.globals.getOrPutAssumeCapacity(id); @@ -10058,7 +10346,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void continue; }, .br => |tag| { - const target: Function.Block.Index = @fromBackingInt(@intCast(instruction.data)); + const target: Function.Block.Index = @fromBackingInt(instruction.data); try w.print(" {s} {f}", .{ @tagName(tag), target.toInst(&function).fmt(function_index, self, .{ .percent = true }), }); @@ -10187,7 +10475,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void .fneg, .@"fneg fast", => |tag| { - const val: Value = @fromBackingInt(@intCast(instruction.data)); + const val: Value = @fromBackingInt(instruction.data); try w.print(" %{f} = {s} {f}", .{ instruction_index.name(&function).fmt(self), @tagName(tag), @@ -10288,7 +10576,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void } }, .ret => |tag| { - const val: Value = @fromBackingInt(@intCast(instruction.data)); + const val: Value = @fromBackingInt(instruction.data); try w.print(" {s} {f}", .{ @tagName(tag), val.fmt(function_index, self, .{ .percent = true }), @@ -11020,7 +11308,7 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type { if (name == .empty) { id = self.next_unnamed_type; assert(id != .none); - self.next_unnamed_type = @fromBackingInt(@intCast(@backingInt(id) + 1)); + self.next_unnamed_type = @fromBackingInt(@backingInt(id) + 1); } else assert(!name.isAnon()); while (true) { const type_gop = self.types.getOrPutAssumeCapacity(id); @@ -11135,7 +11423,7 @@ fn typeExtraDataTrail( ) |field_name, field_type, value| @field(result, field_name) = switch (field_type) { u32 => value, - String, Type => @fromBackingInt(@intCast(value)), + String, Type => @fromBackingInt(value), else => @compileError("bad field type: " ++ @typeName(field_type)), }; return .{ @@ -11746,7 +12034,7 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty: return std.meta.eql(lhs_key.cast, rhs_extra); } }; - const data = Key{ .tag = tag, .cast = .{ .val = val, .type = ty } }; + const data: Key = .{ .tag = tag, .cast = .{ .val = val, .type = ty } }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); if (!gop.found_existing) { gop.key_ptr.* = {}; @@ -11828,10 +12116,10 @@ fn gepConstAssumeCapacity( std.mem.eql(Constant, lhs_key.indices, rhs_indices); } }; - const data = Key{ + const data: Key = .{ .type = ty, .base = base, - .inrange = if (inrange) |index| @fromBackingInt(@intCast(index)) else .none, + .inrange = if (inrange) |index| @fromBackingInt(index) else .none, .indices = indices, }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); @@ -11885,7 +12173,7 @@ fn binConstAssumeCapacity( return std.meta.eql(lhs_key.extra, rhs_extra); } }; - const data = Key{ .tag = tag, .extra = .{ .lhs = lhs, .rhs = rhs } }; + const data: Key = .{ .tag = tag, .extra = .{ .lhs = lhs, .rhs = rhs } }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); if (!gop.found_existing) { gop.key_ptr.* = {}; @@ -11924,8 +12212,8 @@ fn asmConstAssumeCapacity( } }; - const data = Key{ - .tag = @fromBackingInt(@intCast(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info)))), + const data: Key = .{ + .tag = @fromBackingInt(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info))), .extra = .{ .type = ty, .assembly = assembly, .constraints = constraints }, }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); @@ -12073,7 +12361,7 @@ fn constantExtraDataTrail( ) |field_name, field_type, value| @field(result, field_name) = switch (field_type) { u32 => value, - String, Type, Constant, Function.Index, Function.Block.Index => @fromBackingInt(@intCast(value)), + String, Type, Constant, Function.Index, Function.Block.Index => @fromBackingInt(value), Constant.GetElementPtr.Info => @bitCast(value), else => @compileError("bad field type: " ++ @typeName(field_type)), }; @@ -12151,7 +12439,7 @@ fn metadataExtraDataTrail( ) |field_name, field_type, value| @field(result, field_name) = switch (field_type) { u32 => value, - Metadata.String, Metadata.String.Optional, Variable.Index, Value => @fromBackingInt(@intCast(value)), + Metadata.String, Metadata.String.Optional, Variable.Index, Value => @fromBackingInt(value), Metadata, Metadata.Optional, Metadata.DIFlags => @bitCast(value), else => @compileError("bad field type: " ++ @typeName(field_type)), }; @@ -12759,8 +13047,8 @@ fn debugSubprogramAssumeCapacity( compile_unit: ?Metadata, ) Metadata { assert(!self.strip); - const tag: Metadata.Tag = @fromBackingInt(@intCast(@backingInt(Metadata.Tag.subprogram) + - @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2)))); + const tag: Metadata.Tag = @fromBackingInt(@backingInt(Metadata.Tag.subprogram) + + @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2))); return self.metadataDistinctAssumeCapacity(tag, Metadata.Subprogram{ .file = .wrap(file), .name = .wrap(name), @@ -13345,7 +13633,7 @@ fn metadataConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata { pub fn eql(ctx: @This(), lhs_key: Constant, _: void, rhs_index: usize) bool { if (Metadata.Tag.constant != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; - const rhs_data: Constant = @fromBackingInt(@intCast(ctx.builder.metadata_items.items(.data)[rhs_index])); + const rhs_data: Constant = @fromBackingInt(ctx.builder.metadata_items.items(.data)[rhs_index]); return rhs_data == lhs_key; } }; @@ -13577,6 +13865,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco switch (attr_index.toAttribute(self)) { .zeroext, .signext, + .noext, .inreg, .@"noalias", .nocapture, @@ -13594,11 +13883,13 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .readnone, .readonly, .writeonly, + .writable, + .dead_on_unwind, .alwaysinline, .builtin, .cold, .convergent, - .disable_sanitizer_information, + .disable_sanitizer_instrumentation, .fn_ret_thunk_extern, .hot, .inlinehint, @@ -13607,6 +13898,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .naked, .nobuiltin, .nocallback, + .nodivergencesource, .noduplicate, .noimplicitfloat, .@"noinline", @@ -13623,6 +13915,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .nosanitize_bounds, .nosanitize_coverage, .null_pointer_is_valid, + .optdebug, .optforfuzzing, .optnone, .optsize, @@ -13633,18 +13926,21 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .sanitize_thread, .sanitize_hwaddress, .sanitize_memtag, + .sanitize_realtime, + .sanitize_realtime_blocking, + .sanitize_alloc_token, .speculative_load_hardening, .speculatable, .ssp, .sspstrong, .sspreq, .strictfp, + .denormal_fpenv, .nocf_check, .shadowcallstack, .mustprogress, - .no_sanitize_address, - .no_sanitize_hwaddress, - .sanitize_address_dyninit, + .nooutline, + .nocreateundeforpoison, => { try record.ensureUnusedCapacity(self.gpa, 2); record.appendAssumeCapacity(0); @@ -13670,6 +13966,12 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco record.appendAssumeCapacity(@backingInt(kind)); record.appendAssumeCapacity(alignment.resolve(self).toByteUnits() orelse 0); }, + .captures => |captures| { + try record.ensureUnusedCapacity(self.gpa, 3); + record.appendAssumeCapacity(1); + record.appendAssumeCapacity(@backingInt(kind)); + record.appendAssumeCapacity(@as(u32, @bitCast(captures))); + }, .dereferenceable, .dereferenceable_or_null, => |size| { @@ -13684,6 +13986,9 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco record.appendAssumeCapacity(@backingInt(kind)); record.appendAssumeCapacity(@as(u32, @bitCast(fpclass))); }, + .initializes => @panic("TODO"), + .dead_on_return => @panic("TODO"), + .range => @panic("TODO"), .allockind => |allockind| { try record.ensureUnusedCapacity(self.gpa, 3); record.appendAssumeCapacity(1); @@ -14099,7 +14404,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco } }, .string => { - const str: String = @fromBackingInt(@intCast(data)); + const str: String = @fromBackingInt(data); if (str == .none) { try constants_block.writeAbbrev(ConstantsBlock.Null{}); } else { @@ -14226,7 +14531,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .dso_local_equivalent, .no_cfi, => |tag| { - const function: Function.Index = @fromBackingInt(@intCast(data)); + const function: Function.Index = @fromBackingInt(data); try constants_block.writeAbbrev(ConstantsBlock.DsoLocalEquivalentOrNoCfi{ .code = switch (tag) { .dso_local_equivalent => .DSO_LOCAL_EQUIVALENT, @@ -14609,7 +14914,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco }, metadata_adapter); }, .constant => { - const constant: Constant = @fromBackingInt(@intCast(data)); + const constant: Constant = @fromBackingInt(data); try metadata_block.writeAbbrevAdapted(MetadataBlock.Constant{ .ty = constant.typeOf(self), .constant = constant, @@ -14778,7 +15083,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco var adapter: FunctionAdapter = .{ .metadata_adapter = metadata_adapter, .func = &func, - .instruction_index = @fromBackingInt(@intCast(0)), + .instruction_index = @fromBackingInt(0), }; // Emit function level metadata block @@ -14789,7 +15094,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco for (func.debug_values) |value| { try metadata_block.writeAbbrev(MetadataBlock.Value{ .ty = value.typeOf(@fromBackingInt(@intCast(func_index)), self), - .value = @fromBackingInt(@intCast(adapter.getValueIndex(value.toValue()))), + .value = @fromBackingInt(adapter.getValueIndex(value.toValue())), }); } @@ -15071,10 +15376,10 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco }); }, .fneg => try function_block.writeAbbrev(FunctionBlock.FNeg{ - .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))), + .val = adapter.getOffsetValueIndex(@fromBackingInt(data)), }), .@"fneg fast" => try function_block.writeAbbrev(FunctionBlock.FNegFast{ - .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))), + .val = adapter.getOffsetValueIndex(@fromBackingInt(data)), .fast_math = FastMath.fast, }), .extractvalue => { @@ -15274,7 +15579,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco try function_block.writeUnabbrev(16, record.items); }, .ret => try function_block.writeAbbrev(FunctionBlock.Ret{ - .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))), + .val = adapter.getOffsetValueIndex(@fromBackingInt(data)), }), .@"ret void" => try function_block.writeAbbrev(FunctionBlock.RetVoid{}), .atomicrmw => { -- 2.54.0 From 0c0be6da880fd1a6bdd3266125d6c5bcaac2803f Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 26 Jun 2026 01:08:08 -0400 Subject: [PATCH 07/22] llvm: implement c cabi for s390x Closes #35799 --- CMakeLists.txt | 1 + src/codegen/aarch64/abi.zig | 2 +- src/codegen/llvm/FuncGen.zig | 31 +++++++++- src/codegen/s390x/abi.zig | 90 +++++++++++++++++++++++++++ test/c_abi/cfuncs.c | 12 ---- test/c_abi/main.zig | 115 +---------------------------------- 6 files changed, 121 insertions(+), 130 deletions(-) create mode 100644 src/codegen/s390x/abi.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f144cd68374ec7c0ec8c7ba7964cde06943d88a..ad4d8bea72ee199d041ef28559b536de2f20f7e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -358,6 +358,7 @@ set(ZIG_STAGE2_SOURCES src/codegen/c/type/render_defs.zig src/codegen/llvm.zig src/codegen/llvm/bindings.zig + src/codegen/s390x/abi.zig src/crash_report.zig src/dev.zig src/libs/freebsd.zig diff --git a/src/codegen/aarch64/abi.zig b/src/codegen/aarch64/abi.zig index dcd192da8395fc6fca07c101aebff596bc4e99cc..942e4d0660d79fd8bb0e204714586dd7878b3ebe 100644 --- a/src/codegen/aarch64/abi.zig +++ b/src/codegen/aarch64/abi.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assert = std.debug.assert; const std = @import("std"); const InternPool = @import("../../InternPool.zig"); const Type = @import("../../Type.zig"); diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 5e05a779220d002a88fd128d5057f5eef70e1a4a..156aa875926d6d3d55341b2eac6d1e8f93e18972 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -6808,6 +6808,24 @@ const ParamTypeIterator = struct { }, } }, + .s390x_sysv, .s390x_sysv_vx => { + it.zig_index += 1; + switch (s390x_c_abi.classifyType(ty, .arg, zcu)) { + .none => return .no_bits, + .double_or_float, .vector, .simple => { + it.llvm_index += 1; + return .byval; + }, + .simple_aggregate => { + it.llvm_index += 1; + return .abi_sized_int; + }, + .pointer => { + it.llvm_index += 1; + return .byref_mut; + }, + } + }, .wasm_mvp => switch (wasm_c_abi.classifyType(ty, zcu)) { .direct => |scalar_ty| { if (isScalar(zcu, ty)) { @@ -7086,6 +7104,12 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err return .{ .mem_cast = try o.builder.structType(.normal, types[0..types_len]) }; }, }, + .s390x_sysv, .s390x_sysv_vx => return switch (s390x_c_abi.classifyType(ret_ty, .ret, zcu)) { + .none => .void, + .double_or_float, .vector, .simple => .by_val, + .simple_aggregate => unreachable, + .pointer => .sret, + }, .wasm_mvp => switch (wasm_c_abi.classifyType(ret_ty, zcu)) { .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) { assert(!isByRef(ret_ty, zcu)); @@ -7823,12 +7847,13 @@ const Builder = std.zig.llvm.Builder; const assert = std.debug.assert; const math = std.math; -const x86_64_abi = @import("../x86_64/abi.zig"); -const wasm_c_abi = @import("../wasm/abi.zig"); const aarch64_c_abi = @import("../aarch64/abi.zig"); const arm_c_abi = @import("../arm/abi.zig"); -const riscv_c_abi = @import("../riscv64/abi.zig"); const mips_c_abi = @import("../mips/abi.zig"); +const riscv_c_abi = @import("../riscv64/abi.zig"); +const s390x_c_abi = @import("../s390x/abi.zig"); +const wasm_c_abi = @import("../wasm/abi.zig"); +const x86_64_abi = @import("../x86_64/abi.zig"); const Zcu = @import("../../Zcu.zig"); const Air = @import("../../Air.zig"); diff --git a/src/codegen/s390x/abi.zig b/src/codegen/s390x/abi.zig new file mode 100644 index 0000000000000000000000000000000000000000..6fb81d3e6b8792566b9c69156ca63a67ed788299 --- /dev/null +++ b/src/codegen/s390x/abi.zig @@ -0,0 +1,90 @@ +const assert = std.debug.assert; +const std = @import("std"); +const InternPool = @import("../../InternPool.zig"); +const Type = @import("../../Type.zig"); +const Zcu = @import("../../Zcu.zig"); + +pub const Context = enum { ret, arg }; + +pub const Class = enum { + none, + double_or_float, + vector, + simple, + simple_aggregate, + pointer, +}; + +pub fn classifyType(ty: Type, context: Context, zcu: *Zcu) Class { + tag: switch (ty.zigTypeTag(zcu)) { + .type, + .comptime_float, + .comptime_int, + .undefined, + .null, + .error_union, + .error_set, + .@"fn", + .@"opaque", + .frame, + .@"anyframe", + .enum_literal, + .spirv, + => unreachable, + .void, .noreturn => return .none, + .bool => return .simple, + .int, .@"enum" => return switch (ty.intInfo(zcu).bits) { + 0 => .none, + 1...64 => .simple, + else => .pointer, + }, + .float => return switch (ty.floatBits(zcu.getTarget())) { + 16, 32, 64 => .double_or_float, + else => .pointer, + }, + .pointer, .optional => return .simple, + .array => switch (ty.arrayLen(zcu)) { + 0 => return .none, + 1 => switch (context) { + .ret => {}, + .arg => return classifyType(ty.childType(zcu), context, zcu), + }, + else => {}, + }, + .@"struct", .@"union" => |tag| switch (ty.containerLayout(zcu)) { + .auto => unreachable, + .@"extern" => switch (context) { + .ret => {}, + .arg => { + var class: Class = .none; + for (0..switch (tag) { + else => unreachable, + .@"struct" => ty.structFieldCount(zcu), + .@"union" => ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu), + }) |field_index| { + switch (tag) { + else => unreachable, + .@"struct" => if (ty.structFieldIsComptime(field_index, zcu)) continue, + .@"union" => {}, + } + const field_class = classifyType(ty.fieldType(field_index, zcu), context, zcu); + if (field_class == .none) continue; + if (class != .none) break :tag; + class = field_class; + } + return class; + }, + }, + .@"packed" => return classifyType(ty.backingIntType(zcu), context, zcu), + }, + .vector => return if (ty.abiSize(zcu) <= 16) .vector else .pointer, + } + return switch (ty.abiSize(zcu)) { + 0 => .none, + 1, 2, 4, 8 => switch (context) { + .ret => .pointer, + .arg => .simple_aggregate, + }, + else => .pointer, + }; +} diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index cfd3872c94ef750e6663f6e9c4d186516c76beb7..acd8c258649e3cccadadbd4390d8f9b0cf0999a6 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -15564,7 +15564,6 @@ void run_c_tests(void) { #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct Struct_i32_i32 s = {1, 2}; zig_struct_i32_i32(s); @@ -15573,13 +15572,11 @@ void run_c_tests(void) { #endif #endif #endif -#endif #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct BigStruct s = {1, 2, 3, 4, 5}; zig_big_struct(s); @@ -15588,7 +15585,6 @@ void run_c_tests(void) { #endif #endif #endif -#endif #ifndef ZIG_NO_I128 { @@ -15613,7 +15609,6 @@ void run_c_tests(void) { #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct SplitStructInts s = {1234, 100, 1337}; zig_split_struct_ints(s); @@ -15623,13 +15618,11 @@ void run_c_tests(void) { #endif #endif #endif -#endif #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct MedStructMixed s = {1234, 100.0f, 1337.0f}; zig_med_struct_mixed(s); @@ -15638,14 +15631,12 @@ void run_c_tests(void) { #endif #endif #endif -#endif #ifndef __hexagon__ #ifndef __i386__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct SplitStructMixed s = {1234, 100, 1337.0f}; zig_split_struct_mixed(s); @@ -15655,13 +15646,11 @@ void run_c_tests(void) { #endif #endif #endif -#endif #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct BigStruct s = {30, 31, 32, 33, 34}; struct BigStruct res = zig_big_struct_both(s); @@ -15674,7 +15663,6 @@ void run_c_tests(void) { #endif #endif #endif -#endif #endif { diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 974adf898c9fd092396d279bf34a22f050235d73..387eeb88c20b4ebfa9646ff10fde7322db299302 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -13,7 +13,7 @@ const expectEqual = std.testing.expectEqual; const have_i128 = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isMIPS() and !builtin.cpu.arch.isPowerPC32() and builtin.cpu.arch != .riscv32 and builtin.cpu.arch != .hexagon and - builtin.cpu.arch != .s390x; // https://github.com/llvm/llvm-project/issues/168460 + builtin.cpu.arch != .s390x; const have_f128 = builtin.cpu.arch.isWasm() or (builtin.cpu.arch.isX86() and !builtin.os.tag.isDarwin() and builtin.abi != .msvc); const have_f80 = builtin.cpu.arch.isX86() and builtin.abi != .msvc; @@ -5136,7 +5136,6 @@ test "@Vector(24, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_24_u8(); try expect(v[0] == 57); @@ -5220,7 +5219,6 @@ test "@Vector(32, u8)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_u8(); try expect(v[0] == 69); @@ -5330,7 +5328,6 @@ test "@Vector(48, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_48_u8(); try expect(v[0] == 29); @@ -5473,7 +5470,6 @@ test "@Vector(64, u8)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_u8(); try expect(v[0] == 53); @@ -5668,7 +5664,6 @@ test "@Vector(96, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_96_u8(); try expect(v[0] == 82); @@ -5931,7 +5926,6 @@ test "@Vector(128, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_128_u8(); try expect(v[0] == 30); @@ -6296,7 +6290,6 @@ test "@Vector(192, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_192_u8(); try expect(v[0] == 70); @@ -6797,7 +6790,6 @@ test "@Vector(256, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_256_u8(); try expect(v[0] == 66); @@ -7502,7 +7494,6 @@ test "@Vector(384, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_384_u8(); try expect(v[0] == 46); @@ -8479,7 +8470,6 @@ test "@Vector(512, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_512_u8(); try expect(v[0] == 38); @@ -9250,7 +9240,6 @@ test "@Vector(12, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_12_u16(); try expect(v[0] == 121); @@ -9300,7 +9289,6 @@ test "@Vector(16, u16)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_16_u16(); try expect(v[0] == 177); @@ -9366,7 +9354,6 @@ test "@Vector(24, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_24_u16(); try expect(v[0] == 257); @@ -9450,7 +9437,6 @@ test "@Vector(32, u16)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_u16(); try expect(v[0] == 369); @@ -9560,7 +9546,6 @@ test "@Vector(48, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_48_u16(); try expect(v[0] == 529); @@ -9704,7 +9689,6 @@ test "@Vector(64, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_u16(); try expect(v[0] == 753); @@ -9899,7 +9883,6 @@ test "@Vector(96, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_96_u16(); try expect(v[0] == 1082); @@ -10162,7 +10145,6 @@ test "@Vector(128, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_128_u16(); try expect(v[0] == 1530); @@ -10527,7 +10509,6 @@ test "@Vector(192, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_192_u16(); try expect(v[0] == 2170); @@ -11028,7 +11009,6 @@ test "@Vector(256, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_256_u16(); try expect(v[0] == 3066); @@ -11445,7 +11425,6 @@ test "@Vector(6, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_6_u32(); try expect(v[0] == 53); @@ -11481,7 +11460,6 @@ test "@Vector(8, u32)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_8_u32(); try expect(v[0] == 81); @@ -11524,7 +11502,6 @@ test "@Vector(12, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_12_u32(); try expect(v[0] == 121); @@ -11574,7 +11551,6 @@ test "@Vector(16, u32)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_16_u32(); try expect(v[0] == 177); @@ -11640,7 +11616,6 @@ test "@Vector(24, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_24_u32(); try expect(v[0] == 257); @@ -11725,7 +11700,6 @@ test "@Vector(32, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_u32(); try expect(v[0] == 369); @@ -11835,7 +11809,6 @@ test "@Vector(48, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_48_u32(); try expect(v[0] == 529); @@ -11979,7 +11952,6 @@ test "@Vector(64, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_u32(); try expect(v[0] == 753); @@ -12174,7 +12146,6 @@ test "@Vector(96, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_96_u32(); try expect(v[0] == 1082); @@ -12437,7 +12408,6 @@ test "@Vector(128, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_128_u32(); try expect(v[0] == 1530); @@ -12644,7 +12614,6 @@ test "@Vector(3, u64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_3_u64(); try expect(v[0] == 19); @@ -12673,7 +12642,6 @@ test "@Vector(4, u64)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_4_u64(); try expect(v[0] == 33); @@ -12740,7 +12708,6 @@ test "@Vector(8, u64)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_8_u64(); try expect(v[0] == 81); @@ -12832,7 +12799,6 @@ test "@Vector(16, u64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_16_u64(); try expect(v[0] == 177); @@ -12981,7 +12947,6 @@ test "@Vector(32, u64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_u64(); try expect(v[0] == 369); @@ -13233,7 +13198,6 @@ test "@Vector(64, u64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_u64(); try expect(v[0] == 753); @@ -13449,7 +13413,6 @@ test "@Vector(6, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_6_f32(); try expect(v[0] == 53); @@ -13486,7 +13449,6 @@ test "@Vector(8, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_8_f32(); try expect(v[0] == 81); @@ -13529,7 +13491,6 @@ test "@Vector(12, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_12_f32(); try expect(v[0] == 121); @@ -13580,7 +13541,6 @@ test "@Vector(16, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_16_f32(); try expect(v[0] == 177); @@ -13646,7 +13606,6 @@ test "@Vector(24, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_24_f32(); try expect(v[0] == 257); @@ -13731,7 +13690,6 @@ test "@Vector(32, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_f32(); try expect(v[0] == 369); @@ -13841,7 +13799,6 @@ test "@Vector(48, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_48_f32(); try expect(v[0] == 529); @@ -13985,7 +13942,6 @@ test "@Vector(64, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_f32(); try expect(v[0] == 753); @@ -14180,7 +14136,6 @@ test "@Vector(96, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_96_f32(); try expect(v[0] == 1082); @@ -14443,7 +14398,6 @@ test "@Vector(128, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_128_f32(); try expect(v[0] == 1530); @@ -14651,7 +14605,6 @@ test "@Vector(3, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_3_f64(); try expect(v[0] == 19); @@ -14680,7 +14633,6 @@ test "@Vector(4, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899 const v = c_ret_vector_4_f64(); @@ -14714,7 +14666,6 @@ test "@Vector(6, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_6_f64(); try expect(v[0] == 53); @@ -14750,7 +14701,6 @@ test "@Vector(8, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899 const v = c_ret_vector_8_f64(); @@ -14794,7 +14744,6 @@ test "@Vector(12, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_12_f64(); try expect(v[0] == 121); @@ -14845,7 +14794,6 @@ test "@Vector(16, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_16_f64(); try expect(v[0] == 177); @@ -14911,7 +14859,6 @@ test "@Vector(24, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_24_f64(); try expect(v[0] == 257); @@ -14996,7 +14943,6 @@ test "@Vector(32, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_f64(); try expect(v[0] == 369); @@ -15106,7 +15052,6 @@ test "@Vector(48, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_48_f64(); try expect(v[0] == 529); @@ -15250,7 +15195,6 @@ test "@Vector(64, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_f64(); try expect(v[0] == 753); @@ -15345,7 +15289,6 @@ extern fn c_test_struct_u8() void; test "struct u8" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_u8(); @@ -15377,7 +15320,6 @@ test "struct u8, u8" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8(); @@ -15412,7 +15354,6 @@ test "struct u8, u8, u8" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8_u8(); @@ -15450,7 +15391,6 @@ test "struct u8, u8, u8, u8" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8_u8_u8(); @@ -15481,7 +15421,6 @@ extern fn c_test_struct_u16() void; test "struct u16" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_u16(); @@ -15513,7 +15452,6 @@ test "struct u16, u16" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u16_u16(); @@ -15549,7 +15487,6 @@ test "struct u16, u16, u16" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u16_u16_u16(); @@ -15588,7 +15525,6 @@ test "struct u16, u16, u16, u16" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u16_u16_u16_u16(); @@ -15619,7 +15555,6 @@ extern fn c_test_struct_u32() void; test "struct u32" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_u32(); @@ -15651,7 +15586,6 @@ test "struct u32, u32" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_u32_u32(); @@ -15686,7 +15620,6 @@ test "struct u32, u32, u32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u32_u32_u32(); try expect(s.a == 8); @@ -15723,7 +15656,6 @@ test "struct u32, u32, u32, u32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u32_u32_u32_u32(); try expect(s.a == 10); @@ -15753,7 +15685,6 @@ extern fn c_test_struct_u64() void; test "struct u64" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_u64(); @@ -15831,7 +15762,6 @@ extern fn c_test_struct_u64_u64() void; test "struct u64, u64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u64_u64(); try expect(s.a == 21); @@ -15872,7 +15802,6 @@ test "struct u64, u64, u64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u64_u64_u64(); try expect(s.a == 8); @@ -15908,7 +15837,6 @@ test "struct u64, u64, u64, u64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u64_u64_u64_u64(); try expect(s.a == 10); @@ -15938,7 +15866,6 @@ extern fn c_test_struct_f32() void; test "struct f32" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_f32(); @@ -15971,7 +15898,6 @@ test "struct f32, f32" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_f32_f32(); @@ -16007,7 +15933,6 @@ test "struct f32, f32, f32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f32_f32_f32(); try expect(s.a == 8); @@ -16045,7 +15970,6 @@ test "struct f32, f32, f32, f32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f32_f32_f32_f32(); try expect(s.a == 10); @@ -16085,7 +16009,6 @@ test "struct f32, f32, f32, f32, f32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f32_f32_f32_f32_f32(); try expect(s.a == 12); @@ -16120,7 +16043,6 @@ test "struct f32 align(8)" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_f32a8(); @@ -16154,7 +16076,6 @@ test "struct f32 align(8), f32 align(8)" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_f32a8_f32a8(); @@ -16188,7 +16109,6 @@ test "struct {f32, f32}, f32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f32f32_f32(); try expect(s.a.b == 1.0); @@ -16222,7 +16142,6 @@ test "struct f32, {f32, f32}" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f32_f32f32(); try expect(s.a == 1.0); @@ -16252,7 +16171,6 @@ test "struct f64" { if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_f64(); @@ -16283,7 +16201,6 @@ test "struct f64, f64" { if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f64_f64(); try expect(s.a == 6); @@ -16316,7 +16233,6 @@ test "struct f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64(); try expect(s.a == 8); @@ -16352,7 +16268,6 @@ test "struct f64, f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64_f64(); try expect(s.a == 10); @@ -16391,7 +16306,6 @@ test "struct f64, f64, f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64_f64_f64(); try expect(s.a == 12); @@ -16431,7 +16345,6 @@ test "struct{u32,union{u32,struct{u32,u32}}}" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u32_union_u32_u32u32(); try expect(s.a == 1); @@ -16453,7 +16366,6 @@ test "struct i32 i32" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s: Struct_i32_i32 = .{ @@ -16487,7 +16399,6 @@ test "big struct" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = BigStruct{ .a = 1, @@ -16516,7 +16427,6 @@ test "big union" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const x = BigUnion{ .a = BigStruct{ @@ -16552,7 +16462,6 @@ test "medium struct of ints and floats" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = MedStructMixed{ .a = 1234, @@ -16633,7 +16542,6 @@ test "split struct of ints" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = SplitStructInt{ .a = 1234, @@ -16663,7 +16571,6 @@ test "split struct of ints and floats" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = SplitStructMixed{ .a = 1234, @@ -16690,7 +16597,6 @@ test "sret and byval together" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = BigStruct{ .a = 1, @@ -16805,7 +16711,6 @@ test "Struct with array as padding." { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 }); @@ -16833,7 +16738,6 @@ test "Float array like struct" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; c_float_array_struct(.{ .origin = .{ @@ -16869,7 +16773,6 @@ test "DC: Zig passes to C" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 })); } test "DC: Zig returns to C" { @@ -16877,7 +16780,6 @@ test "DC: Zig returns to C" { if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_assert_ret_DC()); } test "DC: C passes to Zig" { @@ -16886,7 +16788,6 @@ test "DC: C passes to Zig" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_send_DC()); } test "DC: C returns to Zig" { @@ -16894,7 +16795,6 @@ test "DC: C returns to Zig" { if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectEqual(DC{ .v1 = -0.25, .v2 = 15 }, c_ret_DC()); } @@ -16922,14 +16822,12 @@ test "CFF: Zig passes to C" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 })); } test "CFF: Zig returns to C" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_assert_ret_CFF()); } test "CFF: C passes to Zig" { @@ -16939,7 +16837,6 @@ test "CFF: C passes to Zig" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_send_CFF()); } @@ -16948,7 +16845,6 @@ test "CFF: C returns to Zig" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectEqual(CFF{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }, c_ret_CFF()); } pub extern fn c_assert_CFF(lv: CFF) c_int; @@ -16975,7 +16871,6 @@ test "PD: Zig passes to C" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 })); } @@ -16983,7 +16878,6 @@ test "PD: Zig returns to C" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_assert_ret_PD()); } test "PD: C passes to Zig" { @@ -16991,7 +16885,6 @@ test "PD: C passes to Zig" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; try expectOk(c_send_PD()); } @@ -16999,7 +16892,6 @@ test "PD: C returns to Zig" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectEqual(PD{ .v1 = null, .v2 = 0.5 }, c_ret_PD()); } pub extern fn c_assert_PD(lv: PD) c_int; @@ -17033,7 +16925,6 @@ extern fn c_modify_by_ref_param(ByRef) ByRef; test "C function modifies by ref param" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const res = c_modify_by_ref_param(.{ .val = 1, .arr = undefined }); try expect(res.val == 42); @@ -17058,7 +16949,6 @@ test "C function that takes byval struct called via function pointer" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; var fn_ptr = &c_func_ptr_byval; _ = &fn_ptr; @@ -17211,7 +17101,6 @@ test "Stdcall ABI structs" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const res = stdcall_coord2( @@ -17228,7 +17117,6 @@ test "Stdcall ABI big union" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const x = BigUnion{ .a = BigStruct{ @@ -17304,7 +17192,6 @@ test "byval tail callsite attribute" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; // Originally reported at https://github.com/ziglang/zig/issues/16290 // the bug was that the extern function had the byval attribute, but -- 2.54.0 From a242b0be888fbcffd4eaa2e3af9cb30bc3c71584 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 24 Jun 2026 19:25:35 -0400 Subject: [PATCH 08/22] compiler_rt: change float abi so it can become compatible with cbe --- lib/compiler/resinator/parse.zig | 2 +- lib/compiler_rt.zig | 292 ++- lib/compiler_rt/absv.zig | 3 +- lib/compiler_rt/absvdi2.zig | 5 +- lib/compiler_rt/absvsi2.zig | 2 +- lib/compiler_rt/absvti2.zig | 5 +- lib/compiler_rt/adddf3.zig | 19 - lib/compiler_rt/addf3.zig | 133 +- lib/compiler_rt/addf3_test.zig | 13 +- lib/compiler_rt/addhf3.zig | 11 - lib/compiler_rt/addsf3.zig | 19 - lib/compiler_rt/addtf3.zig | 22 - lib/compiler_rt/addvdi3.zig | 5 +- lib/compiler_rt/addvsi3.zig | 2 +- lib/compiler_rt/addxf3.zig | 11 - lib/compiler_rt/atomics.zig | 2 +- lib/compiler_rt/aulldiv.zig | 2 +- lib/compiler_rt/cmpdf2.zig | 67 - lib/compiler_rt/cmptf2.zig | 146 -- lib/compiler_rt/cmpxf2.zig | 49 - lib/compiler_rt/comparedf2_test.zig | 90 +- lib/compiler_rt/comparef.zig | 449 +++-- lib/compiler_rt/comparesf2_test.zig | 90 +- lib/compiler_rt/cos.zig | 114 +- lib/compiler_rt/count0bits.zig | 3 +- lib/compiler_rt/divc3.zig | 83 +- lib/compiler_rt/divc3_test.zig | 79 +- lib/compiler_rt/divdc3.zig | 13 - lib/compiler_rt/divdf3.zig | 8 +- lib/compiler_rt/divdf3_test.zig | 4 +- lib/compiler_rt/divhc3.zig | 14 - lib/compiler_rt/divhf3.zig | 11 - lib/compiler_rt/divmodei4.zig | 2 +- lib/compiler_rt/divsc3.zig | 13 - lib/compiler_rt/divsf3.zig | 17 +- lib/compiler_rt/divsf3_test.zig | 4 +- lib/compiler_rt/divtc3.zig | 16 - lib/compiler_rt/divtf3.zig | 11 +- lib/compiler_rt/divtf3_test.zig | 4 +- lib/compiler_rt/divxc3.zig | 13 - lib/compiler_rt/divxf3.zig | 5 +- lib/compiler_rt/divxf3_test.zig | 6 +- lib/compiler_rt/exp.zig | 194 +- lib/compiler_rt/exp2.zig | 153 +- lib/compiler_rt/exp_f128.zig | 4 +- lib/compiler_rt/extenddftf2.zig | 22 - lib/compiler_rt/extenddfxf2.zig | 11 - lib/compiler_rt/extendf.zig | 181 +- lib/compiler_rt/extendf_test.zig | 189 +- lib/compiler_rt/extendhfdf2.zig | 11 - lib/compiler_rt/extendhfsf2.zig | 24 - lib/compiler_rt/extendhftf2.zig | 11 - lib/compiler_rt/extendhfxf2.zig | 11 - lib/compiler_rt/extendsfdf2.zig | 19 - lib/compiler_rt/extendsftf2.zig | 22 - lib/compiler_rt/extendsfxf2.zig | 10 - lib/compiler_rt/extendxftf2.zig | 42 - lib/compiler_rt/fabs.zig | 33 +- lib/compiler_rt/fixdfdi.zig | 23 - lib/compiler_rt/fixdfei.zig | 14 - lib/compiler_rt/fixdfsi.zig | 19 - lib/compiler_rt/fixdfti.zig | 11 - lib/compiler_rt/fixhfei.zig | 14 - lib/compiler_rt/fixint_test.zig | 149 -- lib/compiler_rt/fixsfdi.zig | 23 - lib/compiler_rt/fixsfei.zig | 14 - lib/compiler_rt/fixsfsi.zig | 19 - lib/compiler_rt/fixsfti.zig | 12 - lib/compiler_rt/fixtfdi.zig | 22 - lib/compiler_rt/fixtfei.zig | 14 - lib/compiler_rt/fixtfsi.zig | 22 - lib/compiler_rt/fixtfti.zig | 13 - lib/compiler_rt/fixunsdfdi.zig | 23 - lib/compiler_rt/fixunsdfei.zig | 15 - lib/compiler_rt/fixunsdfsi.zig | 19 - lib/compiler_rt/fixunsdfti.zig | 11 - lib/compiler_rt/fixunshfdi.zig | 10 - lib/compiler_rt/fixunshfei.zig | 15 - lib/compiler_rt/fixunshfsi.zig | 11 - lib/compiler_rt/fixunshfti.zig | 11 - lib/compiler_rt/fixunssfdi.zig | 23 - lib/compiler_rt/fixunssfei.zig | 15 - lib/compiler_rt/fixunssfsi.zig | 19 - lib/compiler_rt/fixunssfti.zig | 12 - lib/compiler_rt/fixunstfdi.zig | 22 - lib/compiler_rt/fixunstfei.zig | 15 - lib/compiler_rt/fixunstfsi.zig | 22 - lib/compiler_rt/fixunstfti.zig | 14 - lib/compiler_rt/fixunsxfdi.zig | 10 - lib/compiler_rt/fixunsxfei.zig | 13 - lib/compiler_rt/fixunsxfsi.zig | 11 - lib/compiler_rt/fixunsxfti.zig | 12 - lib/compiler_rt/fixxfdi.zig | 10 - lib/compiler_rt/fixxfei.zig | 14 - lib/compiler_rt/fixxfsi.zig | 11 - lib/compiler_rt/float_from_int.zig | 476 ++++- lib/compiler_rt/float_from_int_test.zig | 1424 +++++++-------- lib/compiler_rt/floatdidf.zig | 23 - lib/compiler_rt/floatdihf.zig | 10 - lib/compiler_rt/floatdisf.zig | 22 - lib/compiler_rt/floatditf.zig | 22 - lib/compiler_rt/floatdixf.zig | 10 - lib/compiler_rt/floateidf.zig | 15 - lib/compiler_rt/floateihf.zig | 14 - lib/compiler_rt/floateisf.zig | 14 - lib/compiler_rt/floateitf.zig | 14 - lib/compiler_rt/floateixf.zig | 15 - lib/compiler_rt/floatsidf.zig | 19 - lib/compiler_rt/floatsihf.zig | 11 - lib/compiler_rt/floatsisf.zig | 19 - lib/compiler_rt/floatsitf.zig | 22 - lib/compiler_rt/floatsixf.zig | 11 - lib/compiler_rt/floattidf.zig | 11 - lib/compiler_rt/floattihf.zig | 12 - lib/compiler_rt/floattisf.zig | 11 - lib/compiler_rt/floattitf.zig | 13 - lib/compiler_rt/floattixf.zig | 12 - lib/compiler_rt/floatundidf.zig | 22 - lib/compiler_rt/floatundihf.zig | 11 - lib/compiler_rt/floatundisf.zig | 23 - lib/compiler_rt/floatunditf.zig | 22 - lib/compiler_rt/floatundixf.zig | 11 - lib/compiler_rt/floatuneidf.zig | 14 - lib/compiler_rt/floatuneihf.zig | 14 - lib/compiler_rt/floatuneisf.zig | 14 - lib/compiler_rt/floatuneitf.zig | 15 - lib/compiler_rt/floatuneixf.zig | 14 - lib/compiler_rt/floatunsidf.zig | 19 - lib/compiler_rt/floatunsihf.zig | 10 - lib/compiler_rt/floatunsisf.zig | 19 - lib/compiler_rt/floatunsitf.zig | 22 - lib/compiler_rt/floatunsixf.zig | 11 - lib/compiler_rt/floatuntidf.zig | 11 - lib/compiler_rt/floatuntihf.zig | 11 - lib/compiler_rt/floatuntisf.zig | 12 - lib/compiler_rt/floatuntitf.zig | 13 - lib/compiler_rt/floatuntixf.zig | 12 - lib/compiler_rt/floor_ceil.zig | 322 ++-- lib/compiler_rt/fma.zig | 79 +- lib/compiler_rt/fmax.zig | 33 +- lib/compiler_rt/fmin.zig | 33 +- lib/compiler_rt/fmod.zig | 83 +- lib/compiler_rt/fmodq_test.zig | 64 +- lib/compiler_rt/fmodx_test.zig | 62 +- lib/compiler_rt/gedf2.zig | 35 - lib/compiler_rt/gehf2.zig | 21 - lib/compiler_rt/gesf2.zig | 35 - lib/compiler_rt/getf2.zig | 26 - lib/compiler_rt/gexf2.zig | 15 - lib/compiler_rt/int.zig | 79 +- lib/compiler_rt/int_from_float.zig | 522 +++++- lib/compiler_rt/int_from_float_test.zig | 1878 ++++++++++---------- lib/compiler_rt/limb64.zig | 2 +- lib/compiler_rt/log.zig | 209 ++- lib/compiler_rt/log10.zig | 211 ++- lib/compiler_rt/log2.zig | 195 +- lib/compiler_rt/mulc3.zig | 85 +- lib/compiler_rt/mulc3_test.zig | 65 +- lib/compiler_rt/muldc3.zig | 12 - lib/compiler_rt/muldf3.zig | 19 - lib/compiler_rt/mulf3.zig | 68 +- lib/compiler_rt/mulf3_test.zig | 90 +- lib/compiler_rt/mulhc3.zig | 13 - lib/compiler_rt/mulhf3.zig | 11 - lib/compiler_rt/mulsc3.zig | 12 - lib/compiler_rt/mulsf3.zig | 19 - lib/compiler_rt/multc3.zig | 15 - lib/compiler_rt/multf3.zig | 22 - lib/compiler_rt/mulvsi3.zig | 5 +- lib/compiler_rt/mulxc3.zig | 13 - lib/compiler_rt/mulxf3.zig | 11 - lib/compiler_rt/negv.zig | 3 +- lib/compiler_rt/os_version_check.zig | 1 - lib/compiler_rt/parity.zig | 3 +- lib/compiler_rt/popcount.zig | 3 +- lib/compiler_rt/powiXf2.zig | 39 +- lib/compiler_rt/powiXf2_test.zig | 1008 +++++------ lib/compiler_rt/round.zig | 136 +- lib/compiler_rt/sin.zig | 114 +- lib/compiler_rt/sincos.zig | 301 ++-- lib/compiler_rt/sqrt.zig | 281 +-- lib/compiler_rt/subdf3.zig | 24 - lib/compiler_rt/subhf3.zig | 12 - lib/compiler_rt/subsf3.zig | 24 - lib/compiler_rt/subtf3.zig | 27 - lib/compiler_rt/subvdi3.zig | 5 +- lib/compiler_rt/subvsi3.zig | 2 +- lib/compiler_rt/subxf3.zig | 13 - lib/compiler_rt/tan.zig | 85 +- lib/compiler_rt/trunc.zig | 119 +- lib/compiler_rt/truncdfhf2.zig | 18 - lib/compiler_rt/truncdfsf2.zig | 19 - lib/compiler_rt/truncf.zig | 202 ++- lib/compiler_rt/truncf_test.zig | 334 ++-- lib/compiler_rt/truncsfhf2.zig | 24 - lib/compiler_rt/trunctfdf2.zig | 22 - lib/compiler_rt/trunctfhf2.zig | 14 - lib/compiler_rt/trunctfsf2.zig | 22 - lib/compiler_rt/trunctfxf2.zig | 67 - lib/compiler_rt/truncxfdf2.zig | 10 - lib/compiler_rt/truncxfhf2.zig | 11 - lib/compiler_rt/truncxfsf2.zig | 10 - lib/compiler_rt/udivmodei4.zig | 2 +- lib/compiler_rt/unorddf2.zig | 19 - lib/std/crypto/Certificate.zig | 2 +- lib/std/math.zig | 4 +- lib/std/math/atan2.zig | 8 +- lib/std/zig/target.zig | 14 + src/link.zig | 2 +- test/behavior/cast.zig | 2 +- test/behavior/floatop.zig | 8 +- test/behavior/switch.zig | 2 +- test/behavior/switch_on_captured_error.zig | 6 +- 213 files changed, 6385 insertions(+), 7004 deletions(-) delete mode 100644 lib/compiler_rt/adddf3.zig delete mode 100644 lib/compiler_rt/addhf3.zig delete mode 100644 lib/compiler_rt/addsf3.zig delete mode 100644 lib/compiler_rt/addtf3.zig delete mode 100644 lib/compiler_rt/addxf3.zig delete mode 100644 lib/compiler_rt/cmpdf2.zig delete mode 100644 lib/compiler_rt/cmptf2.zig delete mode 100644 lib/compiler_rt/cmpxf2.zig delete mode 100644 lib/compiler_rt/divdc3.zig delete mode 100644 lib/compiler_rt/divhc3.zig delete mode 100644 lib/compiler_rt/divhf3.zig delete mode 100644 lib/compiler_rt/divsc3.zig delete mode 100644 lib/compiler_rt/divtc3.zig delete mode 100644 lib/compiler_rt/divxc3.zig delete mode 100644 lib/compiler_rt/extenddftf2.zig delete mode 100644 lib/compiler_rt/extenddfxf2.zig delete mode 100644 lib/compiler_rt/extendhfdf2.zig delete mode 100644 lib/compiler_rt/extendhfsf2.zig delete mode 100644 lib/compiler_rt/extendhftf2.zig delete mode 100644 lib/compiler_rt/extendhfxf2.zig delete mode 100644 lib/compiler_rt/extendsfdf2.zig delete mode 100644 lib/compiler_rt/extendsftf2.zig delete mode 100644 lib/compiler_rt/extendsfxf2.zig delete mode 100644 lib/compiler_rt/extendxftf2.zig delete mode 100644 lib/compiler_rt/fixdfdi.zig delete mode 100644 lib/compiler_rt/fixdfei.zig delete mode 100644 lib/compiler_rt/fixdfsi.zig delete mode 100644 lib/compiler_rt/fixdfti.zig delete mode 100644 lib/compiler_rt/fixhfei.zig delete mode 100644 lib/compiler_rt/fixint_test.zig delete mode 100644 lib/compiler_rt/fixsfdi.zig delete mode 100644 lib/compiler_rt/fixsfei.zig delete mode 100644 lib/compiler_rt/fixsfsi.zig delete mode 100644 lib/compiler_rt/fixsfti.zig delete mode 100644 lib/compiler_rt/fixtfdi.zig delete mode 100644 lib/compiler_rt/fixtfei.zig delete mode 100644 lib/compiler_rt/fixtfsi.zig delete mode 100644 lib/compiler_rt/fixtfti.zig delete mode 100644 lib/compiler_rt/fixunsdfdi.zig delete mode 100644 lib/compiler_rt/fixunsdfei.zig delete mode 100644 lib/compiler_rt/fixunsdfsi.zig delete mode 100644 lib/compiler_rt/fixunsdfti.zig delete mode 100644 lib/compiler_rt/fixunshfdi.zig delete mode 100644 lib/compiler_rt/fixunshfei.zig delete mode 100644 lib/compiler_rt/fixunshfsi.zig delete mode 100644 lib/compiler_rt/fixunshfti.zig delete mode 100644 lib/compiler_rt/fixunssfdi.zig delete mode 100644 lib/compiler_rt/fixunssfei.zig delete mode 100644 lib/compiler_rt/fixunssfsi.zig delete mode 100644 lib/compiler_rt/fixunssfti.zig delete mode 100644 lib/compiler_rt/fixunstfdi.zig delete mode 100644 lib/compiler_rt/fixunstfei.zig delete mode 100644 lib/compiler_rt/fixunstfsi.zig delete mode 100644 lib/compiler_rt/fixunstfti.zig delete mode 100644 lib/compiler_rt/fixunsxfdi.zig delete mode 100644 lib/compiler_rt/fixunsxfei.zig delete mode 100644 lib/compiler_rt/fixunsxfsi.zig delete mode 100644 lib/compiler_rt/fixunsxfti.zig delete mode 100644 lib/compiler_rt/fixxfdi.zig delete mode 100644 lib/compiler_rt/fixxfei.zig delete mode 100644 lib/compiler_rt/fixxfsi.zig delete mode 100644 lib/compiler_rt/floatdidf.zig delete mode 100644 lib/compiler_rt/floatdihf.zig delete mode 100644 lib/compiler_rt/floatdisf.zig delete mode 100644 lib/compiler_rt/floatditf.zig delete mode 100644 lib/compiler_rt/floatdixf.zig delete mode 100644 lib/compiler_rt/floateidf.zig delete mode 100644 lib/compiler_rt/floateihf.zig delete mode 100644 lib/compiler_rt/floateisf.zig delete mode 100644 lib/compiler_rt/floateitf.zig delete mode 100644 lib/compiler_rt/floateixf.zig delete mode 100644 lib/compiler_rt/floatsidf.zig delete mode 100644 lib/compiler_rt/floatsihf.zig delete mode 100644 lib/compiler_rt/floatsisf.zig delete mode 100644 lib/compiler_rt/floatsitf.zig delete mode 100644 lib/compiler_rt/floatsixf.zig delete mode 100644 lib/compiler_rt/floattidf.zig delete mode 100644 lib/compiler_rt/floattihf.zig delete mode 100644 lib/compiler_rt/floattisf.zig delete mode 100644 lib/compiler_rt/floattitf.zig delete mode 100644 lib/compiler_rt/floattixf.zig delete mode 100644 lib/compiler_rt/floatundidf.zig delete mode 100644 lib/compiler_rt/floatundihf.zig delete mode 100644 lib/compiler_rt/floatundisf.zig delete mode 100644 lib/compiler_rt/floatunditf.zig delete mode 100644 lib/compiler_rt/floatundixf.zig delete mode 100644 lib/compiler_rt/floatuneidf.zig delete mode 100644 lib/compiler_rt/floatuneihf.zig delete mode 100644 lib/compiler_rt/floatuneisf.zig delete mode 100644 lib/compiler_rt/floatuneitf.zig delete mode 100644 lib/compiler_rt/floatuneixf.zig delete mode 100644 lib/compiler_rt/floatunsidf.zig delete mode 100644 lib/compiler_rt/floatunsihf.zig delete mode 100644 lib/compiler_rt/floatunsisf.zig delete mode 100644 lib/compiler_rt/floatunsitf.zig delete mode 100644 lib/compiler_rt/floatunsixf.zig delete mode 100644 lib/compiler_rt/floatuntidf.zig delete mode 100644 lib/compiler_rt/floatuntihf.zig delete mode 100644 lib/compiler_rt/floatuntisf.zig delete mode 100644 lib/compiler_rt/floatuntitf.zig delete mode 100644 lib/compiler_rt/floatuntixf.zig delete mode 100644 lib/compiler_rt/gedf2.zig delete mode 100644 lib/compiler_rt/gehf2.zig delete mode 100644 lib/compiler_rt/gesf2.zig delete mode 100644 lib/compiler_rt/getf2.zig delete mode 100644 lib/compiler_rt/gexf2.zig delete mode 100644 lib/compiler_rt/muldc3.zig delete mode 100644 lib/compiler_rt/muldf3.zig delete mode 100644 lib/compiler_rt/mulhc3.zig delete mode 100644 lib/compiler_rt/mulhf3.zig delete mode 100644 lib/compiler_rt/mulsc3.zig delete mode 100644 lib/compiler_rt/mulsf3.zig delete mode 100644 lib/compiler_rt/multc3.zig delete mode 100644 lib/compiler_rt/multf3.zig delete mode 100644 lib/compiler_rt/mulxc3.zig delete mode 100644 lib/compiler_rt/mulxf3.zig delete mode 100644 lib/compiler_rt/subdf3.zig delete mode 100644 lib/compiler_rt/subhf3.zig delete mode 100644 lib/compiler_rt/subsf3.zig delete mode 100644 lib/compiler_rt/subtf3.zig delete mode 100644 lib/compiler_rt/subxf3.zig delete mode 100644 lib/compiler_rt/truncdfhf2.zig delete mode 100644 lib/compiler_rt/truncdfsf2.zig delete mode 100644 lib/compiler_rt/truncsfhf2.zig delete mode 100644 lib/compiler_rt/trunctfdf2.zig delete mode 100644 lib/compiler_rt/trunctfhf2.zig delete mode 100644 lib/compiler_rt/trunctfsf2.zig delete mode 100644 lib/compiler_rt/trunctfxf2.zig delete mode 100644 lib/compiler_rt/truncxfdf2.zig delete mode 100644 lib/compiler_rt/truncxfhf2.zig delete mode 100644 lib/compiler_rt/truncxfsf2.zig delete mode 100644 lib/compiler_rt/unorddf2.zig diff --git a/lib/compiler/resinator/parse.zig b/lib/compiler/resinator/parse.zig index 445424429ea2249991661e99840331e2b936bd96..1f3b2f156ae15fb7fb548ffe37bce6f036079e19 100644 --- a/lib/compiler/resinator/parse.zig +++ b/lib/compiler/resinator/parse.zig @@ -1277,7 +1277,7 @@ pub const Parser = struct { }, else => unreachable, } - @compileError("unreachable"); + comptime unreachable; } pub const OptionalParamParser = struct { diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index f042d0076e62740c50d61b4e28b8b3ddb07012f3..5ff6e659d56f0797225b7661aa076cb41f715a42 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -1,4 +1,5 @@ const builtin = @import("builtin"); +const compiler_rt = @This(); const ofmt_c = builtin.object_format == .c; const native_endian = builtin.cpu.arch.endian(); @@ -84,144 +85,17 @@ comptime { // Float routines // conversion _ = @import("compiler_rt/extendf.zig"); - _ = @import("compiler_rt/extendhfsf2.zig"); - _ = @import("compiler_rt/extendhfdf2.zig"); - _ = @import("compiler_rt/extendhftf2.zig"); - _ = @import("compiler_rt/extendhfxf2.zig"); - _ = @import("compiler_rt/extendsfdf2.zig"); - _ = @import("compiler_rt/extendsftf2.zig"); - _ = @import("compiler_rt/extendsfxf2.zig"); - _ = @import("compiler_rt/extenddftf2.zig"); - _ = @import("compiler_rt/extenddfxf2.zig"); - _ = @import("compiler_rt/extendxftf2.zig"); - _ = @import("compiler_rt/truncf.zig"); - _ = @import("compiler_rt/truncsfhf2.zig"); - _ = @import("compiler_rt/truncdfhf2.zig"); - _ = @import("compiler_rt/truncdfsf2.zig"); - _ = @import("compiler_rt/truncxfhf2.zig"); - _ = @import("compiler_rt/truncxfsf2.zig"); - _ = @import("compiler_rt/truncxfdf2.zig"); - _ = @import("compiler_rt/trunctfhf2.zig"); - _ = @import("compiler_rt/trunctfsf2.zig"); - _ = @import("compiler_rt/trunctfdf2.zig"); - _ = @import("compiler_rt/trunctfxf2.zig"); - _ = @import("compiler_rt/int_from_float.zig"); - _ = @import("compiler_rt/fixhfei.zig"); - _ = @import("compiler_rt/fixsfsi.zig"); - _ = @import("compiler_rt/fixsfdi.zig"); - _ = @import("compiler_rt/fixsfti.zig"); - _ = @import("compiler_rt/fixsfei.zig"); - _ = @import("compiler_rt/fixdfsi.zig"); - _ = @import("compiler_rt/fixdfdi.zig"); - _ = @import("compiler_rt/fixdfti.zig"); - _ = @import("compiler_rt/fixdfei.zig"); - _ = @import("compiler_rt/fixtfsi.zig"); - _ = @import("compiler_rt/fixtfdi.zig"); - _ = @import("compiler_rt/fixtfti.zig"); - _ = @import("compiler_rt/fixtfei.zig"); - _ = @import("compiler_rt/fixxfsi.zig"); - _ = @import("compiler_rt/fixxfdi.zig"); - _ = @import("compiler_rt/fixxfei.zig"); - - _ = @import("compiler_rt/fixunshfsi.zig"); - _ = @import("compiler_rt/fixunshfdi.zig"); - _ = @import("compiler_rt/fixunshfti.zig"); - _ = @import("compiler_rt/fixunshfei.zig"); - _ = @import("compiler_rt/fixunssfsi.zig"); - _ = @import("compiler_rt/fixunssfdi.zig"); - _ = @import("compiler_rt/fixunssfti.zig"); - _ = @import("compiler_rt/fixunssfei.zig"); - _ = @import("compiler_rt/fixunsdfsi.zig"); - _ = @import("compiler_rt/fixunsdfdi.zig"); - _ = @import("compiler_rt/fixunsdfti.zig"); - _ = @import("compiler_rt/fixunsdfei.zig"); - _ = @import("compiler_rt/fixunstfsi.zig"); - _ = @import("compiler_rt/fixunstfdi.zig"); - _ = @import("compiler_rt/fixunstfti.zig"); - _ = @import("compiler_rt/fixunstfei.zig"); - _ = @import("compiler_rt/fixunsxfsi.zig"); - _ = @import("compiler_rt/fixunsxfdi.zig"); - _ = @import("compiler_rt/fixunsxfti.zig"); - _ = @import("compiler_rt/fixunsxfei.zig"); - _ = @import("compiler_rt/float_from_int.zig"); - _ = @import("compiler_rt/floatsihf.zig"); - _ = @import("compiler_rt/floatsisf.zig"); - _ = @import("compiler_rt/floatsidf.zig"); - _ = @import("compiler_rt/floatsitf.zig"); - _ = @import("compiler_rt/floatsixf.zig"); - _ = @import("compiler_rt/floatdihf.zig"); - _ = @import("compiler_rt/floatdisf.zig"); - _ = @import("compiler_rt/floatdidf.zig"); - _ = @import("compiler_rt/floatditf.zig"); - _ = @import("compiler_rt/floatdixf.zig"); - _ = @import("compiler_rt/floattihf.zig"); - _ = @import("compiler_rt/floattisf.zig"); - _ = @import("compiler_rt/floattidf.zig"); - _ = @import("compiler_rt/floattitf.zig"); - _ = @import("compiler_rt/floattixf.zig"); - _ = @import("compiler_rt/floateihf.zig"); - _ = @import("compiler_rt/floateisf.zig"); - _ = @import("compiler_rt/floateidf.zig"); - _ = @import("compiler_rt/floateitf.zig"); - _ = @import("compiler_rt/floateixf.zig"); - _ = @import("compiler_rt/floatunsihf.zig"); - _ = @import("compiler_rt/floatunsisf.zig"); - _ = @import("compiler_rt/floatunsidf.zig"); - _ = @import("compiler_rt/floatunsitf.zig"); - _ = @import("compiler_rt/floatunsixf.zig"); - _ = @import("compiler_rt/floatundihf.zig"); - _ = @import("compiler_rt/floatundisf.zig"); - _ = @import("compiler_rt/floatundidf.zig"); - _ = @import("compiler_rt/floatunditf.zig"); - _ = @import("compiler_rt/floatundixf.zig"); - _ = @import("compiler_rt/floatuntihf.zig"); - _ = @import("compiler_rt/floatuntisf.zig"); - _ = @import("compiler_rt/floatuntidf.zig"); - _ = @import("compiler_rt/floatuntitf.zig"); - _ = @import("compiler_rt/floatuntixf.zig"); - _ = @import("compiler_rt/floatuneihf.zig"); - _ = @import("compiler_rt/floatuneisf.zig"); - _ = @import("compiler_rt/floatuneidf.zig"); - _ = @import("compiler_rt/floatuneitf.zig"); - _ = @import("compiler_rt/floatuneixf.zig"); // comparison _ = @import("compiler_rt/comparef.zig"); - _ = @import("compiler_rt/cmpdf2.zig"); - _ = @import("compiler_rt/cmptf2.zig"); - _ = @import("compiler_rt/cmpxf2.zig"); - _ = @import("compiler_rt/unorddf2.zig"); - _ = @import("compiler_rt/gehf2.zig"); - _ = @import("compiler_rt/gesf2.zig"); - _ = @import("compiler_rt/gedf2.zig"); - _ = @import("compiler_rt/gexf2.zig"); - _ = @import("compiler_rt/getf2.zig"); // arithmetic _ = @import("compiler_rt/addf3.zig"); - _ = @import("compiler_rt/addhf3.zig"); - _ = @import("compiler_rt/addsf3.zig"); - _ = @import("compiler_rt/adddf3.zig"); - _ = @import("compiler_rt/addtf3.zig"); - _ = @import("compiler_rt/addxf3.zig"); - - _ = @import("compiler_rt/subhf3.zig"); - _ = @import("compiler_rt/subsf3.zig"); - _ = @import("compiler_rt/subdf3.zig"); - _ = @import("compiler_rt/subtf3.zig"); - _ = @import("compiler_rt/subxf3.zig"); - _ = @import("compiler_rt/mulf3.zig"); - _ = @import("compiler_rt/mulhf3.zig"); - _ = @import("compiler_rt/mulsf3.zig"); - _ = @import("compiler_rt/muldf3.zig"); - _ = @import("compiler_rt/multf3.zig"); - _ = @import("compiler_rt/mulxf3.zig"); - _ = @import("compiler_rt/divhf3.zig"); _ = @import("compiler_rt/divsf3.zig"); _ = @import("compiler_rt/divdf3.zig"); _ = @import("compiler_rt/divxf3.zig"); @@ -235,25 +109,17 @@ comptime { symbol(&__negsf2, "__negsf2"); symbol(&__negdf2, "__negdf2"); } - if (want_ppc_abi) symbol(&__negtf2, "__negkf2"); - symbol(&__negtf2, "__negtf2"); + if (want_ppc_abi) { + symbol(&__negtf2, "__negkf2"); + } else { + symbol(&__negtf2, "__negtf2"); + } symbol(&__negxf2, "__negxf2"); // other _ = @import("compiler_rt/powiXf2.zig"); _ = @import("compiler_rt/mulc3.zig"); - _ = @import("compiler_rt/mulhc3.zig"); - _ = @import("compiler_rt/mulsc3.zig"); - _ = @import("compiler_rt/muldc3.zig"); - _ = @import("compiler_rt/mulxc3.zig"); - _ = @import("compiler_rt/multc3.zig"); - _ = @import("compiler_rt/divc3.zig"); - _ = @import("compiler_rt/divhc3.zig"); - _ = @import("compiler_rt/divsc3.zig"); - _ = @import("compiler_rt/divdc3.zig"); - _ = @import("compiler_rt/divxc3.zig"); - _ = @import("compiler_rt/divtc3.zig"); // Math routines. Alphabetically sorted. _ = @import("compiler_rt/cos.zig"); @@ -279,7 +145,7 @@ comptime { _ = @import("compiler_rt/divmodei4.zig"); _ = @import("compiler_rt/udivmodei4.zig"); - _ = @import("compiler_rt/limb64.zig"); + if (builtin.cpu.arch.isWasm()) _ = @import("compiler_rt/limb64.zig"); // extra _ = @import("compiler_rt/os_version_check.zig"); @@ -290,7 +156,7 @@ comptime { _ = @import("compiler_rt/clear_cache.zig"); _ = @import("compiler_rt/hexagon.zig"); - if (@import("builtin").object_format != .c) { + if (builtin.object_format != .c) { if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/atomics.zig"); _ = @import("compiler_rt/stack_probe.zig"); @@ -366,10 +232,7 @@ pub const want_aeabi = switch (builtin.abi) { .gnueabihf, .android, .androideabi, - => switch (builtin.cpu.arch) { - .arm, .armeb, .thumb, .thumbeb => true, - else => false, - }, + => builtin.cpu.arch.isArm(), else => false, }; @@ -443,17 +306,106 @@ pub const gnu_f16_abi = switch (builtin.cpu.arch) { pub const want_sparc64_abi = builtin.cpu.arch == .sparc64; pub const want_sparc32_abi = builtin.cpu.arch == .sparc; -pub fn F16T(comptime OtherType: type) type { - return switch (builtin.cpu.arch) { - .x86, .x86_64 => if (builtin.target.os.tag.isDarwin()) switch (OtherType) { - // Starting with LLVM 16, Darwin uses different abi for f16 - // depending on the type of the other return/argument..??? - f32, f64 => u16, - f80, f128 => f16, - else => unreachable, - } else f16, - else => f16, +/// For operations converting between `f16` and another floating point type. +pub fn f16Conv(comptime OtherType: type) type { + switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) { + .hard => {}, + .soft => return softFloatAbi(f16), + } + if (builtin.cpu.arch.isX86() and builtin.os.tag.isDarwin()) switch (OtherType) { + else => unreachable, + // Starting with LLVM 16, Darwin uses different abi for f16 + // depending on the type of the other return/argument..??? + f32, f64 => return softFloatAbi(f16), + f80, f128 => {}, }; + return hardFloatAbi(f16); +} +pub const @"f16" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) { + .hard => hardFloatAbi(f16), + .soft => softFloatAbi(f16), +}; +pub const @"f32" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 32)) { + .hard => hardFloatAbi(f32), + .soft => softFloatAbi(f32), +}; +pub const @"f64" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 64)) { + .hard => hardFloatAbi(f64), + .soft => softFloatAbi(f64), +}; +pub const @"f80" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 80)) { + .hard => hardFloatAbi(f80), + .soft => struct { + pub const Abi = extern struct { mantissa: u64, exponent: u16 }; + const Repr = packed struct { mantissa: u64, exponent: u16 }; + pub inline fn toAbi(raw: f80) Abi { + const repr: Repr = @bitCast(raw); + return .{ .mantissa = repr.mantissa, .exponent = repr.exponent }; + } + pub inline fn fromAbi(abi: Abi) f80 { + const repr: Repr = .{ .mantissa = abi.mantissa, .exponent = abi.exponent }; + return @bitCast(repr); + } + pub const complex = complexAbi(f80, @This()); + }, +}; +pub const @"f128" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 128)) { + .hard => hardFloatAbi(f128), + .soft => struct { + pub const Abi = switch (builtin.cpu.arch.endian()) { + .big => extern struct { hi: u64, lo: u64 }, + .little => extern struct { lo: u64, hi: u64 }, + }; + const Repr = packed struct { lo: u64, hi: u64 }; + pub inline fn toAbi(raw: f128) Abi { + const repr: Repr = @bitCast(raw); + return .{ .lo = repr.lo, .hi = repr.hi }; + } + pub inline fn fromAbi(abi: Abi) f128 { + const repr: Repr = .{ .lo = abi.lo, .hi = abi.hi }; + return @bitCast(repr); + } + pub const complex = complexAbi(f128, @This()); + }, +}; +fn hardFloatAbi(comptime Float: type) type { + return struct { + pub const Abi = Float; + pub inline fn toAbi(raw: Float) Abi { + return raw; + } + pub inline fn fromAbi(abi: Abi) Float { + return abi; + } + pub const complex = complexAbi(Float, @This()); + }; +} +fn softFloatAbi(comptime Float: type) type { + return struct { + pub const Abi = @Int(.unsigned, @bitSizeOf(Float)); + pub inline fn toAbi(raw: Float) Abi { + return @bitCast(raw); + } + pub inline fn fromAbi(abi: Abi) Float { + return @bitCast(abi); + } + pub const complex = complexAbi(Float, @This()); + }; +} +fn complexAbi(comptime Float: type, comptime float: type) type { + return struct { + pub const Abi = extern struct { real: float.Abi, imag: float.Abi }; + pub inline fn toAbi(raw: Complex(Float)) Abi { + return .{ .real = float.toAbi(raw.real), .imag = float.toAbi(raw.imag) }; + } + pub inline fn fromAbi(abi: Abi) Complex(Float) { + return .{ .real = float.fromAbi(abi.real), .imag = float.fromAbi(abi.imag) }; + } + }; +} + +pub fn Complex(comptime Float: type) type { + return struct { real: Float, imag: Float }; } pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { @@ -588,34 +540,34 @@ pub inline fn fneg(a: anytype) @TypeOf(a) { return @bitCast(negated); } -fn __negxf2(a: f80) callconv(.c) f80 { - return fneg(a); +fn __neghf2(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fneg(compiler_rt.f16.fromAbi(a))); } -fn __neghf2(a: f16) callconv(.c) f16 { - return fneg(a); +fn __negsf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fneg(compiler_rt.f32.fromAbi(a))); } -fn __negdf2(a: f64) callconv(.c) f64 { - return fneg(a); +fn __negdf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fneg(compiler_rt.f64.fromAbi(a))); } -fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 { - return fneg(a); +fn __negxf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fneg(compiler_rt.f80.fromAbi(a))); } -fn __negtf2(a: f128) callconv(.c) f128 { - return fneg(a); -} - -fn __negsf2(a: f32) callconv(.c) f32 { - return fneg(a); +fn __negtf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fneg(compiler_rt.f128.fromAbi(a))); } fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 { return fneg(a); } +fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 { + return fneg(a); +} + /// Allows to access underlying bits as two equally sized lower and higher /// signed or unsigned integers. pub fn HalveInt(comptime T: type, comptime signed_half: bool) type { diff --git a/lib/compiler_rt/absv.zig b/lib/compiler_rt/absv.zig index 8910a4a6b9417bd099065db02f1535ace9968ee0..4621835dd6f6abd9cdb37a53231e88139556eb9a 100644 --- a/lib/compiler_rt/absv.zig +++ b/lib/compiler_rt/absv.zig @@ -14,8 +14,7 @@ pub inline fn absv(comptime ST: type, a: ST) ST { const sign: ST = a >> N - 1; x +%= sign; x ^= sign; - if (x < 0) - @panic("compiler_rt absv: overflow"); + if (x < 0) @panic("integer overflow"); return x; } diff --git a/lib/compiler_rt/absvdi2.zig b/lib/compiler_rt/absvdi2.zig index 408d70ad167d29c7895e6145e7635da95ec62a82..598629ebfc689258a055110aa976cf0d3b56226a 100644 --- a/lib/compiler_rt/absvdi2.zig +++ b/lib/compiler_rt/absvdi2.zig @@ -1,5 +1,6 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const absv = @import("./absv.zig").absv; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; +const absv = @import("absv.zig").absv; comptime { symbol(&__absvdi2, "__absvdi2"); diff --git a/lib/compiler_rt/absvsi2.zig b/lib/compiler_rt/absvsi2.zig index 538d7f7f0155f98cf997b711514145ae77da5c2a..e01627090082800cd53ee4b614f3a68d9480c214 100644 --- a/lib/compiler_rt/absvsi2.zig +++ b/lib/compiler_rt/absvsi2.zig @@ -1,6 +1,6 @@ const compiler_rt = @import("../compiler_rt.zig"); const symbol = compiler_rt.symbol; -const absv = @import("./absv.zig").absv; +const absv = @import("absv.zig").absv; comptime { symbol(&__absvsi2, "__absvsi2"); diff --git a/lib/compiler_rt/absvti2.zig b/lib/compiler_rt/absvti2.zig index ab367d2b78ae2f0a813d011ec74dc532d103303f..008060504e318f7d9979a43d4d53ac34a8d38c76 100644 --- a/lib/compiler_rt/absvti2.zig +++ b/lib/compiler_rt/absvti2.zig @@ -1,5 +1,6 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const absv = @import("./absv.zig").absv; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; +const absv = @import("absv.zig").absv; comptime { symbol(&__absvti2, "__absvti2"); diff --git a/lib/compiler_rt/adddf3.zig b/lib/compiler_rt/adddf3.zig deleted file mode 100644 index 7b6f252da2c7f697b23b8e9e9fd13d34cc99bc80..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/adddf3.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const addf3 = @import("./addf3.zig").addf3; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dadd, "__aeabi_dadd"); - } else { - symbol(&__adddf3, "__adddf3"); - } -} - -fn __adddf3(a: f64, b: f64) callconv(.c) f64 { - return addf3(f64, a, b); -} - -fn __aeabi_dadd(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { - return addf3(f64, a, b); -} diff --git a/lib/compiler_rt/addf3.zig b/lib/compiler_rt/addf3.zig index 1e68c82f0fbcf3a4a28d4d9c0d877b997496d7a2..189f7afd6d02c78bdb63de8e38ca7731c96684d4 100644 --- a/lib/compiler_rt/addf3.zig +++ b/lib/compiler_rt/addf3.zig @@ -1,12 +1,143 @@ const std = @import("std"); const math = std.math; const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; const normalize = compiler_rt.normalize; +comptime { + symbol(&__addhf3, "__addhf3"); + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_fadd, "__aeabi_fadd"); + symbol(&__aeabi_dadd, "__aeabi_dadd"); + } else { + symbol(&__addsf3, "__addsf3"); + symbol(&__adddf3, "__adddf3"); + } + symbol(&__addxf3, "__addxf3"); + if (compiler_rt.want_ppc_abi) { + symbol(&__addtf3, "__addkf3"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_add, "_Qp_add"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__addtf3, "_Q_add"); + } else { + symbol(&__addtf3, "__addtf3"); + } +} + +fn __addhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(add_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); +} +pub fn add_f16(a: f16, b: f16) f16 { + return addf3(f16, a, b); +} + +fn __addsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(add_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); +} +fn __aeabi_fadd(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { + return add_f32(a, b); +} +pub fn add_f32(a: f32, b: f32) f32 { + return addf3(f32, a, b); +} + +fn __adddf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(add_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); +} +fn __aeabi_dadd(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { + return add_f64(a, b); +} +pub fn add_f64(a: f64, b: f64) f64 { + return addf3(f64, a, b); +} + +fn __addxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(add_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} +pub fn add_f80(a: f80, b: f80) f80 { + return addf3(f80, a, b); +} + +fn __addtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(add_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); +} +fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.c) void { + c.* = add_f128(a.*, b.*); +} +pub fn add_f128(a: f128, b: f128) f128 { + return addf3(f128, a, b); +} + +comptime { + symbol(&__subhf3, "__subhf3"); + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_fsub, "__aeabi_fsub"); + symbol(&__aeabi_dsub, "__aeabi_dsub"); + } else { + symbol(&__subsf3, "__subsf3"); + symbol(&__subdf3, "__subdf3"); + } + symbol(&__subxf3, "__subxf3"); + if (compiler_rt.want_ppc_abi) { + symbol(&__subtf3, "__subkf3"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_sub, "_Qp_sub"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__subtf3, "_Q_sub"); + } else { + symbol(&__subtf3, "__subtf3"); + } +} + +fn __subhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(sub_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); +} +pub fn sub_f16(a: f16, b: f16) f16 { + return add_f16(a, compiler_rt.fneg(b)); +} + +fn __subsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(sub_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); +} +fn __aeabi_fsub(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { + return sub_f32(a, b); +} +pub fn sub_f32(a: f32, b: f32) f32 { + return add_f32(a, compiler_rt.fneg(b)); +} + +fn __subdf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(sub_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); +} +fn __aeabi_dsub(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { + return sub_f64(a, b); +} +pub fn sub_f64(a: f64, b: f64) f64 { + return add_f64(a, compiler_rt.fneg(b)); +} + +fn __subxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(sub_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} +pub fn sub_f80(a: f80, b: f80) f80 { + return add_f80(a, compiler_rt.fneg(b)); +} + +fn __subtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(sub_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); +} +fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { + c.* = sub_f128(a.*, b.*); +} +pub fn sub_f128(a: f128, b: f128) f128 { + return add_f128(a, compiler_rt.fneg(b)); +} + /// Ported from: /// /// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc -pub inline fn addf3(comptime T: type, a: T, b: T) T { +inline fn addf3(comptime T: type, a: T, b: T) T { const bits = @typeInfo(T).float.bits; const Z = @Int(.unsigned, bits); diff --git a/lib/compiler_rt/addf3_test.zig b/lib/compiler_rt/addf3_test.zig index 1e9bfa1bbf5403cee4cb6fc839478782714eca5b..ffa3a48086a47e9617145c0d33e049b221303ec5 100644 --- a/lib/compiler_rt/addf3_test.zig +++ b/lib/compiler_rt/addf3_test.zig @@ -8,12 +8,13 @@ const builtin = @import("builtin"); const math = std.math; const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64); -const __addtf3 = @import("addtf3.zig").__addtf3; -const __addxf3 = @import("addxf3.zig").__addxf3; -const __subtf3 = @import("subtf3.zig").__subtf3; +const impl = @import("addf3.zig"); +const add_f128 = impl.add_f128; +const add_f80 = impl.add_f80; +const sub_f128 = impl.sub_f128; fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { - const x = __addtf3(a, b); + const x = add_f128(a, b); const rep: u128 = @bitCast(x); const hi: u64 = @intCast(rep >> 64); @@ -52,7 +53,7 @@ test "addtf3" { } fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { - const x = __subtf3(a, b); + const x = sub_f128(a, b); const rep: u128 = @bitCast(x); const hi: u64 = @intCast(rep >> 64); @@ -91,7 +92,7 @@ test "subtf3" { const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1))); fn test__addxf3(a: f80, b: f80, expected: u80) !void { - const x = __addxf3(a, b); + const x = add_f80(a, b); const rep: u80 = @bitCast(x); if (rep == expected) diff --git a/lib/compiler_rt/addhf3.zig b/lib/compiler_rt/addhf3.zig deleted file mode 100644 index bd13f48cac5f1ebeda2f019b1252d6a6967aa964..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/addhf3.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - symbol(&__addhf3, "__addhf3"); -} - -fn __addhf3(a: f16, b: f16) callconv(.c) f16 { - return addf3(f16, a, b); -} diff --git a/lib/compiler_rt/addsf3.zig b/lib/compiler_rt/addsf3.zig deleted file mode 100644 index 4878fb704d1769469fb0a9155c930f0e24e0cabc..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/addsf3.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const addf3 = @import("./addf3.zig").addf3; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_fadd, "__aeabi_fadd"); - } else { - symbol(&__addsf3, "__addsf3"); - } -} - -fn __addsf3(a: f32, b: f32) callconv(.c) f32 { - return addf3(f32, a, b); -} - -fn __aeabi_fadd(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { - return addf3(f32, a, b); -} diff --git a/lib/compiler_rt/addtf3.zig b/lib/compiler_rt/addtf3.zig deleted file mode 100644 index 3097027f482ed73deee604acfcd7be877192d1fc..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/addtf3.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__addtf3, "__addkf3"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_add, "_Qp_add"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__addtf3, "_Q_add"); - } - symbol(&__addtf3, "__addtf3"); -} - -pub fn __addtf3(a: f128, b: f128) callconv(.c) f128 { - return addf3(f128, a, b); -} - -fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.c) void { - c.* = addf3(f128, a.*, b.*); -} diff --git a/lib/compiler_rt/addvdi3.zig b/lib/compiler_rt/addvdi3.zig index a5cde2494acba14282409395aa47ce9660faa0ff..063c2bcd44f16ea3dcd14fb427b24835830190bd 100644 --- a/lib/compiler_rt/addvdi3.zig +++ b/lib/compiler_rt/addvdi3.zig @@ -1,4 +1,5 @@ -const symbol = @import("../compiler_rt.zig").symbol; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; const testing = @import("std").testing; comptime { @@ -9,7 +10,7 @@ pub fn __addvdi3(a: i64, b: i64) callconv(.c) i64 { const sum = a +% b; // Overflow occurred iff both operands have the same sign, and the sign of the sum does // not match it. In other words, iff the sum sign is not the sign of either operand. - if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow"); + if (((sum ^ a) & (sum ^ b)) < 0) @panic("integer overflow"); return sum; } diff --git a/lib/compiler_rt/addvsi3.zig b/lib/compiler_rt/addvsi3.zig index c35b22e8dfd73703480c89f4a5d305fa5b8ec9fd..f180f680c52e8ddc4a991838714eff4647cb57ba 100644 --- a/lib/compiler_rt/addvsi3.zig +++ b/lib/compiler_rt/addvsi3.zig @@ -10,7 +10,7 @@ pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 { const sum = a +% b; // Overflow occurred iff both operands have the same sign, and the sign of the sum does // not match it. In other words, iff the sum sign is not the sign of either operand. - if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow"); + if (((sum ^ a) & (sum ^ b)) < 0) @panic("integer overflow"); return sum; } diff --git a/lib/compiler_rt/addxf3.zig b/lib/compiler_rt/addxf3.zig deleted file mode 100644 index f57708c98553874b47b62591b339e49b22ecedbd..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/addxf3.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - symbol(&__addxf3, "__addxf3"); -} - -pub fn __addxf3(a: f80, b: f80) callconv(.c) f80 { - return addf3(f80, a, b); -} diff --git a/lib/compiler_rt/atomics.zig b/lib/compiler_rt/atomics.zig index f2c744c730b8c20501af60bf51fa78d57cb7cbc3..83b978a11ca2fad3dc2e4f8483556751c2f6e3d1 100644 --- a/lib/compiler_rt/atomics.zig +++ b/lib/compiler_rt/atomics.zig @@ -5,7 +5,7 @@ const arch = cpu.arch; const std = @import("std"); const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; // This parameter is true iff the target architecture supports the bare minimum // to implement the atomic load/store intrinsics. diff --git a/lib/compiler_rt/aulldiv.zig b/lib/compiler_rt/aulldiv.zig index 4ed92f39eefde1b941634b5b72eac8d1e41ba0d2..3e002379220fa5e957f2d2a728435a2a11972415 100644 --- a/lib/compiler_rt/aulldiv.zig +++ b/lib/compiler_rt/aulldiv.zig @@ -1,7 +1,7 @@ const builtin = @import("builtin"); const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { if (compiler_rt.want_windows_x86_msvc_abi) { diff --git a/lib/compiler_rt/cmpdf2.zig b/lib/compiler_rt/cmpdf2.zig deleted file mode 100644 index e55972efbd00da3c3b215e722ba2277557a37525..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/cmpdf2.zig +++ /dev/null @@ -1,67 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const comparef = @import("./comparef.zig"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dcmpeq, "__aeabi_dcmpeq"); - symbol(&__aeabi_dcmplt, "__aeabi_dcmplt"); - symbol(&__aeabi_dcmple, "__aeabi_dcmple"); - } else { - symbol(&__eqdf2, "__eqdf2"); - symbol(&__nedf2, "__nedf2"); - symbol(&__ledf2, "__ledf2"); - symbol(&__cmpdf2, "__cmpdf2"); - symbol(&__ltdf2, "__ltdf2"); - } -} - -/// "These functions calculate a <=> b. That is, if a is less than b, they return -1; -/// if a is greater than b, they return 1; and if a and b are equal they return 0. -/// If either argument is NaN they return 1..." -/// -/// Note that this matches the definition of `__ledf2`, `__eqdf2`, `__nedf2`, `__cmpdf2`, -/// and `__ltdf2`. -fn __cmpdf2(a: f64, b: f64) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f64, comparef.LE, a, b)); -} - -/// "These functions return a value less than or equal to zero if neither argument is NaN, -/// and a is less than or equal to b." -pub fn __ledf2(a: f64, b: f64) callconv(.c) i32 { - return __cmpdf2(a, b); -} - -/// "These functions return zero if neither argument is NaN, and a and b are equal." -/// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined -/// to have the same return value. -pub fn __eqdf2(a: f64, b: f64) callconv(.c) i32 { - return __cmpdf2(a, b); -} - -/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." -/// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined -/// to have the same return value. -pub fn __nedf2(a: f64, b: f64) callconv(.c) i32 { - return __cmpdf2(a, b); -} - -/// "These functions return a value less than zero if neither argument is NaN, and a -/// is strictly less than b." -pub fn __ltdf2(a: f64, b: f64) callconv(.c) i32 { - return __cmpdf2(a, b); -} - -fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) == .Equal); -} - -fn __aeabi_dcmplt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) == .Less); -} - -fn __aeabi_dcmple(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) != .Greater); -} diff --git a/lib/compiler_rt/cmptf2.zig b/lib/compiler_rt/cmptf2.zig deleted file mode 100644 index 89418fb320b5b8ea3d2f972cf05dde162eccc7c0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/cmptf2.zig +++ /dev/null @@ -1,146 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const comparef = @import("./comparef.zig"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__eqtf2, "__eqkf2"); - symbol(&__netf2, "__nekf2"); - symbol(&__lttf2, "__ltkf2"); - symbol(&__letf2, "__lekf2"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_cmp, "_Qp_cmp"); - symbol(&_Qp_feq, "_Qp_feq"); - symbol(&_Qp_fne, "_Qp_fne"); - symbol(&_Qp_flt, "_Qp_flt"); - symbol(&_Qp_fle, "_Qp_fle"); - symbol(&_Qp_fgt, "_Qp_fgt"); - symbol(&_Qp_fge, "_Qp_fge"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&_Q_cmp, "_Q_cmp"); - symbol(&_Q_feq, "_Q_feq"); - symbol(&_Q_fne, "_Q_fne"); - symbol(&_Q_flt, "_Q_flt"); - symbol(&_Q_fle, "_Q_fle"); - symbol(&_Q_fgt, "_Q_fgt"); - symbol(&_Q_fge, "_Q_fge"); - } - symbol(&__eqtf2, "__eqtf2"); - symbol(&__netf2, "__netf2"); - symbol(&__letf2, "__letf2"); - symbol(&__cmptf2, "__cmptf2"); - symbol(&__lttf2, "__lttf2"); -} - -/// "These functions calculate a <=> b. That is, if a is less than b, they return -1; -/// if a is greater than b, they return 1; and if a and b are equal they return 0. -/// If either argument is NaN they return 1..." -/// -/// Note that this matches the definition of `__letf2`, `__eqtf2`, `__netf2`, `__cmptf2`, -/// and `__lttf2`. -fn __cmptf2(a: f128, b: f128) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f128, comparef.LE, a, b)); -} - -/// "These functions return a value less than or equal to zero if neither argument is NaN, -/// and a is less than or equal to b." -fn __letf2(a: f128, b: f128) callconv(.c) i32 { - return __cmptf2(a, b); -} - -/// "These functions return zero if neither argument is NaN, and a and b are equal." -/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined -/// to have the same return value. -fn __eqtf2(a: f128, b: f128) callconv(.c) i32 { - return __cmptf2(a, b); -} - -/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." -/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined -/// to have the same return value. -fn __netf2(a: f128, b: f128) callconv(.c) i32 { - return __cmptf2(a, b); -} - -/// "These functions return a value less than zero if neither argument is NaN, and a -/// is strictly less than b." -fn __lttf2(a: f128, b: f128) callconv(.c) i32 { - return __cmptf2(a, b); -} - -const SparcFCMP = enum(i32) { - Equal = 0, - Less = 1, - Greater = 2, - Unordered = 3, -}; - -fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f128, SparcFCMP, a.*, b.*)); -} - -fn _Qp_feq(a: *const f128, b: *const f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Equal; -} - -fn _Qp_fne(a: *const f128, b: *const f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) != .Equal; -} - -fn _Qp_flt(a: *const f128, b: *const f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Less; -} - -fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Greater; -} - -fn _Qp_fge(a: *const f128, b: *const f128) callconv(.c) bool { - return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b))))) { - .Equal, .Greater => true, - .Less, .Unordered => false, - }; -} - -fn _Qp_fle(a: *const f128, b: *const f128) callconv(.c) bool { - return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b))))) { - .Equal, .Less => true, - .Greater, .Unordered => false, - }; -} - -fn _Q_cmp(a: f128, b: f128) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f128, SparcFCMP, a, b)); -} - -fn _Q_feq(a: f128, b: f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Equal; -} - -fn _Q_fne(a: f128, b: f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) != .Equal; -} - -fn _Q_flt(a: f128, b: f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Less; -} - -fn _Q_fgt(a: f128, b: f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Greater; -} - -fn _Q_fge(a: f128, b: f128) callconv(.c) bool { - return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b))))) { - .Equal, .Greater => true, - .Less, .Unordered => false, - }; -} - -fn _Q_fle(a: f128, b: f128) callconv(.c) bool { - return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b))))) { - .Equal, .Less => true, - .Greater, .Unordered => false, - }; -} diff --git a/lib/compiler_rt/cmpxf2.zig b/lib/compiler_rt/cmpxf2.zig deleted file mode 100644 index 8146cd83c2f05bff98a3a122de2431820d897a08..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/cmpxf2.zig +++ /dev/null @@ -1,49 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const comparef = @import("./comparef.zig"); - -comptime { - symbol(&__eqxf2, "__eqxf2"); - symbol(&__nexf2, "__nexf2"); - symbol(&__lexf2, "__lexf2"); - symbol(&__cmpxf2, "__cmpxf2"); - symbol(&__ltxf2, "__ltxf2"); -} - -/// "These functions calculate a <=> b. That is, if a is less than b, they return -1; -/// if a is greater than b, they return 1; and if a and b are equal they return 0. -/// If either argument is NaN they return 1..." -/// -/// Note that this matches the definition of `__lexf2`, `__eqxf2`, `__nexf2`, `__cmpxf2`, -/// and `__ltxf2`. -fn __cmpxf2(a: f80, b: f80) callconv(.c) i32 { - return @backingInt(comparef.cmp_f80(comparef.LE, a, b)); -} - -/// "These functions return a value less than or equal to zero if neither argument is NaN, -/// and a is less than or equal to b." -fn __lexf2(a: f80, b: f80) callconv(.c) i32 { - return __cmpxf2(a, b); -} - -/// "These functions return zero if neither argument is NaN, and a and b are equal." -/// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined -/// to have the same return value. -fn __eqxf2(a: f80, b: f80) callconv(.c) i32 { - return __cmpxf2(a, b); -} - -/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." -/// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined -/// to have the same return value. -fn __nexf2(a: f80, b: f80) callconv(.c) i32 { - return __cmpxf2(a, b); -} - -/// "These functions return a value less than zero if neither argument is NaN, and a -/// is strictly less than b." -fn __ltxf2(a: f80, b: f80) callconv(.c) i32 { - return __cmpxf2(a, b); -} diff --git a/lib/compiler_rt/comparedf2_test.zig b/lib/compiler_rt/comparedf2_test.zig index dbae6bbeeca09ef401a17334d57f3f3be824c781..cb8a7b727f993f5b57d46e55cfffdafa1343cc78 100644 --- a/lib/compiler_rt/comparedf2_test.zig +++ b/lib/compiler_rt/comparedf2_test.zig @@ -5,52 +5,12 @@ const std = @import("std"); const builtin = @import("builtin"); -const __eqdf2 = @import("./cmpdf2.zig").__eqdf2; -const __ledf2 = @import("./cmpdf2.zig").__ledf2; -const __ltdf2 = @import("./cmpdf2.zig").__ltdf2; -const __nedf2 = @import("./cmpdf2.zig").__nedf2; +const compiler_rt = @import("../compiler_rt.zig"); -const __gedf2 = @import("./gedf2.zig").__gedf2; -const __gtdf2 = @import("./gedf2.zig").__gtdf2; - -const __unorddf2 = @import("./unorddf2.zig").__unorddf2; - -const TestVector = struct { - a: f64, - b: f64, - eqReference: c_int, - geReference: c_int, - gtReference: c_int, - leReference: c_int, - ltReference: c_int, - neReference: c_int, - unReference: c_int, -}; - -fn test__cmpdf2(vector: TestVector) bool { - if (__eqdf2(vector.a, vector.b) != vector.eqReference) { - return false; - } - if (__gedf2(vector.a, vector.b) != vector.geReference) { - return false; - } - if (__gtdf2(vector.a, vector.b) != vector.gtReference) { - return false; - } - if (__ledf2(vector.a, vector.b) != vector.leReference) { - return false; - } - if (__ltdf2(vector.a, vector.b) != vector.ltReference) { - return false; - } - if (__nedf2(vector.a, vector.b) != vector.neReference) { - return false; - } - if (__unorddf2(vector.a, vector.b) != vector.unReference) { - return false; - } - return true; -} +const impl = @import("comparef.zig"); +const Order = impl.Order; +const cmp_f64 = impl.cmp_f64; +const unord_f64 = impl.unord_f64; const arguments = [_]f64{ std.math.nan(f64), @@ -73,36 +33,20 @@ const arguments = [_]f64{ std.math.inf(f64), }; -fn generateVector(comptime a: f64, comptime b: f64) TestVector { - const leResult = if (a < b) -1 else if (a == b) 0 else 1; - const geResult = if (a > b) 1 else if (a == b) 0 else -1; - const unResult = if (a != a or b != b) 1 else 0; - return TestVector{ - .a = a, - .b = b, - .eqReference = leResult, - .geReference = geResult, - .gtReference = geResult, - .leReference = leResult, - .ltReference = leResult, - .neReference = leResult, - .unReference = unResult, - }; -} - -const test_vectors = init: { - @setEvalBranchQuota(10000); - var vectors: [arguments.len * arguments.len]TestVector = undefined; +test "compare f64" { for (arguments[0..], 0..) |arg_i, i| { for (arguments[0..], 0..) |arg_j, j| { - vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j); + const expected_unord = i == 0 or j == 0; + const expected_order: ?Order = if (expected_unord) null else switch (std.math.order( + if (i >= 9) i - 1 else i, + if (j >= 9) j - 1 else j, + )) { + .lt => .lt, + .eq => .eq, + .gt => .gt, + }; + try std.testing.expect(expected_order == cmp_f64(arg_i, arg_j)); + try std.testing.expect(expected_unord == unord_f64(arg_i, arg_j)); } } - break :init vectors; -}; - -test "compare f64" { - for (test_vectors) |vector| { - try std.testing.expect(test__cmpdf2(vector)); - } } diff --git a/lib/compiler_rt/comparef.zig b/lib/compiler_rt/comparef.zig index a0f7551c74c9068909ef9e10c0ea71fa93140eef..7b397ba02f9aca5a534f015726bcb143a456eb63 100644 --- a/lib/compiler_rt/comparef.zig +++ b/lib/compiler_rt/comparef.zig @@ -1,163 +1,309 @@ +const builtin = @import("builtin"); const std = @import("std"); const compiler_rt = @import("../compiler_rt.zig"); const symbol = compiler_rt.symbol; +const Unordered = if (builtin.cpu.arch == .avr) + i8 +else if (builtin.cpu.arch.isAARCH64()) + i32 +else if (builtin.target.cTypeBitSize(.long) >= builtin.target.ptrBitWidth()) + c_long +else + c_longlong; +pub const Order = enum(Unordered) { lt = -1, eq = 0, gt = 1 }; +const SparcOrder = enum(i32) { eq = 0, lt = 1, gt = 2, un = 3 }; + comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_fcmpun, "__aeabi_fcmpun"); - } else { - symbol(&__unordsf2, "__unordsf2"); - } - - symbol(&__unordxf2, "__unordxf2"); - - symbol(&__eqhf2, "__eqhf2"); - symbol(&__nehf2, "__nehf2"); - symbol(&__lehf2, "__lehf2"); symbol(&__cmphf2, "__cmphf2"); - symbol(&__lthf2, "__lthf2"); + symbol(&__cmphf2, "__eqhf2"); + symbol(&__cmphf2, "__nehf2"); + symbol(&__cmphf2, "__lthf2"); + symbol(&__cmphf2, "__lehf2"); + symbol(&__gehf2, "__gthf2"); + symbol(&__gehf2, "__gehf2"); + symbol(&__unordhf2, "__unordhf2"); if (compiler_rt.want_aeabi) { symbol(&__aeabi_fcmpeq, "__aeabi_fcmpeq"); symbol(&__aeabi_fcmplt, "__aeabi_fcmplt"); symbol(&__aeabi_fcmple, "__aeabi_fcmple"); + symbol(&__aeabi_fcmpgt, "__aeabi_fcmpgt"); + symbol(&__aeabi_fcmpge, "__aeabi_fcmpge"); + symbol(&__aeabi_fcmpun, "__aeabi_fcmpun"); + + symbol(&__aeabi_dcmpeq, "__aeabi_dcmpeq"); + symbol(&__aeabi_dcmplt, "__aeabi_dcmplt"); + symbol(&__aeabi_dcmple, "__aeabi_dcmple"); + symbol(&__aeabi_dcmpgt, "__aeabi_dcmpgt"); + symbol(&__aeabi_dcmpge, "__aeabi_dcmpge"); + symbol(&__aeabi_dcmpun, "__aeabi_dcmpun"); } else { - symbol(&__eqsf2, "__eqsf2"); - symbol(&__nesf2, "__nesf2"); - symbol(&__lesf2, "__lesf2"); symbol(&__cmpsf2, "__cmpsf2"); - symbol(&__ltsf2, "__ltsf2"); + symbol(&__cmpsf2, "__eqsf2"); + symbol(&__cmpsf2, "__nesf2"); + symbol(&__cmpsf2, "__ltsf2"); + symbol(&__cmpsf2, "__lesf2"); + symbol(&__gesf2, "__gtsf2"); + symbol(&__gesf2, "__gesf2"); + symbol(&__unordsf2, "__unordsf2"); + + symbol(&__cmpdf2, "__cmpdf2"); + symbol(&__cmpdf2, "__eqdf2"); + symbol(&__cmpdf2, "__nedf2"); + symbol(&__cmpdf2, "__ltdf2"); + symbol(&__cmpdf2, "__ledf2"); + symbol(&__gedf2, "__gtdf2"); + symbol(&__gedf2, "__gedf2"); + symbol(&__unorddf2, "__unorddf2"); } + symbol(&__cmpxf2, "__cmpxf2"); + symbol(&__cmpxf2, "__eqxf2"); + symbol(&__cmpxf2, "__nexf2"); + symbol(&__cmpxf2, "__ltxf2"); + symbol(&__cmpxf2, "__lexf2"); + symbol(&__gexf2, "__gtxf2"); + symbol(&__gexf2, "__gexf2"); + symbol(&__unordxf2, "__unordxf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__cmptf2, "__eqkf2"); + symbol(&__cmptf2, "__nekf2"); + symbol(&__cmptf2, "__ltkf2"); + symbol(&__cmptf2, "__lekf2"); + symbol(&__getf2, "__gtkf2"); + symbol(&__getf2, "__gekf2"); symbol(&__unordtf2, "__unordkf2"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_cmp, "_Qp_cmp"); + symbol(&_Qp_feq, "_Qp_feq"); + symbol(&_Qp_fne, "_Qp_fne"); + symbol(&_Qp_flt, "_Qp_flt"); + symbol(&_Qp_fle, "_Qp_fle"); + symbol(&_Qp_fgt, "_Qp_fgt"); + symbol(&_Qp_fge, "_Qp_fge"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&_Q_cmp, "_Q_cmp"); + symbol(&_Q_feq, "_Q_feq"); + symbol(&_Q_fne, "_Q_fne"); + symbol(&_Q_flt, "_Q_flt"); + symbol(&_Q_fle, "_Q_fle"); + symbol(&_Q_fgt, "_Q_fgt"); + symbol(&_Q_fge, "_Q_fge"); + } else { + symbol(&__cmptf2, "__cmptf2"); + symbol(&__cmptf2, "__eqtf2"); + symbol(&__cmptf2, "__netf2"); + symbol(&__cmptf2, "__lttf2"); + symbol(&__cmptf2, "__letf2"); + symbol(&__getf2, "__gttf2"); + symbol(&__getf2, "__getf2"); + symbol(&__unordtf2, "__unordtf2"); } - symbol(&__unordtf2, "__unordtf2"); - symbol(&__unordhf2, "__unordhf2"); } -pub fn __unordhf2(a: f16, b: f16) callconv(.c) i32 { - return unordcmp(f16, a, b); +fn __cmphf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order { + return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .gt; } - -pub fn __unordtf2(a: f128, b: f128) callconv(.c) i32 { - return unordcmp(f128, a, b); +fn __gehf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order { + return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .lt; } - -/// "These functions calculate a <=> b. That is, if a is less than b, they return -1; -/// if a is greater than b, they return 1; and if a and b are equal they return 0. -/// If either argument is NaN they return 1..." -/// -/// Note that this matches the definition of `__lesf2`, `__eqsf2`, `__nesf2`, `__cmpsf2`, -/// and `__ltsf2`. -fn __cmpsf2(a: f32, b: f32) callconv(.c) i32 { - return @backingInt(cmpf2(f32, LE, a, b)); +fn __unordhf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Unordered { + return @intFromBool(unord_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); } - -/// "These functions return a value less than or equal to zero if neither argument is NaN, -/// and a is less than or equal to b." -pub fn __lesf2(a: f32, b: f32) callconv(.c) i32 { - return __cmpsf2(a, b); +pub fn cmp_f16(a: f16, b: f16) ?Order { + return cmpf2(f16, a, b); } - -/// "These functions return zero if neither argument is NaN, and a and b are equal." -/// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined -/// to have the same return value. -pub fn __eqsf2(a: f32, b: f32) callconv(.c) i32 { - return __cmpsf2(a, b); +pub fn unord_f16(a: f16, b: f16) bool { + return unord(f16, a, b); } -/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." -/// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined -/// to have the same return value. -pub fn __nesf2(a: f32, b: f32) callconv(.c) i32 { - return __cmpsf2(a, b); +fn __cmpsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order { + return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .gt; } - -/// "These functions return a value less than zero if neither argument is NaN, and a -/// is strictly less than b." -pub fn __ltsf2(a: f32, b: f32) callconv(.c) i32 { - return __cmpsf2(a, b); -} - fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(cmpf2(f32, LE, a, b) == .Equal); + return @intFromBool(cmp_f32(a, b) == .eq); } - fn __aeabi_fcmplt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(cmpf2(f32, LE, a, b) == .Less); + return @intFromBool(cmp_f32(a, b) == .lt); } - fn __aeabi_fcmple(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(cmpf2(f32, LE, a, b) != .Greater); + return @intFromBool(cmp_f32(a, b) orelse .gt != .gt); } - -/// "These functions calculate a <=> b. That is, if a is less than b, they return -1; -/// if a is greater than b, they return 1; and if a and b are equal they return 0. -/// If either argument is NaN they return 1..." -/// -/// Note that this matches the definition of `__lehf2`, `__eqhf2`, `__nehf2`, `__cmphf2`, -/// and `__lthf2`. -fn __cmphf2(a: f16, b: f16) callconv(.c) i32 { - return @backingInt(cmpf2(f16, LE, a, b)); +fn __gesf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order { + return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .lt; } - -/// "These functions return a value less than or equal to zero if neither argument is NaN, -/// and a is less than or equal to b." -fn __lehf2(a: f16, b: f16) callconv(.c) i32 { - return __cmphf2(a, b); +fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f32(a, b) orelse .lt != .lt); } - -/// "These functions return zero if neither argument is NaN, and a and b are equal." -/// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined -/// to have the same return value. -fn __eqhf2(a: f16, b: f16) callconv(.c) i32 { - return __cmphf2(a, b); +fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f32(a, b) == .gt); } - -/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." -/// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined -/// to have the same return value. -fn __nehf2(a: f16, b: f16) callconv(.c) i32 { - return __cmphf2(a, b); +fn __unordsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Unordered { + return @intFromBool(unord_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); } - -/// "These functions return a value less than zero if neither argument is NaN, and a -/// is strictly less than b." -fn __lthf2(a: f16, b: f16) callconv(.c) i32 { - return __cmphf2(a, b); -} - -fn __unordxf2(a: f80, b: f80) callconv(.c) i32 { - return unordcmp(f80, a, b); -} - -pub fn __unordsf2(a: f32, b: f32) callconv(.c) i32 { - return unordcmp(f32, a, b); -} - fn __aeabi_fcmpun(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return unordcmp(f32, a, b); + return @intFromBool(unord_f32(a, b)); } +pub fn cmp_f32(a: f32, b: f32) ?Order { + return cmpf2(f32, a, b); +} +pub fn unord_f32(a: f32, b: f32) bool { + return unord(f32, a, b); +} + +fn __cmpdf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Order { + return cmp_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)) orelse .gt; +} +fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f64(a, b) == .eq); +} +fn __aeabi_dcmplt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f64(a, b) == .lt); +} +fn __aeabi_dcmple(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f64(a, b) orelse .gt != .gt); +} +fn __gedf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Order { + return cmp_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)) orelse .lt; +} +fn __aeabi_dcmpge(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f64(a, b) orelse .lt != .lt); +} +fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f64(a, b) == .gt); +} +fn __unorddf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Unordered { + return @intFromBool(unord_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); +} +fn __aeabi_dcmpun(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(unord_f64(a, b)); +} +pub fn cmp_f64(a: f64, b: f64) ?Order { + return cmpf2(f64, a, b); +} +pub fn unord_f64(a: f64, b: f64) bool { + return unord(f64, a, b); +} + +fn __cmpxf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Order { + return cmp_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)) orelse .gt; +} +fn __gexf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Order { + return cmp_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)) orelse .lt; +} +fn __unordxf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Unordered { + return @intFromBool(unord_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} +pub fn cmp_f80(a: f80, b: f80) ?Order { + const a_rep = std.math.F80.fromFloat(a); + const b_rep = std.math.F80.fromFloat(b); + const sig_bits = std.math.floatMantissaBits(f80); + const int_bit = 0x8000000000000000; + const sign_bit = 0x8000; + const special_exp = 0x7FFF; -pub const LE = enum(i32) { - Less = -1, - Equal = 0, - Greater = 1, + // If either a or b is NaN, they are unordered. + if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or + (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0)) + return null; - const Unordered: LE = .Greater; -}; + // If a and b are both zeros, they are equal. + if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0) + return .eq; -pub const GE = enum(i32) { - Less = -1, - Equal = 0, - Greater = 1, + if (@intFromBool(a_rep.exp == b_rep.exp) & @intFromBool(a_rep.fraction == b_rep.fraction) != 0) { + return .eq; + } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) { + // signs are different + if (@as(i16, @bitCast(a_rep.exp)) < @as(i16, @bitCast(b_rep.exp))) { + return .lt; + } else { + return .gt; + } + } else { + const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits); + const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits); + if ((a_fraction < b_fraction) == (a_rep.exp & sign_bit == 0)) { + return .lt; + } else { + return .gt; + } + } +} +pub fn unord_f80(a: f80, b: f80) bool { + return unord(f80, a, b); +} - const Unordered: GE = .Less; -}; +fn __cmptf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Order { + return cmp_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)) orelse .gt; +} +fn __getf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Order { + return cmp_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)) orelse .lt; +} +fn __unordtf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Unordered { + return @intFromBool(unord_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); +} +fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.c) SparcOrder { + return switch (cmp_f128(a.*, b.*) orelse return .un) { + .lt => .lt, + .eq => .eq, + .gt => .gt, + }; +} +fn _Qp_feq(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a.*, b.*) == .eq); +} +fn _Qp_fne(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a.*, b.*) != .eq); +} +fn _Qp_flt(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a.*, b.*) == .lt); +} +fn _Qp_fle(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool((cmp_f128(a.*, b.*) orelse .gt) != .gt); +} +fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a.*, b.*) == .gt); +} +fn _Qp_fge(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool((cmp_f128(a.*, b.*) orelse .lt) != .lt); +} +fn _Q_cmp(a: f128, b: f128) callconv(.c) SparcOrder { + return switch (cmp_f128(a, b) orelse return .un) { + .lt => .lt, + .eq => .eq, + .gt => .gt, + }; +} +fn _Q_feq(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a, b) == .eq); +} +fn _Q_fne(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a, b) != .eq); +} +fn _Q_flt(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a, b) == .lt); +} +fn _Q_fle(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool((cmp_f128(a, b) orelse .gt) != .gt); +} +fn _Q_fgt(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a, b) == .gt); +} +fn _Q_fge(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool((cmp_f128(a, b) orelse .lt) != .lt); +} +pub fn cmp_f128(a: f128, b: f128) ?Order { + return cmpf2(f128, a, b); +} +pub fn unord_f128(a: f128, b: f128) bool { + return unord(f128, a, b); +} -pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT { +inline fn cmpf2(comptime T: type, a: T, b: T) ?Order { const bits = @typeInfo(T).float.bits; const srep_t = @Int(.signed, bits); const rep_t = @Int(.unsigned, bits); @@ -175,81 +321,42 @@ pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT { const bAbs = @as(rep_t, @bitCast(bInt)) & absMask; // If either a or b is NaN, they are unordered. - if (aAbs > infRep or bAbs > infRep) return RT.Unordered; + if (aAbs > infRep or bAbs > infRep) return null; // If a and b are both zeros, they are equal. - if ((aAbs | bAbs) == 0) return .Equal; + if ((aAbs | bAbs) == 0) return .eq; // If at least one of a and b is positive, we get the same result comparing // a and b as signed integers as we would with a floating-point compare. if ((aInt & bInt) >= 0) { if (aInt < bInt) { - return .Less; + return .lt; } else if (aInt == bInt) { - return .Equal; - } else return .Greater; + return .eq; + } else return .gt; } else { // Otherwise, both are negative, so we need to flip the sense of the // comparison to get the correct result. (This assumes a twos- or ones- // complement integer representation; if integers are represented in a // sign-magnitude representation, then this flip is incorrect). if (aInt > bInt) { - return .Less; + return .lt; } else if (aInt == bInt) { - return .Equal; - } else return .Greater; + return .eq; + } else return .gt; } } -pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT { - const a_rep = std.math.F80.fromFloat(a); - const b_rep = std.math.F80.fromFloat(b); - const sig_bits = std.math.floatMantissaBits(f80); - const int_bit = 0x8000000000000000; - const sign_bit = 0x8000; - const special_exp = 0x7FFF; - - // If either a or b is NaN, they are unordered. - if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or - (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0)) - return RT.Unordered; - - // If a and b are both zeros, they are equal. - if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0) - return .Equal; - - if (@intFromBool(a_rep.exp == b_rep.exp) & @intFromBool(a_rep.fraction == b_rep.fraction) != 0) { - return .Equal; - } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) { - // signs are different - if (@as(i16, @bitCast(a_rep.exp)) < @as(i16, @bitCast(b_rep.exp))) { - return .Less; - } else { - return .Greater; - } - } else { - const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits); - const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits); - if ((a_fraction < b_fraction) == (a_rep.exp & sign_bit == 0)) { - return .Less; - } else { - return .Greater; - } - } -} - -test "cmp_f80" { - inline for (.{ LE, GE }) |RT| { - try std.testing.expect(cmp_f80(RT, 1.0, 1.0) == RT.Equal); - try std.testing.expect(cmp_f80(RT, 0.0, -0.0) == RT.Equal); - try std.testing.expect(cmp_f80(RT, 2.0, 4.0) == RT.Less); - try std.testing.expect(cmp_f80(RT, 2.0, -4.0) == RT.Greater); - try std.testing.expect(cmp_f80(RT, -2.0, -4.0) == RT.Greater); - try std.testing.expect(cmp_f80(RT, -2.0, 4.0) == RT.Less); - } +test cmp_f80 { + try std.testing.expect(cmp_f80(1.0, 1.0) == .eq); + try std.testing.expect(cmp_f80(0.0, -0.0) == .eq); + try std.testing.expect(cmp_f80(2.0, 4.0) == .lt); + try std.testing.expect(cmp_f80(2.0, -4.0) == .gt); + try std.testing.expect(cmp_f80(-2.0, -4.0) == .gt); + try std.testing.expect(cmp_f80(-2.0, 4.0) == .lt); } -pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 { +inline fn unord(comptime T: type, a: T, b: T) bool { const rep_t = @Int(.unsigned, @typeInfo(T).float.bits); const significandBits = std.math.floatMantissaBits(T); @@ -261,7 +368,7 @@ pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 { const aAbs: rep_t = @as(rep_t, @bitCast(a)) & absMask; const bAbs: rep_t = @as(rep_t, @bitCast(b)) & absMask; - return @intFromBool(aAbs > infRep or bAbs > infRep); + return aAbs > infRep or bAbs > infRep; } test { diff --git a/lib/compiler_rt/comparesf2_test.zig b/lib/compiler_rt/comparesf2_test.zig index d42e1ca6db124de615f2eb3a74eadfeb119992eb..5e34b00604b8f7d608cb6d21e51d8118d26d013b 100644 --- a/lib/compiler_rt/comparesf2_test.zig +++ b/lib/compiler_rt/comparesf2_test.zig @@ -5,52 +5,12 @@ const std = @import("std"); const builtin = @import("builtin"); -const __eqsf2 = @import("./comparef.zig").__eqsf2; -const __lesf2 = @import("./comparef.zig").__lesf2; -const __ltsf2 = @import("./comparef.zig").__ltsf2; -const __nesf2 = @import("./comparef.zig").__nesf2; +const compiler_rt = @import("../compiler_rt.zig"); -const __gesf2 = @import("./gesf2.zig").__gesf2; -const __gtsf2 = @import("./gesf2.zig").__gtsf2; - -const __unordsf2 = @import("./comparef.zig").__unordsf2; - -const TestVector = struct { - a: f32, - b: f32, - eqReference: c_int, - geReference: c_int, - gtReference: c_int, - leReference: c_int, - ltReference: c_int, - neReference: c_int, - unReference: c_int, -}; - -fn test__cmpsf2(vector: TestVector) bool { - if (__eqsf2(vector.a, vector.b) != vector.eqReference) { - return false; - } - if (__gesf2(vector.a, vector.b) != vector.geReference) { - return false; - } - if (__gtsf2(vector.a, vector.b) != vector.gtReference) { - return false; - } - if (__lesf2(vector.a, vector.b) != vector.leReference) { - return false; - } - if (__ltsf2(vector.a, vector.b) != vector.ltReference) { - return false; - } - if (__nesf2(vector.a, vector.b) != vector.neReference) { - return false; - } - if (__unordsf2(vector.a, vector.b) != vector.unReference) { - return false; - } - return true; -} +const impl = @import("comparef.zig"); +const Order = impl.Order; +const cmp_f32 = impl.cmp_f32; +const unord_f32 = impl.unord_f32; const arguments = [_]f32{ std.math.nan(f32), @@ -73,36 +33,20 @@ const arguments = [_]f32{ std.math.inf(f32), }; -fn generateVector(comptime a: f32, comptime b: f32) TestVector { - const leResult = if (a < b) -1 else if (a == b) 0 else 1; - const geResult = if (a > b) 1 else if (a == b) 0 else -1; - const unResult = if (a != a or b != b) 1 else 0; - return TestVector{ - .a = a, - .b = b, - .eqReference = leResult, - .geReference = geResult, - .gtReference = geResult, - .leReference = leResult, - .ltReference = leResult, - .neReference = leResult, - .unReference = unResult, - }; -} - -const test_vectors = init: { - @setEvalBranchQuota(10000); - var vectors: [arguments.len * arguments.len]TestVector = undefined; +test "compare f32" { for (arguments[0..], 0..) |arg_i, i| { for (arguments[0..], 0..) |arg_j, j| { - vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j); + const expected_unord = i == 0 or j == 0; + const expected_order: ?Order = if (expected_unord) null else switch (std.math.order( + i - @intFromBool(i >= 9), + j - @intFromBool(j >= 9), + )) { + .lt => .lt, + .eq => .eq, + .gt => .gt, + }; + try std.testing.expect(expected_order == cmp_f32(arg_i, arg_j)); + try std.testing.expect(expected_unord == unord_f32(arg_i, arg_j)); } } - break :init vectors; -}; - -test "compare f32" { - for (test_vectors) |vector| { - try std.testing.expect(test__cmpsf2(vector)); - } } diff --git a/lib/compiler_rt/cos.zig b/lib/compiler_rt/cos.zig index a207f0244f941c3e6730f9e6f5891201840120cc..612698b1e9efb080804656c50e68cd6e0a2e8680 100644 --- a/lib/compiler_rt/cos.zig +++ b/lib/compiler_rt/cos.zig @@ -13,31 +13,35 @@ const expect = std.testing.expect; const expectApproxEqAbs = std.testing.expectApproxEqAbs; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; const trig = @import("trig.zig"); const rem_pio2 = @import("rem_pio2.zig").rem_pio2; const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; comptime { - symbol(&cosh, "__cosh"); - symbol(&cosl, "__cosl"); + symbol(&__cosh, "__cosh"); symbol(&cosf, "cosf"); symbol(&cos, "cos"); - symbol(&cosx, "__cosx"); - if (compiler_rt.want_ppc_abi) { - symbol(&cosq, "cosf128"); - } + symbol(&__cosx, "__cosx"); + if (compiler_rt.want_ppc_abi) symbol(&cosq, "cosf128"); symbol(&cosq, "cosq"); symbol(&cosl, "cosl"); + symbol(&cosl, "__cosl"); // required by musl } -pub fn cosh(a: f16) callconv(.c) f16 { +fn __cosh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(cos_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn cos_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(cosf(a)); + return @floatCast(cos_f32(x)); } -pub fn cosf(x: f32) callconv(.c) f32 { +fn cosf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(cos_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn cos_f32(x: f32) f32 { // Small multiples of pi/2 rounded to double precision. const c1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 const c2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 @@ -94,7 +98,10 @@ pub fn cosf(x: f32) callconv(.c) f32 { }; } -pub fn cos(x: f64) callconv(.c) f64 { +fn cos(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(cos_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn cos_f64(x: f64) f64 { var ix = @as(u64, @bitCast(x)) >> 32; ix &= 0x7fffffff; @@ -123,7 +130,10 @@ pub fn cos(x: f64) callconv(.c) f64 { }; } -pub fn cosx(x: f80) callconv(.c) f80 { +fn __cosx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(cos_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn cos_f80(x: f80) f80 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -147,7 +157,10 @@ pub fn cosx(x: f80) callconv(.c) f80 { }; } -pub fn cosq(x: f128) callconv(.c) f128 { +fn cosq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(cos_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn cos_f128(x: f128) f128 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -173,20 +186,21 @@ pub fn cosq(x: f128) callconv(.c) f128 { pub fn cosl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return cos(x), - 80 => return cosx(x), - 128 => return cosq(x), - else => @compileError("unreachable"), + 64 => return cos_f64(x), + 80 => return cos_f80(x), + 128 => return cos_f128(x), + else => comptime unreachable, } } fn testCosSpecial(comptime T: type) !void { const f = switch (T) { - f32 => cosf, - f64 => cos, - f80 => cosx, - f128 => cosq, - else => @compileError("unimplemented"), + f16 => cos_f16, + f32 => cos_f32, + f64 => cos_f64, + f80 => cos_f80, + f128 => cos_f128, + else => comptime unreachable, }; try expect(f(0.0) == 1.0); @@ -198,13 +212,13 @@ fn testCosSpecial(comptime T: type) !void { test "cos32.normal" { const epsilon = math.floatEps(f32); - try expectApproxEqAbs(@as(f32, 1.0), cosf(0.0), epsilon); - try expectApproxEqAbs(@as(f32, 0.9800666), cosf(0.2), epsilon); - try expectApproxEqAbs(@as(f32, 0.6276231), cosf(0.8923), epsilon); - try expectApproxEqAbs(@as(f32, 0.0707372), cosf(1.5), epsilon); - try expectApproxEqAbs(@as(f32, 0.0707372), cosf(-1.5), epsilon); - try expectApproxEqAbs(@as(f32, 0.96913195), cosf(37.45), epsilon); - try expectApproxEqAbs(@as(f32, 0.40079966), cosf(89.123), epsilon); + try expectApproxEqAbs(@as(f32, 1.0), cos_f32(0.0), epsilon); + try expectApproxEqAbs(@as(f32, 0.9800666), cos_f32(0.2), epsilon); + try expectApproxEqAbs(@as(f32, 0.6276231), cos_f32(0.8923), epsilon); + try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(1.5), epsilon); + try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(-1.5), epsilon); + try expectApproxEqAbs(@as(f32, 0.96913195), cos_f32(37.45), epsilon); + try expectApproxEqAbs(@as(f32, 0.40079966), cos_f32(89.123), epsilon); } test "cos32.special" { @@ -213,13 +227,13 @@ test "cos32.special" { test "cos64.normal" { const epsilon = math.floatEps(f64); - try expectApproxEqAbs(@as(f64, 1.0), cos(0.0), epsilon); - try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos(0.2), epsilon); - try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos(0.8923), epsilon); - try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(1.5), epsilon); - try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(-1.5), epsilon); - try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos(37.45), epsilon); - try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos(89.123), epsilon); + try expectApproxEqAbs(@as(f64, 1.0), cos_f64(0.0), epsilon); + try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos_f64(0.2), epsilon); + try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos_f64(0.8923), epsilon); + try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(1.5), epsilon); + try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(-1.5), epsilon); + try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos_f64(37.45), epsilon); + try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos_f64(89.123), epsilon); } test "cos64.special" { @@ -228,13 +242,13 @@ test "cos64.special" { test "cos80.normal" { const epsilon = math.floatEps(f80); - try expectApproxEqAbs(@as(f80, 1.0), cosx(0.0), epsilon); - try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cosx(0.2), epsilon); - try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cosx(0.8923), epsilon); - try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(1.5), epsilon); - try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(-1.5), epsilon); - try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cosx(37.45), epsilon); - try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cosx(89.123), epsilon); + try expectApproxEqAbs(@as(f80, 1.0), cos_f80(0.0), epsilon); + try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cos_f80(0.2), epsilon); + try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cos_f80(0.8923), epsilon); + try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(1.5), epsilon); + try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(-1.5), epsilon); + try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cos_f80(37.45), epsilon); + try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cos_f80(89.123), epsilon); } test "cos80.special" { @@ -243,13 +257,13 @@ test "cos80.special" { test "cos128.normal" { const epsilon = math.floatEps(f128); - try expectApproxEqAbs(@as(f128, 1.0), cosq(0.0), epsilon); - try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cosq(0.2), epsilon); - try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cosq(0.8923), epsilon); - try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(1.5), epsilon); - try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(-1.5), epsilon); - try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cosq(37.45), epsilon); - try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cosq(89.123), epsilon); + try expectApproxEqAbs(@as(f128, 1.0), cos_f128(0.0), epsilon); + try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cos_f128(0.2), epsilon); + try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cos_f128(0.8923), epsilon); + try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(1.5), epsilon); + try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(-1.5), epsilon); + try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cos_f128(37.45), epsilon); + try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cos_f128(89.123), epsilon); } test "cos128.special" { diff --git a/lib/compiler_rt/count0bits.zig b/lib/compiler_rt/count0bits.zig index a8d0445dc69276e4639211818eb42707a8782c6c..fca372b33b98865ec041ee3ca764a5d8207ae330 100644 --- a/lib/compiler_rt/count0bits.zig +++ b/lib/compiler_rt/count0bits.zig @@ -1,6 +1,7 @@ const builtin = @import("builtin"); const std = @import("std"); -const symbol = @import("../compiler_rt.zig").symbol; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; comptime { symbol(&__clzsi2, "__clzsi2"); diff --git a/lib/compiler_rt/divc3.zig b/lib/compiler_rt/divc3.zig index 92d2b39f663d272bdb83042f69abcd6a91c2ba09..a76a63c7e0f9059a112dc5c3b4406349766351f6 100644 --- a/lib/compiler_rt/divc3.zig +++ b/lib/compiler_rt/divc3.zig @@ -7,12 +7,81 @@ const maxInt = std.math.maxInt; const minInt = std.math.minInt; const isFinite = std.math.isFinite; const copysign = std.math.copysign; -const Complex = @import("mulc3.zig").Complex; + +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; +const Complex = compiler_rt.Complex; + +comptime { + if (@import("builtin").zig_backend != .stage2_c) { + symbol(&__divhc3, "__divhc3"); + symbol(&__divsc3, "__divsc3"); + symbol(&__divdc3, "__divdc3"); + symbol(&__divxc3, "__divxc3"); + if (compiler_rt.want_ppc_abi) { + symbol(&__divtc3, "__divkc3"); + } else { + symbol(&__divtc3, "__divtc3"); + } + } +} + +fn __divhc3(lhs_real: compiler_rt.f16.Abi, lhs_imag: compiler_rt.f16.Abi, rhs_real: compiler_rt.f16.Abi, rhs_imag: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.complex.Abi { + return compiler_rt.f16.complex.toAbi(div_cf16( + compiler_rt.f16.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f16.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn div_cf16(a: Complex(f16), b: Complex(f16)) Complex(f16) { + return divc3(f16, a, b); +} + +fn __divsc3(lhs_real: compiler_rt.f32.Abi, lhs_imag: compiler_rt.f32.Abi, rhs_real: compiler_rt.f32.Abi, rhs_imag: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.complex.Abi { + return compiler_rt.f32.complex.toAbi(div_cf32( + compiler_rt.f32.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f32.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn div_cf32(a: Complex(f32), b: Complex(f32)) Complex(f32) { + return divc3(f32, a, b); +} + +fn __divdc3(lhs_real: compiler_rt.f64.Abi, lhs_imag: compiler_rt.f64.Abi, rhs_real: compiler_rt.f64.Abi, rhs_imag: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.complex.Abi { + return compiler_rt.f64.complex.toAbi(div_cf64( + compiler_rt.f64.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f64.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn div_cf64(a: Complex(f64), b: Complex(f64)) Complex(f64) { + return divc3(f64, a, b); +} + +fn __divxc3(lhs_real: compiler_rt.f80.Abi, lhs_imag: compiler_rt.f80.Abi, rhs_real: compiler_rt.f80.Abi, rhs_imag: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.complex.Abi { + return compiler_rt.f80.complex.toAbi(div_cf80( + compiler_rt.f80.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f80.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn div_cf80(a: Complex(f80), b: Complex(f80)) Complex(f80) { + return divc3(f80, a, b); +} + +fn __divtc3(lhs_real: compiler_rt.f128.Abi, lhs_imag: compiler_rt.f128.Abi, rhs_real: compiler_rt.f128.Abi, rhs_imag: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.complex.Abi { + return compiler_rt.f128.complex.toAbi(div_cf128( + compiler_rt.f128.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f128.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn div_cf128(a: Complex(f128), b: Complex(f128)) Complex(f128) { + return divc3(f128, a, b); +} /// Implementation based on Annex G of C17 Standard (N2176) -pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) { - var c = c_in; - var d = d_in; +inline fn divc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) { + const a = lhs.real; + const b = lhs.imag; + var c = rhs.real; + var d = rhs.imag; // logbw used to prevent under/over-flow const logbw = ilogb(@max(@abs(c), @abs(d))); @@ -23,7 +92,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) { break :b logbw; } else 0; const denom = c * c + d * d; - const result = Complex(T){ + const result: Complex(T) = .{ .real = scalbn((a * c + b * d) / denom, -ilogbw), .imag = scalbn((b * c - a * d) / denom, -ilogbw), }; @@ -58,3 +127,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) { return result; } + +test { + _ = @import("divc3_test.zig"); +} diff --git a/lib/compiler_rt/divc3_test.zig b/lib/compiler_rt/divc3_test.zig index d3c400d46cacb1f12ec677d0f5dd0fb661bace4d..277a879253eed991a5e2cfa8453e8d28ab589f21 100644 --- a/lib/compiler_rt/divc3_test.zig +++ b/lib/compiler_rt/divc3_test.zig @@ -2,76 +2,53 @@ const std = @import("std"); const math = std.math; const expect = std.testing.expect; -const Complex = @import("./mulc3.zig").Complex; -const __divhc3 = @import("./divhc3.zig").__divhc3; -const __divsc3 = @import("./divsc3.zig").__divsc3; -const __divdc3 = @import("./divdc3.zig").__divdc3; -const __divxc3 = @import("./divxc3.zig").__divxc3; -const __divtc3 = @import("./divtc3.zig").__divtc3; +const Complex = @import("../compiler_rt.zig").Complex; + +const impl = @import("divc3.zig"); +const div_cf16 = impl.div_cf16; +const div_cf32 = impl.div_cf32; +const div_cf64 = impl.div_cf64; +const div_cf80 = impl.div_cf80; +const div_cf128 = impl.div_cf128; test "divc3" { - try testDiv(f16, __divhc3); - try testDiv(f32, __divsc3); - try testDiv(f64, __divdc3); - try testDiv(f80, __divxc3); - try testDiv(f128, __divtc3); + try testDiv(f16, div_cf16); + try testDiv(f32, div_cf32); + try testDiv(f64, div_cf64); + try testDiv(f80, div_cf80); + try testDiv(f128, div_cf128); } -fn testDiv(comptime T: type, comptime f: fn (T, T, T, T) callconv(.c) Complex(T)) !void { +fn testDiv(comptime T: type, comptime f: fn (Complex(T), Complex(T)) Complex(T)) !void { { - const a: T = 1.0; - const b: T = 0.0; - const c: T = -1.0; - const d: T = 0.0; - - const result = f(a, b, c, d); + const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.0 }); try expect(result.real == -1.0); - try expect(result.imag == 0.0); + try expect(math.isNegativeZero(result.imag)); } { - const a: T = 1.0; - const b: T = 0.0; - const c: T = -4.0; - const d: T = 0.0; - - const result = f(a, b, c, d); + const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.0 }); try expect(result.real == -0.25); - try expect(result.imag == 0.0); + try expect(math.isNegativeZero(result.imag)); } { // if the first operand is an infinity and the second operand is a finite number, then the - // result of the / operator is an infinity; - const a: T = -math.inf(T); - const b: T = 0.0; - const c: T = -4.0; - const d: T = 1.0; - - const result = f(a, b, c, d); - try expect(result.real == math.inf(T)); - try expect(result.imag == math.inf(T)); + // resultult of the / operator is an infinity; + const result = f(.{ .real = -math.inf(T), .imag = 0.0 }, .{ .real = -4.0, .imag = 1.0 }); + try expect(math.isPositiveInf(result.real)); + try expect(math.isPositiveInf(result.imag)); } { // if the first operand is a finite number and the second operand is an infinity, then the // result of the / operator is a zero; - const a: T = 17.2; - const b: T = 0.0; - const c: T = -math.inf(T); - const d: T = 0.0; - - const result = f(a, b, c, d); - try expect(result.real == -0.0); - try expect(result.imag == 0.0); + const result = f(.{ .real = 17.2, .imag = 0.0 }, .{ .real = -math.inf(T), .imag = 0.0 }); + try expect(math.isNegativeZero(result.real)); + try expect(math.isNegativeZero(result.imag)); } { // if the first operand is a nonzero finite number or an infinity and the second operand is // a zero, then the result of the / operator is an infinity - const a: T = 1.1; - const b: T = 0.1; - const c: T = 0.0; - const d: T = 0.0; - - const result = f(a, b, c, d); - try expect(result.real == math.inf(T)); - try expect(result.imag == math.inf(T)); + const result = f(.{ .real = 1.1, .imag = 0.1 }, .{ .real = 0.0, .imag = 0.0 }); + try expect(math.isPositiveInf(result.real)); + try expect(math.isPositiveInf(result.imag)); } } diff --git a/lib/compiler_rt/divdc3.zig b/lib/compiler_rt/divdc3.zig deleted file mode 100644 index e26dd26d61552832bcd1d19c022e8b0455551a40..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divdc3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const divc3 = @import("./divc3.zig"); -const Complex = @import("./mulc3.zig").Complex; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__divdc3, "__divdc3"); - } -} - -pub fn __divdc3(a: f64, b: f64, c: f64, d: f64) callconv(.c) Complex(f64) { - return divc3.divc3(f64, a, b, c, d); -} diff --git a/lib/compiler_rt/divdf3.zig b/lib/compiler_rt/divdf3.zig index 3ad767dbf2292d403aa0e2aafbdaf20f80ff9571..90953e0d0616d6a211872eef0b0c18ba1ff0cdb4 100644 --- a/lib/compiler_rt/divdf3.zig +++ b/lib/compiler_rt/divdf3.zig @@ -17,15 +17,15 @@ comptime { } } -pub fn __divdf3(a: f64, b: f64) callconv(.c) f64 { - return div(a, b); +fn __divdf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(div_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); } fn __aeabi_ddiv(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { - return div(a, b); + return div_f64(a, b); } -inline fn div(a: f64, b: f64) f64 { +pub fn div_f64(a: f64, b: f64) f64 { const Z = @Int(.unsigned, 64); const SignedZ = @Int(.signed, 64); diff --git a/lib/compiler_rt/divdf3_test.zig b/lib/compiler_rt/divdf3_test.zig index 45de9b27ef794706fc6e0e297f4289be3ae549fc..cd927bafc4d28921e9fb0bf191537b43cb953986 100644 --- a/lib/compiler_rt/divdf3_test.zig +++ b/lib/compiler_rt/divdf3_test.zig @@ -6,7 +6,7 @@ const std = @import("std"); const math = std.math; const testing = std.testing; -const __divdf3 = @import("divdf3.zig").__divdf3; +const div_f64 = @import("divdf3.zig").div_f64; const nanRep: u64 = @as(u64, @bitCast(math.nan(f64))); const infRep: u64 = @as(u64, @bitCast(math.inf(f64))); @@ -30,7 +30,7 @@ fn compareResultD(result: f64, expected: u64) bool { } fn test__divdf3(a: f64, b: f64, expected: u64) !void { - const x = __divdf3(a, b); + const x = div_f64(a, b); const ret = compareResultD(x, expected); try testing.expect(ret == true); } diff --git a/lib/compiler_rt/divhc3.zig b/lib/compiler_rt/divhc3.zig deleted file mode 100644 index c9668f4ca8ae84840ab3ee65446b682b6223832b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divhc3.zig +++ /dev/null @@ -1,14 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const divc3 = @import("./divc3.zig"); -const Complex = @import("./mulc3.zig").Complex; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__divhc3, "__divhc3"); - } -} - -pub fn __divhc3(a: f16, b: f16, c: f16, d: f16) callconv(.c) Complex(f16) { - return divc3.divc3(f16, a, b, c, d); -} diff --git a/lib/compiler_rt/divhf3.zig b/lib/compiler_rt/divhf3.zig deleted file mode 100644 index fc2710ff2761fce7e8822583b86aefc562f98486..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divhf3.zig +++ /dev/null @@ -1,11 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const divsf3 = @import("./divsf3.zig"); - -comptime { - symbol(&__divhf3, "__divhf3"); -} - -pub fn __divhf3(a: f16, b: f16) callconv(.c) f16 { - // TODO: more efficient implementation - return @floatCast(divsf3.__divsf3(a, b)); -} diff --git a/lib/compiler_rt/divmodei4.zig b/lib/compiler_rt/divmodei4.zig index 55c7ec5792549933d22e8962f58b8cb6e23a5d54..9198951fe554a89cd2f65c69ce3fea087952db0a 100644 --- a/lib/compiler_rt/divmodei4.zig +++ b/lib/compiler_rt/divmodei4.zig @@ -5,7 +5,7 @@ const std = @import("std"); const compiler_rt = @import("../compiler_rt.zig"); const udivmod = @import("udivmodei4.zig").divmod; -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { symbol(&__divei4, "__divei4"); diff --git a/lib/compiler_rt/divsc3.zig b/lib/compiler_rt/divsc3.zig deleted file mode 100644 index 9378bfab8ce80584b3b5b1b6d1fbd70200ef6648..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divsc3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const divc3 = @import("./divc3.zig"); -const Complex = @import("./mulc3.zig").Complex; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__divsc3, "__divsc3"); - } -} - -pub fn __divsc3(a: f32, b: f32, c: f32, d: f32) callconv(.c) Complex(f32) { - return divc3.divc3(f32, a, b, c, d); -} diff --git a/lib/compiler_rt/divsf3.zig b/lib/compiler_rt/divsf3.zig index c0fbcb92b743fff4e12db533d7694210e7ebb0a2..c86c860948d315b260498c959e4678f5f64b9e94 100644 --- a/lib/compiler_rt/divsf3.zig +++ b/lib/compiler_rt/divsf3.zig @@ -9,6 +9,7 @@ const symbol = compiler_rt.symbol; const normalize = compiler_rt.normalize; comptime { + symbol(&__divhf3, "__divhf3"); if (compiler_rt.want_aeabi) { symbol(&__aeabi_fdiv, "__aeabi_fdiv"); } else { @@ -16,15 +17,23 @@ comptime { } } -pub fn __divsf3(a: f32, b: f32) callconv(.c) f32 { - return div(a, b); +fn __divhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(div_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); +} +pub fn div_f16(a: f16, b: f16) f16 { + // TODO: more efficient implementation + return @floatCast(div_f32(a, b)); +} + +fn __divsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(div_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); } fn __aeabi_fdiv(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { - return div(a, b); + return div_f32(a, b); } -inline fn div(a: f32, b: f32) f32 { +pub fn div_f32(a: f32, b: f32) f32 { const Z = @Int(.unsigned, 32); const significandBits = std.math.floatMantissaBits(f32); diff --git a/lib/compiler_rt/divsf3_test.zig b/lib/compiler_rt/divsf3_test.zig index c457915e49cd41986f1470b2f868398cfad855e9..f12e152b31b41b1fd85d1f1493838dd68a43f983 100644 --- a/lib/compiler_rt/divsf3_test.zig +++ b/lib/compiler_rt/divsf3_test.zig @@ -6,7 +6,7 @@ const std = @import("std"); const math = std.math; const testing = std.testing; -const __divsf3 = @import("divsf3.zig").__divsf3; +const div_f32 = @import("divsf3.zig").div_f32; const nanRep: u32 = @as(u32, @bitCast(math.nan(f32))); const infRep: u32 = @as(u32, @bitCast(math.inf(f32))); @@ -30,7 +30,7 @@ fn compareResultF(result: f32, expected: u32) bool { } fn test__divsf3(a: f32, b: f32, expected: u32) !void { - const x = __divsf3(a, b); + const x = div_f32(a, b); const ret = compareResultF(x, expected); try testing.expect(ret == true); } diff --git a/lib/compiler_rt/divtc3.zig b/lib/compiler_rt/divtc3.zig deleted file mode 100644 index b0e0f35f5447488f4d15ba76ede68bab2425f96b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divtc3.zig +++ /dev/null @@ -1,16 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const divc3 = @import("./divc3.zig"); -const Complex = @import("./mulc3.zig").Complex; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - if (compiler_rt.want_ppc_abi) - symbol(&__divtc3, "__divkc3"); - symbol(&__divtc3, "__divtc3"); - } -} - -pub fn __divtc3(a: f128, b: f128, c: f128, d: f128) callconv(.c) Complex(f128) { - return divc3.divc3(f128, a, b, c, d); -} diff --git a/lib/compiler_rt/divtf3.zig b/lib/compiler_rt/divtf3.zig index 3b6f648e3ac33e2fb3183bdd7fcb892ea239500c..9995a9bfd796070d9573ac050bf233c9646a5d98 100644 --- a/lib/compiler_rt/divtf3.zig +++ b/lib/compiler_rt/divtf3.zig @@ -13,19 +13,20 @@ comptime { symbol(&_Qp_div, "_Qp_div"); } else if (compiler_rt.want_sparc32_abi) { symbol(&__divtf3, "_Q_div"); + } else { + symbol(&__divtf3, "__divtf3"); } - symbol(&__divtf3, "__divtf3"); } -pub fn __divtf3(a: f128, b: f128) callconv(.c) f128 { - return div(a, b); +fn __divtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(div_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); } fn _Qp_div(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { - c.* = div(a.*, b.*); + c.* = div_f128(a.*, b.*); } -inline fn div(a: f128, b: f128) f128 { +pub fn div_f128(a: f128, b: f128) f128 { const Z = @Int(.unsigned, 128); const significandBits = std.math.floatMantissaBits(f128); diff --git a/lib/compiler_rt/divtf3_test.zig b/lib/compiler_rt/divtf3_test.zig index 4d10e5c39d7dc61b1c317364750757148635543d..dfc7e1e954ea96eb6927f4c56179efc15fe4a2ee 100644 --- a/lib/compiler_rt/divtf3_test.zig +++ b/lib/compiler_rt/divtf3_test.zig @@ -2,7 +2,7 @@ const std = @import("std"); const math = std.math; const testing = std.testing; -const __divtf3 = @import("divtf3.zig").__divtf3; +const div_f128 = @import("divtf3.zig").div_f128; fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool { const rep: u128 = @bitCast(result); @@ -24,7 +24,7 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool { } fn test__divtf3(a: f128, b: f128, expectedHi: u64, expectedLo: u64) !void { - const x = __divtf3(a, b); + const x = div_f128(a, b); const ret = compareResultLD(x, expectedHi, expectedLo); try testing.expect(ret == true); } diff --git a/lib/compiler_rt/divxc3.zig b/lib/compiler_rt/divxc3.zig deleted file mode 100644 index 86c737a83931c6c34f73303eeaba00536d8e1bd4..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divxc3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const divc3 = @import("./divc3.zig"); -const Complex = @import("./mulc3.zig").Complex; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__divxc3, "__divxc3"); - } -} - -pub fn __divxc3(a: f80, b: f80, c: f80, d: f80) callconv(.c) Complex(f80) { - return divc3.divc3(f80, a, b, c, d); -} diff --git a/lib/compiler_rt/divxf3.zig b/lib/compiler_rt/divxf3.zig index fdf43dc83bce6adbb53995826c516aecd7310fe2..eb3fde6862ab3937e8828d729287a35ea9d3ead9 100644 --- a/lib/compiler_rt/divxf3.zig +++ b/lib/compiler_rt/divxf3.zig @@ -11,7 +11,10 @@ comptime { symbol(&__divxf3, "__divxf3"); } -pub fn __divxf3(a: f80, b: f80) callconv(.c) f80 { +fn __divxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(div_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} +pub fn div_f80(a: f80, b: f80) f80 { const T = f80; const Z = @Int(.unsigned, @bitSizeOf(T)); diff --git a/lib/compiler_rt/divxf3_test.zig b/lib/compiler_rt/divxf3_test.zig index cb897a1014022d50e8cb93043749b033b56af55d..88d7cada4606920997b5b0030134aaab476da576 100644 --- a/lib/compiler_rt/divxf3_test.zig +++ b/lib/compiler_rt/divxf3_test.zig @@ -2,7 +2,7 @@ const std = @import("std"); const math = std.math; const testing = std.testing; -const __divxf3 = @import("divxf3.zig").__divxf3; +const div_f80 = @import("divxf3.zig").div_f80; const nanRep: u80 = @as(u80, @bitCast(math.nan(f80))); const infRep: u80 = @as(u80, @bitCast(math.inf(f80))); @@ -19,14 +19,14 @@ fn compareResult(result: f80, expected: u80) bool { } fn expect__divxf3_result(a: f80, b: f80, expected: u80) !void { - const x = __divxf3(a, b); + const x = div_f80(a, b); const ret = compareResult(x, expected); try testing.expect(ret == true); } fn test__divxf3(a: f80, b: f80) !void { const integerBit = 1 << math.floatFractionalBits(f80); - const x = __divxf3(a, b); + const x = div_f80(a, b); // Next float (assuming normal, non-zero result) const x_plus_eps: f80 = @bitCast((@as(u80, @bitCast(x)) + 1) | integerBit); diff --git a/lib/compiler_rt/exp.zig b/lib/compiler_rt/exp.zig index ce2eadb7f1edfe49ca51562a8b3ec4432f2017eb..ddec21869f166538e3497bb84050e55eba3ff33c 100644 --- a/lib/compiler_rt/exp.zig +++ b/lib/compiler_rt/exp.zig @@ -14,7 +14,7 @@ const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { symbol(&__exph, "__exph"); @@ -28,12 +28,18 @@ comptime { symbol(&expl, "expl"); } -pub fn __exph(a: f16) callconv(.c) f16 { +fn __exph(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(exp_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn exp_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(expf(a)); + return @floatCast(exp_f32(x)); } -pub fn expf(x_: f32) callconv(.c) f32 { +fn expf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(exp_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn exp_f32(x_: f32) f32 { const half = [_]f32{ 0.5, -0.5 }; const ln2hi = 6.9314575195e-1; const ln2lo = 1.4286067653e-6; @@ -108,7 +114,10 @@ pub fn expf(x_: f32) callconv(.c) f32 { } } -pub fn exp(x_: f64) callconv(.c) f64 { +fn exp(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(exp_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn exp_f64(x_: f64) f64 { const half = [_]f64{ 0.5, -0.5 }; const ln2hi: f64 = 6.93147180369123816490e-01; const ln2lo: f64 = 1.90821492927058770002e-10; @@ -189,116 +198,121 @@ pub fn exp(x_: f64) callconv(.c) f64 { } } -pub fn __expx(a: f80) callconv(.c) f80 { +fn __expx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(exp_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn exp_f80(x: f80) f80 { // TODO: more efficient implementation - return @floatCast(expq(a)); + return @floatCast(exp_f128(x)); } -const expq = @import("exp_f128.zig").exp; +fn expq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(exp_f128(compiler_rt.f128.fromAbi(x))); +} +pub const exp_f128 = @import("exp_f128.zig").exp; pub fn expl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return exp(x), - 80 => return __expx(x), - 128 => return expq(x), - else => @compileError("unreachable"), + 64 => return exp_f64(x), + 80 => return exp_f80(x), + 128 => return exp_f128(x), + else => comptime unreachable, } } test "expf() special" { - try expectEqual(expf(0.0), 1.0); - try expectEqual(expf(-0.0), 1.0); - try expectEqual(expf(1.0), math.e); - try expectEqual(expf(math.ln2), 2.0); - try expectEqual(expf(math.inf(f32)), math.inf(f32)); - try expect(math.isPositiveZero(expf(-math.inf(f32)))); - try expect(math.isNan(expf(math.nan(f32)))); - try expect(math.isNan(expf(math.snan(f32)))); + try expectEqual(exp_f32(0.0), 1.0); + try expectEqual(exp_f32(-0.0), 1.0); + try expectEqual(exp_f32(1.0), math.e); + try expectEqual(exp_f32(math.ln2), 2.0); + try expectEqual(exp_f32(math.inf(f32)), math.inf(f32)); + try expect(math.isPositiveZero(exp_f32(-math.inf(f32)))); + try expect(math.isNan(exp_f32(math.nan(f32)))); + try expect(math.isNan(exp_f32(math.snan(f32)))); } test "expf() sanity" { - try expectEqual(expf(-0x1.0223a0p+3), 0x1.490320p-12); - try expectEqual(expf(0x1.161868p+2), 0x1.34712ap+6); - try expectEqual(expf(-0x1.0c34b4p+3), 0x1.e06b1ap-13); - try expectEqual(expf(-0x1.a206f0p+2), 0x1.7dd484p-10); - try expectEqual(expf(0x1.288bbcp+3), 0x1.4abc80p+13); - try expectEqual(expf(0x1.52efd0p-1), 0x1.f04a9cp+0); - try expectEqual(expf(-0x1.a05cc8p-2), 0x1.54f1e0p-1); - try expectEqual(expf(0x1.1f9efap-1), 0x1.c0f628p+0); - try expectEqual(expf(0x1.8c5db0p-1), 0x1.1599b2p+1); - try expectEqual(expf(-0x1.5b86eap-1), 0x1.03b572p-1); - try expectEqual(expf(-0x1.57f25cp+2), 0x1.2fbea2p-8); - try expectEqual(expf(0x1.c7d310p+3), 0x1.76eefp+20); - try expectEqual(expf(0x1.19be70p+4), 0x1.52d3dep+25); - try expectEqual(expf(-0x1.ab6d70p+3), 0x1.a88adep-20); - try expectEqual(expf(-0x1.5ac18ep+2), 0x1.22b328p-8); - try expectEqual(expf(-0x1.925982p-1), 0x1.d2acc0p-2); - try expectEqual(expf(0x1.7221cep+3), 0x1.9c2ceap+16); - try expectEqual(expf(0x1.11a0d4p+4), 0x1.980ee6p+24); - try expectEqual(expf(-0x1.ae41a2p+1), 0x1.1c28d0p-5); - try expectEqual(expf(-0x1.329154p+4), 0x1.47ef94p-28); + try expectEqual(exp_f32(-0x1.0223a0p+3), 0x1.490320p-12); + try expectEqual(exp_f32(0x1.161868p+2), 0x1.34712ap+6); + try expectEqual(exp_f32(-0x1.0c34b4p+3), 0x1.e06b1ap-13); + try expectEqual(exp_f32(-0x1.a206f0p+2), 0x1.7dd484p-10); + try expectEqual(exp_f32(0x1.288bbcp+3), 0x1.4abc80p+13); + try expectEqual(exp_f32(0x1.52efd0p-1), 0x1.f04a9cp+0); + try expectEqual(exp_f32(-0x1.a05cc8p-2), 0x1.54f1e0p-1); + try expectEqual(exp_f32(0x1.1f9efap-1), 0x1.c0f628p+0); + try expectEqual(exp_f32(0x1.8c5db0p-1), 0x1.1599b2p+1); + try expectEqual(exp_f32(-0x1.5b86eap-1), 0x1.03b572p-1); + try expectEqual(exp_f32(-0x1.57f25cp+2), 0x1.2fbea2p-8); + try expectEqual(exp_f32(0x1.c7d310p+3), 0x1.76eefp+20); + try expectEqual(exp_f32(0x1.19be70p+4), 0x1.52d3dep+25); + try expectEqual(exp_f32(-0x1.ab6d70p+3), 0x1.a88adep-20); + try expectEqual(exp_f32(-0x1.5ac18ep+2), 0x1.22b328p-8); + try expectEqual(exp_f32(-0x1.925982p-1), 0x1.d2acc0p-2); + try expectEqual(exp_f32(0x1.7221cep+3), 0x1.9c2ceap+16); + try expectEqual(exp_f32(0x1.11a0d4p+4), 0x1.980ee6p+24); + try expectEqual(exp_f32(-0x1.ae41a2p+1), 0x1.1c28d0p-5); + try expectEqual(exp_f32(-0x1.329154p+4), 0x1.47ef94p-28); } test "expf() boundary" { - try expectEqual(expf(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite - try expectEqual(expf(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf - try expectEqual(expf(0x1.fffffep+127), math.inf(f32)); // Max input value - try expectEqual(expf(0x1p-149), 1.0); // Min positive input value - try expectEqual(expf(-0x1p-149), 1.0); // Min negative input value - try expectEqual(expf(0x1p-126), 1.0); // First positive subnormal input - try expectEqual(expf(-0x1p-126), 1.0); // First negative subnormal input - try expectEqual(expf(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero - try expectEqual(expf(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero - try expectEqual(expf(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal - try expectEqual(expf(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal - + try expectEqual(exp_f32(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite + try expectEqual(exp_f32(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf + try expectEqual(exp_f32(0x1.fffffep+127), math.inf(f32)); // Max input value + try expectEqual(exp_f32(0x1p-149), 1.0); // Min positive input value + try expectEqual(exp_f32(-0x1p-149), 1.0); // Min negative input value + try expectEqual(exp_f32(0x1p-126), 1.0); // First positive subnormal input + try expectEqual(exp_f32(-0x1p-126), 1.0); // First negative subnormal input + try expectEqual(exp_f32(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero + try expectEqual(exp_f32(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero + try expectEqual(exp_f32(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal + try expectEqual(exp_f32(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal } test "exp() special" { - try expectEqual(exp(0.0), 1.0); - try expectEqual(exp(-0.0), 1.0); + try expectEqual(exp_f64(0.0), 1.0); + try expectEqual(exp_f64(-0.0), 1.0); // TODO: Accuracy error - off in the last bit in 64-bit, disagreeing with GCC // try expectEqual(exp(1.0), math.e); - try expectEqual(exp(math.ln2), 2.0); - try expectEqual(exp(math.inf(f64)), math.inf(f64)); - try expect(math.isPositiveZero(exp(-math.inf(f64)))); - try expect(math.isNan(exp(math.nan(f64)))); - try expect(math.isNan(exp(math.snan(f64)))); + try expectEqual(exp_f64(math.ln2), 2.0); + try expectEqual(exp_f64(math.inf(f64)), math.inf(f64)); + try expect(math.isPositiveZero(exp_f64(-math.inf(f64)))); + try expect(math.isNan(exp_f64(math.nan(f64)))); + try expect(math.isNan(exp_f64(math.snan(f64)))); } test "exp() sanity" { - try expectEqual(exp(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12); - try expectEqual(exp(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6); - try expectEqual(exp(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13); - try expectEqual(exp(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10); - try expectEqual(exp(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13); - try expectEqual(exp(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0); - try expectEqual(exp(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1); - try expectEqual(exp(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0); - try expectEqual(exp(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1); - try expectEqual(exp(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1); - try expectEqual(exp(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8); - try expectEqual(exp(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20); - try expectEqual(exp(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25); - try expectEqual(exp(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20); - try expectEqual(exp(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8); - try expectEqual(exp(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2); - try expectEqual(exp(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16); - try expectEqual(exp(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24); - try expectEqual(exp(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5); - try expectEqual(exp(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28); + try expectEqual(exp_f64(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12); + try expectEqual(exp_f64(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6); + try expectEqual(exp_f64(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13); + try expectEqual(exp_f64(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10); + try expectEqual(exp_f64(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13); + try expectEqual(exp_f64(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0); + try expectEqual(exp_f64(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1); + try expectEqual(exp_f64(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0); + try expectEqual(exp_f64(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1); + try expectEqual(exp_f64(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1); + try expectEqual(exp_f64(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8); + try expectEqual(exp_f64(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20); + try expectEqual(exp_f64(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25); + try expectEqual(exp_f64(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20); + try expectEqual(exp_f64(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8); + try expectEqual(exp_f64(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2); + try expectEqual(exp_f64(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16); + try expectEqual(exp_f64(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24); + try expectEqual(exp_f64(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5); + try expectEqual(exp_f64(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28); } test "exp() boundary" { - try expectEqual(exp(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite - try expectEqual(exp(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf - try expectEqual(exp(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value - try expectEqual(exp(0x1p-1074), 1.0); // Min positive input value - try expectEqual(exp(-0x1p-1074), 1.0); // Min negative input value - try expectEqual(exp(0x1p-1022), 1.0); // First positive subnormal input - try expectEqual(exp(-0x1p-1022), 1.0); // First negative subnormal input - try expectEqual(exp(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero - try expectEqual(exp(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero - try expectEqual(exp(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal - try expectEqual(exp(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal + try expectEqual(exp_f64(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite + try expectEqual(exp_f64(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf + try expectEqual(exp_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value + try expectEqual(exp_f64(0x1p-1074), 1.0); // Min positive input value + try expectEqual(exp_f64(-0x1p-1074), 1.0); // Min negative input value + try expectEqual(exp_f64(0x1p-1022), 1.0); // First positive subnormal input + try expectEqual(exp_f64(-0x1p-1022), 1.0); // First negative subnormal input + try expectEqual(exp_f64(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero + try expectEqual(exp_f64(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero + try expectEqual(exp_f64(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal + try expectEqual(exp_f64(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal } diff --git a/lib/compiler_rt/exp2.zig b/lib/compiler_rt/exp2.zig index abcef881073619a860997766283c950cc702a3e6..36ee7c14c90be2c13dd0e09ca91d656a19a539a7 100644 --- a/lib/compiler_rt/exp2.zig +++ b/lib/compiler_rt/exp2.zig @@ -26,12 +26,18 @@ comptime { symbol(&exp2l, "exp2l"); } -pub fn __exp2h(x: f16) callconv(.c) f16 { +fn __exp2h(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(exp2_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn exp2_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(exp2f(x)); + return @floatCast(exp2_f32(x)); } -pub fn exp2f(x: f32) callconv(.c) f32 { +fn exp2f(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(exp2_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn exp2_f32(x: f32) f32 { const tblsiz: u32 = @intCast(exp2ft.len); const redux: f32 = 0x1.8p23 / @as(f32, @floatFromInt(tblsiz)); const P1: f32 = 0x1.62e430p-1; @@ -88,7 +94,10 @@ pub fn exp2f(x: f32) callconv(.c) f32 { return @floatCast(r * uk); } -pub fn exp2(x: f64) callconv(.c) f64 { +fn exp2(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(exp2_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn exp2_f64(x: f64) f64 { const tblsiz: u32 = @intCast(exp2dt.len / 2); const redux: f64 = 0x1.8p52 / @as(f64, @floatFromInt(tblsiz)); const P1: f64 = 0x1.62e42fefa39efp-1; @@ -156,19 +165,25 @@ pub fn exp2(x: f64) callconv(.c) f64 { return math.scalbn(r, ik); } -pub fn __exp2x(x: f80) callconv(.c) f80 { +fn __exp2x(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(exp2_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn exp2_f80(x: f80) f80 { // TODO: more efficient implementation - return @floatCast(exp2q(x)); + return @floatCast(exp2_f128(x)); } -pub const exp2q = @import("exp_f128.zig").exp2; +fn exp2q(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(exp2_f128(compiler_rt.f128.fromAbi(x))); +} +pub const exp2_f128 = @import("exp_f128.zig").exp2; pub fn exp2l(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return exp2(x), - 80 => return __exp2x(x), - 128 => return exp2q(x), - else => @compileError("unreachable"), + 64 => return exp2_f64(x), + 80 => return exp2_f80(x), + 128 => return exp2_f128(x), + else => comptime unreachable, } } @@ -452,77 +467,77 @@ const exp2dt = [_]f64{ }; test "exp2f() special" { - try expectEqual(exp2f(0.0), 1.0); - try expectEqual(exp2f(-0.0), 1.0); - try expectEqual(exp2f(1.0), 2.0); - try expectEqual(exp2f(-1.0), 0.5); - try expectEqual(exp2f(math.inf(f32)), math.inf(f32)); - try expect(math.isPositiveZero(exp2f(-math.inf(f32)))); - try expect(math.isNan(exp2f(math.nan(f32)))); - try expect(math.isNan(exp2f(math.snan(f32)))); + try expectEqual(exp2_f32(0.0), 1.0); + try expectEqual(exp2_f32(-0.0), 1.0); + try expectEqual(exp2_f32(1.0), 2.0); + try expectEqual(exp2_f32(-1.0), 0.5); + try expectEqual(exp2_f32(math.inf(f32)), math.inf(f32)); + try expect(math.isPositiveZero(exp2_f32(-math.inf(f32)))); + try expect(math.isNan(exp2_f32(math.nan(f32)))); + try expect(math.isNan(exp2_f32(math.snan(f32)))); } test "exp2f() sanity" { - try expectEqual(exp2f(-0x1.0223a0p+3), 0x1.e8d134p-9); - try expectEqual(exp2f(0x1.161868p+2), 0x1.453672p+4); - try expectEqual(exp2f(-0x1.0c34b4p+3), 0x1.890ca0p-9); - try expectEqual(exp2f(-0x1.a206f0p+2), 0x1.622d4ep-7); - try expectEqual(exp2f(0x1.288bbcp+3), 0x1.340ecep+9); - try expectEqual(exp2f(0x1.52efd0p-1), 0x1.950eeep+0); - try expectEqual(exp2f(-0x1.a05cc8p-2), 0x1.824056p-1); - try expectEqual(exp2f(0x1.1f9efap-1), 0x1.79dfa2p+0); - try expectEqual(exp2f(0x1.8c5db0p-1), 0x1.b5ceacp+0); - try expectEqual(exp2f(-0x1.5b86eap-1), 0x1.3fd8bap-1); + try expectEqual(exp2_f32(-0x1.0223a0p+3), 0x1.e8d134p-9); + try expectEqual(exp2_f32(0x1.161868p+2), 0x1.453672p+4); + try expectEqual(exp2_f32(-0x1.0c34b4p+3), 0x1.890ca0p-9); + try expectEqual(exp2_f32(-0x1.a206f0p+2), 0x1.622d4ep-7); + try expectEqual(exp2_f32(0x1.288bbcp+3), 0x1.340ecep+9); + try expectEqual(exp2_f32(0x1.52efd0p-1), 0x1.950eeep+0); + try expectEqual(exp2_f32(-0x1.a05cc8p-2), 0x1.824056p-1); + try expectEqual(exp2_f32(0x1.1f9efap-1), 0x1.79dfa2p+0); + try expectEqual(exp2_f32(0x1.8c5db0p-1), 0x1.b5ceacp+0); + try expectEqual(exp2_f32(-0x1.5b86eap-1), 0x1.3fd8bap-1); } test "exp2f() boundary" { - try expectEqual(exp2f(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite - try expectEqual(exp2f(0x1p+7), math.inf(f32)); // The first value that gives infinite result - try expectEqual(exp2f(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero - try expectEqual(exp2f(-0x1.2cp+7), 0); // The first value at which the result flushes to zero - try expectEqual(exp2f(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal - try expectEqual(exp2f(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal - try expectEqual(exp2f(0x1.fffffep+127), math.inf(f32)); // Max input value - try expectEqual(exp2f(0x1p-149), 1); // Min positive input value - try expectEqual(exp2f(-0x1p-149), 1); // Min negative input value - try expectEqual(exp2f(0x1p-126), 1); // First positive subnormal input - try expectEqual(exp2f(-0x1p-126), 1); // First negative subnormal input + try expectEqual(exp2_f32(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite + try expectEqual(exp2_f32(0x1p+7), math.inf(f32)); // The first value that gives infinite result + try expectEqual(exp2_f32(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero + try expectEqual(exp2_f32(-0x1.2cp+7), 0); // The first value at which the result flushes to zero + try expectEqual(exp2_f32(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal + try expectEqual(exp2_f32(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal + try expectEqual(exp2_f32(0x1.fffffep+127), math.inf(f32)); // Max input value + try expectEqual(exp2_f32(0x1p-149), 1); // Min positive input value + try expectEqual(exp2_f32(-0x1p-149), 1); // Min negative input value + try expectEqual(exp2_f32(0x1p-126), 1); // First positive subnormal input + try expectEqual(exp2_f32(-0x1p-126), 1); // First negative subnormal input } test "exp2() special" { - try expectEqual(exp2(0.0), 1.0); - try expectEqual(exp2(-0.0), 1.0); - try expectEqual(exp2(1.0), 2.0); - try expectEqual(exp2(-1.0), 0.5); - try expectEqual(exp2(math.inf(f64)), math.inf(f64)); - try expect(math.isPositiveZero(exp2(-math.inf(f64)))); - try expect(math.isNan(exp2(math.nan(f64)))); - try expect(math.isNan(exp2(math.snan(f64)))); + try expectEqual(exp2_f64(0.0), 1.0); + try expectEqual(exp2_f64(-0.0), 1.0); + try expectEqual(exp2_f64(1.0), 2.0); + try expectEqual(exp2_f64(-1.0), 0.5); + try expectEqual(exp2_f64(math.inf(f64)), math.inf(f64)); + try expect(math.isPositiveZero(exp2_f64(-math.inf(f64)))); + try expect(math.isNan(exp2_f64(math.nan(f64)))); + try expect(math.isNan(exp2_f64(math.snan(f64)))); } test "exp2() sanity" { - try expectEqual(exp2(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9); - try expectEqual(exp2(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4); - try expectEqual(exp2(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9); - try expectEqual(exp2(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7); - try expectEqual(exp2(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9); - try expectEqual(exp2(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0); - try expectEqual(exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1); - try expectEqual(exp2(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0); - try expectEqual(exp2(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0); - try expectEqual(exp2(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1); + try expectEqual(exp2_f64(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9); + try expectEqual(exp2_f64(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4); + try expectEqual(exp2_f64(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9); + try expectEqual(exp2_f64(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7); + try expectEqual(exp2_f64(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9); + try expectEqual(exp2_f64(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0); + try expectEqual(exp2_f64(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1); + try expectEqual(exp2_f64(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0); + try expectEqual(exp2_f64(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0); + try expectEqual(exp2_f64(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1); } test "exp2() boundary" { - try expectEqual(exp2(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite - try expectEqual(exp2(0x1p+10), math.inf(f64)); // The first value that gives infinite result - try expectEqual(exp2(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero - try expectEqual(exp2(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero - try expectEqual(exp2(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal - try expectEqual(exp2(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal - try expectEqual(exp2(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value - try expectEqual(exp2(0x1p-1074), 1); // Min positive input value - try expectEqual(exp2(-0x1p-1074), 1); // Min negative input value - try expectEqual(exp2(0x1p-1022), 1); // First positive subnormal input - try expectEqual(exp2(-0x1p-1022), 1); // First negative subnormal input + try expectEqual(exp2_f64(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite + try expectEqual(exp2_f64(0x1p+10), math.inf(f64)); // The first value that gives infinite result + try expectEqual(exp2_f64(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero + try expectEqual(exp2_f64(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero + try expectEqual(exp2_f64(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal + try expectEqual(exp2_f64(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal + try expectEqual(exp2_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value + try expectEqual(exp2_f64(0x1p-1074), 1); // Min positive input value + try expectEqual(exp2_f64(-0x1p-1074), 1); // Min negative input value + try expectEqual(exp2_f64(0x1p-1022), 1); // First positive subnormal input + try expectEqual(exp2_f64(-0x1p-1022), 1); // First negative subnormal input } diff --git a/lib/compiler_rt/exp_f128.zig b/lib/compiler_rt/exp_f128.zig index ac09308ff30ee94c46403e4e7cd9f6afd0bea60c..c7a042c2b11edb228cd597eebdefcadbd3b689bd 100644 --- a/lib/compiler_rt/exp_f128.zig +++ b/lib/compiler_rt/exp_f128.zig @@ -26,7 +26,7 @@ const exp_f128 = @This(); const std = @import("std"); const math = std.math; -pub fn exp(x: f128) callconv(.c) f128 { +pub fn exp(x: f128) f128 { if (!math.isFinite(x)) { if (math.isNan(x)) { if (math.isSignalNan(x)) math.raiseInvalid(); @@ -91,7 +91,7 @@ fn expPoly(r_hi: f128, r_lo: f128) f128 { } /// Computes 2^x -pub fn exp2(x: f128) callconv(.c) f128 { +pub fn exp2(x: f128) f128 { if (!math.isFinite(x)) { if (math.isNan(x)) { if (math.isSignalNan(x)) math.raiseInvalid(); diff --git a/lib/compiler_rt/extenddftf2.zig b/lib/compiler_rt/extenddftf2.zig deleted file mode 100644 index d6267d7d8a93acd5a56d528d803f789a013dced5..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extenddftf2.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const extendf = @import("./extendf.zig").extendf; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__extenddftf2, "__extenddfkf2"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_dtoq, "_Qp_dtoq"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__extenddftf2, "_Q_dtoq"); - } - symbol(&__extenddftf2, "__extenddftf2"); -} - -pub fn __extenddftf2(a: f64) callconv(.c) f128 { - return extendf(f128, f64, @as(u64, @bitCast(a))); -} - -fn _Qp_dtoq(c: *f128, a: f64) callconv(.c) void { - c.* = extendf(f128, f64, @as(u64, @bitCast(a))); -} diff --git a/lib/compiler_rt/extenddfxf2.zig b/lib/compiler_rt/extenddfxf2.zig deleted file mode 100644 index d18195aea357d8fdd8fc26a0d34db798bc06f187..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extenddfxf2.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const extend_f80 = @import("./extendf.zig").extend_f80; - -comptime { - symbol(&__extenddfxf2, "__extenddfxf2"); -} - -pub fn __extenddfxf2(a: f64) callconv(.c) f80 { - return extend_f80(f64, @as(u64, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendf.zig b/lib/compiler_rt/extendf.zig index b923e9d25b7fe41a733b0aeb10db9d51b24176df..a0c637b352680a3b1bf1728c662bce3bdb6db91c 100644 --- a/lib/compiler_rt/extendf.zig +++ b/lib/compiler_rt/extendf.zig @@ -1,10 +1,175 @@ const std = @import("std"); -pub inline fn extendf( - comptime dst_t: type, - comptime src_t: type, - a: @Int(.unsigned, @typeInfo(src_t).float.bits), -) dst_t { +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; + +comptime { + if (compiler_rt.want_aeabi) { + if (compiler_rt.gnu_f16_abi) { + symbol(&__aeabi_h2f, "__gnu_h2f_ieee"); + } else { + symbol(&__aeabi_h2f, "__aeabi_h2f"); + } + } else if (compiler_rt.gnu_f16_abi) { + symbol(&__extendhfsf2, "__gnu_h2f_ieee"); + } + symbol(&__extendhfsf2, "__extendhfsf2"); + symbol(&__extendhfdf2, "__extendhfdf2"); + symbol(&__extendhfxf2, "__extendhfxf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__extendhftf2, "__extendhfkf2"); + } else { + symbol(&__extendhftf2, "__extendhftf2"); + } + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_f2d, "__aeabi_f2d"); + } else { + symbol(&__extendsfdf2, "__extendsfdf2"); + } + symbol(&__extendsfxf2, "__extendsfxf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__extendsftf2, "__extendsfkf2"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_stoq, "_Qp_stoq"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__extendsftf2, "_Q_stoq"); + } else { + symbol(&__extendsftf2, "__extendsftf2"); + } + + symbol(&__extenddfxf2, "__extenddfxf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__extenddftf2, "__extenddfkf2"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_dtoq, "_Qp_dtoq"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__extenddftf2, "_Q_dtoq"); + } else { + symbol(&__extenddftf2, "__extenddftf2"); + } + + if (compiler_rt.want_ppc_abi) { + symbol(&__extendxftf2, "__extendxfkf2"); + } else { + symbol(&__extendxftf2, "__extendxftf2"); + } +} + +fn __extendhfsf2(a: compiler_rt.f16Conv(f32).Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatCast_f16(compiler_rt.f16Conv(f32).fromAbi(a))); +} +fn __aeabi_h2f(a: u16) callconv(.{ .arm_aapcs = .{} }) u32 { + return @bitCast(f32_floatCast_f16(@bitCast(a))); +} +pub fn f32_floatCast_f16(a: f16) f32 { + return extendf(f32, f16, a); +} + +fn __extendhfdf2(a: compiler_rt.f16Conv(f64).Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatCast_f16(compiler_rt.f16Conv(f64).fromAbi(a))); +} +pub fn f64_floatCast_f16(a: f16) f64 { + return extendf(f64, f16, a); +} + +fn __extendhfxf2(a: compiler_rt.f16Conv(f80).Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatCast_f16(compiler_rt.f16Conv(f80).fromAbi(a))); +} +pub fn f80_floatCast_f16(a: f16) f80 { + return extend_f80(f16, a); +} + +fn __extendhftf2(a: compiler_rt.f16Conv(f128).Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatCast_f16(compiler_rt.f16Conv(f128).fromAbi(a))); +} +pub fn f128_floatCast_f16(a: f16) f128 { + return extendf(f128, f16, a); +} + +fn __extendsfdf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatCast_f32(compiler_rt.f32.fromAbi(a))); +} +fn __aeabi_f2d(a: f32) callconv(.{ .arm_aapcs = .{} }) f64 { + return f64_floatCast_f32(a); +} +pub fn f64_floatCast_f32(a: f32) f64 { + return extendf(f64, f32, a); +} + +fn __extendsfxf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatCast_f32(compiler_rt.f32.fromAbi(a))); +} +pub fn f80_floatCast_f32(a: f32) f80 { + return extend_f80(f32, a); +} + +pub fn __extendsftf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatCast_f32(compiler_rt.f32.fromAbi(a))); +} +fn _Qp_stoq(c: *f128, a: f32) callconv(.c) void { + c.* = f128_floatCast_f32(a); +} +pub fn f128_floatCast_f32(a: f32) f128 { + return extendf(f128, f32, a); +} + +fn __extenddfxf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatCast_f64(compiler_rt.f64.fromAbi(a))); +} +pub fn f80_floatCast_f64(a: f64) f80 { + return extend_f80(f64, a); +} + +fn __extenddftf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatCast_f64(compiler_rt.f64.fromAbi(a))); +} +fn _Qp_dtoq(c: *f128, a: f64) callconv(.c) void { + c.* = f128_floatCast_f64(a); +} +pub fn f128_floatCast_f64(a: f64) f128 { + return extendf(f128, f64, a); +} + +fn __extendxftf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatCast_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn f128_floatCast_f80(a: f80) f128 { + const src_int_bit: u64 = 0x8000000000000000; + const src_sig_mask = ~src_int_bit; + const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit + const dst_sig_bits = std.math.floatMantissaBits(f128); + + const dst_bits = @bitSizeOf(f128); + + // Break a into a sign and representation of the absolute value + var a_rep: std.math.F80 = .fromFloat(a); + const sign = a_rep.exp & 0x8000; + a_rep.exp &= 0x7FFF; + var abs_result: u128 = undefined; + + if (a_rep.exp == 0 and a_rep.fraction == 0) { + // zero + abs_result = 0; + } else if (a_rep.exp == 0x7FFF) { + // a is nan or infinite + abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits); + abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; + } else if (a_rep.fraction & src_int_bit != 0) { + // a is a normal value + abs_result = @as(u128, a_rep.fraction & src_sig_mask) << (dst_sig_bits - src_sig_bits); + abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; + } else { + // a is denormal + abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits); + } + + // Apply the signbit to (dst_t)abs(a). + const result: u128 = abs_result | @as(u128, sign) << (dst_bits - 16); + return @bitCast(result); +} + +inline fn extendf(comptime dst_t: type, comptime src_t: type, f: src_t) dst_t { const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits); const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits); const srcSigBits = std.math.floatMantissaBits(src_t); @@ -31,6 +196,7 @@ pub inline fn extendf( const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits; + const a: src_rep_t = @bitCast(f); // Break a into a sign and representation of the absolute value const aRep: src_rep_t = @bitCast(a); const aAbs: src_rep_t = aRep & srcAbsMask; @@ -66,11 +232,11 @@ pub inline fn extendf( } // Apply the signbit to (dst_t)abs(a). - const result: dst_rep_t align(@alignOf(dst_t)) = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits); + const result: dst_rep_t = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits); return @bitCast(result); } -pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_t).float.bits)) f80 { +inline fn extend_f80(comptime src_t: type, f: src_t) f80 { const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits); const src_sig_bits = std.math.floatMantissaBits(src_t); const dst_int_bit = 0x8000000000000000; @@ -92,6 +258,7 @@ pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_ var dst: std.math.F80 = undefined; + const a: src_rep_t = @bitCast(f); // Break a into a sign and representation of the absolute value const a_abs = a & src_abs_mask; const sign: u16 = if (a & src_sign_mask != 0) 0x8000 else 0; diff --git a/lib/compiler_rt/extendf_test.zig b/lib/compiler_rt/extendf_test.zig index f572495b6634f8096fa5dd41dd9d2fd1b362a0a1..4cba105a6dc88b24230e9624d250b05da947edf2 100644 --- a/lib/compiler_rt/extendf_test.zig +++ b/lib/compiler_rt/extendf_test.zig @@ -1,31 +1,37 @@ const builtin = @import("builtin"); - const std = @import("std"); -const math = std.math; +const testing = std.testing; -const __extendhfsf2 = @import("extendhfsf2.zig").__extendhfsf2; -const __extendhftf2 = @import("extendhftf2.zig").__extendhftf2; -const __extendsftf2 = @import("extendsftf2.zig").__extendsftf2; -const __extenddftf2 = @import("extenddftf2.zig").__extenddftf2; -const __extenddfxf2 = @import("extenddfxf2.zig").__extenddfxf2; -const F16T = @import("../compiler_rt.zig").F16T; +const impl = @import("extendf.zig"); -fn test__extenddfxf2(a: f64, expected: u80) !void { - const x = __extenddfxf2(a); +const f32_floatCast_f16 = impl.f32_floatCast_f16; +const f64_floatCast_f16 = impl.f64_floatCast_f16; +const f80_floatCast_f16 = impl.f80_floatCast_f16; +const f128_floatCast_f16 = impl.f128_floatCast_f16; + +const f64_floatCast_f32 = impl.f64_floatCast_f32; +const f80_floatCast_f32 = impl.f80_floatCast_f32; +const f128_floatCast_f32 = impl.f128_floatCast_f32; + +const f80_floatCast_f64 = impl.f80_floatCast_f64; +const f128_floatCast_f64 = impl.f128_floatCast_f64; + +const f128_floatCast_f80 = impl.f128_floatCast_f80; + +fn test_f80_floatCast_f64(a: f64, expected: u80) !void { + const x = f80_floatCast_f64(a); const rep: u80 = @bitCast(x); if (rep == expected) return; - // test other possible NaN representation(signal NaN) - if (math.isNan(@as(f80, @bitCast(expected))) and math.isNan(x)) + if (std.math.isNan(@as(f80, @bitCast(expected))) and std.math.isNan(x)) return; - - @panic("__extenddfxf2 test failure"); + return error.TestFailure; } -fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void { - const x = __extenddftf2(a); +fn test_f128_floatCast_f64(a: f64, expected_hi: u64, expected_lo: u64) !void { + const x = f128_floatCast_f64(a); const rep: u128 = @bitCast(x); const hi: u64 = @intCast(rep >> 64); @@ -33,7 +39,6 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void { if (hi == expected_hi and lo == expected_lo) return; - // test other possible NaN representation(signal NaN) if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and @@ -42,12 +47,11 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void { return; } } - - @panic("__extenddftf2 test failure"); + return error.TestFailure; } -fn test__extendhfsf2(a: u16, expected: u32) !void { - const x = __extendhfsf2(@as(F16T(f32), @bitCast(a))); +fn test_f32_floatCast_f16(a: u16, expected: u32) !void { + const x = f32_floatCast_f16(@bitCast(a)); const rep: u32 = @bitCast(x); if (rep == expected) { @@ -58,12 +62,11 @@ fn test__extendhfsf2(a: u16, expected: u32) !void { return; } } - return error.TestFailure; } -fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void { - const x = __extendsftf2(a); +fn test_f128_floatCast_f32(a: f32, expected_hi: u64, expected_lo: u64) !void { + const x = f128_floatCast_f32(a); const rep: u128 = @bitCast(x); const hi: u64 = @intCast(rep >> 64); @@ -71,7 +74,6 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void { if (hi == expected_hi and lo == expected_lo) return; - // test other possible NaN representation(signal NaN) if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and @@ -80,111 +82,108 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void { return; } } - return error.TestFailure; } -test "extenddfxf2" { +test f80_floatCast_f64 { // qNaN - try test__extenddfxf2(makeQNaN64(), 0x7fffc000000000000000); + try test_f80_floatCast_f64(makeQNaN64(), 0x7fffc000000000000000); // NaN - try test__extenddfxf2(makeNaN64(0x7100000000000), 0x7fffe080000000000000); + try test_f80_floatCast_f64(makeNaN64(0x7100000000000), 0x7fffe080000000000000); // This is bad? // inf - try test__extenddfxf2(makeInf64(), 0x7fff8000000000000000); + try test_f80_floatCast_f64(makeInf64(), 0x7fff8000000000000000); // zero - try test__extenddfxf2(0.0, 0x0); + try test_f80_floatCast_f64(0.0, 0x0); - try test__extenddfxf2(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000); + try test_f80_floatCast_f64(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000); - try test__extenddfxf2(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000); + try test_f80_floatCast_f64(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000); - try test__extenddfxf2(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000); + try test_f80_floatCast_f64(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000); - try test__extenddfxf2(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000); + try test_f80_floatCast_f64(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000); // subnormal - try test__extenddfxf2(0x1.8000000000001p-1022, 0x3c01c000000000000800); - try test__extenddfxf2(0x1.8000000000002p-1023, 0x3c00c000000000001000); + try test_f80_floatCast_f64(0x1.8000000000001p-1022, 0x3c01c000000000000800); + try test_f80_floatCast_f64(0x1.8000000000002p-1023, 0x3c00c000000000001000); } -test "extenddftf2" { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - +test f128_floatCast_f64 { // qNaN - try test__extenddftf2(makeQNaN64(), 0x7fff800000000000, 0x0); + try test_f128_floatCast_f64(makeQNaN64(), 0x7fff800000000000, 0x0); // NaN - try test__extenddftf2(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0); + try test_f128_floatCast_f64(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0); // inf - try test__extenddftf2(makeInf64(), 0x7fff000000000000, 0x0); + try test_f128_floatCast_f64(makeInf64(), 0x7fff000000000000, 0x0); // zero - try test__extenddftf2(0.0, 0x0, 0x0); + try test_f128_floatCast_f64(0.0, 0x0, 0x0); - try test__extenddftf2(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000); + try test_f128_floatCast_f64(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000); - try test__extenddftf2(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000); + try test_f128_floatCast_f64(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000); - try test__extenddftf2(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000); + try test_f128_floatCast_f64(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000); - try test__extenddftf2(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000); + try test_f128_floatCast_f64(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000); // subnormal - try test__extenddftf2(0x1.8p-1022, 0x3c01800000000000, 0x0); - try test__extenddftf2(0x1.8p-1023, 0x3c00800000000000, 0x0); + try test_f128_floatCast_f64(0x1.8p-1022, 0x3c01800000000000, 0x0); + try test_f128_floatCast_f64(0x1.8p-1023, 0x3c00800000000000, 0x0); } -test "extendhfsf2" { - try test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN - try test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN +test f32_floatCast_f16 { + try test_f32_floatCast_f16(0x7e00, 0x7fc00000); // qNaN + try test_f32_floatCast_f16(0x7f00, 0x7fe00000); // sNaN // On x86 the NaN becomes quiet because the return is pushed on the x87 // stack due to ABI requirements if (builtin.target.cpu.arch != .x86 and builtin.target.os.tag == .windows) - try test__extendhfsf2(0x7c01, 0x7f802000); // sNaN + try test_f32_floatCast_f16(0x7c01, 0x7f802000); // sNaN - try test__extendhfsf2(0, 0); // 0 - try test__extendhfsf2(0x8000, 0x80000000); // -0 + try test_f32_floatCast_f16(0, 0); // 0 + try test_f32_floatCast_f16(0x8000, 0x80000000); // -0 - try test__extendhfsf2(0x7c00, 0x7f800000); // inf - try test__extendhfsf2(0xfc00, 0xff800000); // -inf + try test_f32_floatCast_f16(0x7c00, 0x7f800000); // inf + try test_f32_floatCast_f16(0xfc00, 0xff800000); // -inf - try test__extendhfsf2(0x0001, 0x33800000); // denormal (min), 2**-24 - try test__extendhfsf2(0x8001, 0xb3800000); // denormal (min), -2**-24 + try test_f32_floatCast_f16(0x0001, 0x33800000); // denormal (min), 2**-24 + try test_f32_floatCast_f16(0x8001, 0xb3800000); // denormal (min), -2**-24 - try test__extendhfsf2(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24 - try test__extendhfsf2(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24 + try test_f32_floatCast_f16(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24 + try test_f32_floatCast_f16(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24 - try test__extendhfsf2(0x0400, 0x38800000); // normal (min), 2**-14 - try test__extendhfsf2(0x8400, 0xb8800000); // normal (min), -2**-14 + try test_f32_floatCast_f16(0x0400, 0x38800000); // normal (min), 2**-14 + try test_f32_floatCast_f16(0x8400, 0xb8800000); // normal (min), -2**-14 - try test__extendhfsf2(0x7bff, 0x477fe000); // normal (max), 65504 - try test__extendhfsf2(0xfbff, 0xc77fe000); // normal (max), -65504 + try test_f32_floatCast_f16(0x7bff, 0x477fe000); // normal (max), 65504 + try test_f32_floatCast_f16(0xfbff, 0xc77fe000); // normal (max), -65504 - try test__extendhfsf2(0x3c01, 0x3f802000); // normal, 1 + 2**-10 - try test__extendhfsf2(0xbc01, 0xbf802000); // normal, -1 - 2**-10 + try test_f32_floatCast_f16(0x3c01, 0x3f802000); // normal, 1 + 2**-10 + try test_f32_floatCast_f16(0xbc01, 0xbf802000); // normal, -1 - 2**-10 - try test__extendhfsf2(0x3555, 0x3eaaa000); // normal, approx. 1/3 - try test__extendhfsf2(0xb555, 0xbeaaa000); // normal, approx. -1/3 + try test_f32_floatCast_f16(0x3555, 0x3eaaa000); // normal, approx. 1/3 + try test_f32_floatCast_f16(0xb555, 0xbeaaa000); // normal, approx. -1/3 } -test "extendsftf2" { +test f128_floatCast_f32 { // qNaN - try test__extendsftf2(makeQNaN32(), 0x7fff800000000000, 0x0); + try test_f128_floatCast_f32(makeQNaN32(), 0x7fff800000000000, 0x0); // NaN - try test__extendsftf2(makeNaN32(0x410000), 0x7fff820000000000, 0x0); + try test_f128_floatCast_f32(makeNaN32(0x410000), 0x7fff820000000000, 0x0); // inf - try test__extendsftf2(makeInf32(), 0x7fff000000000000, 0x0); + try test_f128_floatCast_f32(makeInf32(), 0x7fff000000000000, 0x0); // zero - try test__extendsftf2(0.0, 0x0, 0x0); - try test__extendsftf2(0x1.23456p+5, 0x4004234560000000, 0x0); - try test__extendsftf2(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0); - try test__extendsftf2(0x1.23456p+45, 0x402c234560000000, 0x0); - try test__extendsftf2(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0); + try test_f128_floatCast_f32(0.0, 0x0, 0x0); + try test_f128_floatCast_f32(0x1.23456p+5, 0x4004234560000000, 0x0); + try test_f128_floatCast_f32(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0); + try test_f128_floatCast_f32(0x1.23456p+45, 0x402c234560000000, 0x0); + try test_f128_floatCast_f32(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0); } fn makeQNaN64() f64 { @@ -211,8 +210,8 @@ fn makeInf32() f32 { return @bitCast(@as(u32, 0x7f800000)); } -fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void { - const x = __extendhftf2(@as(F16T(f128), @bitCast(a))); +fn test_f128_floatCast_f16(a: u16, expected_hi: u64, expected_lo: u64) !void { + const x = f128_floatCast_f16(@bitCast(a)); const rep: u128 = @bitCast(x); const hi: u64 = @intCast(rep >> 64); @@ -233,26 +232,26 @@ fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void { return error.TestFailure; } -test "extendhftf2" { +test f128_floatCast_f16 { // qNaN - try test__extendhftf2(0x7e00, 0x7fff800000000000, 0x0); + try test_f128_floatCast_f16(0x7e00, 0x7fff800000000000, 0x0); // NaN - try test__extendhftf2(0x7d00, 0x7fff400000000000, 0x0); + try test_f128_floatCast_f16(0x7d00, 0x7fff400000000000, 0x0); // inf - try test__extendhftf2(0x7c00, 0x7fff000000000000, 0x0); - try test__extendhftf2(0xfc00, 0xffff000000000000, 0x0); + try test_f128_floatCast_f16(0x7c00, 0x7fff000000000000, 0x0); + try test_f128_floatCast_f16(0xfc00, 0xffff000000000000, 0x0); // zero - try test__extendhftf2(0x0000, 0x0000000000000000, 0x0); - try test__extendhftf2(0x8000, 0x8000000000000000, 0x0); + try test_f128_floatCast_f16(0x0000, 0x0000000000000000, 0x0); + try test_f128_floatCast_f16(0x8000, 0x8000000000000000, 0x0); // denormal - try test__extendhftf2(0x0010, 0x3feb000000000000, 0x0); - try test__extendhftf2(0x0001, 0x3fe7000000000000, 0x0); - try test__extendhftf2(0x8001, 0xbfe7000000000000, 0x0); + try test_f128_floatCast_f16(0x0010, 0x3feb000000000000, 0x0); + try test_f128_floatCast_f16(0x0001, 0x3fe7000000000000, 0x0); + try test_f128_floatCast_f16(0x8001, 0xbfe7000000000000, 0x0); // pi - try test__extendhftf2(0x4248, 0x4000920000000000, 0x0); - try test__extendhftf2(0xc248, 0xc000920000000000, 0x0); + try test_f128_floatCast_f16(0x4248, 0x4000920000000000, 0x0); + try test_f128_floatCast_f16(0xc248, 0xc000920000000000, 0x0); - try test__extendhftf2(0x508c, 0x4004230000000000, 0x0); - try test__extendhftf2(0x1bb7, 0x3ff6edc000000000, 0x0); + try test_f128_floatCast_f16(0x508c, 0x4004230000000000, 0x0); + try test_f128_floatCast_f16(0x1bb7, 0x3ff6edc000000000, 0x0); } diff --git a/lib/compiler_rt/extendhfdf2.zig b/lib/compiler_rt/extendhfdf2.zig deleted file mode 100644 index 8cadc7139eebbad29f39b5245a14971c5c187a0d..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendhfdf2.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const extendf = @import("./extendf.zig").extendf; - -comptime { - symbol(&__extendhfdf2, "__extendhfdf2"); -} - -pub fn __extendhfdf2(a: compiler_rt.F16T(f64)) callconv(.c) f64 { - return extendf(f64, f16, @as(u16, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendhfsf2.zig b/lib/compiler_rt/extendhfsf2.zig deleted file mode 100644 index b638192c47502e6e698e86fcce8be3fbc0f7d2f9..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendhfsf2.zig +++ /dev/null @@ -1,24 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const extendf = @import("./extendf.zig").extendf; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.gnu_f16_abi) { - symbol(&__gnu_h2f_ieee, "__gnu_h2f_ieee"); - } else if (compiler_rt.want_aeabi) { - symbol(&__aeabi_h2f, "__aeabi_h2f"); - } - symbol(&__extendhfsf2, "__extendhfsf2"); -} - -pub fn __extendhfsf2(a: compiler_rt.F16T(f32)) callconv(.c) f32 { - return extendf(f32, f16, @as(u16, @bitCast(a))); -} - -fn __gnu_h2f_ieee(a: compiler_rt.F16T(f32)) callconv(.c) f32 { - return extendf(f32, f16, @as(u16, @bitCast(a))); -} - -fn __aeabi_h2f(a: u16) callconv(.{ .arm_aapcs = .{} }) f32 { - return extendf(f32, f16, @as(u16, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendhftf2.zig b/lib/compiler_rt/extendhftf2.zig deleted file mode 100644 index 29e7866b663389aae7048a474e585916fec7cac1..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendhftf2.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const extendf = @import("./extendf.zig").extendf; - -comptime { - symbol(&__extendhftf2, "__extendhftf2"); -} - -pub fn __extendhftf2(a: compiler_rt.F16T(f128)) callconv(.c) f128 { - return extendf(f128, f16, @as(u16, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendhfxf2.zig b/lib/compiler_rt/extendhfxf2.zig deleted file mode 100644 index e76daf4f55045262daa10cb4547688ed012a6bc0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendhfxf2.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const extend_f80 = @import("./extendf.zig").extend_f80; - -comptime { - symbol(&__extendhfxf2, "__extendhfxf2"); -} - -fn __extendhfxf2(a: compiler_rt.F16T(f80)) callconv(.c) f80 { - return extend_f80(f16, @as(u16, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendsfdf2.zig b/lib/compiler_rt/extendsfdf2.zig deleted file mode 100644 index 4f34b05242a5f57155c9bb83c3e978c6ec3ace42..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendsfdf2.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const extendf = @import("./extendf.zig").extendf; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2d, "__aeabi_f2d"); - } else { - symbol(&__extendsfdf2, "__extendsfdf2"); - } -} - -fn __extendsfdf2(a: f32) callconv(.c) f64 { - return extendf(f64, f32, @as(u32, @bitCast(a))); -} - -fn __aeabi_f2d(a: f32) callconv(.{ .arm_aapcs = .{} }) f64 { - return extendf(f64, f32, @as(u32, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendsftf2.zig b/lib/compiler_rt/extendsftf2.zig deleted file mode 100644 index 6135065b14297e34c04e7cefec5b9387321089a7..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendsftf2.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const extendf = @import("./extendf.zig").extendf; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__extendsftf2, "__extendsfkf2"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_stoq, "_Qp_stoq"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__extendsftf2, "_Q_stoq"); - } - symbol(&__extendsftf2, "__extendsftf2"); -} - -pub fn __extendsftf2(a: f32) callconv(.c) f128 { - return extendf(f128, f32, @as(u32, @bitCast(a))); -} - -fn _Qp_stoq(c: *f128, a: f32) callconv(.c) void { - c.* = extendf(f128, f32, @as(u32, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendsfxf2.zig b/lib/compiler_rt/extendsfxf2.zig deleted file mode 100644 index 9a6796bd668602b1d653a6581613fcb69edb7853..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendsfxf2.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const extend_f80 = @import("./extendf.zig").extend_f80; - -comptime { - symbol(&__extendsfxf2, "__extendsfxf2"); -} - -fn __extendsfxf2(a: f32) callconv(.c) f80 { - return extend_f80(f32, @as(u32, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendxftf2.zig b/lib/compiler_rt/extendxftf2.zig deleted file mode 100644 index 1c39e1e84c7a3beb0a9470a123c05dea456eed77..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendxftf2.zig +++ /dev/null @@ -1,42 +0,0 @@ -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__extendxftf2, "__extendxftf2"); -} - -fn __extendxftf2(a: f80) callconv(.c) f128 { - const src_int_bit: u64 = 0x8000000000000000; - const src_sig_mask = ~src_int_bit; - const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit - const dst_sig_bits = std.math.floatMantissaBits(f128); - - const dst_bits = @bitSizeOf(f128); - - // Break a into a sign and representation of the absolute value - var a_rep = std.math.F80.fromFloat(a); - const sign = a_rep.exp & 0x8000; - a_rep.exp &= 0x7FFF; - var abs_result: u128 = undefined; - - if (a_rep.exp == 0 and a_rep.fraction == 0) { - // zero - abs_result = 0; - } else if (a_rep.exp == 0x7FFF) { - // a is nan or infinite - abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits); - abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; - } else if (a_rep.fraction & src_int_bit != 0) { - // a is a normal value - abs_result = @as(u128, a_rep.fraction & src_sig_mask) << (dst_sig_bits - src_sig_bits); - abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; - } else { - // a is denormal - abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits); - } - - // Apply the signbit to (dst_t)abs(a). - const result: u128 align(@alignOf(f128)) = abs_result | @as(u128, sign) << (dst_bits - 16); - return @bitCast(result); -} diff --git a/lib/compiler_rt/fabs.zig b/lib/compiler_rt/fabs.zig index abdf21df8f33de1c080aba1452ae233287283540..50d2cc17d590a11615bdc471e6926af6c1f7bc6c 100644 --- a/lib/compiler_rt/fabs.zig +++ b/lib/compiler_rt/fabs.zig @@ -16,32 +16,47 @@ comptime { symbol(&fabsl, "fabsl"); } -pub fn __fabsh(a: f16) callconv(.c) f16 { +fn __fabsh(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fabs_f16(compiler_rt.f16.fromAbi(a))); +} +pub fn fabs_f16(a: f16) f16 { return generic_fabs(a); } -pub fn fabsf(a: f32) callconv(.c) f32 { +fn fabsf(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fabs_f32(compiler_rt.f32.fromAbi(a))); +} +pub fn fabs_f32(a: f32) f32 { return generic_fabs(a); } -pub fn fabs(a: f64) callconv(.c) f64 { +fn fabs(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fabs_f64(compiler_rt.f64.fromAbi(a))); +} +pub fn fabs_f64(a: f64) f64 { return generic_fabs(a); } -pub fn __fabsx(a: f80) callconv(.c) f80 { +fn __fabsx(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fabs_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn fabs_f80(a: f80) f80 { return generic_fabs(a); } -pub fn fabsq(a: f128) callconv(.c) f128 { +fn fabsq(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fabs_f128(compiler_rt.f128.fromAbi(a))); +} +pub fn fabs_f128(a: f128) f128 { return generic_fabs(a); } pub fn fabsl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return fabs(x), - 80 => return __fabsx(x), - 128 => return fabsq(x), - else => @compileError("unreachable"), + 64 => return fabs_f64(x), + 80 => return fabs_f80(x), + 128 => return fabs_f128(x), + else => comptime unreachable, } } diff --git a/lib/compiler_rt/fixdfdi.zig b/lib/compiler_rt/fixdfdi.zig deleted file mode 100644 index 5a66cc124f0f4ec092f1c49715ae6c547a396b66..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixdfdi.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2lz, "__aeabi_d2lz"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__fixdfdi, "__dtoi64"); - } - symbol(&__fixdfdi, "__fixdfdi"); - } -} - -pub fn __fixdfdi(a: f64) callconv(.c) i64 { - return intFromFloat(i64, a); -} - -fn __aeabi_d2lz(a: f64) callconv(.{ .arm_aapcs = .{} }) i64 { - return intFromFloat(i64, a); -} diff --git a/lib/compiler_rt/fixdfei.zig b/lib/compiler_rt/fixdfei.zig deleted file mode 100644 index 170b4a160337fe5fc426fe2e715ab46426d76d7e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixdfei.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixdfei, "__fixdfei"); -} - -pub fn __fixdfei(r: [*]u8, bits: usize, a: f64) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixdfsi.zig b/lib/compiler_rt/fixdfsi.zig deleted file mode 100644 index 1d42337ea54573e4c7423147323046b029f9af52..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixdfsi.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2iz, "__aeabi_d2iz"); - } else { - symbol(&__fixdfsi, "__fixdfsi"); - } -} - -pub fn __fixdfsi(a: f64) callconv(.c) i32 { - return intFromFloat(i32, a); -} - -fn __aeabi_d2iz(a: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return intFromFloat(i32, a); -} diff --git a/lib/compiler_rt/fixdfti.zig b/lib/compiler_rt/fixdfti.zig deleted file mode 100644 index ff7434d63da148afc20b22bbfb54d6c1bdd17822..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixdfti.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__fixdfti, "__fixdfti"); -} - -pub fn __fixdfti(a: f64) callconv(.c) i128 { - return intFromFloat(i128, a); -} diff --git a/lib/compiler_rt/fixhfei.zig b/lib/compiler_rt/fixhfei.zig deleted file mode 100644 index 5b759c3fc683d909ce7808242a59129c310bbb56..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixhfei.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixhfei, "__fixhfei"); -} - -pub fn __fixhfei(r: [*]u8, bits: usize, a: f16) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixint_test.zig b/lib/compiler_rt/fixint_test.zig deleted file mode 100644 index 198167ab867c22ed6160e83ed90920a6c5e97f28..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixint_test.zig +++ /dev/null @@ -1,149 +0,0 @@ -const std = @import("std"); -const math = std.math; -const testing = std.testing; - -const fixint = @import("fixint.zig").fixint; - -fn test__fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t, expected: fixint_t) !void { - const x = fixint(fp_t, fixint_t, a); - try testing.expect(x == expected); -} - -test "fixint.i1" { - try test__fixint(f32, i1, -math.inf(f32), -1); - try test__fixint(f32, i1, -math.floatMax(f32), -1); - try test__fixint(f32, i1, -2.0, -1); - try test__fixint(f32, i1, -1.1, -1); - try test__fixint(f32, i1, -1.0, -1); - try test__fixint(f32, i1, -0.9, 0); - try test__fixint(f32, i1, -0.1, 0); - try test__fixint(f32, i1, -math.floatMin(f32), 0); - try test__fixint(f32, i1, -0.0, 0); - try test__fixint(f32, i1, 0.0, 0); - try test__fixint(f32, i1, math.floatMin(f32), 0); - try test__fixint(f32, i1, 0.1, 0); - try test__fixint(f32, i1, 0.9, 0); - try test__fixint(f32, i1, 1.0, 0); - try test__fixint(f32, i1, 2.0, 0); - try test__fixint(f32, i1, math.floatMax(f32), 0); - try test__fixint(f32, i1, math.inf(f32), 0); -} - -test "fixint.i2" { - try test__fixint(f32, i2, -math.inf(f32), -2); - try test__fixint(f32, i2, -math.floatMax(f32), -2); - try test__fixint(f32, i2, -2.0, -2); - try test__fixint(f32, i2, -1.9, -1); - try test__fixint(f32, i2, -1.1, -1); - try test__fixint(f32, i2, -1.0, -1); - try test__fixint(f32, i2, -0.9, 0); - try test__fixint(f32, i2, -0.1, 0); - try test__fixint(f32, i2, -math.floatMin(f32), 0); - try test__fixint(f32, i2, -0.0, 0); - try test__fixint(f32, i2, 0.0, 0); - try test__fixint(f32, i2, math.floatMin(f32), 0); - try test__fixint(f32, i2, 0.1, 0); - try test__fixint(f32, i2, 0.9, 0); - try test__fixint(f32, i2, 1.0, 1); - try test__fixint(f32, i2, 2.0, 1); - try test__fixint(f32, i2, math.floatMax(f32), 1); - try test__fixint(f32, i2, math.inf(f32), 1); -} - -test "fixint.i3" { - try test__fixint(f32, i3, -math.inf(f32), -4); - try test__fixint(f32, i3, -math.floatMax(f32), -4); - try test__fixint(f32, i3, -4.0, -4); - try test__fixint(f32, i3, -3.0, -3); - try test__fixint(f32, i3, -2.0, -2); - try test__fixint(f32, i3, -1.9, -1); - try test__fixint(f32, i3, -1.1, -1); - try test__fixint(f32, i3, -1.0, -1); - try test__fixint(f32, i3, -0.9, 0); - try test__fixint(f32, i3, -0.1, 0); - try test__fixint(f32, i3, -math.floatMin(f32), 0); - try test__fixint(f32, i3, -0.0, 0); - try test__fixint(f32, i3, 0.0, 0); - try test__fixint(f32, i3, math.floatMin(f32), 0); - try test__fixint(f32, i3, 0.1, 0); - try test__fixint(f32, i3, 0.9, 0); - try test__fixint(f32, i3, 1.0, 1); - try test__fixint(f32, i3, 2.0, 2); - try test__fixint(f32, i3, 3.0, 3); - try test__fixint(f32, i3, 4.0, 3); - try test__fixint(f32, i3, math.floatMax(f32), 3); - try test__fixint(f32, i3, math.inf(f32), 3); -} - -test "fixint.i32" { - try test__fixint(f64, i32, -math.inf(f64), math.minInt(i32)); - try test__fixint(f64, i32, -math.floatMax(f64), math.minInt(i32)); - try test__fixint(f64, i32, @as(f64, math.minInt(i32)), math.minInt(i32)); - try test__fixint(f64, i32, @as(f64, math.minInt(i32)) + 1, math.minInt(i32) + 1); - try test__fixint(f64, i32, -2.0, -2); - try test__fixint(f64, i32, -1.9, -1); - try test__fixint(f64, i32, -1.1, -1); - try test__fixint(f64, i32, -1.0, -1); - try test__fixint(f64, i32, -0.9, 0); - try test__fixint(f64, i32, -0.1, 0); - try test__fixint(f64, i32, -@as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i32, -0.0, 0); - try test__fixint(f64, i32, 0.0, 0); - try test__fixint(f64, i32, @as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i32, 0.1, 0); - try test__fixint(f64, i32, 0.9, 0); - try test__fixint(f64, i32, 1.0, 1); - try test__fixint(f64, i32, @as(f64, math.maxInt(i32)) - 1, math.maxInt(i32) - 1); - try test__fixint(f64, i32, @as(f64, math.maxInt(i32)), math.maxInt(i32)); - try test__fixint(f64, i32, math.floatMax(f64), math.maxInt(i32)); - try test__fixint(f64, i32, math.inf(f64), math.maxInt(i32)); -} - -test "fixint.i64" { - try test__fixint(f64, i64, -math.inf(f64), math.minInt(i64)); - try test__fixint(f64, i64, -math.floatMax(f64), math.minInt(i64)); - try test__fixint(f64, i64, @as(f64, math.minInt(i64)), math.minInt(i64)); - try test__fixint(f64, i64, @as(f64, math.minInt(i64)) + 1, math.minInt(i64)); - try test__fixint(f64, i64, @as(f64, math.minInt(i64) / 2), math.minInt(i64) / 2); - try test__fixint(f64, i64, -2.0, -2); - try test__fixint(f64, i64, -1.9, -1); - try test__fixint(f64, i64, -1.1, -1); - try test__fixint(f64, i64, -1.0, -1); - try test__fixint(f64, i64, -0.9, 0); - try test__fixint(f64, i64, -0.1, 0); - try test__fixint(f64, i64, -@as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i64, -0.0, 0); - try test__fixint(f64, i64, 0.0, 0); - try test__fixint(f64, i64, @as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i64, 0.1, 0); - try test__fixint(f64, i64, 0.9, 0); - try test__fixint(f64, i64, 1.0, 1); - try test__fixint(f64, i64, @as(f64, math.maxInt(i64)) - 1, math.maxInt(i64)); - try test__fixint(f64, i64, @as(f64, math.maxInt(i64)), math.maxInt(i64)); - try test__fixint(f64, i64, math.floatMax(f64), math.maxInt(i64)); - try test__fixint(f64, i64, math.inf(f64), math.maxInt(i64)); -} - -test "fixint.i128" { - try test__fixint(f64, i128, -math.inf(f64), math.minInt(i128)); - try test__fixint(f64, i128, -math.floatMax(f64), math.minInt(i128)); - try test__fixint(f64, i128, @as(f64, math.minInt(i128)), math.minInt(i128)); - try test__fixint(f64, i128, @as(f64, math.minInt(i128)) + 1, math.minInt(i128)); - try test__fixint(f64, i128, -2.0, -2); - try test__fixint(f64, i128, -1.9, -1); - try test__fixint(f64, i128, -1.1, -1); - try test__fixint(f64, i128, -1.0, -1); - try test__fixint(f64, i128, -0.9, 0); - try test__fixint(f64, i128, -0.1, 0); - try test__fixint(f64, i128, -@as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i128, -0.0, 0); - try test__fixint(f64, i128, 0.0, 0); - try test__fixint(f64, i128, @as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i128, 0.1, 0); - try test__fixint(f64, i128, 0.9, 0); - try test__fixint(f64, i128, 1.0, 1); - try test__fixint(f64, i128, @as(f64, math.maxInt(i128)) - 1, math.maxInt(i128)); - try test__fixint(f64, i128, @as(f64, math.maxInt(i128)), math.maxInt(i128)); - try test__fixint(f64, i128, math.floatMax(f64), math.maxInt(i128)); - try test__fixint(f64, i128, math.inf(f64), math.maxInt(i128)); -} diff --git a/lib/compiler_rt/fixsfdi.zig b/lib/compiler_rt/fixsfdi.zig deleted file mode 100644 index 0a3731877e8bf7c7591391c8d76a6a5f953e74f1..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixsfdi.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2lz, "__aeabi_f2lz"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__fixsfdi, "__stoi64"); - } - symbol(&__fixsfdi, "__fixsfdi"); - } -} - -pub fn __fixsfdi(a: f32) callconv(.c) i64 { - return intFromFloat(i64, a); -} - -fn __aeabi_f2lz(a: f32) callconv(.{ .arm_aapcs = .{} }) i64 { - return intFromFloat(i64, a); -} diff --git a/lib/compiler_rt/fixsfei.zig b/lib/compiler_rt/fixsfei.zig deleted file mode 100644 index 43243254059d78d0ba678bcf1ae9ab37b50c3f47..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixsfei.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixsfei, "__fixsfei"); -} - -pub fn __fixsfei(r: [*]u8, bits: usize, a: f32) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixsfsi.zig b/lib/compiler_rt/fixsfsi.zig deleted file mode 100644 index 9c07c5824a25aac5f83ae2e2f58ce4df66f53b38..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixsfsi.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2iz, "__aeabi_f2iz"); - } else { - symbol(&__fixsfsi, "__fixsfsi"); - } -} - -pub fn __fixsfsi(a: f32) callconv(.c) i32 { - return intFromFloat(i32, a); -} - -fn __aeabi_f2iz(a: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return intFromFloat(i32, a); -} diff --git a/lib/compiler_rt/fixsfti.zig b/lib/compiler_rt/fixsfti.zig deleted file mode 100644 index 121eff084d58a00726ed140a0d4f4cacafdce87b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixsfti.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixsfti, "__fixsfti"); -} - -pub fn __fixsfti(a: f32) callconv(.c) i128 { - return intFromFloat(i128, a); -} diff --git a/lib/compiler_rt/fixtfdi.zig b/lib/compiler_rt/fixtfdi.zig deleted file mode 100644 index d64682db1c1153d982acba2636b39f2b17e63753..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixtfdi.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__fixtfdi, "__fixkfdi"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtox, "_Qp_qtox"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__fixtfdi, "_Q_qtoll"); - } - symbol(&__fixtfdi, "__fixtfdi"); -} - -pub fn __fixtfdi(a: f128) callconv(.c) i64 { - return intFromFloat(i64, a); -} - -fn _Qp_qtox(a: *const f128) callconv(.c) i64 { - return intFromFloat(i64, a.*); -} diff --git a/lib/compiler_rt/fixtfei.zig b/lib/compiler_rt/fixtfei.zig deleted file mode 100644 index 6443a0cb3be226c25affb17567fa8c860868aaa1..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixtfei.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixtfei, "__fixtfei"); -} - -pub fn __fixtfei(r: [*]u8, bits: usize, a: f128) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixtfsi.zig b/lib/compiler_rt/fixtfsi.zig deleted file mode 100644 index 9acc5ec8eac8cb72a826c50d6d034e1ea48ef603..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixtfsi.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__fixtfsi, "__fixkfsi"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtoi, "_Qp_qtoi"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__fixtfsi, "_Q_qtoi"); - } - symbol(&__fixtfsi, "__fixtfsi"); -} - -pub fn __fixtfsi(a: f128) callconv(.c) i32 { - return intFromFloat(i32, a); -} - -fn _Qp_qtoi(a: *const f128) callconv(.c) i32 { - return intFromFloat(i32, a.*); -} diff --git a/lib/compiler_rt/fixtfti.zig b/lib/compiler_rt/fixtfti.zig deleted file mode 100644 index 0aac298ca2c4d0fa3f8d7fd02cf1290f98929c2b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixtfti.zig +++ /dev/null @@ -1,13 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) - symbol(&__fixtfti, "__fixkfti"); - symbol(&__fixtfti, "__fixtfti"); -} - -pub fn __fixtfti(a: f128) callconv(.c) i128 { - return intFromFloat(i128, a); -} diff --git a/lib/compiler_rt/fixunsdfdi.zig b/lib/compiler_rt/fixunsdfdi.zig deleted file mode 100644 index 340bb8f6b11276fd9fff401b7f6a655e63d0a218..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsdfdi.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2ulz, "__aeabi_d2ulz"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__fixunsdfdi, "__dtou64"); - } - symbol(&__fixunsdfdi, "__fixunsdfdi"); - } -} - -pub fn __fixunsdfdi(a: f64) callconv(.c) u64 { - return intFromFloat(u64, a); -} - -fn __aeabi_d2ulz(a: f64) callconv(.{ .arm_aapcs = .{} }) u64 { - return intFromFloat(u64, a); -} diff --git a/lib/compiler_rt/fixunsdfei.zig b/lib/compiler_rt/fixunsdfei.zig deleted file mode 100644 index f564f7f7a32869e7cdad92a2f264941a3eab7511..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsdfei.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixunsdfei, "__fixunsdfei"); -} - -pub fn __fixunsdfei(r: [*]u8, bits: usize, a: f64) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixunsdfsi.zig b/lib/compiler_rt/fixunsdfsi.zig deleted file mode 100644 index e8b976d03d690d0de88d07e3fe4b97c0490e5901..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsdfsi.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2uiz, "__aeabi_d2uiz"); - } else { - symbol(&__fixunsdfsi, "__fixunsdfsi"); - } -} - -pub fn __fixunsdfsi(a: f64) callconv(.c) u32 { - return intFromFloat(u32, a); -} - -fn __aeabi_d2uiz(a: f64) callconv(.{ .arm_aapcs = .{} }) u32 { - return intFromFloat(u32, a); -} diff --git a/lib/compiler_rt/fixunsdfti.zig b/lib/compiler_rt/fixunsdfti.zig deleted file mode 100644 index 1a634baaf5a6da399abaebb3e236ea5c02005ead..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsdfti.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixunsdfti, "__fixunsdfti"); -} - -pub fn __fixunsdfti(a: f64) callconv(.c) u128 { - return intFromFloat(u128, a); -} diff --git a/lib/compiler_rt/fixunshfdi.zig b/lib/compiler_rt/fixunshfdi.zig deleted file mode 100644 index 741e482506d2df3ffbb1388a9848f9317f6f1808..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunshfdi.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixunshfdi, "__fixunshfdi"); -} - -fn __fixunshfdi(a: f16) callconv(.c) u64 { - return intFromFloat(u64, a); -} diff --git a/lib/compiler_rt/fixunshfei.zig b/lib/compiler_rt/fixunshfei.zig deleted file mode 100644 index a61d94f3958f4cc8f5f01f57f317e5a44f32fc20..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunshfei.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixunshfei, "__fixunshfei"); -} - -pub fn __fixunshfei(r: [*]u8, bits: usize, a: f16) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixunshfsi.zig b/lib/compiler_rt/fixunshfsi.zig deleted file mode 100644 index 438767c7a89a57c22385a1b666a6f59875d1f7ba..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunshfsi.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixunshfsi, "__fixunshfsi"); -} - -fn __fixunshfsi(a: f16) callconv(.c) u32 { - return intFromFloat(u32, a); -} diff --git a/lib/compiler_rt/fixunshfti.zig b/lib/compiler_rt/fixunshfti.zig deleted file mode 100644 index 3dc7a5f99390d05606bb09298651e1d4482e3ab6..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunshfti.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__fixunshfti, "__fixunshfti"); -} - -pub fn __fixunshfti(a: f16) callconv(.c) u128 { - return intFromFloat(u128, a); -} diff --git a/lib/compiler_rt/fixunssfdi.zig b/lib/compiler_rt/fixunssfdi.zig deleted file mode 100644 index ffc238a53fb9f12a64446371a3d3191331d6994c..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunssfdi.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2ulz, "__aeabi_f2ulz"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__fixunssfdi, "__stou64"); - } - symbol(&__fixunssfdi, "__fixunssfdi"); - } -} - -pub fn __fixunssfdi(a: f32) callconv(.c) u64 { - return intFromFloat(u64, a); -} - -fn __aeabi_f2ulz(a: f32) callconv(.{ .arm_aapcs = .{} }) u64 { - return intFromFloat(u64, a); -} diff --git a/lib/compiler_rt/fixunssfei.zig b/lib/compiler_rt/fixunssfei.zig deleted file mode 100644 index 2fd123bd1b4693f96b51604a794dc2879660dc87..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunssfei.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixunssfei, "__fixunssfei"); -} - -pub fn __fixunssfei(r: [*]u8, bits: usize, a: f32) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixunssfsi.zig b/lib/compiler_rt/fixunssfsi.zig deleted file mode 100644 index f9c09b3f3d881774c21117e3c32b3a0b0b0a9f82..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunssfsi.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2uiz, "__aeabi_f2uiz"); - } else { - symbol(&__fixunssfsi, "__fixunssfsi"); - } -} - -pub fn __fixunssfsi(a: f32) callconv(.c) u32 { - return intFromFloat(u32, a); -} - -fn __aeabi_f2uiz(a: f32) callconv(.{ .arm_aapcs = .{} }) u32 { - return intFromFloat(u32, a); -} diff --git a/lib/compiler_rt/fixunssfti.zig b/lib/compiler_rt/fixunssfti.zig deleted file mode 100644 index 6824afcde4b518642189696a47c0983047dd47c3..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunssfti.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__fixunssfti, "__fixunssfti"); -} - -pub fn __fixunssfti(a: f32) callconv(.c) u128 { - return intFromFloat(u128, a); -} diff --git a/lib/compiler_rt/fixunstfdi.zig b/lib/compiler_rt/fixunstfdi.zig deleted file mode 100644 index c535bcc3583c93721f4fc07146f66edcc7611b01..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunstfdi.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__fixunstfdi, "__fixunskfdi"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtoux, "_Qp_qtoux"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__fixunstfdi, "_Q_qtoull"); - } - symbol(&__fixunstfdi, "__fixunstfdi"); -} - -pub fn __fixunstfdi(a: f128) callconv(.c) u64 { - return intFromFloat(u64, a); -} - -fn _Qp_qtoux(a: *const f128) callconv(.c) u64 { - return intFromFloat(u64, a.*); -} diff --git a/lib/compiler_rt/fixunstfei.zig b/lib/compiler_rt/fixunstfei.zig deleted file mode 100644 index 3d8986da90790a1a9cbf9a5fa2939e94c8009cc2..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunstfei.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixunstfei, "__fixunstfei"); -} - -pub fn __fixunstfei(r: [*]u8, bits: usize, a: f128) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixunstfsi.zig b/lib/compiler_rt/fixunstfsi.zig deleted file mode 100644 index d31cd759744d7616b30050335f70c50921a76ca9..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunstfsi.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__fixunstfsi, "__fixunskfsi"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtoui, "_Qp_qtoui"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__fixunstfsi, "_Q_qtou"); - } - symbol(&__fixunstfsi, "__fixunstfsi"); -} - -pub fn __fixunstfsi(a: f128) callconv(.c) u32 { - return intFromFloat(u32, a); -} - -fn _Qp_qtoui(a: *const f128) callconv(.c) u32 { - return intFromFloat(u32, a.*); -} diff --git a/lib/compiler_rt/fixunstfti.zig b/lib/compiler_rt/fixunstfti.zig deleted file mode 100644 index 78c6b1e8f7b90aa5d90a957920e949bb0aa2cbc0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunstfti.zig +++ /dev/null @@ -1,14 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_ppc_abi) - symbol(&__fixunstfti, "__fixunskfti"); - symbol(&__fixunstfti, "__fixunstfti"); -} - -pub fn __fixunstfti(a: f128) callconv(.c) u128 { - return intFromFloat(u128, a); -} diff --git a/lib/compiler_rt/fixunsxfdi.zig b/lib/compiler_rt/fixunsxfdi.zig deleted file mode 100644 index 8385961b6b2ea2cd7632776ffa46d41e9e6f8bf3..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsxfdi.zig +++ /dev/null @@ -1,10 +0,0 @@ -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__fixunsxfdi, "__fixunsxfdi"); -} - -fn __fixunsxfdi(a: f80) callconv(.c) u64 { - return intFromFloat(u64, a); -} diff --git a/lib/compiler_rt/fixunsxfei.zig b/lib/compiler_rt/fixunsxfei.zig deleted file mode 100644 index d7902ddff54773d5240a57c8aaf6910ab6f9f02e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsxfei.zig +++ /dev/null @@ -1,13 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const symbol = @import("../compiler_rt.zig").symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixunsxfei, "__fixunsxfei"); -} - -pub fn __fixunsxfei(r: [*]u8, bits: usize, a: f80) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixunsxfsi.zig b/lib/compiler_rt/fixunsxfsi.zig deleted file mode 100644 index 7309fbf5a6cf72a7eb862773fbb121437243c2ee..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsxfsi.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixunsxfsi, "__fixunsxfsi"); -} - -fn __fixunsxfsi(a: f80) callconv(.c) u32 { - return intFromFloat(u32, a); -} diff --git a/lib/compiler_rt/fixunsxfti.zig b/lib/compiler_rt/fixunsxfti.zig deleted file mode 100644 index 064c1352c9045870c1a984850f71c86fcf6e8e61..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsxfti.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixunsxfti, "__fixunsxfti"); -} - -pub fn __fixunsxfti(a: f80) callconv(.c) u128 { - return intFromFloat(u128, a); -} diff --git a/lib/compiler_rt/fixxfdi.zig b/lib/compiler_rt/fixxfdi.zig deleted file mode 100644 index e9e4b7528b07168dafdf4791a6cc13d795d5b78a..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixxfdi.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixxfdi, "__fixxfdi"); -} - -fn __fixxfdi(a: f80) callconv(.c) i64 { - return intFromFloat(i64, a); -} diff --git a/lib/compiler_rt/fixxfei.zig b/lib/compiler_rt/fixxfei.zig deleted file mode 100644 index 82cd67648df13ac446de3a74ef796ba55ad45065..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixxfei.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixxfei, "__fixxfei"); -} - -pub fn __fixxfei(r: [*]u8, bits: usize, a: f80) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixxfsi.zig b/lib/compiler_rt/fixxfsi.zig deleted file mode 100644 index 363492168c760bcd12432e7c757ec4b8f60a2cc1..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixxfsi.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixxfsi, "__fixxfsi"); -} - -fn __fixxfsi(a: f80) callconv(.c) i32 { - return intFromFloat(i32, a); -} diff --git a/lib/compiler_rt/float_from_int.zig b/lib/compiler_rt/float_from_int.zig index 548d027accbb674e1ecbaeb77ef01a5491e256bc..898f246579c2902f5267d7e54c87422292931891 100644 --- a/lib/compiler_rt/float_from_int.zig +++ b/lib/compiler_rt/float_from_int.zig @@ -1,7 +1,475 @@ +const builtin = @import("builtin"); const std = @import("std"); const math = std.math; -pub fn floatFromInt(comptime T: type, x: anytype) T { +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; + +comptime { + symbol(&__floatsihf, "__floatsihf"); + symbol(&__floatdihf, "__floatdihf"); + symbol(&__floattihf, "__floattihf"); + symbol(&__floateihf, "__floateihf"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_i2f, "__aeabi_i2f"); + symbol(&__aeabi_l2f, "__aeabi_l2f"); + } else { + symbol(&__floatsisf, "__floatsisf"); + symbol(&__floatdisf, "__floatdisf"); + if (compiler_rt.want_windows_arm_abi) symbol(&__floatdisf, "__i64tos"); + } + symbol(&__floattisf, "__floattisf"); + symbol(&__floateisf, "__floateisf"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_i2d, "__aeabi_i2d"); + symbol(&__aeabi_l2d, "__aeabi_l2d"); + } else { + symbol(&__floatsidf, "__floatsidf"); + symbol(&__floatdidf, "__floatdidf"); + if (compiler_rt.want_windows_arm_abi) symbol(&__floatdidf, "__i64tod"); + } + symbol(&__floattidf, "__floattidf"); + symbol(&__floateidf, "__floateidf"); + + symbol(&__floatsixf, "__floatsixf"); + symbol(&__floatdixf, "__floatdixf"); + symbol(&__floattixf, "__floattixf"); + symbol(&__floateixf, "__floateixf"); + + if (compiler_rt.want_ppc_abi) { + symbol(&__floatsitf, "__floatsikf"); + symbol(&__floatditf, "__floatdikf"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_itoq, "_Qp_itoq"); + symbol(&_Qp_xtoq, "_Qp_xtoq"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__floatsitf, "_Q_itoq"); + symbol(&__floatditf, "_Q_lltoq"); + } else { + symbol(&__floatsitf, "__floatsitf"); + symbol(&__floatditf, "__floatditf"); + } + if (compiler_rt.want_ppc_abi) { + symbol(&__floattitf, "__floattikf"); + symbol(&__floateitf, "__floateikf"); + } else { + if (builtin.cpu.arch == .x86) { + symbol(&__floattitf_x86, "__floattitf"); + } else { + symbol(&__floattitf, "__floattitf"); + } + symbol(&__floateitf, "__floateitf"); + } +} + +fn __floatsihf(a: i32) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_i32(a)); +} +pub fn f16_floatFromInt_i32(a: i32) f16 { + return floatFromInt(f16, a); +} + +fn __floatdihf(a: i64) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_i64(a)); +} +pub fn f16_floatFromInt_i64(a: i64) f16 { + return floatFromInt(f16, a); +} + +fn __floattihf(a: i128) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_i128(a)); +} +pub fn f16_floatFromInt_i128(a: i128) f16 { + return floatFromInt(f16, a); +} + +fn __floateihf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f16.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f16.toAbi(f16_floatFromInt_signed(a[0..byte_size])); +} +pub fn f16_floatFromInt_signed(a: []const u8) f16 { + return floatFromBigInt(f16, .signed, @ptrCast(@alignCast(a))); +} + +fn __floatsisf(a: i32) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_i32(a)); +} +fn __aeabi_i2f(a: i32) callconv(.{ .arm_aapcs = .{} }) f32 { + return f32_floatFromInt_i32(a); +} +pub fn f32_floatFromInt_i32(a: i32) f32 { + return floatFromInt(f32, a); +} + +fn __floatdisf(a: i64) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_i64(a)); +} +fn __aeabi_l2f(a: i64) callconv(.{ .arm_aapcs = .{} }) f32 { + return f32_floatFromInt_i64(a); +} +pub fn f32_floatFromInt_i64(a: i64) f32 { + return floatFromInt(f32, a); +} + +fn __floattisf(a: i128) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_i128(a)); +} +pub fn f32_floatFromInt_i128(a: i128) f32 { + return floatFromInt(f32, a); +} + +fn __floateisf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f32.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f32.toAbi(f32_floatFromInt_signed(a[0..byte_size])); +} +pub fn f32_floatFromInt_signed(a: []const u8) f32 { + return floatFromBigInt(f32, .signed, @ptrCast(@alignCast(a))); +} + +fn __floatsidf(a: i32) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_i32(a)); +} +fn __aeabi_i2d(a: i32) callconv(.{ .arm_aapcs = .{} }) f64 { + return f64_floatFromInt_i32(a); +} +pub fn f64_floatFromInt_i32(a: i32) f64 { + return floatFromInt(f64, a); +} + +fn __floatdidf(a: i64) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_i64(a)); +} +fn __aeabi_l2d(a: i64) callconv(.{ .arm_aapcs = .{} }) f64 { + return f64_floatFromInt_i64(a); +} +pub fn f64_floatFromInt_i64(a: i64) f64 { + return floatFromInt(f64, a); +} + +fn __floattidf(a: i128) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_i128(a)); +} +pub fn f64_floatFromInt_i128(a: i128) f64 { + return floatFromInt(f64, a); +} + +fn __floateidf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f64.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f64.toAbi(f64_floatFromInt_signed(a[0..byte_size])); +} +pub fn f64_floatFromInt_signed(a: []const u8) f64 { + return floatFromBigInt(f64, .signed, @ptrCast(@alignCast(a))); +} + +fn __floatsixf(a: i32) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_i32(a)); +} +pub fn f80_floatFromInt_i32(a: i32) f80 { + return floatFromInt(f80, a); +} + +fn __floatdixf(a: i64) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_i64(a)); +} +pub fn f80_floatFromInt_i64(a: i64) f80 { + return floatFromInt(f80, a); +} + +fn __floattixf(a: i128) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_i128(a)); +} +pub fn f80_floatFromInt_i128(a: i128) f80 { + return floatFromInt(f80, a); +} + +fn __floateixf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f80.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f80.toAbi(f80_floatFromInt_signed(a[0..byte_size])); +} +pub fn f80_floatFromInt_signed(a: []const u8) f80 { + return floatFromBigInt(f80, .signed, @ptrCast(@alignCast(a))); +} + +fn __floatsitf(a: i32) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_i32(a)); +} +fn _Qp_itoq(c: *f128, a: i32) callconv(.c) void { + c.* = f128_floatFromInt_i32(a); +} +pub fn f128_floatFromInt_i32(a: i32) f128 { + return floatFromInt(f128, a); +} + +fn __floatditf(a: i64) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_i64(a)); +} +fn _Qp_xtoq(c: *f128, a: i64) callconv(.c) void { + c.* = f128_floatFromInt_i64(a); +} +pub fn f128_floatFromInt_i64(a: i64) f128 { + return floatFromInt(f128, a); +} + +fn __floattitf(a: i128) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_i128(a)); +} +fn __floattitf_x86(a: f128) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_i128(@bitCast(a))); +} +pub fn f128_floatFromInt_i128(a: i128) f128 { + return floatFromInt(f128, a); +} + +fn __floateitf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f128.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f128.toAbi(f128_floatFromInt_signed(a[0..byte_size])); +} +pub fn f128_floatFromInt_signed(a: []const u8) f128 { + return floatFromBigInt(f128, .signed, @ptrCast(@alignCast(a))); +} + +comptime { + symbol(&__floatunsihf, "__floatunsihf"); + symbol(&__floatundihf, "__floatundihf"); + symbol(&__floatuntihf, "__floatuntihf"); + symbol(&__floatuneihf, "__floatuneihf"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_ui2f, "__aeabi_ui2f"); + symbol(&__aeabi_ul2f, "__aeabi_ul2f"); + } else { + symbol(&__floatunsisf, "__floatunsisf"); + symbol(&__floatundisf, "__floatundisf"); + if (compiler_rt.want_windows_arm_abi) symbol(&__floatundisf, "__u64tos"); + } + symbol(&__floatuntisf, "__floatuntisf"); + symbol(&__floatuneisf, "__floatuneisf"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_ui2d, "__aeabi_ui2d"); + } else { + symbol(&__floatunsidf, "__floatunsidf"); + } + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_ul2d, "__aeabi_ul2d"); + } else { + if (compiler_rt.want_windows_arm_abi) { + symbol(&__floatundidf, "__u64tod"); + } + symbol(&__floatundidf, "__floatundidf"); + } + symbol(&__floatuntidf, "__floatuntidf"); + symbol(&__floatuneidf, "__floatuneidf"); + + symbol(&__floatunsixf, "__floatunsixf"); + symbol(&__floatundixf, "__floatundixf"); + symbol(&__floatuntixf, "__floatuntixf"); + symbol(&__floatuneixf, "__floatuneixf"); + + if (compiler_rt.want_ppc_abi) { + symbol(&__floatunsitf, "__floatunsikf"); + symbol(&__floatunditf, "__floatundikf"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_uitoq, "_Qp_uitoq"); + symbol(&_Qp_uxtoq, "_Qp_uxtoq"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__floatunsitf, "_Q_utoq"); + symbol(&__floatunditf, "_Q_ulltoq"); + } else { + symbol(&__floatunsitf, "__floatunsitf"); + symbol(&__floatunditf, "__floatunditf"); + } + if (compiler_rt.want_ppc_abi) { + symbol(&__floatuntitf, "__floatuntikf"); + symbol(&__floatuneitf, "__floatuneikf"); + } else { + if (builtin.cpu.arch == .x86) { + symbol(&__floatuntitf_x86, "__floatuntitf"); + } else if (builtin.cpu.arch == .x86_64 and + (builtin.os.tag == .windows or builtin.os.tag == .uefi)) + { + symbol(&__floatuntitf_x86_64_windows, "__floatuntitf"); + } else { + symbol(&__floatuntitf, "__floatuntitf"); + } + symbol(&__floatuneitf, "__floatuneitf"); + } +} + +fn __floatunsihf(a: u32) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_u32(a)); +} +pub fn f16_floatFromInt_u32(a: u32) f16 { + return floatFromInt(f16, a); +} + +fn __floatundihf(a: u64) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_u64(a)); +} +pub fn f16_floatFromInt_u64(a: u64) f16 { + return floatFromInt(f16, a); +} + +fn __floatuntihf(a: u128) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_u128(a)); +} +pub fn f16_floatFromInt_u128(a: u128) f16 { + return floatFromInt(f16, a); +} + +fn __floatuneihf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f16.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f16.toAbi(f16_floatFromInt_unsigned(a[0..byte_size])); +} +pub fn f16_floatFromInt_unsigned(a: []const u8) f16 { + return floatFromBigInt(f16, .unsigned, @ptrCast(@alignCast(a))); +} + +fn __floatunsisf(a: u32) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_u32(a)); +} +fn __aeabi_ui2f(a: u32) callconv(.{ .arm_aapcs = .{} }) f32 { + return f32_floatFromInt_u32(a); +} +pub fn f32_floatFromInt_u32(a: u32) f32 { + return floatFromInt(f32, a); +} + +fn __floatundisf(a: u64) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_u64(a)); +} +fn __aeabi_ul2f(a: u64) callconv(.{ .arm_aapcs = .{} }) f32 { + return f32_floatFromInt_u64(a); +} +pub fn f32_floatFromInt_u64(a: u64) f32 { + return floatFromInt(f32, a); +} + +fn __floatuntisf(a: u128) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_u128(a)); +} +pub fn f32_floatFromInt_u128(a: u128) f32 { + return floatFromInt(f32, a); +} + +fn __floatuneisf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f32.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f32.toAbi(f32_floatFromInt_unsigned(a[0..byte_size])); +} +pub fn f32_floatFromInt_unsigned(a: []const u8) f32 { + return floatFromBigInt(f32, .unsigned, @ptrCast(@alignCast(a))); +} + +fn __floatunsidf(a: u32) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_u32(a)); +} +fn __aeabi_ui2d(a: u32) callconv(.{ .arm_aapcs = .{} }) f64 { + return f64_floatFromInt_u32(a); +} +pub fn f64_floatFromInt_u32(a: u32) f64 { + return floatFromInt(f64, a); +} + +fn __floatundidf(a: u64) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_u64(a)); +} +fn __aeabi_ul2d(a: u64) callconv(.{ .arm_aapcs = .{} }) f64 { + return f64_floatFromInt_u64(a); +} +pub fn f64_floatFromInt_u64(a: u64) f64 { + return floatFromInt(f64, a); +} + +fn __floatuntidf(a: u128) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_u128(a)); +} +pub fn f64_floatFromInt_u128(a: u128) f64 { + return floatFromInt(f64, a); +} + +fn __floatuneidf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f64.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f64.toAbi(f64_floatFromInt_unsigned(a[0..byte_size])); +} +pub fn f64_floatFromInt_unsigned(a: []const u8) f64 { + return floatFromBigInt(f64, .unsigned, @ptrCast(@alignCast(a))); +} + +fn __floatunsixf(a: u32) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_u32(a)); +} +pub fn f80_floatFromInt_u32(a: u32) f80 { + return floatFromInt(f80, a); +} + +fn __floatundixf(a: u64) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_u64(a)); +} +pub fn f80_floatFromInt_u64(a: u64) f80 { + return floatFromInt(f80, a); +} + +fn __floatuntixf(a: u128) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_u128(a)); +} +pub fn f80_floatFromInt_u128(a: u128) f80 { + return floatFromInt(f80, a); +} + +fn __floatuneixf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f80.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f80.toAbi(f80_floatFromInt_unsigned(a[0..byte_size])); +} +pub fn f80_floatFromInt_unsigned(a: []const u8) f80 { + return floatFromBigInt(f80, .unsigned, @ptrCast(@alignCast(a))); +} + +fn __floatunsitf(a: u32) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_u32(a)); +} +fn _Qp_uitoq(c: *f128, a: u32) callconv(.c) void { + c.* = f128_floatFromInt_u32(a); +} +pub fn f128_floatFromInt_u32(a: u32) f128 { + return floatFromInt(f128, a); +} + +fn __floatunditf(a: u64) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_u64(a)); +} +fn _Qp_uxtoq(c: *f128, a: u64) callconv(.c) void { + c.* = f128_floatFromInt_u64(a); +} +pub fn f128_floatFromInt_u64(a: u64) f128 { + return floatFromInt(f128, a); +} + +fn __floatuntitf(a: u128) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_u128(a)); +} +fn __floatuntitf_x86(a: f128) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_u128(@bitCast(a))); +} +fn __floatuntitf_x86_64_windows(a_lo: u64, a_hi: u64) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_u128(@bitCast( + packed struct { lo: u64, hi: u64 }{ .lo = a_lo, .hi = a_hi }, + ))); +} +pub fn f128_floatFromInt_u128(a: u128) f128 { + return floatFromInt(f128, a); +} + +fn __floatuneitf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f128.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f128.toAbi(f128_floatFromInt_unsigned(a[0..byte_size])); +} +pub fn f128_floatFromInt_unsigned(a: []const u8) f128 { + return floatFromBigInt(f128, .unsigned, @ptrCast(@alignCast(a))); +} + +inline fn floatFromInt(comptime T: type, x: anytype) T { if (x == 0) return 0; // Various constants whose values follow from the type parameters. @@ -53,7 +521,7 @@ pub fn floatFromInt(comptime T: type, x: anytype) T { return @bitCast(sign_bit | result); } -const endian = @import("builtin").cpu.arch.endian(); +const endian = builtin.cpu.arch.endian(); inline fn limb(limbs: []const u32, index: usize) u32 { return switch (endian) { .little => limbs[index], @@ -61,11 +529,11 @@ inline fn limb(limbs: []const u32, index: usize) u32 { }; } -pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin.Signedness, x: []const u32) T { +inline fn floatFromBigInt(comptime T: type, comptime signedness: std.lang.Signedness, x: []const u32) T { switch (x.len) { 0 => return 0, inline 1...4 => |limbs_len| { - const low_to_high: [limbs_len]u32 = switch (@import("builtin").cpu.arch.endian()) { + const low_to_high: [limbs_len]u32 = switch (endian) { .little => x[0..limbs_len].*, .big => switch (limbs_len) { 1 => .{x[0]}, diff --git a/lib/compiler_rt/float_from_int_test.zig b/lib/compiler_rt/float_from_int_test.zig index 8c908f420959b28fe107f290cb0bcb709c9ffd85..4ce3129f890f3f303d835733644afcf2fedbff4c 100644 --- a/lib/compiler_rt/float_from_int_test.zig +++ b/lib/compiler_rt/float_from_int_test.zig @@ -2,571 +2,593 @@ const std = @import("std"); const testing = std.testing; const math = std.math; -const __floatunsihf = @import("floatunsihf.zig").__floatunsihf; - -// Conversion to f32 -const __floatsisf = @import("floatsisf.zig").__floatsisf; -const __floatunsisf = @import("floatunsisf.zig").__floatunsisf; -const __floatdisf = @import("floatdisf.zig").__floatdisf; -const __floatundisf = @import("floatundisf.zig").__floatundisf; -const __floattisf = @import("floattisf.zig").__floattisf; -const __floatuntisf = @import("floatuntisf.zig").__floatuntisf; -const __floateisf = @import("floateisf.zig").__floateisf; -const __floatuneisf = @import("floatuneisf.zig").__floatuneisf; - -// Conversion to f64 -const __floatsidf = @import("floatsidf.zig").__floatsidf; -const __floatunsidf = @import("floatunsidf.zig").__floatunsidf; -const __floatdidf = @import("floatdidf.zig").__floatdidf; -const __floatundidf = @import("floatundidf.zig").__floatundidf; -const __floattidf = @import("floattidf.zig").__floattidf; -const __floatuntidf = @import("floatuntidf.zig").__floatuntidf; - -// Conversion to f128 -const __floatsitf = @import("floatsitf.zig").__floatsitf; -const __floatunsitf = @import("floatunsitf.zig").__floatunsitf; -const __floatditf = @import("floatditf.zig").__floatditf; -const __floatunditf = @import("floatunditf.zig").__floatunditf; -const __floattitf = @import("floattitf.zig").__floattitf; -const __floatuntitf = @import("floatuntitf.zig").__floatuntitf; - -fn test__floatsisf(a: i32, expected: u32) !void { - const r = __floatsisf(a); +const impl = @import("float_from_int.zig"); + +const f16_floatFromInt_i32 = impl.f16_floatFromInt_i32; +const f16_floatFromInt_u32 = impl.f16_floatFromInt_u32; +const f16_floatFromInt_i64 = impl.f16_floatFromInt_i64; +const f16_floatFromInt_u64 = impl.f16_floatFromInt_u64; +const f16_floatFromInt_i128 = impl.f16_floatFromInt_i128; +const f16_floatFromInt_u128 = impl.f16_floatFromInt_u128; +const f16_floatFromInt_signed = impl.f16_floatFromInt_signed; +const f16_floatFromInt_unsigned = impl.f16_floatFromInt_unsigned; + +const f32_floatFromInt_i32 = impl.f32_floatFromInt_i32; +const f32_floatFromInt_u32 = impl.f32_floatFromInt_u32; +const f32_floatFromInt_i64 = impl.f32_floatFromInt_i64; +const f32_floatFromInt_u64 = impl.f32_floatFromInt_u64; +const f32_floatFromInt_i128 = impl.f32_floatFromInt_i128; +const f32_floatFromInt_u128 = impl.f32_floatFromInt_u128; +const f32_floatFromInt_signed = impl.f32_floatFromInt_signed; +const f32_floatFromInt_unsigned = impl.f32_floatFromInt_unsigned; + +const f64_floatFromInt_i32 = impl.f64_floatFromInt_i32; +const f64_floatFromInt_u32 = impl.f64_floatFromInt_u32; +const f64_floatFromInt_i64 = impl.f64_floatFromInt_i64; +const f64_floatFromInt_u64 = impl.f64_floatFromInt_u64; +const f64_floatFromInt_i128 = impl.f64_floatFromInt_i128; +const f64_floatFromInt_u128 = impl.f64_floatFromInt_u128; +const f64_floatFromInt_signed = impl.f64_floatFromInt_signed; +const f64_floatFromInt_unsigned = impl.f64_floatFromInt_unsigned; + +const f80_floatFromInt_i32 = impl.f80_floatFromInt_i32; +const f80_floatFromInt_u32 = impl.f80_floatFromInt_u32; +const f80_floatFromInt_i64 = impl.f80_floatFromInt_i64; +const f80_floatFromInt_u64 = impl.f80_floatFromInt_u64; +const f80_floatFromInt_i128 = impl.f80_floatFromInt_i128; +const f80_floatFromInt_u128 = impl.f80_floatFromInt_u128; +const f80_floatFromInt_signed = impl.f80_floatFromInt_signed; +const f80_floatFromInt_unsigned = impl.f80_floatFromInt_unsigned; + +const f128_floatFromInt_i32 = impl.f128_floatFromInt_i32; +const f128_floatFromInt_u32 = impl.f128_floatFromInt_u32; +const f128_floatFromInt_i64 = impl.f128_floatFromInt_i64; +const f128_floatFromInt_u64 = impl.f128_floatFromInt_u64; +const f128_floatFromInt_i128 = impl.f128_floatFromInt_i128; +const f128_floatFromInt_u128 = impl.f128_floatFromInt_u128; +const f128_floatFromInt_signed = impl.f128_floatFromInt_signed; +const f128_floatFromInt_unsigned = impl.f128_floatFromInt_unsigned; + +fn test_f32_floatFromInt_i32(a: i32, expected: u32) !void { + const r = f32_floatFromInt_i32(a); try std.testing.expect(@as(u32, @bitCast(r)) == expected); } -fn test_one_floatunsisf(a: u32, expected: u32) !void { - const r = __floatunsisf(a); +fn test_f32_floatFromInt_u32(a: u32, expected: u32) !void { + const r = f32_floatFromInt_u32(a); try std.testing.expect(@as(u32, @bitCast(r)) == expected); } -test "floatsisf" { - try test__floatsisf(0, 0x00000000); - try test__floatsisf(1, 0x3f800000); - try test__floatsisf(-1, 0xbf800000); - try test__floatsisf(0x7FFFFFFF, 0x4f000000); - try test__floatsisf(@bitCast(@as(u32, @intCast(0x80000000))), 0xcf000000); +test f32_floatFromInt_i32 { + try test_f32_floatFromInt_i32(0, 0x00000000); + try test_f32_floatFromInt_i32(1, 0x3f800000); + try test_f32_floatFromInt_i32(-1, 0xbf800000); + try test_f32_floatFromInt_i32(0x7FFFFFFF, 0x4f000000); + try test_f32_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xcf000000); + + try testing.expect(f32_floatFromInt_i32(math.minInt(i32)) == math.minInt(i32)); } -test "floatunsisf" { +test f32_floatFromInt_u32 { // Test the produced bit pattern - try test_one_floatunsisf(0, 0); - try test_one_floatunsisf(1, 0x3f800000); - try test_one_floatunsisf(0x7FFFFFFF, 0x4f000000); - try test_one_floatunsisf(0x80000000, 0x4f000000); - try test_one_floatunsisf(0xFFFFFFFF, 0x4f800000); + try test_f32_floatFromInt_u32(0, 0); + try test_f32_floatFromInt_u32(1, 0x3f800000); + try test_f32_floatFromInt_u32(0x7FFFFFFF, 0x4f000000); + try test_f32_floatFromInt_u32(0x80000000, 0x4f000000); + try test_f32_floatFromInt_u32(0xFFFFFFFF, 0x4f800000); + + try testing.expect(f32_floatFromInt_u32(0) == 0.0); + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24)) == math.maxInt(u24)); + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact + try testing.expect(f32_floatFromInt_u32(math.maxInt(u32)) == math.maxInt(u32) + 1); } -fn test__floatdisf(a: i64, expected: f32) !void { - const x = __floatdisf(a); +fn test_f32_floatFromInt_i64(a: i64, expected: f32) !void { + const x = f32_floatFromInt_i64(a); try testing.expect(x == expected); } -fn test__floatundisf(a: u64, expected: f32) !void { - try std.testing.expectEqual(expected, __floatundisf(a)); +fn test_f32_floatFromInt_u64(a: u64, expected: f32) !void { + const x = f32_floatFromInt_u64(a); + try testing.expect(x == expected); } -test "floatdisf" { - try test__floatdisf(0, 0.0); - try test__floatdisf(1, 1.0); - try test__floatdisf(2, 2.0); - try test__floatdisf(-1, -1.0); - try test__floatdisf(-2, -2.0); - try test__floatdisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatdisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatdisf(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62); - try test__floatdisf(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62); - try test__floatdisf(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63); - try test__floatdisf(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63); - try test__floatdisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); - try test__floatdisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); +test f32_floatFromInt_i64 { + try test_f32_floatFromInt_i64(0, 0.0); + try test_f32_floatFromInt_i64(1, 1.0); + try test_f32_floatFromInt_i64(2, 2.0); + try test_f32_floatFromInt_i64(-1, -1.0); + try test_f32_floatFromInt_i64(-2, -2.0); + try test_f32_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f32_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62); + try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62); + try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63); + try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63); + try test_f32_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBCp+50); + try test_f32_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB8p+50); } -test "floatundisf" { - try test__floatundisf(0, 0.0); - try test__floatundisf(1, 1.0); - try test__floatundisf(2, 2.0); - try test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatundisf(0x8000008000000000, 0x1p+63); - try test__floatundisf(0x8000010000000000, 0x1.000002p+63); - try test__floatundisf(0x8000000000000000, 0x1p+63); - try test__floatundisf(0x8000000000000001, 0x1p+63); - try test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64); - try test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64); - try test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); - try test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); +test f32_floatFromInt_u64 { + try test_f32_floatFromInt_u64(0, 0.0); + try test_f32_floatFromInt_u64(1, 1.0); + try test_f32_floatFromInt_u64(2, 2.0); + try test_f32_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f32_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f32_floatFromInt_u64(0x8000008000000000, 0x1p+63); + try test_f32_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63); + try test_f32_floatFromInt_u64(0x8000000000000000, 0x1p+63); + try test_f32_floatFromInt_u64(0x8000000000000001, 0x1p+63); + try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFE, 0x1p+64); + try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFF, 0x1p+64); + try test_f32_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBCp+50); + try test_f32_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB8p+50); } -fn test__floattisf(a: i128, expected: f32) !void { - const x = __floattisf(a); +fn test_f32_floatFromInt_i128(a: i128, expected: f32) !void { + const x = f32_floatFromInt_i128(a); try testing.expect(x == expected); } -fn test__floatuntisf(a: u128, expected: f32) !void { - const x = __floatuntisf(a); +fn test_f32_floatFromInt_u128(a: u128, expected: f32) !void { + const x = f32_floatFromInt_u128(a); try testing.expect(x == expected); } -test "floattisf" { - try test__floattisf(0, 0.0); +test f32_floatFromInt_i128 { + try test_f32_floatFromInt_i128(0, 0.0); - try test__floattisf(1, 1.0); - try test__floattisf(2, 2.0); - try test__floattisf(-1, -1.0); - try test__floattisf(-2, -2.0); + try test_f32_floatFromInt_i128(1, 1.0); + try test_f32_floatFromInt_i128(2, 2.0); + try test_f32_floatFromInt_i128(-1, -1.0); + try test_f32_floatFromInt_i128(-2, -2.0); - try test__floattisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floattisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f32_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f32_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62); - try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62); + try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62); + try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62); - try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63); - try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63); + try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63); + try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63); - try test__floattisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); - try test__floattisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBCp+50); + try test_f32_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); + try test_f32_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB8p+50); - try test__floattisf(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114); - try test__floattisf(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114); } -test "floatuntisf" { - try test__floatuntisf(0, 0.0); +test f32_floatFromInt_u128 { + try test_f32_floatFromInt_u128(0, 0.0); - try test__floatuntisf(1, 1.0); - try test__floatuntisf(2, 2.0); - try test__floatuntisf(20, 20.0); + try test_f32_floatFromInt_u128(1, 1.0); + try test_f32_floatFromInt_u128(2, 2.0); + try test_f32_floatFromInt_u128(20, 20.0); - try test__floatuntisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatuntisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f32_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f32_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatuntisf(make_uti(0x8000008000000000, 0), 0x1.000001p+127); - try test__floatuntisf(make_uti(0x8000000000000800, 0), 0x1.0p+127); - try test__floatuntisf(make_uti(0x8000010000000000, 0), 0x1.000002p+127); + try test_f32_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127); + try test_f32_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0p+127); + try test_f32_floatFromInt_u128(make_uti(0x8000010000000000, 0), 0x1.000002p+127); - try test__floatuntisf(make_uti(0x8000000000000000, 0), 0x1.000000p+127); + try test_f32_floatFromInt_u128(make_uti(0x8000000000000000, 0), 0x1.000000p+127); - try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f32_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f32_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB9p+50); + try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50); - try test__floatuntisf(0xFFFFFFFFFFFFFFFE, 0x1p+64); - try test__floatuntisf(0xFFFFFFFFFFFFFFFF, 0x1p+64); + try test_f32_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0x1p+64); + try test_f32_floatFromInt_u128(0xFFFFFFFFFFFFFFFF, 0x1p+64); - try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); - try test__floatuntisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBCp+50); + try test_f32_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); + try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB8p+50); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76); // Test overflow to infinity - try test__floatuntisf(math.maxInt(u128), @bitCast(math.inf(f32))); + try test_f32_floatFromInt_u128(math.maxInt(u128), @bitCast(math.inf(f32))); } -fn test_floateisf(expected: u32, comptime T: type, a: T) !void { +fn test_f32_floatFromInt(expected: u32, comptime T: type, a: T) !void { const int = @typeInfo(T).int; const r = switch (int.signedness) { - .signed => __floateisf, - .unsigned => __floatuneisf, - }(@ptrCast(&a), int.bits); + .signed => f32_floatFromInt_signed, + .unsigned => f32_floatFromInt_unsigned, + }(@ptrCast(&a)); try testing.expect(expected == @as(u32, @bitCast(r))); } -test "floateisf" { - try test_floateisf(0xFF000000, i256, -1 << 127); - try test_floateisf(0xFF000000, i256, -math.maxInt(u127)); - try test_floateisf(0xDF012347, i256, -0x8123468100000000); - try test_floateisf(0xDF012347, i256, -0x8123468000000001); - try test_floateisf(0xDF012346, i256, -0x8123468000000000); - try test_floateisf(0xDF012346, i256, -0x8123458100000000); - try test_floateisf(0xDF012346, i256, -0x8123458000000001); - try test_floateisf(0xDF012346, i256, -0x8123458000000000); - try test_floateisf(0xDF012345, i256, -0x8123456789ABCDEF); - try test_floateisf(0xBF800000, i256, -1); - try test_floateisf(0x00000000, i256, 0); - try test_floateisf(0x5F012345, i256, 0x8123456789ABCDEF); - try test_floateisf(0x5F012346, i256, 0x8123458000000000); - try test_floateisf(0x5F012346, i256, 0x8123458000000001); - try test_floateisf(0x5F012346, i256, 0x8123458100000000); - try test_floateisf(0x5F012346, i256, 0x8123468000000000); - try test_floateisf(0x5F012347, i256, 0x8123468000000001); - try test_floateisf(0x5F012347, i256, 0x8123468100000000); - try test_floateisf(0x7F000000, i256, math.maxInt(u127)); - try test_floateisf(0x7F000000, i256, 1 << 127); +test f32_floatFromInt_signed { + try test_f32_floatFromInt(0xFF000000, i256, -1 << 127); + try test_f32_floatFromInt(0xFF000000, i256, -math.maxInt(u127)); + try test_f32_floatFromInt(0xDF012347, i256, -0x8123468100000000); + try test_f32_floatFromInt(0xDF012347, i256, -0x8123468000000001); + try test_f32_floatFromInt(0xDF012346, i256, -0x8123468000000000); + try test_f32_floatFromInt(0xDF012346, i256, -0x8123458100000000); + try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000001); + try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000000); + try test_f32_floatFromInt(0xDF012345, i256, -0x8123456789ABCDEF); + try test_f32_floatFromInt(0xBF800000, i256, -1); + try test_f32_floatFromInt(0x00000000, i256, 0); + try test_f32_floatFromInt(0x5F012345, i256, 0x8123456789ABCDEF); + try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000000); + try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000001); + try test_f32_floatFromInt(0x5F012346, i256, 0x8123458100000000); + try test_f32_floatFromInt(0x5F012346, i256, 0x8123468000000000); + try test_f32_floatFromInt(0x5F012347, i256, 0x8123468000000001); + try test_f32_floatFromInt(0x5F012347, i256, 0x8123468100000000); + try test_f32_floatFromInt(0x7F000000, i256, math.maxInt(u127)); + try test_f32_floatFromInt(0x7F000000, i256, 1 << 127); } -test "floatuneisf" { - try test_floateisf(0x00000000, u256, 0); - try test_floateisf(0x5F012345, u256, 0x8123456789ABCDEF); - try test_floateisf(0x5F012346, u256, 0x8123458000000000); - try test_floateisf(0x5F012346, u256, 0x8123458000000001); - try test_floateisf(0x5F012346, u256, 0x8123458080000000); - try test_floateisf(0x5F012346, u256, 0x8123468000000000); - try test_floateisf(0x5F012347, u256, 0x8123468000000001); - try test_floateisf(0x5F012347, u256, 0x8123468080000000); - try test_floateisf(0x7F000000, u256, math.maxInt(u127)); - try test_floateisf(0x7F000000, u256, 1 << 127); - try test_floateisf(0x7F800000, u256, math.maxInt(u256)); +test f32_floatFromInt_unsigned { + try test_f32_floatFromInt(0x00000000, u256, 0); + try test_f32_floatFromInt(0x5F012345, u256, 0x8123456789ABCDEF); + try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000000); + try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000001); + try test_f32_floatFromInt(0x5F012346, u256, 0x8123458080000000); + try test_f32_floatFromInt(0x5F012346, u256, 0x8123468000000000); + try test_f32_floatFromInt(0x5F012347, u256, 0x8123468000000001); + try test_f32_floatFromInt(0x5F012347, u256, 0x8123468080000000); + try test_f32_floatFromInt(0x7F000000, u256, math.maxInt(u127)); + try test_f32_floatFromInt(0x7F000000, u256, 1 << 127); + try test_f32_floatFromInt(0x7F800000, u256, math.maxInt(u256)); } -fn test_one_floatsidf(a: i32, expected: u64) !void { - const r = __floatsidf(a); +fn test_f64_floatFromInt_i32(a: i32, expected: u64) !void { + const r = f64_floatFromInt_i32(a); try std.testing.expect(@as(u64, @bitCast(r)) == expected); } -fn test_one_floatunsidf(a: u32, expected: u64) !void { - const r = __floatunsidf(a); +fn test_f64_floatFromInt_u32(a: u32, expected: u64) !void { + const r = f64_floatFromInt_u32(a); try std.testing.expect(@as(u64, @bitCast(r)) == expected); } -test "floatsidf" { - try test_one_floatsidf(0, 0x0000000000000000); - try test_one_floatsidf(1, 0x3ff0000000000000); - try test_one_floatsidf(-1, 0xbff0000000000000); - try test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000); - try test_one_floatsidf(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000); +test f64_floatFromInt_i32 { + try test_f64_floatFromInt_i32(0, 0x0000000000000000); + try test_f64_floatFromInt_i32(1, 0x3ff0000000000000); + try test_f64_floatFromInt_i32(-1, 0xbff0000000000000); + try test_f64_floatFromInt_i32(0x7FFFFFFF, 0x41dfffffffc00000); + try test_f64_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000); } -test "floatunsidf" { - try test_one_floatunsidf(0, 0x0000000000000000); - try test_one_floatunsidf(1, 0x3ff0000000000000); - try test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000); - try test_one_floatunsidf(@intCast(0x80000000), 0x41e0000000000000); - try test_one_floatunsidf(@intCast(0xFFFFFFFF), 0x41efffffffe00000); +test f64_floatFromInt_u32 { + try test_f64_floatFromInt_u32(0, 0x0000000000000000); + try test_f64_floatFromInt_u32(1, 0x3ff0000000000000); + try test_f64_floatFromInt_u32(0x7FFFFFFF, 0x41dfffffffc00000); + try test_f64_floatFromInt_u32(@intCast(0x80000000), 0x41e0000000000000); + try test_f64_floatFromInt_u32(@intCast(0xFFFFFFFF), 0x41efffffffe00000); } -fn test__floatdidf(a: i64, expected: f64) !void { - const r = __floatdidf(a); +fn test_f64_floatFromInt_i64(a: i64, expected: f64) !void { + const r = f64_floatFromInt_i64(a); try testing.expect(r == expected); } -fn test__floatundidf(a: u64, expected: f64) !void { - const r = __floatundidf(a); +fn test_f64_floatFromInt_u64(a: u64, expected: f64) !void { + const r = f64_floatFromInt_u64(a); try testing.expect(r == expected); } -test "floatdidf" { - try test__floatdidf(0, 0.0); - try test__floatdidf(1, 1.0); - try test__floatdidf(2, 2.0); - try test__floatdidf(20, 20.0); - try test__floatdidf(-1, -1.0); - try test__floatdidf(-2, -2.0); - try test__floatdidf(-20, -20.0); - try test__floatdidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001 - try test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floatdidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floatdidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floatdidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - try test__floatdidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floatdidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floatdidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floatdidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floatdidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - try test__floatdidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); - try test__floatdidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); - try test__floatdidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); - try test__floatdidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); - try test__floatdidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); +test f64_floatFromInt_i64 { + try test_f64_floatFromInt_i64(0, 0.0); + try test_f64_floatFromInt_i64(1, 1.0); + try test_f64_floatFromInt_i64(2, 2.0); + try test_f64_floatFromInt_i64(20, 20.0); + try test_f64_floatFromInt_i64(-1, -1.0); + try test_f64_floatFromInt_i64(-2, -2.0); + try test_f64_floatFromInt_i64(-20, -20.0); + try test_f64_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f64_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001 + try test_f64_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f64_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f64_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f64_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f64_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f64_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + try test_f64_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f64_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f64_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f64_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f64_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB9p+50); + try test_f64_floatFromInt_i64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); } -test "floatundidf" { - try test__floatundidf(0, 0.0); - try test__floatundidf(1, 1.0); - try test__floatundidf(2, 2.0); - try test__floatundidf(20, 20.0); - try test__floatundidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatundidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floatundidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatundidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - try test__floatundidf(0x8000008000000000, 0x1.000001p+63); - try test__floatundidf(0x8000000000000800, 0x1.0000000000001p+63); - try test__floatundidf(0x8000010000000000, 0x1.000002p+63); - try test__floatundidf(0x8000000000001000, 0x1.0000000000002p+63); - try test__floatundidf(0x8000000000000000, 0x1p+63); - try test__floatundidf(0x8000000000000001, 0x1p+63); - try test__floatundidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatundidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floatundidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floatundidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floatundidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floatundidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - try test__floatundidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floatundidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floatundidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floatundidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floatundidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - try test__floatundidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); - try test__floatundidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); - try test__floatundidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); - try test__floatundidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); - try test__floatundidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); +test f64_floatFromInt_u64 { + try test_f64_floatFromInt_u64(0, 0.0); + try test_f64_floatFromInt_u64(1, 1.0); + try test_f64_floatFromInt_u64(2, 2.0); + try test_f64_floatFromInt_u64(20, 20.0); + try test_f64_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f64_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + try test_f64_floatFromInt_u64(0x8000008000000000, 0x1.000001p+63); + try test_f64_floatFromInt_u64(0x8000000000000800, 0x1.0000000000001p+63); + try test_f64_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63); + try test_f64_floatFromInt_u64(0x8000000000001000, 0x1.0000000000002p+63); + try test_f64_floatFromInt_u64(0x8000000000000000, 0x1p+63); + try test_f64_floatFromInt_u64(0x8000000000000001, 0x1p+63); + try test_f64_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f64_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f64_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f64_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f64_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f64_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + try test_f64_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f64_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f64_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f64_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f64_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB9p+50); + try test_f64_floatFromInt_u64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); } -fn test__floattidf(a: i128, expected: f64) !void { - const x = __floattidf(a); +fn test_f64_floatFromInt_i128(a: i128, expected: f64) !void { + const x = f64_floatFromInt_i128(a); try testing.expect(x == expected); } -fn test__floatuntidf(a: u128, expected: f64) !void { - const x = __floatuntidf(a); +fn test_f64_floatFromInt_u128(a: u128, expected: f64) !void { + const x = f64_floatFromInt_u128(a); try testing.expect(x == expected); } -test "floattidf" { - try test__floattidf(0, 0.0); - - try test__floattidf(1, 1.0); - try test__floattidf(2, 2.0); - try test__floattidf(20, 20.0); - try test__floattidf(-1, -1.0); - try test__floattidf(-2, -2.0); - try test__floattidf(-20, -20.0); - - try test__floattidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floattidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floattidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floattidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - - try test__floattidf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); - try test__floattidf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); - try test__floattidf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); - try test__floattidf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); - - try test__floattidf(make_ti(0x8000000000000000, 0), -0x1.000000p+127); - try test__floattidf(make_ti(0x8000000000000001, 0), -0x1.000000p+127); - - try test__floattidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - - try test__floattidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floattidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floattidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floattidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floattidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - - try test__floattidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floattidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floattidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floattidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floattidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - - try test__floattidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); - try test__floattidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); - try test__floattidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); - try test__floattidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); - try test__floattidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); - - try test__floattidf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); - try test__floattidf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); - try test__floattidf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); - try test__floattidf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); - try test__floattidf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); +test f64_floatFromInt_i128 { + try test_f64_floatFromInt_i128(0, 0.0); + + try test_f64_floatFromInt_i128(1, 1.0); + try test_f64_floatFromInt_i128(2, 2.0); + try test_f64_floatFromInt_i128(20, 20.0); + try test_f64_floatFromInt_i128(-1, -1.0); + try test_f64_floatFromInt_i128(-2, -2.0); + try test_f64_floatFromInt_i128(-20, -20.0); + + try test_f64_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f64_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + + try test_f64_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); + try test_f64_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); + try test_f64_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); + try test_f64_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); + + try test_f64_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127); + try test_f64_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.000000p+127); + + try test_f64_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50); + + try test_f64_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f64_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f64_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f64_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f64_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + + try test_f64_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f64_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f64_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f64_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f64_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50); + + try test_f64_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); + + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); } -test "floatuntidf" { - try test__floatuntidf(0, 0.0); - - try test__floatuntidf(1, 1.0); - try test__floatuntidf(2, 2.0); - try test__floatuntidf(20, 20.0); - - try test__floatuntidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatuntidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floatuntidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatuntidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - - try test__floatuntidf(make_uti(0x8000008000000000, 0), 0x1.000001p+127); - try test__floatuntidf(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127); - try test__floatuntidf(make_uti(0x8000010000000000, 0), 0x1.000002p+127); - try test__floatuntidf(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127); - - try test__floatuntidf(make_uti(0x8000000000000000, 0), 0x1.000000p+127); - try test__floatuntidf(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127); - - try test__floatuntidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - - try test__floatuntidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floatuntidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floatuntidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floatuntidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floatuntidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - - try test__floatuntidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floatuntidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floatuntidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floatuntidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floatuntidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - - try test__floatuntidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); - try test__floatuntidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); - try test__floatuntidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); - try test__floatuntidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); - try test__floatuntidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); - - try test__floatuntidf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); - try test__floatuntidf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); - try test__floatuntidf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); - try test__floatuntidf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); - try test__floatuntidf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); +test f64_floatFromInt_u128 { + try test_f64_floatFromInt_u128(0, 0.0); + + try test_f64_floatFromInt_u128(1, 1.0); + try test_f64_floatFromInt_u128(2, 2.0); + try test_f64_floatFromInt_u128(20, 20.0); + + try test_f64_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f64_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + + try test_f64_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127); + try test_f64_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127); + try test_f64_floatFromInt_u128(make_uti(0x8000010000000000, 0), 0x1.000002p+127); + try test_f64_floatFromInt_u128(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127); + + try test_f64_floatFromInt_u128(make_uti(0x8000000000000000, 0), 0x1.000000p+127); + try test_f64_floatFromInt_u128(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127); + + try test_f64_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); + + try test_f64_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f64_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f64_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f64_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f64_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + + try test_f64_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f64_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f64_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f64_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f64_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50); + + try test_f64_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); + + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); } -fn test__floatsitf(a: i32, expected: u128) !void { - const r = __floatsitf(a); +fn test_f128_floatFromInt_i32(a: i32, expected: u128) !void { + const r = f128_floatFromInt_i32(a); try std.testing.expect(@as(u128, @bitCast(r)) == expected); } -test "floatsitf" { - try test__floatsitf(0, 0); - try test__floatsitf(0x7FFFFFFF, 0x401dfffffffc00000000000000000000); - try test__floatsitf(0x12345678, 0x401b2345678000000000000000000000); - try test__floatsitf(-0x12345678, 0xc01b2345678000000000000000000000); - try test__floatsitf(@bitCast(@as(u32, @intCast(0xffffffff))), 0xbfff0000000000000000000000000000); - try test__floatsitf(@bitCast(@as(u32, @intCast(0x80000000))), 0xc01e0000000000000000000000000000); -} - -fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void { - const x = __floatunsitf(a); +fn test_f128_floatFromInt_u32(a: u32, expected_hi: u64, expected_lo: u64) !void { + const x = f128_floatFromInt_u32(a); const x_repr: u128 = @bitCast(x); const x_hi: u64 = @intCast(x_repr >> 64); @@ -581,24 +603,32 @@ fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void { return; } } + return error.TestFailure; +} - @panic("__floatunsitf test failure"); +test f128_floatFromInt_i32 { + try test_f128_floatFromInt_i32(0, 0); + try test_f128_floatFromInt_i32(0x7FFFFFFF, 0x401dfffffffc00000000000000000000); + try test_f128_floatFromInt_i32(0x12345678, 0x401b2345678000000000000000000000); + try test_f128_floatFromInt_i32(-0x12345678, 0xc01b2345678000000000000000000000); + try test_f128_floatFromInt_i32(@bitCast(@as(u32, @intCast(0xffffffff))), 0xbfff0000000000000000000000000000); + try test_f128_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xc01e0000000000000000000000000000); } -test "floatunsitf" { - try test__floatunsitf(0x7fffffff, 0x401dfffffffc0000, 0x0); - try test__floatunsitf(0, 0x0, 0x0); - try test__floatunsitf(0xffffffff, 0x401efffffffe0000, 0x0); - try test__floatunsitf(0x12345678, 0x401b234567800000, 0x0); +test f128_floatFromInt_u32 { + try test_f128_floatFromInt_u32(0x7fffffff, 0x401dfffffffc0000, 0x0); + try test_f128_floatFromInt_u32(0, 0x0, 0x0); + try test_f128_floatFromInt_u32(0xffffffff, 0x401efffffffe0000, 0x0); + try test_f128_floatFromInt_u32(0x12345678, 0x401b234567800000, 0x0); } -fn test__floatditf(a: i64, expected: f128) !void { - const x = __floatditf(a); +fn test_f128_floatFromInt_i64(a: i64, expected: f128) !void { + const x = f128_floatFromInt_i64(a); try testing.expect(x == expected); } -fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void { - const x = __floatunditf(a); +fn test_f128_floatFromInt_u64(a: u64, expected_hi: u64, expected_lo: u64) !void { + const x = f128_floatFromInt_u64(a); const x_repr: u128 = @bitCast(x); const x_hi: u64 = @intCast(x_repr >> 64); @@ -613,208 +643,207 @@ fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void { return; } } - - @panic("__floatunditf test failure"); + return error.TestFailure; } -test "floatditf" { - try test__floatditf(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000)); - try test__floatditf(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000)); - try test__floatditf(0x2, make_tf(0x4000000000000000, 0x0)); - try test__floatditf(0x1, make_tf(0x3fff000000000000, 0x0)); - try test__floatditf(0x0, make_tf(0x0, 0x0)); - try test__floatditf(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0)); - try test__floatditf(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0)); - try test__floatditf(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000)); - try test__floatditf(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0)); +test f128_floatFromInt_i64 { + try test_f128_floatFromInt_i64(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000)); + try test_f128_floatFromInt_i64(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000)); + try test_f128_floatFromInt_i64(0x2, make_tf(0x4000000000000000, 0x0)); + try test_f128_floatFromInt_i64(0x1, make_tf(0x3fff000000000000, 0x0)); + try test_f128_floatFromInt_i64(0x0, make_tf(0x0, 0x0)); + try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0)); + try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0)); + try test_f128_floatFromInt_i64(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000)); + try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0)); } -test "floatunditf" { - try test__floatunditf(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000); - try test__floatunditf(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000); - try test__floatunditf(0x8000000000000000, 0x403e000000000000, 0x0); - try test__floatunditf(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000); - try test__floatunditf(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000); - try test__floatunditf(0x2, 0x4000000000000000, 0x0); - try test__floatunditf(0x1, 0x3fff000000000000, 0x0); - try test__floatunditf(0x0, 0x0, 0x0); +test f128_floatFromInt_u64 { + try test_f128_floatFromInt_u64(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000); + try test_f128_floatFromInt_u64(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000); + try test_f128_floatFromInt_u64(0x8000000000000000, 0x403e000000000000, 0x0); + try test_f128_floatFromInt_u64(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000); + try test_f128_floatFromInt_u64(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000); + try test_f128_floatFromInt_u64(0x2, 0x4000000000000000, 0x0); + try test_f128_floatFromInt_u64(0x1, 0x3fff000000000000, 0x0); + try test_f128_floatFromInt_u64(0x0, 0x0, 0x0); } -fn test__floattitf(a: i128, expected: f128) !void { - const x = __floattitf(a); +fn test_f128_floatFromInt_i128(a: i128, expected: f128) !void { + const x = f128_floatFromInt_i128(a); try testing.expect(x == expected); } -fn test__floatuntitf(a: u128, expected: f128) !void { - const x = __floatuntitf(a); +fn test_f128_floatFromInt_u128(a: u128, expected: f128) !void { + const x = f128_floatFromInt_u128(a); try testing.expect(x == expected); } -test "floattitf" { - try test__floattitf(0, 0.0); - - try test__floattitf(1, 1.0); - try test__floattitf(2, 2.0); - try test__floattitf(20, 20.0); - try test__floattitf(-1, -1.0); - try test__floattitf(-2, -2.0); - try test__floattitf(-20, -20.0); - - try test__floattitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floattitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floattitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floattitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - - try test__floattitf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); - try test__floattitf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); - try test__floattitf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); - try test__floattitf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); - - try test__floattitf(make_ti(0x8000000000000000, 0), -0x1.000000p+127); - try test__floattitf(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126); - - try test__floattitf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - - try test__floattitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floattitf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floattitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floattitf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floattitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - - try test__floattitf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floattitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floattitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floattitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floattitf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - - try test__floattitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floattitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); - try test__floattitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); - try test__floattitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); - try test__floattitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); - try test__floattitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); - try test__floattitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); - try test__floattitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); - try test__floattitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); - try test__floattitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); - try test__floattitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); - try test__floattitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); - try test__floattitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); - try test__floattitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); - try test__floattitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); - - try test__floattitf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); - try test__floattitf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); - try test__floattitf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); - try test__floattitf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); - try test__floattitf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); - try test__floattitf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); - try test__floattitf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); - try test__floattitf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); - try test__floattitf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); - try test__floattitf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); - try test__floattitf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); - try test__floattitf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); - try test__floattitf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); - try test__floattitf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); - try test__floattitf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); - - try test__floattitf(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); - - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); +test f128_floatFromInt_i128 { + try test_f128_floatFromInt_i128(0, 0.0); + + try test_f128_floatFromInt_i128(1, 1.0); + try test_f128_floatFromInt_i128(2, 2.0); + try test_f128_floatFromInt_i128(20, 20.0); + try test_f128_floatFromInt_i128(-1, -1.0); + try test_f128_floatFromInt_i128(-2, -2.0); + try test_f128_floatFromInt_i128(-20, -20.0); + + try test_f128_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f128_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + + try test_f128_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); + try test_f128_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); + try test_f128_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); + try test_f128_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); + + try test_f128_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127); + try test_f128_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126); + + try test_f128_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50); + + try test_f128_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f128_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f128_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f128_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f128_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + + try test_f128_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f128_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f128_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f128_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f128_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50); + + try test_f128_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); + + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); + + try test_f128_floatFromInt_i128(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); + + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); } -test "floatuntitf" { - try test__floatuntitf(0, 0.0); - - try test__floatuntitf(1, 1.0); - try test__floatuntitf(2, 2.0); - try test__floatuntitf(20, 20.0); - - try test__floatuntitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatuntitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floatuntitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatuntitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - try test__floatuntitf(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59); - try test__floatuntitf(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60); - try test__floatuntitf(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60); - - try test__floatuntitf(0x8000008000000000, 0x8.000008p+60); - try test__floatuntitf(0x8000000000000800, 0x8.0000000000008p+60); - try test__floatuntitf(0x8000010000000000, 0x8.00001p+60); - try test__floatuntitf(0x8000000000001000, 0x8.000000000001p+60); - - try test__floatuntitf(0x8000000000000000, 0x8p+60); - try test__floatuntitf(0x8000000000000001, 0x8.000000000000001p+60); - - try test__floatuntitf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - - try test__floatuntitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floatuntitf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floatuntitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floatuntitf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floatuntitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - - try test__floatuntitf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floatuntitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floatuntitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floatuntitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floatuntitf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - - try test__floatuntitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floatuntitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); - try test__floatuntitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); - try test__floatuntitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); - try test__floatuntitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); - try test__floatuntitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); - try test__floatuntitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); - try test__floatuntitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); - try test__floatuntitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); - try test__floatuntitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); - try test__floatuntitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); - try test__floatuntitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); - try test__floatuntitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); - try test__floatuntitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); - try test__floatuntitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); - - try test__floatuntitf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); - try test__floatuntitf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); - try test__floatuntitf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); - try test__floatuntitf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); - try test__floatuntitf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); - - try test__floatuntitf(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); - - try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127); - try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128); - - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); +test f128_floatFromInt_u128 { + try test_f128_floatFromInt_u128(0, 0.0); + + try test_f128_floatFromInt_u128(1, 1.0); + try test_f128_floatFromInt_u128(2, 2.0); + try test_f128_floatFromInt_u128(20, 20.0); + + try test_f128_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f128_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59); + try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60); + try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60); + + try test_f128_floatFromInt_u128(0x8000008000000000, 0x8.000008p+60); + try test_f128_floatFromInt_u128(0x8000000000000800, 0x8.0000000000008p+60); + try test_f128_floatFromInt_u128(0x8000010000000000, 0x8.00001p+60); + try test_f128_floatFromInt_u128(0x8000000000001000, 0x8.000000000001p+60); + + try test_f128_floatFromInt_u128(0x8000000000000000, 0x8p+60); + try test_f128_floatFromInt_u128(0x8000000000000001, 0x8.000000000000001p+60); + + try test_f128_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); + + try test_f128_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f128_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f128_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f128_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f128_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + + try test_f128_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f128_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f128_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f128_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f128_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50); + + try test_f128_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); + + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); + + try test_f128_floatFromInt_u128(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); + + try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127); + try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128); + + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); } fn make_ti(high: u64, low: u64) i128 { @@ -838,45 +867,40 @@ fn make_tf(high: u64, low: u64) f128 { return @bitCast(result); } -test "conversion to f16" { - try testing.expect(__floatunsihf(@as(u32, 0)) == 0.0); - try testing.expect(__floatunsihf(@as(u32, 1)) == 1.0); - try testing.expect(__floatunsihf(@as(u32, 65504)) == 65504); - try testing.expect(__floatunsihf(@as(u32, 65504 + (1 << 4))) == math.inf(f16)); +test f16_floatFromInt_u32 { + try testing.expect(f16_floatFromInt_u32(0) == 0.0); + try testing.expect(f16_floatFromInt_u32(1) == 1.0); + try testing.expect(f16_floatFromInt_u32(65504) == 65504); + try testing.expect(f16_floatFromInt_u32(65504 + (1 << 4)) == math.inf(f16)); } -test "conversion to f32" { - try testing.expect(__floatunsisf(@as(u32, 0)) == 0.0); - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u32))) != 1.0); - try testing.expect(__floatsisf(@as(i32, math.minInt(i32))) != 1.0); - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24))) == math.maxInt(u24)); - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact +test f80_floatFromInt_u32 { + try testing.expect(f80_floatFromInt_u32(0) == 0.0); + try testing.expect(f80_floatFromInt_u32(1) == 1.0); + try testing.expect(f80_floatFromInt_u32(math.maxInt(u24) + 0) == math.maxInt(u24)); } -test "conversion to f80" { - const floatFromInt = @import("./float_from_int.zig").floatFromInt; +test f80_floatFromInt_u64 { + try testing.expect(f80_floatFromInt_u64(math.maxInt(u64) + 0) == math.maxInt(u64) + 0); +} + +test f80_floatFromInt_i128 { + try testing.expect(f80_floatFromInt_i128(-12) == -12); +} - try testing.expect(floatFromInt(f80, @as(i80, -12)) == -12); - try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u64, math.maxInt(u64)) + 0))) == math.maxInt(u64) + 0); - try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1); +test f80_floatFromInt_u128 { + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1); - try testing.expect(floatFromInt(f80, @as(u32, 0)) == 0.0); - try testing.expect(floatFromInt(f80, @as(u32, 1)) == 1.0); - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u32, math.maxInt(u24)) + 0))) == math.maxInt(u24)); - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 0))) == math.maxInt(u64)); - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1); // Exact - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 2))) == math.maxInt(u64) + 1); // Rounds down - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 3))) == math.maxInt(u64) + 3); // Tie - Exact - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 4))) == math.maxInt(u64) + 5); // Rounds up + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 0) == math.maxInt(u64)); + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1); // Exact + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 2) == math.maxInt(u64) + 1); // Rounds down + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 3) == math.maxInt(u64) + 3); // Tie - Exact + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 4) == math.maxInt(u64) + 5); // Rounds up - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 0))) == math.maxInt(u65) + 1); // Rounds up - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 1))) == math.maxInt(u65) + 1); // Exact - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 2))) == math.maxInt(u65) + 1); // Rounds down - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 3))) == math.maxInt(u65) + 1); // Tie - Rounds down - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 4))) == math.maxInt(u65) + 5); // Rounds up - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 5))) == math.maxInt(u65) + 5); // Exact + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 0) == math.maxInt(u65) + 1); // Rounds up + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 1) == math.maxInt(u65) + 1); // Exact + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 2) == math.maxInt(u65) + 1); // Rounds down + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 3) == math.maxInt(u65) + 1); // Tie - Rounds down + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 4) == math.maxInt(u65) + 5); // Rounds up + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 5) == math.maxInt(u65) + 5); // Exact } diff --git a/lib/compiler_rt/floatdidf.zig b/lib/compiler_rt/floatdidf.zig deleted file mode 100644 index f8d5153d5b43896b3dd26a32e84f613151b84653..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatdidf.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_l2d, "__aeabi_l2d"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__floatdidf, "__i64tod"); - } - symbol(&__floatdidf, "__floatdidf"); - } -} - -pub fn __floatdidf(a: i64) callconv(.c) f64 { - return floatFromInt(f64, a); -} - -fn __aeabi_l2d(a: i64) callconv(.{ .arm_aapcs = .{} }) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floatdihf.zig b/lib/compiler_rt/floatdihf.zig deleted file mode 100644 index c6865dff6b8025e49b8f1a0ffc36674c230247a4..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatdihf.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatdihf, "__floatdihf"); -} - -fn __floatdihf(a: i64) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floatdisf.zig b/lib/compiler_rt/floatdisf.zig deleted file mode 100644 index 3da1faba367a6a17b81f97c93db6ff2041765b84..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatdisf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_l2f, "__aeabi_l2f"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__floatdisf, "__i64tos"); - } - symbol(&__floatdisf, "__floatdisf"); - } -} - -pub fn __floatdisf(a: i64) callconv(.c) f32 { - return floatFromInt(f32, a); -} - -fn __aeabi_l2f(a: i64) callconv(.{ .arm_aapcs = .{} }) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floatditf.zig b/lib/compiler_rt/floatditf.zig deleted file mode 100644 index 033c35ffcbdd2137d84890c9176d7c77fe29541e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatditf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__floatditf, "__floatdikf"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_xtoq, "_Qp_xtoq"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__floatditf, "_Q_lltoq"); - } - symbol(&__floatditf, "__floatditf"); -} - -pub fn __floatditf(a: i64) callconv(.c) f128 { - return floatFromInt(f128, a); -} - -fn _Qp_xtoq(c: *f128, a: i64) callconv(.c) void { - c.* = floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floatdixf.zig b/lib/compiler_rt/floatdixf.zig deleted file mode 100644 index 6bd06245d584402e7ed93b0d57d71f471bde05d4..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatdixf.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatdixf, "__floatdixf"); -} - -fn __floatdixf(a: i64) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floateidf.zig b/lib/compiler_rt/floateidf.zig deleted file mode 100644 index ac3972c28778600d342d0412741e9a3e41797546..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floateidf.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__floateidf, "__floateidf"); -} - -pub fn __floateidf(a: [*]const u8, bits: usize) callconv(.c) f64 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f64, .signed, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floateihf.zig b/lib/compiler_rt/floateihf.zig deleted file mode 100644 index c1ec290fb1084a05b6353ffde4968bce3c3cd3d8..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floateihf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floateihf, "__floateihf"); -} - -pub fn __floateihf(a: [*]const u8, bits: usize) callconv(.c) f16 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f16, .signed, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floateisf.zig b/lib/compiler_rt/floateisf.zig deleted file mode 100644 index dd5933b7dff321ee90d0b13ee6d9a5e0d85a9f20..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floateisf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floateisf, "__floateisf"); -} - -pub fn __floateisf(a: [*]const u8, bits: usize) callconv(.c) f32 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f32, .signed, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floateitf.zig b/lib/compiler_rt/floateitf.zig deleted file mode 100644 index 0df893bd18881c9ec382e718a7664bf4d0f7a8e4..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floateitf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floateitf, "__floateitf"); -} - -pub fn __floateitf(a: [*]const u8, bits: usize) callconv(.c) f128 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f128, .signed, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floateixf.zig b/lib/compiler_rt/floateixf.zig deleted file mode 100644 index dafefa4e8f11b978f26b5e4d10cc8b0feeed480b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floateixf.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floateixf, "__floateixf"); -} - -pub fn __floateixf(a: [*]const u8, bits: usize) callconv(.c) f80 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f80, .signed, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatsidf.zig b/lib/compiler_rt/floatsidf.zig deleted file mode 100644 index dc5a261a08f1e86155d7af20b62b43b02c99bbe5..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatsidf.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_i2d, "__aeabi_i2d"); - } else { - symbol(&__floatsidf, "__floatsidf"); - } -} - -pub fn __floatsidf(a: i32) callconv(.c) f64 { - return floatFromInt(f64, a); -} - -fn __aeabi_i2d(a: i32) callconv(.{ .arm_aapcs = .{} }) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floatsihf.zig b/lib/compiler_rt/floatsihf.zig deleted file mode 100644 index e1d588cfb0da1ed1007496f3d32db0fcdd8612ef..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatsihf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatsihf, "__floatsihf"); -} - -fn __floatsihf(a: i32) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floatsisf.zig b/lib/compiler_rt/floatsisf.zig deleted file mode 100644 index 0dac860ebfded913a3eacb1666cb34e246f87dde..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatsisf.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_i2f, "__aeabi_i2f"); - } else { - symbol(&__floatsisf, "__floatsisf"); - } -} - -pub fn __floatsisf(a: i32) callconv(.c) f32 { - return floatFromInt(f32, a); -} - -fn __aeabi_i2f(a: i32) callconv(.{ .arm_aapcs = .{} }) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floatsitf.zig b/lib/compiler_rt/floatsitf.zig deleted file mode 100644 index 865ebce60fddaa5d8234cf76293b08e12be30000..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatsitf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__floatsitf, "__floatsikf"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_itoq, "_Qp_itoq"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__floatsitf, "_Q_itoq"); - } - symbol(&__floatsitf, "__floatsitf"); -} - -pub fn __floatsitf(a: i32) callconv(.c) f128 { - return floatFromInt(f128, a); -} - -fn _Qp_itoq(c: *f128, a: i32) callconv(.c) void { - c.* = floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floatsixf.zig b/lib/compiler_rt/floatsixf.zig deleted file mode 100644 index bd28eaf1fa68f9580f63b918bfeea6cc78295699..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatsixf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__floatsixf, "__floatsixf"); -} - -fn __floatsixf(a: i32) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floattidf.zig b/lib/compiler_rt/floattidf.zig deleted file mode 100644 index 02298705324edcd49b36f69a64c0c78873ecb57b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floattidf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floattidf, "__floattidf"); -} - -pub fn __floattidf(a: i128) callconv(.c) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floattihf.zig b/lib/compiler_rt/floattihf.zig deleted file mode 100644 index a751e3142c5b273819199105a6848c0280aee3c5..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floattihf.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floattihf, "__floattihf"); -} - -pub fn __floattihf(a: i128) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floattisf.zig b/lib/compiler_rt/floattisf.zig deleted file mode 100644 index 72af61c6b6805d9bd03e6d215dd300fe7589c21f..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floattisf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__floattisf, "__floattisf"); -} - -pub fn __floattisf(a: i128) callconv(.c) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floattitf.zig b/lib/compiler_rt/floattitf.zig deleted file mode 100644 index 3e49a68fd56912ebe7573346b6b8aea6b98b91ba..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floattitf.zig +++ /dev/null @@ -1,13 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_ppc_abi) - symbol(&__floattitf, "__floattikf"); - symbol(&__floattitf, "__floattitf"); -} - -pub fn __floattitf(a: i128) callconv(.c) f128 { - return floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floattixf.zig b/lib/compiler_rt/floattixf.zig deleted file mode 100644 index be05180795aef517800c15d01c928bab4f7f19a0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floattixf.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floattixf, "__floattixf"); -} - -pub fn __floattixf(a: i128) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floatundidf.zig b/lib/compiler_rt/floatundidf.zig deleted file mode 100644 index 852675370503bab154245fd685ff2c2a5449aea0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatundidf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_ul2d, "__aeabi_ul2d"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__floatundidf, "__u64tod"); - } - symbol(&__floatundidf, "__floatundidf"); - } -} - -pub fn __floatundidf(a: u64) callconv(.c) f64 { - return floatFromInt(f64, a); -} - -fn __aeabi_ul2d(a: u64) callconv(.{ .arm_aapcs = .{} }) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floatundihf.zig b/lib/compiler_rt/floatundihf.zig deleted file mode 100644 index 064d565d2dc4ec4f118dee8400375de802400f2b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatundihf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatundihf, "__floatundihf"); -} - -fn __floatundihf(a: u64) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floatundisf.zig b/lib/compiler_rt/floatundisf.zig deleted file mode 100644 index 827a419fd5315624866af773ea71a9098b2bcb3e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatundisf.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_ul2f, "__aeabi_ul2f"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__floatundisf, "__u64tos"); - } - symbol(&__floatundisf, "__floatundisf"); - } -} - -pub fn __floatundisf(a: u64) callconv(.c) f32 { - return floatFromInt(f32, a); -} - -fn __aeabi_ul2f(a: u64) callconv(.{ .arm_aapcs = .{} }) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floatunditf.zig b/lib/compiler_rt/floatunditf.zig deleted file mode 100644 index 79f9f54e176f5741bbc901b1790895feaadf1f98..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunditf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__floatunditf, "__floatundikf"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_uxtoq, "_Qp_uxtoq"); - } else if (compiler_rt.want_sparc32_abi) { - @export(&__floatunditf, "_Q_ulltoq"); - } - symbol(&__floatunditf, "__floatunditf"); -} - -pub fn __floatunditf(a: u64) callconv(.c) f128 { - return floatFromInt(f128, a); -} - -fn _Qp_uxtoq(c: *f128, a: u64) callconv(.c) void { - c.* = floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floatundixf.zig b/lib/compiler_rt/floatundixf.zig deleted file mode 100644 index ce36d47a4ef225c67e4e45f3695cdb14649cee4c..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatundixf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatundixf, "__floatundixf"); -} - -fn __floatundixf(a: u64) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floatuneidf.zig b/lib/compiler_rt/floatuneidf.zig deleted file mode 100644 index 6e391b7cf1c4baeacb55c731ca24c66750c6d346..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuneidf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floatuneidf, "__floatuneidf"); -} - -pub fn __floatuneidf(a: [*]const u8, bits: usize) callconv(.c) f64 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f64, .unsigned, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatuneihf.zig b/lib/compiler_rt/floatuneihf.zig deleted file mode 100644 index 0df0cf155be8e7d39afb5012940fa85ec3211603..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuneihf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floatuneihf, "__floatuneihf"); -} - -pub fn __floatuneihf(a: [*]const u8, bits: usize) callconv(.c) f16 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f16, .unsigned, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatuneisf.zig b/lib/compiler_rt/floatuneisf.zig deleted file mode 100644 index e2dadd9ffddc6efe13ffd53bb9f2cdeeffc3530d..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuneisf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floatuneisf, "__floatuneisf"); -} - -pub fn __floatuneisf(a: [*]const u8, bits: usize) callconv(.c) f32 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f32, .unsigned, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatuneitf.zig b/lib/compiler_rt/floatuneitf.zig deleted file mode 100644 index ddee65dfb18b793bffe08d850384842fcff5747e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuneitf.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floatuneitf, "__floatuneitf"); -} - -pub fn __floatuneitf(a: [*]const u8, bits: usize) callconv(.c) f128 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f128, .unsigned, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatuneixf.zig b/lib/compiler_rt/floatuneixf.zig deleted file mode 100644 index 75dd565daffe16ffb4e95230266fca2f5d288603..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuneixf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floatuneixf, "__floatuneixf"); -} - -pub fn __floatuneixf(a: [*]const u8, bits: usize) callconv(.c) f80 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f80, .unsigned, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatunsidf.zig b/lib/compiler_rt/floatunsidf.zig deleted file mode 100644 index 94949c7bff4eafff900a0b22e53998a930c3d7ea..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunsidf.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_ui2d, "__aeabi_ui2d"); - } else { - symbol(&__floatunsidf, "__floatunsidf"); - } -} - -pub fn __floatunsidf(a: u32) callconv(.c) f64 { - return floatFromInt(f64, a); -} - -fn __aeabi_ui2d(a: u32) callconv(.{ .arm_aapcs = .{} }) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floatunsihf.zig b/lib/compiler_rt/floatunsihf.zig deleted file mode 100644 index a2e42ca10f3af950e900f5250fa6a3d23e2b1266..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunsihf.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatunsihf, "__floatunsihf"); -} - -pub fn __floatunsihf(a: u32) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floatunsisf.zig b/lib/compiler_rt/floatunsisf.zig deleted file mode 100644 index 04da1aa5c03cf76815cccf2273731501d1c8edc0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunsisf.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_ui2f, "__aeabi_ui2f"); - } else { - symbol(&__floatunsisf, "__floatunsisf"); - } -} - -pub fn __floatunsisf(a: u32) callconv(.c) f32 { - return floatFromInt(f32, a); -} - -fn __aeabi_ui2f(a: u32) callconv(.{ .arm_aapcs = .{} }) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floatunsitf.zig b/lib/compiler_rt/floatunsitf.zig deleted file mode 100644 index 2b7c58eab8bd7c2a238062e0cc123f5ce6b8c9e0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunsitf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__floatunsitf, "__floatunsikf"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_uitoq, "_Qp_uitoq"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__floatunsitf, "_Q_utoq"); - } - symbol(&__floatunsitf, "__floatunsitf"); -} - -pub fn __floatunsitf(a: u32) callconv(.c) f128 { - return floatFromInt(f128, a); -} - -fn _Qp_uitoq(c: *f128, a: u32) callconv(.c) void { - c.* = floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floatunsixf.zig b/lib/compiler_rt/floatunsixf.zig deleted file mode 100644 index 906f0270f5c53d28970a0c250b24abcadfa72946..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunsixf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatunsixf, "__floatunsixf"); -} - -fn __floatunsixf(a: u32) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floatuntidf.zig b/lib/compiler_rt/floatuntidf.zig deleted file mode 100644 index b770457bc4992a5bd6237d832e2ca4c0cbed11e0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuntidf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__floatuntidf, "__floatuntidf"); -} - -pub fn __floatuntidf(a: u128) callconv(.c) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floatuntihf.zig b/lib/compiler_rt/floatuntihf.zig deleted file mode 100644 index 5b4373cb7c496b0acf1a2fe6ef988872b30e8780..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuntihf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatuntihf, "__floatuntihf"); -} - -pub fn __floatuntihf(a: u128) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floatuntisf.zig b/lib/compiler_rt/floatuntisf.zig deleted file mode 100644 index de9a021476edecfcc26761133c0645d799c677da..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuntisf.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatuntisf, "__floatuntisf"); -} - -pub fn __floatuntisf(a: u128) callconv(.c) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floatuntitf.zig b/lib/compiler_rt/floatuntitf.zig deleted file mode 100644 index 47cd65cc3ff4460d937e0ccd7acabb2455ae704a..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuntitf.zig +++ /dev/null @@ -1,13 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) - symbol(&__floatuntitf, "__floatuntikf"); - symbol(&__floatuntitf, "__floatuntitf"); -} - -pub fn __floatuntitf(a: u128) callconv(.c) f128 { - return floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floatuntixf.zig b/lib/compiler_rt/floatuntixf.zig deleted file mode 100644 index 41fb45b3a3a1b8e213c03a4ef5e847feb8d31211..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuntixf.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatuntixf, "__floatuntixf"); -} - -pub fn __floatuntixf(a: u128) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floor_ceil.zig b/lib/compiler_rt/floor_ceil.zig index f81d2e0011286a1ea45a3ef147fc704eadac4b4e..f31c352d026c549bd230c9d7d5f15677a85968ce 100644 --- a/lib/compiler_rt/floor_ceil.zig +++ b/lib/compiler_rt/floor_ceil.zig @@ -15,7 +15,7 @@ const mem = std.mem; const expect = std.testing.expect; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { // floor @@ -41,52 +41,92 @@ comptime { symbol(&ceill, "ceill"); } -pub fn __floorh(x: f16) callconv(.c) f16 { +fn __floorh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(floor_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn floor_f16(x: f16) f16 { return impl(f16, .floor, x); } -pub fn floorf(x: f32) callconv(.c) f32 { +fn floorf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(floor_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn floor_f32(x: f32) f32 { return impl(f32, .floor, x); } -pub fn floor(x: f64) callconv(.c) f64 { +fn floor(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(floor_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn floor_f64(x: f64) f64 { return impl(f64, .floor, x); } -pub fn __floorx(x: f80) callconv(.c) f80 { +fn __floorx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(floor_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn floor_f80(x: f80) f80 { return impl(f80, .floor, x); } -pub fn floorq(x: f128) callconv(.c) f128 { +fn floorq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(floor_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn floor_f128(x: f128) f128 { return impl(f128, .floor, x); } pub fn floorl(x: c_longdouble) callconv(.c) c_longdouble { - return impl(std.meta.Float(@bitSizeOf(c_longdouble)), .floor, x); + switch (@typeInfo(c_longdouble).float.bits) { + 64 => return floor_f64(x), + 80 => return floor_f80(x), + 128 => return floor_f128(x), + else => comptime unreachable, + } } -pub fn __ceilh(x: f16) callconv(.c) f16 { +fn __ceilh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(ceil_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn ceil_f16(x: f16) f16 { return impl(f16, .ceil, x); } -pub fn ceilf(x: f32) callconv(.c) f32 { +fn ceilf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(ceil_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn ceil_f32(x: f32) f32 { return impl(f32, .ceil, x); } -pub fn ceil(x: f64) callconv(.c) f64 { +fn ceil(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(ceil_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn ceil_f64(x: f64) f64 { return impl(f64, .ceil, x); } -pub fn __ceilx(x: f80) callconv(.c) f80 { +fn __ceilx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(ceil_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn ceil_f80(x: f80) f80 { return impl(f80, .ceil, x); } -pub fn ceilq(x: f128) callconv(.c) f128 { +fn ceilq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(ceil_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn ceil_f128(x: f128) f128 { return impl(f128, .ceil, x); } pub fn ceill(x: c_longdouble) callconv(.c) c_longdouble { - return impl(std.meta.Float(@bitSizeOf(c_longdouble)), .ceil, x); + switch (@typeInfo(c_longdouble).float.bits) { + 64 => return ceil_f64(x), + 80 => return ceil_f80(x), + 128 => return ceil_f128(x), + else => comptime unreachable, + } } inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T { @@ -144,142 +184,122 @@ inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T { } } -test "floor16" { - try expect(__floorh(1.3) == 1.0); - try expect(__floorh(-1.3) == -2.0); - try expect(__floorh(0.2) == 0.0); -} - -test "floor32" { - try expect(floorf(1.3) == 1.0); - try expect(floorf(-1.3) == -2.0); - try expect(floorf(0.2) == 0.0); -} - -test "floor64" { - try expect(floor(1.3) == 1.0); - try expect(floor(-1.3) == -2.0); - try expect(floor(0.2) == 0.0); -} - -test "floor80" { - try expect(__floorx(1.3) == 1.0); - try expect(__floorx(-1.3) == -2.0); - try expect(__floorx(0.2) == 0.0); -} - -test "floor128" { - try expect(floorq(1.3) == 1.0); - try expect(floorq(-1.3) == -2.0); - try expect(floorq(0.2) == 0.0); -} - -test "floor16.special" { - try expect(__floorh(0.0) == 0.0); - try expect(__floorh(-0.0) == -0.0); - try expect(math.isPositiveInf(__floorh(math.inf(f16)))); - try expect(math.isNegativeInf(__floorh(-math.inf(f16)))); - try expect(math.isNan(__floorh(math.nan(f16)))); -} - -test "floor32.special" { - try expect(floorf(0.0) == 0.0); - try expect(floorf(-0.0) == -0.0); - try expect(math.isPositiveInf(floorf(math.inf(f32)))); - try expect(math.isNegativeInf(floorf(-math.inf(f32)))); - try expect(math.isNan(floorf(math.nan(f32)))); -} - -test "floor64.special" { - try expect(floor(0.0) == 0.0); - try expect(floor(-0.0) == -0.0); - try expect(math.isPositiveInf(floor(math.inf(f64)))); - try expect(math.isNegativeInf(floor(-math.inf(f64)))); - try expect(math.isNan(floor(math.nan(f64)))); -} - -test "floor80.special" { - try expect(__floorx(0.0) == 0.0); - try expect(__floorx(-0.0) == -0.0); - try expect(math.isPositiveInf(__floorx(math.inf(f80)))); - try expect(math.isNegativeInf(__floorx(-math.inf(f80)))); - try expect(math.isNan(__floorx(math.nan(f80)))); -} - -test "floor128.special" { - try expect(floorq(0.0) == 0.0); - try expect(floorq(-0.0) == -0.0); - try expect(math.isPositiveInf(floorq(math.inf(f128)))); - try expect(math.isNegativeInf(floorq(-math.inf(f128)))); - try expect(math.isNan(floorq(math.nan(f128)))); -} - -test "ceil16" { - try expect(__ceilh(1.3) == 2.0); - try expect(__ceilh(-1.3) == -1.0); - try expect(__ceilh(0.2) == 1.0); -} - -test "ceil32" { - try expect(ceilf(1.3) == 2.0); - try expect(ceilf(-1.3) == -1.0); - try expect(ceilf(0.2) == 1.0); -} - -test "ceil64" { - try expect(ceil(1.3) == 2.0); - try expect(ceil(-1.3) == -1.0); - try expect(ceil(0.2) == 1.0); -} - -test "ceil80" { - try expect(__ceilx(1.3) == 2.0); - try expect(__ceilx(-1.3) == -1.0); - try expect(__ceilx(0.2) == 1.0); -} - -test "ceil128" { - try expect(ceilq(1.3) == 2.0); - try expect(ceilq(-1.3) == -1.0); - try expect(ceilq(0.2) == 1.0); -} - -test "ceil16.special" { - try expect(__ceilh(0.0) == 0.0); - try expect(__ceilh(-0.0) == -0.0); - try expect(math.isPositiveInf(__ceilh(math.inf(f16)))); - try expect(math.isNegativeInf(__ceilh(-math.inf(f16)))); - try expect(math.isNan(__ceilh(math.nan(f16)))); -} - -test "ceil32.special" { - try expect(ceilf(0.0) == 0.0); - try expect(ceilf(-0.0) == -0.0); - try expect(math.isPositiveInf(ceilf(math.inf(f32)))); - try expect(math.isNegativeInf(ceilf(-math.inf(f32)))); - try expect(math.isNan(ceilf(math.nan(f32)))); -} - -test "ceil64.special" { - try expect(ceil(0.0) == 0.0); - try expect(ceil(-0.0) == -0.0); - try expect(math.isPositiveInf(ceil(math.inf(f64)))); - try expect(math.isNegativeInf(ceil(-math.inf(f64)))); - try expect(math.isNan(ceil(math.nan(f64)))); -} - -test "ceil80.special" { - try expect(__ceilx(0.0) == 0.0); - try expect(__ceilx(-0.0) == -0.0); - try expect(math.isPositiveInf(__ceilx(math.inf(f80)))); - try expect(math.isNegativeInf(__ceilx(-math.inf(f80)))); - try expect(math.isNan(__ceilx(math.nan(f80)))); -} - -test "ceil128.special" { - try expect(ceilq(0.0) == 0.0); - try expect(ceilq(-0.0) == -0.0); - try expect(math.isPositiveInf(ceilq(math.inf(f128)))); - try expect(math.isNegativeInf(ceilq(-math.inf(f128)))); - try expect(math.isNan(ceilq(math.nan(f128)))); +test floor_f16 { + try expect(floor_f16(1.3) == 1.0); + try expect(floor_f16(-1.3) == -2.0); + try expect(floor_f16(-0.2) == -1.0); + try expect(math.isPositiveZero(floor_f16(0.2))); + try expect(math.isPositiveZero(floor_f16(0.0))); + try expect(math.isNegativeZero(floor_f16(-0.0))); + try expect(math.isPositiveInf(floor_f16(math.inf(f16)))); + try expect(math.isNegativeInf(floor_f16(-math.inf(f16)))); + try expect(math.isNan(floor_f16(math.nan(f16)))); +} + +test floor_f32 { + try expect(floor_f32(1.3) == 1.0); + try expect(floor_f32(-1.3) == -2.0); + try expect(floor_f32(-0.2) == -1.0); + try expect(math.isPositiveZero(floor_f32(0.2))); + try expect(math.isPositiveZero(floor_f32(0.0))); + try expect(math.isNegativeZero(floor_f32(-0.0))); + try expect(math.isPositiveInf(floor_f32(math.inf(f32)))); + try expect(math.isNegativeInf(floor_f32(-math.inf(f32)))); + try expect(math.isNan(floor_f32(math.nan(f32)))); +} + +test floor_f64 { + try expect(floor_f64(1.3) == 1.0); + try expect(floor_f64(-1.3) == -2.0); + try expect(floor_f64(-0.2) == -1.0); + try expect(math.isPositiveZero(floor_f64(0.2))); + try expect(math.isPositiveZero(floor_f64(0.0))); + try expect(math.isNegativeZero(floor_f64(-0.0))); + try expect(math.isPositiveInf(floor_f64(math.inf(f64)))); + try expect(math.isNegativeInf(floor_f64(-math.inf(f64)))); + try expect(math.isNan(floor_f64(math.nan(f64)))); +} + +test floor_f80 { + try expect(floor_f80(1.3) == 1.0); + try expect(floor_f80(-1.3) == -2.0); + try expect(floor_f80(-0.2) == -1.0); + try expect(math.isPositiveZero(floor_f80(0.2))); + try expect(math.isPositiveZero(floor_f80(0.0))); + try expect(math.isNegativeZero(floor_f80(-0.0))); + try expect(math.isPositiveInf(floor_f80(math.inf(f80)))); + try expect(math.isNegativeInf(floor_f80(-math.inf(f80)))); + try expect(math.isNan(floor_f80(math.nan(f80)))); +} + +test floor_f128 { + try expect(floor_f128(1.3) == 1.0); + try expect(floor_f128(-1.3) == -2.0); + try expect(floor_f128(-0.2) == -1.0); + try expect(math.isPositiveZero(floor_f128(0.2))); + try expect(math.isPositiveZero(floor_f128(0.0))); + try expect(math.isNegativeZero(floor_f128(-0.0))); + try expect(math.isPositiveInf(floor_f128(math.inf(f128)))); + try expect(math.isNegativeInf(floor_f128(-math.inf(f128)))); + try expect(math.isNan(floor_f128(math.nan(f128)))); +} + +test ceil_f16 { + try expect(ceil_f16(1.3) == 2.0); + try expect(ceil_f16(-1.3) == -1.0); + try expect(ceil_f16(0.2) == 1.0); + try expect(math.isNegativeZero(ceil_f16(-0.2))); + try expect(math.isPositiveZero(ceil_f16(0.0))); + try expect(math.isNegativeZero(ceil_f16(-0.0))); + try expect(math.isPositiveInf(ceil_f16(math.inf(f16)))); + try expect(math.isNegativeInf(ceil_f16(-math.inf(f16)))); + try expect(math.isNan(ceil_f16(math.nan(f16)))); +} + +test ceil_f32 { + try expect(ceil_f32(1.3) == 2.0); + try expect(ceil_f32(-1.3) == -1.0); + try expect(ceil_f32(0.2) == 1.0); + try expect(math.isNegativeZero(ceil_f32(-0.2))); + try expect(math.isPositiveZero(ceil_f32(0.0))); + try expect(math.isNegativeZero(ceil_f32(-0.0))); + try expect(math.isPositiveInf(ceil_f32(math.inf(f32)))); + try expect(math.isNegativeInf(ceil_f32(-math.inf(f32)))); + try expect(math.isNan(ceil_f32(math.nan(f32)))); +} + +test ceil_f64 { + try expect(ceil_f64(1.3) == 2.0); + try expect(ceil_f64(-1.3) == -1.0); + try expect(ceil_f64(0.2) == 1.0); + try expect(math.isNegativeZero(ceil_f64(-0.2))); + try expect(math.isPositiveZero(ceil_f64(0.0))); + try expect(math.isNegativeZero(ceil_f64(-0.0))); + try expect(math.isPositiveInf(ceil_f64(math.inf(f64)))); + try expect(math.isNegativeInf(ceil_f64(-math.inf(f64)))); + try expect(math.isNan(ceil_f64(math.nan(f64)))); +} + +test ceil_f80 { + try expect(ceil_f80(1.3) == 2.0); + try expect(ceil_f80(-1.3) == -1.0); + try expect(ceil_f80(0.2) == 1.0); + try expect(math.isNegativeZero(ceil_f80(-0.2))); + try expect(math.isPositiveZero(ceil_f80(0.0))); + try expect(math.isNegativeZero(ceil_f80(-0.0))); + try expect(math.isPositiveInf(ceil_f80(math.inf(f80)))); + try expect(math.isNegativeInf(ceil_f80(-math.inf(f80)))); + try expect(math.isNan(ceil_f80(math.nan(f80)))); +} + +test ceil_f128 { + try expect(ceil_f128(1.3) == 2.0); + try expect(ceil_f128(-1.3) == -1.0); + try expect(ceil_f128(0.2) == 1.0); + try expect(math.isNegativeZero(ceil_f128(-0.2))); + try expect(math.isPositiveZero(ceil_f128(0.0))); + try expect(math.isNegativeZero(ceil_f128(-0.0))); + try expect(math.isPositiveInf(ceil_f128(math.inf(f128)))); + try expect(math.isNegativeInf(ceil_f128(-math.inf(f128)))); + try expect(math.isNan(ceil_f128(math.nan(f128)))); } diff --git a/lib/compiler_rt/fma.zig b/lib/compiler_rt/fma.zig index 61732585db2ece3fb84c3029293cab41662781d2..f10d08fc63f2038fa98cd4b28c5d4ee8a2ca0a84 100644 --- a/lib/compiler_rt/fma.zig +++ b/lib/compiler_rt/fma.zig @@ -23,12 +23,18 @@ comptime { symbol(&fmal, "fmal"); } -pub fn __fmah(x: f16, y: f16, z: f16) callconv(.c) f16 { +fn __fmah(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi, z: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fma_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y), compiler_rt.f16.fromAbi(z))); +} +pub fn fma_f16(x: f16, y: f16, z: f16) f16 { // TODO: more efficient implementation - return @floatCast(fmaf(x, y, z)); + return @floatCast(fma_f32(x, y, z)); } -pub fn fmaf(x: f32, y: f32, z: f32) callconv(.c) f32 { +fn fmaf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi, z: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fma_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y), compiler_rt.f32.fromAbi(z))); +} +pub fn fma_f32(x: f32, y: f32, z: f32) f32 { const xy = @as(f64, x) * y; const xy_z = xy + z; const u = @as(u64, @bitCast(xy_z)); @@ -42,8 +48,11 @@ pub fn fmaf(x: f32, y: f32, z: f32) callconv(.c) f32 { } } +fn fma(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi, z: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fma_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y), compiler_rt.f64.fromAbi(z))); +} /// NOTE: Upstream fma.c has been rewritten completely to raise fp exceptions more accurately. -pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 { +pub fn fma_f64(x: f64, y: f64, z: f64) f64 { if (!math.isFinite(x) or !math.isFinite(y)) { return x * y + z; } @@ -90,11 +99,17 @@ pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 { } } -pub fn __fmax(a: f80, b: f80, c: f80) callconv(.c) f80 { +fn __fmax(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi, c: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fma_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b), compiler_rt.f80.fromAbi(c))); +} +pub fn fma_f80(a: f80, b: f80, c: f80) f80 { // TODO: more efficient implementation - return @floatCast(fmaq(a, b, c)); + return @floatCast(fma_f128(a, b, c)); } +fn fmaq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi, z: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fma_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y), compiler_rt.f128.fromAbi(z))); +} /// Fused multiply-add: Compute x * y + z with a single rounding error. /// /// We use scaling to avoid overflow/underflow, along with the @@ -102,7 +117,7 @@ pub fn __fmax(a: f80, b: f80, c: f80) callconv(.c) f80 { /// /// Dekker, T. A Floating-Point Technique for Extending the /// Available Precision. Numer. Math. 18, 224-242 (1971). -pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 { +pub fn fma_f128(x: f128, y: f128, z: f128) f128 { if (!math.isFinite(x) or !math.isFinite(y)) { return x * y + z; } @@ -151,10 +166,10 @@ pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 { pub fn fmal(x: c_longdouble, y: c_longdouble, z: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return fma(x, y, z), - 80 => return __fmax(x, y, z), - 128 => return fmaq(x, y, z), - else => @compileError("unreachable"), + 64 => return fma_f64(x, y, z), + 80 => return fma_f80(x, y, z), + 128 => return fma_f128(x, y, z), + else => comptime unreachable, } } @@ -316,35 +331,35 @@ fn dd_mul128(a: f128, b: f128) dd128 { test "32" { const epsilon = 0.000001; - try expect(math.approxEqAbs(f32, fmaf(0.0, 5.0, 9.124), 9.124, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(0.2, 5.0, 9.124), 10.124, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(0.8923, 5.0, 9.124), 13.5855, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(1.5, 5.0, 9.124), 16.624, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(37.45, 5.0, 9.124), 196.374004, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(89.123, 5.0, 9.124), 454.739005, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(0.0, 5.0, 9.124), 9.124, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(0.2, 5.0, 9.124), 10.124, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(0.8923, 5.0, 9.124), 13.5855, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(1.5, 5.0, 9.124), 16.624, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(37.45, 5.0, 9.124), 196.374004, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(89.123, 5.0, 9.124), 454.739005, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); } test "64" { const epsilon = 0.000001; - try expect(math.approxEqAbs(f64, fma(0.0, 5.0, 9.124), 9.124, epsilon)); - try expect(math.approxEqAbs(f64, fma(0.2, 5.0, 9.124), 10.124, epsilon)); - try expect(math.approxEqAbs(f64, fma(0.8923, 5.0, 9.124), 13.5855, epsilon)); - try expect(math.approxEqAbs(f64, fma(1.5, 5.0, 9.124), 16.624, epsilon)); - try expect(math.approxEqAbs(f64, fma(37.45, 5.0, 9.124), 196.374, epsilon)); - try expect(math.approxEqAbs(f64, fma(89.123, 5.0, 9.124), 454.739, epsilon)); - try expect(math.approxEqAbs(f64, fma(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(0.0, 5.0, 9.124), 9.124, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(0.2, 5.0, 9.124), 10.124, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(0.8923, 5.0, 9.124), 13.5855, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(1.5, 5.0, 9.124), 16.624, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(37.45, 5.0, 9.124), 196.374, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(89.123, 5.0, 9.124), 454.739, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); } test "128" { const epsilon = 0.000001; - try expect(math.approxEqAbs(f128, fmaq(0.0, 5.0, 9.124), 9.124, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(0.2, 5.0, 9.124), 10.124, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(0.8923, 5.0, 9.124), 13.5855, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(1.5, 5.0, 9.124), 16.624, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(37.45, 5.0, 9.124), 196.374, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(89.123, 5.0, 9.124), 454.739, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(0.0, 5.0, 9.124), 9.124, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(0.2, 5.0, 9.124), 10.124, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(0.8923, 5.0, 9.124), 13.5855, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(1.5, 5.0, 9.124), 16.624, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(37.45, 5.0, 9.124), 196.374, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(89.123, 5.0, 9.124), 454.739, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); } diff --git a/lib/compiler_rt/fmax.zig b/lib/compiler_rt/fmax.zig index 317d93f2d3e42fcfb88c4f36fe2203dab6bfeed2..cf323533952e542e126e11f69ec5a8352c37bcdb 100644 --- a/lib/compiler_rt/fmax.zig +++ b/lib/compiler_rt/fmax.zig @@ -17,32 +17,47 @@ comptime { symbol(&fmaxl, "fmaxl"); } -pub fn __fmaxh(x: f16, y: f16) callconv(.c) f16 { +fn __fmaxh(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fmax_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y))); +} +pub fn fmax_f16(x: f16, y: f16) f16 { return generic_fmax(f16, x, y); } -pub fn fmaxf(x: f32, y: f32) callconv(.c) f32 { +fn fmaxf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fmax_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y))); +} +pub fn fmax_f32(x: f32, y: f32) f32 { return generic_fmax(f32, x, y); } -pub fn fmax(x: f64, y: f64) callconv(.c) f64 { +fn fmax(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fmax_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y))); +} +pub fn fmax_f64(x: f64, y: f64) f64 { return generic_fmax(f64, x, y); } -pub fn __fmaxx(x: f80, y: f80) callconv(.c) f80 { +fn __fmaxx(x: compiler_rt.f80.Abi, y: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fmax_f80(compiler_rt.f80.fromAbi(x), compiler_rt.f80.fromAbi(y))); +} +pub fn fmax_f80(x: f80, y: f80) f80 { return generic_fmax(f80, x, y); } -pub fn fmaxq(x: f128, y: f128) callconv(.c) f128 { +fn fmaxq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fmax_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y))); +} +pub fn fmax_f128(x: f128, y: f128) f128 { return generic_fmax(f128, x, y); } pub fn fmaxl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return fmax(x, y), - 80 => return __fmaxx(x, y), - 128 => return fmaxq(x, y), - else => @compileError("unreachable"), + 64 => return fmax_f64(x, y), + 80 => return fmax_f80(x, y), + 128 => return fmax_f128(x, y), + else => comptime unreachable, } } diff --git a/lib/compiler_rt/fmin.zig b/lib/compiler_rt/fmin.zig index 36cf9c121bbf17c1e282cfcf982f69ce7f1ec17c..48b5dcdc225118ce3a2096b15c98b0b534f75ae3 100644 --- a/lib/compiler_rt/fmin.zig +++ b/lib/compiler_rt/fmin.zig @@ -17,32 +17,47 @@ comptime { symbol(&fminl, "fminl"); } -pub fn __fminh(x: f16, y: f16) callconv(.c) f16 { +fn __fminh(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fmin_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y))); +} +pub fn fmin_f16(x: f16, y: f16) f16 { return generic_fmin(f16, x, y); } -pub fn fminf(x: f32, y: f32) callconv(.c) f32 { +fn fminf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fmin_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y))); +} +pub fn fmin_f32(x: f32, y: f32) f32 { return generic_fmin(f32, x, y); } -pub fn fmin(x: f64, y: f64) callconv(.c) f64 { +fn fmin(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fmin_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y))); +} +pub fn fmin_f64(x: f64, y: f64) f64 { return generic_fmin(f64, x, y); } -pub fn __fminx(x: f80, y: f80) callconv(.c) f80 { +fn __fminx(x: compiler_rt.f80.Abi, y: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fmin_f80(compiler_rt.f80.fromAbi(x), compiler_rt.f80.fromAbi(y))); +} +pub fn fmin_f80(x: f80, y: f80) f80 { return generic_fmin(f80, x, y); } -pub fn fminq(x: f128, y: f128) callconv(.c) f128 { +fn fminq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fmin_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y))); +} +pub fn fmin_f128(x: f128, y: f128) f128 { return generic_fmin(f128, x, y); } pub fn fminl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return fmin(x, y), - 80 => return __fminx(x, y), - 128 => return fminq(x, y), - else => @compileError("unreachable"), + 64 => return fmin_f64(x, y), + 80 => return fmin_f80(x, y), + 128 => return fmin_f128(x, y), + else => comptime unreachable, } } diff --git a/lib/compiler_rt/fmod.zig b/lib/compiler_rt/fmod.zig index 009eedd8ac84ab7eb905a74900fc17d07e8be421..636138516bf1f13d2a15b597d21fd6a617e7ee0d 100644 --- a/lib/compiler_rt/fmod.zig +++ b/lib/compiler_rt/fmod.zig @@ -19,22 +19,34 @@ comptime { symbol(&fmodl, "fmodl"); } -pub fn __fmodh(x: f16, y: f16) callconv(.c) f16 { +fn __fmodh(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fmod_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); +} +pub fn fmod_f16(x: f16, y: f16) f16 { // TODO: more efficient implementation - return @floatCast(fmodf(x, y)); + return @floatCast(fmod_f32(x, y)); } -pub fn fmodf(x: f32, y: f32) callconv(.c) f32 { +fn fmodf(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fmod_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); +} +pub fn fmod_f32(x: f32, y: f32) f32 { return generic_fmod(f32, x, y); } -pub fn fmod(x: f64, y: f64) callconv(.c) f64 { +fn fmod(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fmod_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); +} +pub fn fmod_f64(x: f64, y: f64) f64 { return generic_fmod(f64, x, y); } +fn __fmodx(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fmod_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} /// fmodx - floating modulo large, returns the remainder of division for f80 types /// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits -pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 { +pub fn fmod_f80(a: f80, b: f80) f80 { const T = f80; const Z = @Int(.unsigned, @bitSizeOf(T)); @@ -130,9 +142,12 @@ pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 { } } +fn fmodq(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fmod_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); +} /// fmodq - floating modulo large, returns the remainder of division for f128 types /// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits -pub fn fmodq(a: f128, b: f128) callconv(.c) f128 { +pub fn fmod_f128(a: f128, b: f128) f128 { var amod = a; var bmod = b; const aPtr_u64: [*]u64 = @ptrCast(&amod); @@ -251,10 +266,10 @@ pub fn fmodq(a: f128, b: f128) callconv(.c) f128 { pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return fmod(a, b), - 80 => return __fmodx(a, b), - 128 => return fmodq(a, b), - else => @compileError("unreachable"), + 64 => return fmod_f64(a, b), + 80 => return fmod_f80(a, b), + 128 => return fmod_f128(a, b), + else => comptime unreachable, } } @@ -342,42 +357,42 @@ inline fn generic_fmod(comptime T: type, x: T, y: T) T { return @bitCast(ux); } -test "fmodf" { +test fmod_f32 { const nan_val = math.nan(f32); const inf_val = math.inf(f32); - try std.testing.expect(math.isNan(fmodf(nan_val, 1.0))); - try std.testing.expect(math.isNan(fmodf(1.0, nan_val))); - try std.testing.expect(math.isNan(fmodf(inf_val, 1.0))); - try std.testing.expect(math.isNan(fmodf(0.0, 0.0))); - try std.testing.expect(math.isNan(fmodf(1.0, 0.0))); + try std.testing.expect(math.isNan(fmod_f32(nan_val, 1.0))); + try std.testing.expect(math.isNan(fmod_f32(1.0, nan_val))); + try std.testing.expect(math.isNan(fmod_f32(inf_val, 1.0))); + try std.testing.expect(math.isNan(fmod_f32(0.0, 0.0))); + try std.testing.expect(math.isNan(fmod_f32(1.0, 0.0))); - try std.testing.expectEqual(@as(f32, 0.0), fmodf(0.0, 2.0)); - try std.testing.expectEqual(@as(f32, -0.0), fmodf(-0.0, 2.0)); + try std.testing.expectEqual(@as(f32, 0.0), fmod_f32(0.0, 2.0)); + try std.testing.expectEqual(@as(f32, -0.0), fmod_f32(-0.0, 2.0)); - try std.testing.expectEqual(@as(f32, -2.0), fmodf(-32.0, 10.0)); - try std.testing.expectEqual(@as(f32, -2.0), fmodf(-32.0, -10.0)); - try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, 10.0)); - try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, -10.0)); + try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, 10.0)); + try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, -10.0)); + try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, 10.0)); + try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, -10.0)); } -test "fmod" { +test fmod_f64 { const nan_val = math.nan(f64); const inf_val = math.inf(f64); - try std.testing.expect(math.isNan(fmod(nan_val, 1.0))); - try std.testing.expect(math.isNan(fmod(1.0, nan_val))); - try std.testing.expect(math.isNan(fmod(inf_val, 1.0))); - try std.testing.expect(math.isNan(fmod(0.0, 0.0))); - try std.testing.expect(math.isNan(fmod(1.0, 0.0))); + try std.testing.expect(math.isNan(fmod_f64(nan_val, 1.0))); + try std.testing.expect(math.isNan(fmod_f64(1.0, nan_val))); + try std.testing.expect(math.isNan(fmod_f64(inf_val, 1.0))); + try std.testing.expect(math.isNan(fmod_f64(0.0, 0.0))); + try std.testing.expect(math.isNan(fmod_f64(1.0, 0.0))); - try std.testing.expectEqual(@as(f64, 0.0), fmod(0.0, 2.0)); - try std.testing.expectEqual(@as(f64, -0.0), fmod(-0.0, 2.0)); + try std.testing.expectEqual(@as(f64, 0.0), fmod_f64(0.0, 2.0)); + try std.testing.expectEqual(@as(f64, -0.0), fmod_f64(-0.0, 2.0)); - try std.testing.expectEqual(@as(f64, -2.0), fmod(-32.0, 10.0)); - try std.testing.expectEqual(@as(f64, -2.0), fmod(-32.0, -10.0)); - try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, 10.0)); - try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, -10.0)); + try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, 10.0)); + try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, -10.0)); + try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, 10.0)); + try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, -10.0)); } test { diff --git a/lib/compiler_rt/fmodq_test.zig b/lib/compiler_rt/fmodq_test.zig index 07ddb8d182e41fe2ff80414aeff256728e1ce365..b98dc0762e664f09b0d648e290658bf4502da416 100644 --- a/lib/compiler_rt/fmodq_test.zig +++ b/lib/compiler_rt/fmodq_test.zig @@ -1,52 +1,52 @@ const std = @import("std"); -const fmod = @import("fmod.zig"); +const fmod_f128 = @import("fmod.zig").fmod_f128; const testing = std.testing; -fn test_fmodq(a: f128, b: f128, exp: f128) !void { - const res = fmod.fmodq(a, b); +fn test_fmod_f128(a: f128, b: f128, exp: f128) !void { + const res = fmod_f128(a, b); try testing.expect(exp == res); } -fn test_fmodq_nans() !void { - try testing.expect(std.math.isNan(fmod.fmodq(1.0, std.math.nan(f128)))); - try testing.expect(std.math.isNan(fmod.fmodq(1.0, -std.math.nan(f128)))); - try testing.expect(std.math.isNan(fmod.fmodq(std.math.nan(f128), 1.0))); - try testing.expect(std.math.isNan(fmod.fmodq(-std.math.nan(f128), 1.0))); +fn test_fmod_f128_nans() !void { + try testing.expect(std.math.isNan(fmod_f128(1.0, std.math.nan(f128)))); + try testing.expect(std.math.isNan(fmod_f128(1.0, -std.math.nan(f128)))); + try testing.expect(std.math.isNan(fmod_f128(std.math.nan(f128), 1.0))); + try testing.expect(std.math.isNan(fmod_f128(-std.math.nan(f128), 1.0))); } -fn test_fmodq_infs() !void { - try testing.expect(fmod.fmodq(1.0, std.math.inf(f128)) == 1.0); - try testing.expect(fmod.fmodq(1.0, -std.math.inf(f128)) == 1.0); - try testing.expect(std.math.isNan(fmod.fmodq(std.math.inf(f128), 1.0))); - try testing.expect(std.math.isNan(fmod.fmodq(-std.math.inf(f128), 1.0))); +fn test_fmod_f128_infs() !void { + try testing.expect(fmod_f128(1.0, std.math.inf(f128)) == 1.0); + try testing.expect(fmod_f128(1.0, -std.math.inf(f128)) == 1.0); + try testing.expect(std.math.isNan(fmod_f128(std.math.inf(f128), 1.0))); + try testing.expect(std.math.isNan(fmod_f128(-std.math.inf(f128), 1.0))); } -test "fmodq" { - try test_fmodq(6.8, 4.0, 2.8); - try test_fmodq(6.8, -4.0, 2.8); - try test_fmodq(-6.8, 4.0, -2.8); - try test_fmodq(-6.8, -4.0, -2.8); - try test_fmodq(3.0, 2.0, 1.0); - try test_fmodq(-5.0, 3.0, -2.0); - try test_fmodq(3.0, 2.0, 1.0); - try test_fmodq(1.0, 2.0, 1.0); - try test_fmodq(0.0, 1.0, 0.0); - try test_fmodq(-0.0, 1.0, -0.0); - try test_fmodq(7046119.0, 5558362.0, 1487757.0); - try test_fmodq(9010357.0, 1957236.0, 1181413.0); - try test_fmodq(5192296858534827628530496329220095, 10.0, 5.0); - try test_fmodq(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157); +test fmod_f128 { + try test_fmod_f128(6.8, 4.0, 2.8); + try test_fmod_f128(6.8, -4.0, 2.8); + try test_fmod_f128(-6.8, 4.0, -2.8); + try test_fmod_f128(-6.8, -4.0, -2.8); + try test_fmod_f128(3.0, 2.0, 1.0); + try test_fmod_f128(-5.0, 3.0, -2.0); + try test_fmod_f128(3.0, 2.0, 1.0); + try test_fmod_f128(1.0, 2.0, 1.0); + try test_fmod_f128(0.0, 1.0, 0.0); + try test_fmod_f128(-0.0, 1.0, -0.0); + try test_fmod_f128(7046119.0, 5558362.0, 1487757.0); + try test_fmod_f128(9010357.0, 1957236.0, 1181413.0); + try test_fmod_f128(5192296858534827628530496329220095, 10.0, 5.0); + try test_fmod_f128(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157); // Denormals const a1: f128 = 0xedcb34a235253948765432134674p-16494; const b1: f128 = 0x5d2e38791cfbc0737402da5a9518p-16494; const exp1: f128 = 0x336ec3affb2db8618e4e7d5e1c44p-16494; - try test_fmodq(a1, b1, exp1); + try test_fmod_f128(a1, b1, exp1); const a2: f128 = 0x0.7654_3210_fdec_ba98_7654_3210_fdecp-16382; const b2: f128 = 0x0.0012_fdac_bdef_1234_fdec_3222_1111p-16382; const exp2: f128 = 0x0.0001_aecd_9d66_4a6e_67b7_d7d0_a901p-16382; - try test_fmodq(a2, b2, exp2); + try test_fmod_f128(a2, b2, exp2); - try test_fmodq_nans(); - try test_fmodq_infs(); + try test_fmod_f128_nans(); + try test_fmod_f128_infs(); } diff --git a/lib/compiler_rt/fmodx_test.zig b/lib/compiler_rt/fmodx_test.zig index ca8229147ab693264b555676af664e7bf8acccbc..b32d354094ed97a1ab8d7c9d840610b9a8ac12a7 100644 --- a/lib/compiler_rt/fmodx_test.zig +++ b/lib/compiler_rt/fmodx_test.zig @@ -1,52 +1,52 @@ const std = @import("std"); const builtin = @import("builtin"); -const fmod = @import("fmod.zig"); +const fmod_f80 = @import("fmod.zig").fmod_f80; const testing = std.testing; -fn test_fmodx(a: f80, b: f80, exp: f80) !void { - const res = fmod.__fmodx(a, b); +fn test_fmod_f80(a: f80, b: f80, exp: f80) !void { + const res = fmod_f80(a, b); try testing.expect(exp == res); } -fn test_fmodx_nans() !void { - try testing.expect(std.math.isNan(fmod.__fmodx(1.0, std.math.nan(f80)))); - try testing.expect(std.math.isNan(fmod.__fmodx(1.0, -std.math.nan(f80)))); - try testing.expect(std.math.isNan(fmod.__fmodx(std.math.nan(f80), 1.0))); - try testing.expect(std.math.isNan(fmod.__fmodx(-std.math.nan(f80), 1.0))); +fn test_fmod_f80_nans() !void { + try testing.expect(std.math.isNan(fmod_f80(1.0, std.math.nan(f80)))); + try testing.expect(std.math.isNan(fmod_f80(1.0, -std.math.nan(f80)))); + try testing.expect(std.math.isNan(fmod_f80(std.math.nan(f80), 1.0))); + try testing.expect(std.math.isNan(fmod_f80(-std.math.nan(f80), 1.0))); } -fn test_fmodx_infs() !void { - try testing.expect(fmod.__fmodx(1.0, std.math.inf(f80)) == 1.0); - try testing.expect(fmod.__fmodx(1.0, -std.math.inf(f80)) == 1.0); - try testing.expect(std.math.isNan(fmod.__fmodx(std.math.inf(f80), 1.0))); - try testing.expect(std.math.isNan(fmod.__fmodx(-std.math.inf(f80), 1.0))); +fn test_fmod_f80_infs() !void { + try testing.expect(fmod_f80(1.0, std.math.inf(f80)) == 1.0); + try testing.expect(fmod_f80(1.0, -std.math.inf(f80)) == 1.0); + try testing.expect(std.math.isNan(fmod_f80(std.math.inf(f80), 1.0))); + try testing.expect(std.math.isNan(fmod_f80(-std.math.inf(f80), 1.0))); } -test "fmodx" { - try test_fmodx(6.4, 4.0, 2.4); - try test_fmodx(6.4, -4.0, 2.4); - try test_fmodx(-6.4, 4.0, -2.4); - try test_fmodx(-6.4, -4.0, -2.4); - try test_fmodx(3.0, 2.0, 1.0); - try test_fmodx(-5.0, 3.0, -2.0); - try test_fmodx(3.0, 2.0, 1.0); - try test_fmodx(1.0, 2.0, 1.0); - try test_fmodx(0.0, 1.0, 0.0); - try test_fmodx(-0.0, 1.0, -0.0); - try test_fmodx(7046119.0, 5558362.0, 1487757.0); - try test_fmodx(9010357.0, 1957236.0, 1181413.0); - try test_fmodx(9223372036854775807, 10.0, 7.0); +test fmod_f80 { + try test_fmod_f80(6.4, 4.0, 2.4); + try test_fmod_f80(6.4, -4.0, 2.4); + try test_fmod_f80(-6.4, 4.0, -2.4); + try test_fmod_f80(-6.4, -4.0, -2.4); + try test_fmod_f80(3.0, 2.0, 1.0); + try test_fmod_f80(-5.0, 3.0, -2.0); + try test_fmod_f80(3.0, 2.0, 1.0); + try test_fmod_f80(1.0, 2.0, 1.0); + try test_fmod_f80(0.0, 1.0, 0.0); + try test_fmod_f80(-0.0, 1.0, -0.0); + try test_fmod_f80(7046119.0, 5558362.0, 1487757.0); + try test_fmod_f80(9010357.0, 1957236.0, 1181413.0); + try test_fmod_f80(9223372036854775807, 10.0, 7.0); // Denormals const a1: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381; const b1: f80 = 0x0.2e97_1c3c_8e7d_e03ap-16381; const exp1: f80 = 0x0.19b7_61d7_fd96_dc30p-16381; - try test_fmodx(a1, b1, exp1); + try test_fmod_f80(a1, b1, exp1); const a2: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381; const b2: f80 = 0x0.0e97_1c3c_8e7d_e03ap-16381; const exp2: f80 = 0x0.022c_b86c_a6a3_9ad4p-16381; - try test_fmodx(a2, b2, exp2); + try test_fmod_f80(a2, b2, exp2); - try test_fmodx_nans(); - try test_fmodx_infs(); + try test_fmod_f80_nans(); + try test_fmod_f80_infs(); } diff --git a/lib/compiler_rt/gedf2.zig b/lib/compiler_rt/gedf2.zig deleted file mode 100644 index f6b4b6d718fd20d8068244cfa6250f030f890e92..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/gedf2.zig +++ /dev/null @@ -1,35 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const comparef = @import("./comparef.zig"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dcmpge, "__aeabi_dcmpge"); - symbol(&__aeabi_dcmpgt, "__aeabi_dcmpgt"); - } else { - symbol(&__gedf2, "__gedf2"); - symbol(&__gtdf2, "__gtdf2"); - } -} - -/// "These functions return a value greater than or equal to zero if neither -/// argument is NaN, and a is greater than or equal to b." -pub fn __gedf2(a: f64, b: f64) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f64, comparef.GE, a, b)); -} - -/// "These functions return a value greater than zero if neither argument is NaN, -/// and a is strictly greater than b." -pub fn __gtdf2(a: f64, b: f64) callconv(.c) i32 { - return __gedf2(a, b); -} - -fn __aeabi_dcmpge(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f64, comparef.GE, a, b) != .Less); -} - -fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f64, comparef.GE, a, b) == .Greater); -} diff --git a/lib/compiler_rt/gehf2.zig b/lib/compiler_rt/gehf2.zig deleted file mode 100644 index 8008a06849887d2f317be4517a5cb6c485c2675a..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/gehf2.zig +++ /dev/null @@ -1,21 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const symbol = @import("../compiler_rt.zig").symbol; -const comparef = @import("./comparef.zig"); - -comptime { - symbol(&__gehf2, "__gehf2"); - symbol(&__gthf2, "__gthf2"); -} - -/// "These functions return a value greater than or equal to zero if neither -/// argument is NaN, and a is greater than or equal to b." -pub fn __gehf2(a: f16, b: f16) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f16, comparef.GE, a, b)); -} - -/// "These functions return a value greater than zero if neither argument is NaN, -/// and a is strictly greater than b." -pub fn __gthf2(a: f16, b: f16) callconv(.c) i32 { - return __gehf2(a, b); -} diff --git a/lib/compiler_rt/gesf2.zig b/lib/compiler_rt/gesf2.zig deleted file mode 100644 index 7f5022104eba9378efe6184befcd7f40f479306f..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/gesf2.zig +++ /dev/null @@ -1,35 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const comparef = @import("./comparef.zig"); - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_fcmpge, "__aeabi_fcmpge"); - symbol(&__aeabi_fcmpgt, "__aeabi_fcmpgt"); - } else { - symbol(&__gesf2, "__gesf2"); - symbol(&__gtsf2, "__gtsf2"); - } -} - -/// "These functions return a value greater than or equal to zero if neither -/// argument is NaN, and a is greater than or equal to b." -pub fn __gesf2(a: f32, b: f32) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f32, comparef.GE, a, b)); -} - -/// "These functions return a value greater than zero if neither argument is NaN, -/// and a is strictly greater than b." -pub fn __gtsf2(a: f32, b: f32) callconv(.c) i32 { - return __gesf2(a, b); -} - -fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f32, comparef.GE, a, b) != .Less); -} - -fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f32, comparef.LE, a, b) == .Greater); -} diff --git a/lib/compiler_rt/getf2.zig b/lib/compiler_rt/getf2.zig deleted file mode 100644 index 88a91600f1e32c5f7124f5e9be9d5828b2471f2e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/getf2.zig +++ /dev/null @@ -1,26 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const comparef = @import("./comparef.zig"); - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__getf2, "__gekf2"); - symbol(&__gttf2, "__gtkf2"); - } - symbol(&__getf2, "__getf2"); - symbol(&__gttf2, "__gttf2"); -} - -/// "These functions return a value greater than or equal to zero if neither -/// argument is NaN, and a is greater than or equal to b." -fn __getf2(a: f128, b: f128) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f128, comparef.GE, a, b)); -} - -/// "These functions return a value greater than zero if neither argument is NaN, -/// and a is strictly greater than b." -fn __gttf2(a: f128, b: f128) callconv(.c) i32 { - return __getf2(a, b); -} diff --git a/lib/compiler_rt/gexf2.zig b/lib/compiler_rt/gexf2.zig deleted file mode 100644 index 9f1f356187cdf9c7b85be2d49f9e2e73439f381b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/gexf2.zig +++ /dev/null @@ -1,15 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const comparef = @import("./comparef.zig"); - -comptime { - symbol(&__gexf2, "__gexf2"); - symbol(&__gtxf2, "__gtxf2"); -} - -fn __gexf2(a: f80, b: f80) callconv(.c) i32 { - return @backingInt(comparef.cmp_f80(comparef.GE, a, b)); -} - -fn __gtxf2(a: f80, b: f80) callconv(.c) i32 { - return __gexf2(a, b); -} diff --git a/lib/compiler_rt/int.zig b/lib/compiler_rt/int.zig index 48c900207bce8946adf6bb9cafe9407b214946d4..e387be858213a7afb575bd3b81f62e016e16a19e 100644 --- a/lib/compiler_rt/int.zig +++ b/lib/compiler_rt/int.zig @@ -36,7 +36,7 @@ comptime { pub fn __divmodti4(a: i128, b: i128, rem: *i128) callconv(.c) i128 { const d = __divti3(a, b); - rem.* = a -% (d * b); + rem.* = a - d *% b; return d; } @@ -69,7 +69,7 @@ fn test_one_divmodti4(a: i128, b: i128, expected_q: i128, expected_r: i128) !voi pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.c) i64 { const d = __divdi3(a, b); - rem.* = a -% (d * b); + rem.* = a - d *% b; return d; } @@ -79,21 +79,20 @@ fn test_one_divmoddi4(a: i64, b: i64, expected_q: i64, expected_r: i64) !void { try testing.expect(q == expected_q and r == expected_r); } -const cases__divmoddi4 = - [_][4]i64{ - [_]i64{ 0, 1, 0, 0 }, - [_]i64{ 0, -1, 0, 0 }, - [_]i64{ 2, 1, 2, 0 }, - [_]i64{ 2, -1, -2, 0 }, - [_]i64{ -2, 1, -2, 0 }, - [_]i64{ -2, -1, 2, 0 }, - [_]i64{ 7, 5, 1, 2 }, - [_]i64{ -7, 5, -1, -2 }, - [_]i64{ 19, 5, 3, 4 }, - [_]i64{ 19, -5, -3, 4 }, - [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 }, - [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 }, - }; +const cases__divmoddi4 = [_][4]i64{ + [_]i64{ 0, 1, 0, 0 }, + [_]i64{ 0, -1, 0, 0 }, + [_]i64{ 2, 1, 2, 0 }, + [_]i64{ 2, -1, -2, 0 }, + [_]i64{ -2, 1, -2, 0 }, + [_]i64{ -2, -1, 2, 0 }, + [_]i64{ 7, 5, 1, 2 }, + [_]i64{ -7, 5, -1, -2 }, + [_]i64{ 19, 5, 3, 4 }, + [_]i64{ 19, -5, -3, 4 }, + [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 }, + [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 }, +}; test "test_divmoddi4" { for (cases__divmoddi4) |case| { @@ -105,10 +104,6 @@ pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.c) u64 { return udivmod(u64, a, b, maybe_rem); } -test "test_udivmoddi4" { - _ = @import("udivmoddi4_test.zig"); -} - pub fn __divdi3(a: i64, b: i64) callconv(.c) i64 { // Set aside the sign of the quotient. const sign: u64 = @bitCast((a ^ b) >> 63); @@ -209,25 +204,24 @@ fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) !void { pub fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.c) i32 { const d = __divsi3(a, b); - rem.* = a -% (d * b); + rem.* = a - d *% b; return d; } -const cases__divmodsi4 = - [_][4]i32{ - [_]i32{ 0, 1, 0, 0 }, - [_]i32{ 0, -1, 0, 0 }, - [_]i32{ 2, 1, 2, 0 }, - [_]i32{ 2, -1, -2, 0 }, - [_]i32{ -2, 1, -2, 0 }, - [_]i32{ -2, -1, 2, 0 }, - [_]i32{ 7, 5, 1, 2 }, - [_]i32{ -7, 5, -1, -2 }, - [_]i32{ 19, 5, 3, 4 }, - [_]i32{ 19, -5, -3, 4 }, - [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 }, - [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 }, - }; +const cases__divmodsi4 = [_][4]i32{ + [_]i32{ 0, 1, 0, 0 }, + [_]i32{ 0, -1, 0, 0 }, + [_]i32{ 2, 1, 2, 0 }, + [_]i32{ 2, -1, -2, 0 }, + [_]i32{ -2, 1, -2, 0 }, + [_]i32{ -2, -1, 2, 0 }, + [_]i32{ 7, 5, 1, 2 }, + [_]i32{ -7, 5, -1, -2 }, + [_]i32{ 19, 5, 3, 4 }, + [_]i32{ 19, -5, -3, 4 }, + [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 }, + [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 }, +}; fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) !void { var r: i32 = undefined; @@ -243,7 +237,7 @@ test "test_divmodsi4" { pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.c) u32 { const d = __udivsi3(a, b); - rem.* = @bitCast(@as(i32, @bitCast(a)) -% (@as(i32, @bitCast(d)) * @as(i32, @bitCast(b)))); + rem.* = a - d * b; return d; } @@ -486,7 +480,7 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void { } pub fn __modsi3(n: i32, d: i32) callconv(.c) i32 { - return n -% __divsi3(n, d) * d; + return n - __divsi3(n, d) *% d; } test "test_modsi3" { @@ -515,7 +509,7 @@ fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void { } pub fn __umodsi3(n: u32, d: u32) callconv(.c) u32 { - return n -% __udivsi3(n, d) * d; + return n - __udivsi3(n, d) * d; } test "test_umodsi3" { @@ -663,3 +657,8 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void { const r: u32 = __umodsi3(a, b); try testing.expect(r == expected_r); } + +test { + _ = @import("udivmodsi4_test.zig"); + _ = @import("udivmoddi4_test.zig"); +} diff --git a/lib/compiler_rt/int_from_float.zig b/lib/compiler_rt/int_from_float.zig index 5445e7fb7c6d36111d89112350b5bfc9ced375c8..8eb4c2fcbc79f9d254255372062e473443bffdde 100644 --- a/lib/compiler_rt/int_from_float.zig +++ b/lib/compiler_rt/int_from_float.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const std = @import("std"); const math = std.math; const Log2Int = std.math.Log2Int; @@ -6,29 +7,532 @@ const compiler_rt = @import("../compiler_rt.zig"); const symbol = compiler_rt.symbol; comptime { - symbol(&__fixxfti, "__fixxfti"); symbol(&__fixhfsi, "__fixhfsi"); symbol(&__fixhfdi, "__fixhfdi"); symbol(&__fixhfti, "__fixhfti"); + symbol(&__fixhfei, "__fixhfei"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_f2iz, "__aeabi_f2iz"); + symbol(&__aeabi_f2lz, "__aeabi_f2lz"); + symbol(&__aeabi_fixsfti, "__fixsfti"); + } else { + symbol(&__fixsfsi, "__fixsfsi"); + symbol(&__fixsfdi, "__fixsfdi"); + if (compiler_rt.want_windows_arm_abi) symbol(&__fixsfdi, "__stoi64"); + symbol(&__fixsfti, "__fixsfti"); + } + symbol(&__fixsfei, "__fixsfei"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_d2iz, "__aeabi_d2iz"); + symbol(&__aeabi_d2lz, "__aeabi_d2lz"); + symbol(&__aeabi_fixdfti, "__fixdfti"); + } else { + symbol(&__fixdfsi, "__fixdfsi"); + symbol(&__fixdfdi, "__fixdfdi"); + if (compiler_rt.want_windows_arm_abi) symbol(&__fixdfdi, "__dtoi64"); + symbol(&__fixdfti, "__fixdfti"); + } + symbol(&__fixdfei, "__fixdfei"); + + symbol(&__fixxfsi, "__fixxfsi"); + symbol(&__fixxfdi, "__fixxfdi"); + symbol(&__fixxfti, "__fixxfti"); + symbol(&__fixxfei, "__fixxfei"); + + if (compiler_rt.want_ppc_abi) { + symbol(&__fixtfsi, "__fixkfsi"); + symbol(&__fixtfdi, "__fixkfdi"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_qtoi, "_Qp_qtoi"); + symbol(&_Qp_qtox, "_Qp_qtox"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__fixtfsi, "_Q_qtoi"); + symbol(&__fixtfdi, "_Q_qtoll"); + } else { + symbol(&__fixtfsi, "__fixtfsi"); + symbol(&__fixtfdi, "__fixtfdi"); + } + if (compiler_rt.want_ppc_abi) { + symbol(&__fixtfti, "__fixkfti"); + symbol(&__fixtfei, "__fixkfei"); + } else { + symbol(&__fixtfti, "__fixtfti"); + symbol(&__fixtfei, "__fixtfei"); + } +} + +fn __fixhfsi(a: compiler_rt.f16.Abi) callconv(.c) i32 { + return i32_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn i32_intFromFloat_f16(a: f16) i32 { + return intFromFloat(i32, a); } -pub fn __fixhfti(a: f16) callconv(.c) i128 { +fn __fixhfdi(a: compiler_rt.f16.Abi) callconv(.c) i64 { + return i64_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn i64_intFromFloat_f16(a: f16) i64 { + return intFromFloat(i64, a); +} + +fn __fixhfti(a: compiler_rt.f16.Abi) callconv(.c) i128 { + return i128_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn i128_intFromFloat_f16(a: f16) i128 { return intFromFloat(i128, a); } -fn __fixhfdi(a: f16) callconv(.c) i64 { +fn __fixhfei(r: [*]u8, bits: usize, a: compiler_rt.f16.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return signed_intFromFloat_f16(r[0..byte_size], compiler_rt.f16.fromAbi(a)); +} +pub fn signed_intFromFloat_f16(result: []u8, a: f16) void { + bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); +} + +fn __fixsfsi(a: compiler_rt.f32.Abi) callconv(.c) i32 { + return i32_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_f2iz(a: f32) callconv(.{ .arm_aapcs = .{} }) i32 { + return i32_intFromFloat_f32(a); +} +pub fn i32_intFromFloat_f32(a: f32) i32 { + return intFromFloat(i32, a); +} + +fn __fixsfdi(a: compiler_rt.f32.Abi) callconv(.c) i64 { + return i64_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_f2lz(a: f32) callconv(.{ .arm_aapcs = .{} }) i64 { + return i64_intFromFloat_f32(a); +} +pub fn i64_intFromFloat_f32(a: f32) i64 { return intFromFloat(i64, a); } -fn __fixhfsi(a: f16) callconv(.c) i32 { +fn __fixsfti(a: compiler_rt.f32.Abi) callconv(.c) i128 { + return i128_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_fixsfti(_: compiler_rt.f32.Abi) callconv(.naked) i128 { + switch (builtin.abi.float()) { + .soft => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r1, r0 + \\ mov r0, sp + \\ bl %[__fixsfti] + \\ pop {r0-r4, pc} + : + : [__fixsfti] "X" (&__fixsfti), + ), + .hard => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r0, sp + \\ bl %[__fixsfti] + \\ pop {r0-r4, pc} + : + : [__fixsfti] "X" (&__fixsfti), + ), + } +} +pub fn i128_intFromFloat_f32(a: f32) i128 { + return intFromFloat(i128, a); +} + +fn __fixsfei(r: [*]u8, bits: usize, a: compiler_rt.f32.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return signed_intFromFloat_f32(r[0..byte_size], compiler_rt.f32.fromAbi(a)); +} +pub fn signed_intFromFloat_f32(result: []u8, a: f32) void { + bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); +} + +fn __fixdfsi(a: compiler_rt.f64.Abi) callconv(.c) i32 { + return i32_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_d2iz(a: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return i32_intFromFloat_f64(a); +} +pub fn i32_intFromFloat_f64(a: f64) i32 { return intFromFloat(i32, a); } -pub fn __fixxfti(a: f80) callconv(.c) i128 { +fn __fixdfdi(a: compiler_rt.f64.Abi) callconv(.c) i64 { + return i64_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_d2lz(a: f64) callconv(.{ .arm_aapcs = .{} }) i64 { + return i64_intFromFloat_f64(a); +} +pub fn i64_intFromFloat_f64(a: f64) i64 { + return intFromFloat(i64, a); +} + +fn __fixdfti(a: compiler_rt.f64.Abi) callconv(.c) i128 { + return i128_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_fixdfti(_: compiler_rt.f64.Abi) callconv(.naked) i128 { + switch (builtin.abi.float()) { + .soft => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r3, r1 + \\ mov r2, r0 + \\ mov r0, sp + \\ bl %[__fixdfti] + \\ pop {r0-r4, pc} + : + : [__fixdfti] "X" (&__fixdfti), + ), + .hard => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r0, sp + \\ bl %[__fixdfti] + \\ pop {r0-r4, pc} + : + : [__fixdfti] "X" (&__fixdfti), + ), + } +} +pub fn i128_intFromFloat_f64(a: f64) i128 { return intFromFloat(i128, a); } -pub inline fn intFromFloat(comptime I: type, a: anytype) I { +fn __fixdfei(r: [*]u8, bits: usize, a: compiler_rt.f64.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return signed_intFromFloat_f64(r[0..byte_size], compiler_rt.f64.fromAbi(a)); +} +pub fn signed_intFromFloat_f64(result: []u8, a: f64) void { + bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); +} + +fn __fixxfsi(a: compiler_rt.f80.Abi) callconv(.c) i32 { + return i32_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn i32_intFromFloat_f80(a: f80) i32 { + return intFromFloat(i32, a); +} + +fn __fixxfdi(a: compiler_rt.f80.Abi) callconv(.c) i64 { + return i64_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn i64_intFromFloat_f80(a: f80) i64 { + return intFromFloat(i64, a); +} + +fn __fixxfti(a: compiler_rt.f80.Abi) callconv(.c) i128 { + return i128_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn i128_intFromFloat_f80(a: f80) i128 { + return intFromFloat(i128, a); +} + +fn __fixxfei(r: [*]u8, bits: usize, a: compiler_rt.f80.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return signed_intFromFloat_f80(r[0..byte_size], compiler_rt.f80.fromAbi(a)); +} +pub fn signed_intFromFloat_f80(result: []u8, a: f80) void { + bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); +} + +fn __fixtfsi(a: compiler_rt.f128.Abi) callconv(.c) i32 { + return i32_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +fn _Qp_qtoi(a: *const f128) callconv(.c) i32 { + return i32_intFromFloat_f128(a.*); +} +pub fn i32_intFromFloat_f128(a: f128) i32 { + return intFromFloat(i32, a); +} + +fn __fixtfdi(a: compiler_rt.f128.Abi) callconv(.c) i64 { + return i64_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +fn _Qp_qtox(a: *const f128) callconv(.c) i64 { + return i64_intFromFloat_f128(a.*); +} +pub fn i64_intFromFloat_f128(a: f128) i64 { + return intFromFloat(i64, a); +} + +fn __fixtfti(a: compiler_rt.f128.Abi) callconv(.c) i128 { + return i128_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +pub fn i128_intFromFloat_f128(a: f128) i128 { + return intFromFloat(i128, a); +} + +fn __fixtfei(r: [*]u8, bits: usize, a: compiler_rt.f128.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return signed_intFromFloat_f128(r[0..byte_size], compiler_rt.f128.fromAbi(a)); +} +pub fn signed_intFromFloat_f128(result: []u8, a: f128) void { + bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); +} + +comptime { + symbol(&__fixunshfsi, "__fixunshfsi"); + symbol(&__fixunshfdi, "__fixunshfdi"); + symbol(&__fixunshfti, "__fixunshfti"); + symbol(&__fixunshfei, "__fixunshfei"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_f2uiz, "__aeabi_f2uiz"); + symbol(&__aeabi_f2ulz, "__aeabi_f2ulz"); + symbol(&__aeabi_fixunssfti, "__fixunssfti"); + } else { + symbol(&__fixunssfsi, "__fixunssfsi"); + symbol(&__fixunssfdi, "__fixunssfdi"); + if (compiler_rt.want_windows_arm_abi) symbol(&__fixunssfdi, "__stou64"); + symbol(&__fixunssfti, "__fixunssfti"); + } + symbol(&__fixunssfei, "__fixunssfei"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_d2uiz, "__aeabi_d2uiz"); + symbol(&__aeabi_d2ulz, "__aeabi_d2ulz"); + symbol(&__aeabi_fixunsdfti, "__fixunsdfti"); + } else { + symbol(&__fixunsdfsi, "__fixunsdfsi"); + symbol(&__fixunsdfdi, "__fixunsdfdi"); + if (compiler_rt.want_windows_arm_abi) symbol(&__fixunsdfdi, "__dtou64"); + symbol(&__fixunsdfti, "__fixunsdfti"); + } + symbol(&__fixunsdfei, "__fixunsdfei"); + + symbol(&__fixunsxfsi, "__fixunsxfsi"); + symbol(&__fixunsxfdi, "__fixunsxfdi"); + symbol(&__fixunsxfti, "__fixunsxfti"); + symbol(&__fixunsxfei, "__fixunsxfei"); + + if (compiler_rt.want_ppc_abi) { + symbol(&__fixunstfsi, "__fixunskfsi"); + symbol(&__fixunstfdi, "__fixunskfdi"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_qtoui, "_Qp_qtoui"); + symbol(&_Qp_qtoux, "_Qp_qtoux"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__fixunstfsi, "_Q_qtou"); + symbol(&__fixunstfdi, "_Q_qtoull"); + } else { + symbol(&__fixunstfsi, "__fixunstfsi"); + symbol(&__fixunstfdi, "__fixunstfdi"); + } + if (compiler_rt.want_ppc_abi) { + symbol(&__fixunstfti, "__fixunskfti"); + symbol(&__fixunstfei, "__fixunskfei"); + } else { + symbol(&__fixunstfti, "__fixunstfti"); + symbol(&__fixunstfei, "__fixunstfei"); + } +} + +fn __fixunshfsi(a: compiler_rt.f16.Abi) callconv(.c) u32 { + return u32_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn u32_intFromFloat_f16(a: f16) u32 { + return intFromFloat(u32, a); +} + +fn __fixunshfdi(a: compiler_rt.f16.Abi) callconv(.c) u64 { + return u64_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn u64_intFromFloat_f16(a: f16) u64 { + return intFromFloat(u64, a); +} + +fn __fixunshfti(a: compiler_rt.f16.Abi) callconv(.c) u128 { + return u128_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn u128_intFromFloat_f16(a: f16) u128 { + return intFromFloat(u128, a); +} + +fn __fixunshfei(r: [*]u8, bits: usize, a: compiler_rt.f16.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return unsigned_intFromFloat_f16(r[0..byte_size], compiler_rt.f16.fromAbi(a)); +} +pub fn unsigned_intFromFloat_f16(result: []u8, a: f16) void { + bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); +} + +fn __fixunssfsi(a: compiler_rt.f32.Abi) callconv(.c) u32 { + return u32_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_f2uiz(a: f32) callconv(.{ .arm_aapcs = .{} }) u32 { + return u32_intFromFloat_f32(a); +} +pub fn u32_intFromFloat_f32(a: f32) u32 { + return intFromFloat(u32, a); +} + +fn __fixunssfdi(a: compiler_rt.f32.Abi) callconv(.c) u64 { + return u64_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_f2ulz(a: f32) callconv(.{ .arm_aapcs = .{} }) u64 { + return u64_intFromFloat_f32(a); +} +pub fn u64_intFromFloat_f32(a: f32) u64 { + return intFromFloat(u64, a); +} + +fn __fixunssfti(a: compiler_rt.f32.Abi) callconv(.c) u128 { + return u128_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_fixunssfti(_: compiler_rt.f32.Abi) callconv(.naked) u128 { + switch (builtin.abi.float()) { + .soft => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r1, r0 + \\ mov r0, sp + \\ bl %[__fixunssfti] + \\ pop {r0-r4, pc} + : + : [__fixunssfti] "X" (&__fixunssfti), + ), + .hard => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r0, sp + \\ bl %[__fixunssfti] + \\ pop {r0-r4, pc} + : + : [__fixunssfti] "X" (&__fixunssfti), + ), + } +} +pub fn u128_intFromFloat_f32(a: f32) u128 { + return intFromFloat(u128, a); +} + +fn __fixunssfei(r: [*]u8, bits: usize, a: compiler_rt.f32.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return unsigned_intFromFloat_f32(r[0..byte_size], compiler_rt.f32.fromAbi(a)); +} +pub fn unsigned_intFromFloat_f32(result: []u8, a: f32) void { + bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); +} + +fn __fixunsdfsi(a: compiler_rt.f64.Abi) callconv(.c) u32 { + return u32_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_d2uiz(a: f64) callconv(.{ .arm_aapcs = .{} }) u32 { + return u32_intFromFloat_f64(a); +} +pub fn u32_intFromFloat_f64(a: f64) u32 { + return intFromFloat(u32, a); +} + +fn __fixunsdfdi(a: compiler_rt.f64.Abi) callconv(.c) u64 { + return u64_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_d2ulz(a: f64) callconv(.{ .arm_aapcs = .{} }) u64 { + return u64_intFromFloat_f64(a); +} +pub fn u64_intFromFloat_f64(a: f64) u64 { + return intFromFloat(u64, a); +} + +fn __fixunsdfti(a: compiler_rt.f64.Abi) callconv(.c) u128 { + return u128_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_fixunsdfti(_: compiler_rt.f64.Abi) callconv(.naked) u128 { + switch (builtin.abi.float()) { + .soft => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r3, r1 + \\ mov r2, r0 + \\ mov r0, sp + \\ bl %[__fixunsdfti] + \\ pop {r0-r4, pc} + : + : [__fixunsdfti] "X" (&__fixunsdfti), + ), + .hard => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r0, sp + \\ bl %[__fixunsdfti] + \\ pop {r0-r4, pc} + : + : [__fixunsdfti] "X" (&__fixunsdfti), + ), + } +} +pub fn u128_intFromFloat_f64(a: f64) u128 { + return intFromFloat(u128, a); +} + +fn __fixunsdfei(r: [*]u8, bits: usize, a: compiler_rt.f64.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return unsigned_intFromFloat_f64(r[0..byte_size], compiler_rt.f64.fromAbi(a)); +} +pub fn unsigned_intFromFloat_f64(result: []u8, a: f64) void { + bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); +} + +fn __fixunsxfsi(a: compiler_rt.f80.Abi) callconv(.c) u32 { + return u32_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn u32_intFromFloat_f80(a: f80) u32 { + return intFromFloat(u32, a); +} + +fn __fixunsxfdi(a: compiler_rt.f80.Abi) callconv(.c) u64 { + return u64_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn u64_intFromFloat_f80(a: f80) u64 { + return intFromFloat(u64, a); +} + +fn __fixunsxfti(a: compiler_rt.f80.Abi) callconv(.c) u128 { + return u128_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn u128_intFromFloat_f80(a: f80) u128 { + return intFromFloat(u128, a); +} + +fn __fixunsxfei(r: [*]u8, bits: usize, a: compiler_rt.f80.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return unsigned_intFromFloat_f80(r[0..byte_size], compiler_rt.f80.fromAbi(a)); +} +pub fn unsigned_intFromFloat_f80(result: []u8, a: f80) void { + bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); +} + +fn __fixunstfsi(a: compiler_rt.f128.Abi) callconv(.c) u32 { + return u32_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +fn _Qp_qtoui(a: *const f128) callconv(.c) u32 { + return u32_intFromFloat_f128(a.*); +} +pub fn u32_intFromFloat_f128(a: f128) u32 { + return intFromFloat(u32, a); +} + +fn __fixunstfdi(a: compiler_rt.f128.Abi) callconv(.c) u64 { + return u64_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +fn _Qp_qtoux(a: *const f128) callconv(.c) u64 { + return u64_intFromFloat_f128(a.*); +} +pub fn u64_intFromFloat_f128(a: f128) u64 { + return intFromFloat(u64, a); +} + +fn __fixunstfti(a: compiler_rt.f128.Abi) callconv(.c) u128 { + return u128_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +pub fn u128_intFromFloat_f128(a: f128) u128 { + return intFromFloat(u128, a); +} + +fn __fixunstfei(r: [*]u8, bits: usize, a: compiler_rt.f128.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return unsigned_intFromFloat_f128(r[0..byte_size], compiler_rt.f128.fromAbi(a)); +} +pub fn unsigned_intFromFloat_f128(result: []u8, a: f128) void { + bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); +} + +inline fn intFromFloat(comptime I: type, a: anytype) I { const F = @TypeOf(a); const float_bits = @typeInfo(F).float.bits; const int_bits = @typeInfo(I).int.bits; @@ -76,13 +580,14 @@ pub inline fn intFromFloat(comptime I: type, a: anytype) I { return result; } -pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, result: []u32, a: anytype) void { +inline fn bigIntFromFloat(comptime signedness: std.lang.Signedness, result: []u32, a: anytype) void { + const endian = builtin.cpu.arch.endian(); switch (result.len) { 0 => return, inline 1...4 => |limbs_len| { const I = @Int(signedness, 32 * limbs_len); const low_to_high: [limbs_len]u32 = @bitCast(@as(I, @intFromFloat(a))); - result[0..limbs_len].* = switch (@import("builtin").cpu.arch.endian()) { + result[0..limbs_len].* = switch (endian) { .little => low_to_high, .big => switch (limbs_len) { 1 => .{low_to_high[0]}, @@ -111,7 +616,6 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul }); switch (signedness) { .signed => { - const endian = @import("builtin").cpu.arch.endian(); const exponent_limb = switch (endian) { .little => exponent / 32, .big => result.len - 1 - exponent / 32, diff --git a/lib/compiler_rt/int_from_float_test.zig b/lib/compiler_rt/int_from_float_test.zig index de96954dd15474c6d9f9c5109c717b3d5b6417c2..23f04e2b88a2a01756ad608cb2d9774b54d38c25 100644 --- a/lib/compiler_rt/int_from_float_test.zig +++ b/lib/compiler_rt/int_from_float_test.zig @@ -2,1023 +2,1039 @@ const std = @import("std"); const testing = std.testing; const math = std.math; -const __fixunshfti = @import("fixunshfti.zig").__fixunshfti; -const __fixunsxfti = @import("fixunsxfti.zig").__fixunsxfti; - -// Conversion from f32 -const __fixsfsi = @import("fixsfsi.zig").__fixsfsi; -const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi; -const __fixsfdi = @import("fixsfdi.zig").__fixsfdi; -const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi; -const __fixsfti = @import("fixsfti.zig").__fixsfti; -const __fixunssfti = @import("fixunssfti.zig").__fixunssfti; -const __fixsfei = @import("fixsfei.zig").__fixsfei; -const __fixunssfei = @import("fixunssfei.zig").__fixunssfei; - -// Conversion from f64 -const __fixdfsi = @import("fixdfsi.zig").__fixdfsi; -const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi; -const __fixdfdi = @import("fixdfdi.zig").__fixdfdi; -const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi; -const __fixdfti = @import("fixdfti.zig").__fixdfti; -const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti; -const __fixdfei = @import("fixdfei.zig").__fixdfei; -const __fixunsdfei = @import("fixunsdfei.zig").__fixunsdfei; - -// Conversion from f128 -const __fixtfsi = @import("fixtfsi.zig").__fixtfsi; -const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi; -const __fixtfdi = @import("fixtfdi.zig").__fixtfdi; -const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi; -const __fixtfti = @import("fixtfti.zig").__fixtfti; -const __fixunstfti = @import("fixunstfti.zig").__fixunstfti; - -fn test__fixsfsi(a: f32, expected: i32) !void { - const x = __fixsfsi(a); +const impl = @import("int_from_float.zig"); + +const i32_intFromFloat_f16 = impl.i32_intFromFloat_f16; +const u32_intFromFloat_f16 = impl.u32_intFromFloat_f16; +const i64_intFromFloat_f16 = impl.i64_intFromFloat_f16; +const u64_intFromFloat_f16 = impl.u64_intFromFloat_f16; +const i128_intFromFloat_f16 = impl.i128_intFromFloat_f16; +const u128_intFromFloat_f16 = impl.u128_intFromFloat_f16; +const signed_intFromFloat_f16 = impl.signed_intFromFloat_f16; +const unsigned_intFromFloat_f16 = impl.unsigned_intFromFloat_f16; + +const i32_intFromFloat_f32 = impl.i32_intFromFloat_f32; +const u32_intFromFloat_f32 = impl.u32_intFromFloat_f32; +const i64_intFromFloat_f32 = impl.i64_intFromFloat_f32; +const u64_intFromFloat_f32 = impl.u64_intFromFloat_f32; +const i128_intFromFloat_f32 = impl.i128_intFromFloat_f32; +const u128_intFromFloat_f32 = impl.u128_intFromFloat_f32; +const signed_intFromFloat_f32 = impl.signed_intFromFloat_f32; +const unsigned_intFromFloat_f32 = impl.unsigned_intFromFloat_f32; + +const i32_intFromFloat_f64 = impl.i32_intFromFloat_f64; +const u32_intFromFloat_f64 = impl.u32_intFromFloat_f64; +const i64_intFromFloat_f64 = impl.i64_intFromFloat_f64; +const u64_intFromFloat_f64 = impl.u64_intFromFloat_f64; +const i128_intFromFloat_f64 = impl.i128_intFromFloat_f64; +const u128_intFromFloat_f64 = impl.u128_intFromFloat_f64; +const signed_intFromFloat_f64 = impl.signed_intFromFloat_f64; +const unsigned_intFromFloat_f64 = impl.unsigned_intFromFloat_f64; + +const i32_intFromFloat_f80 = impl.i32_intFromFloat_f80; +const u32_intFromFloat_f80 = impl.u32_intFromFloat_f80; +const i64_intFromFloat_f80 = impl.i64_intFromFloat_f80; +const u64_intFromFloat_f80 = impl.u64_intFromFloat_f80; +const i128_intFromFloat_f80 = impl.i128_intFromFloat_f80; +const u128_intFromFloat_f80 = impl.u128_intFromFloat_f80; +const signed_intFromFloat_f80 = impl.signed_intFromFloat_f80; +const unsigned_intFromFloat_f80 = impl.unsigned_intFromFloat_f80; + +const i32_intFromFloat_f128 = impl.i32_intFromFloat_f128; +const u32_intFromFloat_f128 = impl.u32_intFromFloat_f128; +const i64_intFromFloat_f128 = impl.i64_intFromFloat_f128; +const u64_intFromFloat_f128 = impl.u64_intFromFloat_f128; +const i128_intFromFloat_f128 = impl.i128_intFromFloat_f128; +const u128_intFromFloat_f128 = impl.u128_intFromFloat_f128; +const signed_intFromFloat_f128 = impl.signed_intFromFloat_f128; +const unsigned_intFromFloat_f128 = impl.unsigned_intFromFloat_f128; + +fn test_i32_intFromFloat_f32(a: f32, expected: i32) !void { + const x = i32_intFromFloat_f32(a); try testing.expect(x == expected); } -fn test__fixunssfsi(a: f32, expected: u32) !void { - const x = __fixunssfsi(a); +fn test_u32_intFromFloat_f32(a: f32, expected: u32) !void { + const x = u32_intFromFloat_f32(a); try testing.expect(x == expected); } -test "fixsfsi" { - try test__fixsfsi(-math.floatMax(f32), math.minInt(i32)); - - try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); - try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); - - try test__fixsfsi(-0x1.0000000000000p+127, -0x80000000); - try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); - try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); - - try test__fixsfsi(-0x1.0000000000001p+63, -0x80000000); - try test__fixsfsi(-0x1.0000000000000p+63, -0x80000000); - try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); - try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); - - try test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000); - try test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000); - - try test__fixsfsi(-0x1.000000p+31, -0x80000000); - try test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000); - try test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); - try test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); - - try test__fixsfsi(-2.01, -2); - try test__fixsfsi(-2.0, -2); - try test__fixsfsi(-1.99, -1); - try test__fixsfsi(-1.0, -1); - try test__fixsfsi(-0.99, 0); - try test__fixsfsi(-0.5, 0); - - try test__fixsfsi(-math.floatMin(f32), 0); - try test__fixsfsi(0.0, 0); - try test__fixsfsi(math.floatMin(f32), 0); - try test__fixsfsi(0.5, 0); - try test__fixsfsi(0.99, 0); - try test__fixsfsi(1.0, 1); - try test__fixsfsi(1.5, 1); - try test__fixsfsi(1.99, 1); - try test__fixsfsi(2.0, 2); - try test__fixsfsi(2.01, 2); - - try test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00); - try test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF); - try test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF); - - try test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); - try test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); - - try test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); - try test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); - try test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF); - try test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF); - - try test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); - try test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); - try test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF); - - try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); - try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); - - try test__fixsfsi(math.floatMax(f32), math.maxInt(i32)); -} - -test "fixunssfsi" { - try test__fixunssfsi(0.0, 0); - - try test__fixunssfsi(0.5, 0); - try test__fixunssfsi(0.99, 0); - try test__fixunssfsi(1.0, 1); - try test__fixunssfsi(1.5, 1); - try test__fixunssfsi(1.99, 1); - try test__fixunssfsi(2.0, 2); - try test__fixunssfsi(2.01, 2); - try test__fixunssfsi(-0.5, 0); - try test__fixunssfsi(-0.99, 0); - - try test__fixunssfsi(-1.0, 0); - try test__fixunssfsi(-1.5, 0); - try test__fixunssfsi(-1.99, 0); - try test__fixunssfsi(-2.0, 0); - try test__fixunssfsi(-2.01, 0); - - try test__fixunssfsi(0x1.000000p+31, 0x80000000); - try test__fixunssfsi(0x1.000000p+32, 0xFFFFFFFF); - try test__fixunssfsi(0x1.FFFFFEp+31, 0xFFFFFF00); - try test__fixunssfsi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixunssfsi(0x1.FFFFFCp+30, 0x7FFFFF00); - - try test__fixunssfsi(-0x1.FFFFFEp+30, 0); - try test__fixunssfsi(-0x1.FFFFFCp+30, 0); -} - -fn test__fixsfdi(a: f32, expected: i64) !void { - const x = __fixsfdi(a); +test i32_intFromFloat_f32 { + try test_i32_intFromFloat_f32(-math.floatMax(f32), math.minInt(i32)); + + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); + + try test_i32_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); + + try test_i32_intFromFloat_f32(-0x1.0000000000001p+63, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.0000000000000p+63, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); + + try test_i32_intFromFloat_f32(-0x1.FFFFFEp+62, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFCp+62, -0x80000000); + + try test_i32_intFromFloat_f32(-0x1.000000p+31, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80); + try test_i32_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00); + + try test_i32_intFromFloat_f32(-2.01, -2); + try test_i32_intFromFloat_f32(-2.0, -2); + try test_i32_intFromFloat_f32(-1.99, -1); + try test_i32_intFromFloat_f32(-1.0, -1); + try test_i32_intFromFloat_f32(-0.99, 0); + try test_i32_intFromFloat_f32(-0.5, 0); + + try test_i32_intFromFloat_f32(-math.floatMin(f32), 0); + try test_i32_intFromFloat_f32(0.0, 0); + try test_i32_intFromFloat_f32(math.floatMin(f32), 0); + try test_i32_intFromFloat_f32(0.5, 0); + try test_i32_intFromFloat_f32(0.99, 0); + try test_i32_intFromFloat_f32(1.0, 1); + try test_i32_intFromFloat_f32(1.5, 1); + try test_i32_intFromFloat_f32(1.99, 1); + try test_i32_intFromFloat_f32(2.0, 2); + try test_i32_intFromFloat_f32(2.01, 2); + + try test_i32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00); + try test_i32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_i32_intFromFloat_f32(0x1.FFFFFFp+30, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.000000p+31, 0x7FFFFFFF); + + try test_i32_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFFFF); + + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFF); + + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFF); + + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); + + try test_i32_intFromFloat_f32(math.floatMax(f32), math.maxInt(i32)); +} + +test u32_intFromFloat_f32 { + try test_u32_intFromFloat_f32(0.0, 0); + + try test_u32_intFromFloat_f32(0.5, 0); + try test_u32_intFromFloat_f32(0.99, 0); + try test_u32_intFromFloat_f32(1.0, 1); + try test_u32_intFromFloat_f32(1.5, 1); + try test_u32_intFromFloat_f32(1.99, 1); + try test_u32_intFromFloat_f32(2.0, 2); + try test_u32_intFromFloat_f32(2.01, 2); + try test_u32_intFromFloat_f32(-0.5, 0); + try test_u32_intFromFloat_f32(-0.99, 0); + + try test_u32_intFromFloat_f32(-1.0, 0); + try test_u32_intFromFloat_f32(-1.5, 0); + try test_u32_intFromFloat_f32(-1.99, 0); + try test_u32_intFromFloat_f32(-2.0, 0); + try test_u32_intFromFloat_f32(-2.01, 0); + + try test_u32_intFromFloat_f32(0x1.000000p+31, 0x80000000); + try test_u32_intFromFloat_f32(0x1.000000p+32, 0xFFFFFFFF); + try test_u32_intFromFloat_f32(0x1.FFFFFEp+31, 0xFFFFFF00); + try test_u32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_u32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00); + + try test_u32_intFromFloat_f32(-0x1.FFFFFEp+30, 0); + try test_u32_intFromFloat_f32(-0x1.FFFFFCp+30, 0); +} + +fn test_i64_intFromFloat_f32(a: f32, expected: i64) !void { + const x = i64_intFromFloat_f32(a); try testing.expect(x == expected); } -fn test__fixunssfdi(a: f32, expected: u64) !void { - const x = __fixunssfdi(a); +fn test_u64_intFromFloat_f32(a: f32, expected: u64) !void { + const x = u64_intFromFloat_f32(a); try testing.expect(x == expected); } -test "fixsfdi" { - try test__fixsfdi(-math.floatMax(f32), math.minInt(i64)); - - try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); - try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); - - try test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000); - try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); - try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); - - try test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000); - try test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); - try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); - - try test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000); - try test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); - try test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); - - try test__fixsfdi(-2.01, -2); - try test__fixsfdi(-2.0, -2); - try test__fixsfdi(-1.99, -1); - try test__fixsfdi(-1.0, -1); - try test__fixsfdi(-0.99, 0); - try test__fixsfdi(-0.5, 0); - try test__fixsfdi(-math.floatMin(f32), 0); - try test__fixsfdi(0.0, 0); - try test__fixsfdi(math.floatMin(f32), 0); - try test__fixsfdi(0.5, 0); - try test__fixsfdi(0.99, 0); - try test__fixsfdi(1.0, 1); - try test__fixsfdi(1.5, 1); - try test__fixsfdi(1.99, 1); - try test__fixsfdi(2.0, 2); - try test__fixsfdi(2.01, 2); - - try test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF); - - try test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); - - try test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); - - try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); - - try test__fixsfdi(math.floatMax(f32), math.maxInt(i64)); -} - -test "fixunssfdi" { - try test__fixunssfdi(0.0, 0); - - try test__fixunssfdi(0.5, 0); - try test__fixunssfdi(0.99, 0); - try test__fixunssfdi(1.0, 1); - try test__fixunssfdi(1.5, 1); - try test__fixunssfdi(1.99, 1); - try test__fixunssfdi(2.0, 2); - try test__fixunssfdi(2.01, 2); - try test__fixunssfdi(-0.5, 0); - try test__fixunssfdi(-0.99, 0); - - try test__fixunssfdi(-1.0, 0); - try test__fixunssfdi(-1.5, 0); - try test__fixunssfdi(-1.99, 0); - try test__fixunssfdi(-2.0, 0); - try test__fixunssfdi(-2.01, 0); - - try test__fixunssfdi(0x1.FFFFFEp+63, 0xFFFFFF0000000000); - try test__fixunssfdi(0x1.000000p+63, 0x8000000000000000); - try test__fixunssfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixunssfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - - try test__fixunssfdi(-0x1.FFFFFEp+62, 0x0000000000000000); - try test__fixunssfdi(-0x1.FFFFFCp+62, 0x0000000000000000); -} - -fn test__fixsfti(a: f32, expected: i128) !void { - const x = __fixsfti(a); +test i64_intFromFloat_f32 { + try test_i64_intFromFloat_f32(-math.floatMax(f32), math.minInt(i64)); + + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); + + try test_i64_intFromFloat_f32(-0x1.0000000000000p+127, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); + + try test_i64_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); + + try test_i64_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000); + + try test_i64_intFromFloat_f32(-2.01, -2); + try test_i64_intFromFloat_f32(-2.0, -2); + try test_i64_intFromFloat_f32(-1.99, -1); + try test_i64_intFromFloat_f32(-1.0, -1); + try test_i64_intFromFloat_f32(-0.99, 0); + try test_i64_intFromFloat_f32(-0.5, 0); + try test_i64_intFromFloat_f32(-math.floatMin(f32), 0); + try test_i64_intFromFloat_f32(0.0, 0); + try test_i64_intFromFloat_f32(math.floatMin(f32), 0); + try test_i64_intFromFloat_f32(0.5, 0); + try test_i64_intFromFloat_f32(0.99, 0); + try test_i64_intFromFloat_f32(1.0, 1); + try test_i64_intFromFloat_f32(1.5, 1); + try test_i64_intFromFloat_f32(1.99, 1); + try test_i64_intFromFloat_f32(2.0, 2); + try test_i64_intFromFloat_f32(2.01, 2); + + try test_i64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_i64_intFromFloat_f32(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); + + try test_i64_intFromFloat_f32(math.floatMax(f32), math.maxInt(i64)); +} + +test u64_intFromFloat_f32 { + try test_u64_intFromFloat_f32(0.0, 0); + + try test_u64_intFromFloat_f32(0.5, 0); + try test_u64_intFromFloat_f32(0.99, 0); + try test_u64_intFromFloat_f32(1.0, 1); + try test_u64_intFromFloat_f32(1.5, 1); + try test_u64_intFromFloat_f32(1.99, 1); + try test_u64_intFromFloat_f32(2.0, 2); + try test_u64_intFromFloat_f32(2.01, 2); + try test_u64_intFromFloat_f32(-0.5, 0); + try test_u64_intFromFloat_f32(-0.99, 0); + + try test_u64_intFromFloat_f32(-1.0, 0); + try test_u64_intFromFloat_f32(-1.5, 0); + try test_u64_intFromFloat_f32(-1.99, 0); + try test_u64_intFromFloat_f32(-2.0, 0); + try test_u64_intFromFloat_f32(-2.01, 0); + + try test_u64_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000); + try test_u64_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000); + try test_u64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_u64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + + try test_u64_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000); + try test_u64_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000); +} + +fn test_i128_intFromFloat_f32(a: f32, expected: i128) !void { + const x = i128_intFromFloat_f32(a); try testing.expect(x == expected); } -fn test__fixunssfti(a: f32, expected: u128) !void { - const x = __fixunssfti(a); +fn test_u128_intFromFloat_f32(a: f32, expected: u128) !void { + const x = u128_intFromFloat_f32(a); try testing.expect(x == expected); } -test "fixsfti" { - try test__fixsfti(-math.floatMax(f32), math.minInt(i128)); - - try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); - try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); - - try test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); - try test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000); - try test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000); - try test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000); - try test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000); - try test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000); - - try test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000); - try test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); - try test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); - - try test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000); - try test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); - try test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); - - try test__fixsfti(-0x1.000000p+31, -0x80000000); - try test__fixsfti(-0x1.FFFFFFp+30, -0x80000000); - try test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80); - try test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00); - - try test__fixsfti(-2.01, -2); - try test__fixsfti(-2.0, -2); - try test__fixsfti(-1.99, -1); - try test__fixsfti(-1.0, -1); - try test__fixsfti(-0.99, 0); - try test__fixsfti(-0.5, 0); - try test__fixsfti(-math.floatMin(f32), 0); - try test__fixsfti(0.0, 0); - try test__fixsfti(math.floatMin(f32), 0); - try test__fixsfti(0.5, 0); - try test__fixsfti(0.99, 0); - try test__fixsfti(1.0, 1); - try test__fixsfti(1.5, 1); - try test__fixsfti(1.99, 1); - try test__fixsfti(2.0, 2); - try test__fixsfti(2.01, 2); - - try test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00); - try test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixsfti(0x1.FFFFFFp+30, 0x80000000); - try test__fixsfti(0x1.000000p+31, 0x80000000); - - try test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000); - - try test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000); - try test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000); - try test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000); - try test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000); - - try test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000); - try test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000); - try test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - - try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); - - try test__fixsfti(math.floatMax(f32), math.maxInt(i128)); -} - -test "fixunssfti" { - try test__fixunssfti(0.0, 0); - - try test__fixunssfti(0.5, 0); - try test__fixunssfti(0.99, 0); - try test__fixunssfti(1.0, 1); - try test__fixunssfti(1.5, 1); - try test__fixunssfti(1.99, 1); - try test__fixunssfti(2.0, 2); - try test__fixunssfti(2.01, 2); - try test__fixunssfti(-0.5, 0); - try test__fixunssfti(-0.99, 0); - - try test__fixunssfti(-1.0, 0); - try test__fixunssfti(-1.5, 0); - try test__fixunssfti(-1.99, 0); - try test__fixunssfti(-2.0, 0); - try test__fixunssfti(-2.01, 0); - - try test__fixunssfti(0x1.FFFFFEp+63, 0xFFFFFF0000000000); - try test__fixunssfti(0x1.000000p+63, 0x8000000000000000); - try test__fixunssfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixunssfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixunssfti(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000); - try test__fixunssfti(0x1.000000p+127, 0x80000000000000000000000000000000); - try test__fixunssfti(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000); - try test__fixunssfti(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000); - - try test__fixunssfti(-0x1.FFFFFEp+62, 0x0000000000000000); - try test__fixunssfti(-0x1.FFFFFCp+62, 0x0000000000000000); - try test__fixunssfti(-0x1.FFFFFEp+126, 0x0000000000000000); - try test__fixunssfti(-0x1.FFFFFCp+126, 0x0000000000000000); - try test__fixunssfti(math.floatMax(f32), 0xffffff00000000000000000000000000); - try test__fixunssfti(math.inf(f32), math.maxInt(u128)); -} - -fn test_fixsfei(comptime T: type, expected: T, a: f32) !void { +test i128_intFromFloat_f32 { + try test_i128_intFromFloat_f32(-math.floatMax(f32), math.minInt(i128)); + + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); + + try test_i128_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000); + + try test_i128_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000); + try test_i128_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); + + try test_i128_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000); + + try test_i128_intFromFloat_f32(-0x1.000000p+31, -0x80000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80); + try test_i128_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00); + + try test_i128_intFromFloat_f32(-2.01, -2); + try test_i128_intFromFloat_f32(-2.0, -2); + try test_i128_intFromFloat_f32(-1.99, -1); + try test_i128_intFromFloat_f32(-1.0, -1); + try test_i128_intFromFloat_f32(-0.99, 0); + try test_i128_intFromFloat_f32(-0.5, 0); + try test_i128_intFromFloat_f32(-math.floatMin(f32), 0); + try test_i128_intFromFloat_f32(0.0, 0); + try test_i128_intFromFloat_f32(math.floatMin(f32), 0); + try test_i128_intFromFloat_f32(0.5, 0); + try test_i128_intFromFloat_f32(0.99, 0); + try test_i128_intFromFloat_f32(1.0, 1); + try test_i128_intFromFloat_f32(1.5, 1); + try test_i128_intFromFloat_f32(1.99, 1); + try test_i128_intFromFloat_f32(2.0, 2); + try test_i128_intFromFloat_f32(2.01, 2); + + try test_i128_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00); + try test_i128_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_i128_intFromFloat_f32(0x1.FFFFFFp+30, 0x80000000); + try test_i128_intFromFloat_f32(0x1.000000p+31, 0x80000000); + + try test_i128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_i128_intFromFloat_f32(0x1.FFFFFFp+62, 0x8000000000000000); + + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000); + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000); + try test_i128_intFromFloat_f32(0x1.0000000000000p+63, 0x8000000000000000); + try test_i128_intFromFloat_f32(0x1.0000000000001p+63, 0x8000000000000000); + + try test_i128_intFromFloat_f32(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000); + try test_i128_intFromFloat_f32(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000); + try test_i128_intFromFloat_f32(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); + + try test_i128_intFromFloat_f32(math.floatMax(f32), math.maxInt(i128)); +} + +test u128_intFromFloat_f32 { + try test_u128_intFromFloat_f32(0.0, 0); + + try test_u128_intFromFloat_f32(0.5, 0); + try test_u128_intFromFloat_f32(0.99, 0); + try test_u128_intFromFloat_f32(1.0, 1); + try test_u128_intFromFloat_f32(1.5, 1); + try test_u128_intFromFloat_f32(1.99, 1); + try test_u128_intFromFloat_f32(2.0, 2); + try test_u128_intFromFloat_f32(2.01, 2); + try test_u128_intFromFloat_f32(-0.5, 0); + try test_u128_intFromFloat_f32(-0.99, 0); + + try test_u128_intFromFloat_f32(-1.0, 0); + try test_u128_intFromFloat_f32(-1.5, 0); + try test_u128_intFromFloat_f32(-1.99, 0); + try test_u128_intFromFloat_f32(-2.0, 0); + try test_u128_intFromFloat_f32(-2.01, 0); + + try test_u128_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000); + try test_u128_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000); + try test_u128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_u128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_u128_intFromFloat_f32(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000); + try test_u128_intFromFloat_f32(0x1.000000p+127, 0x80000000000000000000000000000000); + try test_u128_intFromFloat_f32(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000); + try test_u128_intFromFloat_f32(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000); + + try test_u128_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000); + try test_u128_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000); + try test_u128_intFromFloat_f32(-0x1.FFFFFEp+126, 0x0000000000000000); + try test_u128_intFromFloat_f32(-0x1.FFFFFCp+126, 0x0000000000000000); + try test_u128_intFromFloat_f32(math.floatMax(f32), 0xffffff00000000000000000000000000); + try test_u128_intFromFloat_f32(math.inf(f32), math.maxInt(u128)); +} + +fn test_intFromFloat_f32(comptime T: type, expected: T, a: f32) !void { const int = @typeInfo(T).int; var actual: T = undefined; _ = switch (int.signedness) { - .signed => __fixsfei, - .unsigned => __fixunssfei, - }(@ptrCast(&actual), int.bits, a); + .signed => signed_intFromFloat_f32, + .unsigned => unsigned_intFromFloat_f32, + }(@ptrCast(&actual), a); try testing.expect(expected == actual); } -test "fixsfei" { - try test_fixsfei(i256, -1 << 127, -0x1p127); - try test_fixsfei(i256, -1 << 100, -0x1p100); - try test_fixsfei(i256, -1 << 50, -0x1p50); - try test_fixsfei(i256, -1 << 1, -0x1p1); - try test_fixsfei(i256, -1 << 0, -0x1p0); - try test_fixsfei(i256, 0, 0); - try test_fixsfei(i256, 1 << 0, 0x1p0); - try test_fixsfei(i256, 1 << 1, 0x1p1); - try test_fixsfei(i256, 1 << 50, 0x1p50); - try test_fixsfei(i256, 1 << 100, 0x1p100); - try test_fixsfei(i256, 1 << 127, 0x1p127); +test signed_intFromFloat_f32 { + try test_intFromFloat_f32(i256, -1 << 127, -0x1p127); + try test_intFromFloat_f32(i256, -1 << 100, -0x1p100); + try test_intFromFloat_f32(i256, -1 << 50, -0x1p50); + try test_intFromFloat_f32(i256, -1 << 1, -0x1p1); + try test_intFromFloat_f32(i256, -1 << 0, -0x1p0); + try test_intFromFloat_f32(i256, 0, 0); + try test_intFromFloat_f32(i256, 1 << 0, 0x1p0); + try test_intFromFloat_f32(i256, 1 << 1, 0x1p1); + try test_intFromFloat_f32(i256, 1 << 50, 0x1p50); + try test_intFromFloat_f32(i256, 1 << 100, 0x1p100); + try test_intFromFloat_f32(i256, 1 << 127, 0x1p127); } -test "fixunsfei" { - try test_fixsfei(u256, 0, 0); - try test_fixsfei(u256, 1 << 0, 0x1p0); - try test_fixsfei(u256, 1 << 1, 0x1p1); - try test_fixsfei(u256, 1 << 50, 0x1p50); - try test_fixsfei(u256, 1 << 100, 0x1p100); - try test_fixsfei(u256, 1 << 127, 0x1p127); +test unsigned_intFromFloat_f32 { + try test_intFromFloat_f32(u256, 0, 0); + try test_intFromFloat_f32(u256, 1 << 0, 0x1p0); + try test_intFromFloat_f32(u256, 1 << 1, 0x1p1); + try test_intFromFloat_f32(u256, 1 << 50, 0x1p50); + try test_intFromFloat_f32(u256, 1 << 100, 0x1p100); + try test_intFromFloat_f32(u256, 1 << 127, 0x1p127); } -fn test__fixdfsi(a: f64, expected: i32) !void { - const x = __fixdfsi(a); +fn test_i32_intFromFloat_f64(a: f64, expected: i32) !void { + const x = i32_intFromFloat_f64(a); try testing.expect(x == expected); } -fn test__fixunsdfsi(a: f64, expected: u32) !void { - const x = __fixunsdfsi(a); +fn test_u32_intFromFloat_f64(a: f64, expected: u32) !void { + const x = u32_intFromFloat_f64(a); try testing.expect(x == expected); } -test "fixdfsi" { - try test__fixdfsi(-math.floatMax(f64), math.minInt(i32)); - - try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); - try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); - - try test__fixdfsi(-0x1.0000000000000p+127, -0x80000000); - try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); - try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); - - try test__fixdfsi(-0x1.0000000000001p+63, -0x80000000); - try test__fixdfsi(-0x1.0000000000000p+63, -0x80000000); - try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); - try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); - - try test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000); - try test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000); - - try test__fixdfsi(-0x1.000000p+31, -0x80000000); - try test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); - try test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); - - try test__fixdfsi(-2.01, -2); - try test__fixdfsi(-2.0, -2); - try test__fixdfsi(-1.99, -1); - try test__fixdfsi(-1.0, -1); - try test__fixdfsi(-0.99, 0); - try test__fixdfsi(-0.5, 0); - try test__fixdfsi(-math.floatMin(f64), 0); - try test__fixdfsi(0.0, 0); - try test__fixdfsi(math.floatMin(f64), 0); - try test__fixdfsi(0.5, 0); - try test__fixdfsi(0.99, 0); - try test__fixdfsi(1.0, 1); - try test__fixdfsi(1.5, 1); - try test__fixdfsi(1.99, 1); - try test__fixdfsi(2.0, 2); - try test__fixdfsi(2.01, 2); - - try test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); - try test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF); - - try test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); - try test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); - - try test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); - try test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); - try test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF); - try test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF); - - try test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); - try test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); - try test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF); - - try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); - try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); - - try test__fixdfsi(math.floatMax(f64), math.maxInt(i32)); -} - -test "fixunsdfsi" { - try test__fixunsdfsi(0.0, 0); - - try test__fixunsdfsi(0.5, 0); - try test__fixunsdfsi(0.99, 0); - try test__fixunsdfsi(1.0, 1); - try test__fixunsdfsi(1.5, 1); - try test__fixunsdfsi(1.99, 1); - try test__fixunsdfsi(2.0, 2); - try test__fixunsdfsi(2.01, 2); - try test__fixunsdfsi(-0.5, 0); - try test__fixunsdfsi(-0.99, 0); - try test__fixunsdfsi(-1.0, 0); - try test__fixunsdfsi(-1.5, 0); - try test__fixunsdfsi(-1.99, 0); - try test__fixunsdfsi(-2.0, 0); - try test__fixunsdfsi(-2.01, 0); - - try test__fixunsdfsi(0x1.000000p+31, 0x80000000); - try test__fixunsdfsi(0x1.000000p+32, 0xFFFFFFFF); - try test__fixunsdfsi(0x1.FFFFFEp+31, 0xFFFFFF00); - try test__fixunsdfsi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixunsdfsi(0x1.FFFFFCp+30, 0x7FFFFF00); - - try test__fixunsdfsi(-0x1.FFFFFEp+30, 0); - try test__fixunsdfsi(-0x1.FFFFFCp+30, 0); - - try test__fixunsdfsi(0x1.FFFFFFFEp+31, 0xFFFFFFFF); - try test__fixunsdfsi(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF); - try test__fixunsdfsi(0x1.FFFFFFF800000p+30, 0x7FFFFFFE); -} - -fn test__fixdfdi(a: f64, expected: i64) !void { - const x = __fixdfdi(a); +test i32_intFromFloat_f64 { + try test_i32_intFromFloat_f64(-math.floatMax(f64), math.minInt(i32)); + + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); + + try test_i32_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); + + try test_i32_intFromFloat_f64(-0x1.0000000000001p+63, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.0000000000000p+63, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); + + try test_i32_intFromFloat_f64(-0x1.FFFFFEp+62, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFCp+62, -0x80000000); + + try test_i32_intFromFloat_f64(-0x1.000000p+31, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFFp+30, -0x7FFFFFC0); + try test_i32_intFromFloat_f64(-0x1.FFFFFEp+30, -0x7FFFFF80); + + try test_i32_intFromFloat_f64(-2.01, -2); + try test_i32_intFromFloat_f64(-2.0, -2); + try test_i32_intFromFloat_f64(-1.99, -1); + try test_i32_intFromFloat_f64(-1.0, -1); + try test_i32_intFromFloat_f64(-0.99, 0); + try test_i32_intFromFloat_f64(-0.5, 0); + try test_i32_intFromFloat_f64(-math.floatMin(f64), 0); + try test_i32_intFromFloat_f64(0.0, 0); + try test_i32_intFromFloat_f64(math.floatMin(f64), 0); + try test_i32_intFromFloat_f64(0.5, 0); + try test_i32_intFromFloat_f64(0.99, 0); + try test_i32_intFromFloat_f64(1.0, 1); + try test_i32_intFromFloat_f64(1.5, 1); + try test_i32_intFromFloat_f64(1.99, 1); + try test_i32_intFromFloat_f64(2.0, 2); + try test_i32_intFromFloat_f64(2.01, 2); + + try test_i32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_i32_intFromFloat_f64(0x1.FFFFFFp+30, 0x7FFFFFC0); + try test_i32_intFromFloat_f64(0x1.000000p+31, 0x7FFFFFFF); + + try test_i32_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFFFF); + + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFF); + + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFF); + + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); + + try test_i32_intFromFloat_f64(math.floatMax(f64), math.maxInt(i32)); +} + +test u32_intFromFloat_f64 { + try test_u32_intFromFloat_f64(0.0, 0); + + try test_u32_intFromFloat_f64(0.5, 0); + try test_u32_intFromFloat_f64(0.99, 0); + try test_u32_intFromFloat_f64(1.0, 1); + try test_u32_intFromFloat_f64(1.5, 1); + try test_u32_intFromFloat_f64(1.99, 1); + try test_u32_intFromFloat_f64(2.0, 2); + try test_u32_intFromFloat_f64(2.01, 2); + try test_u32_intFromFloat_f64(-0.5, 0); + try test_u32_intFromFloat_f64(-0.99, 0); + try test_u32_intFromFloat_f64(-1.0, 0); + try test_u32_intFromFloat_f64(-1.5, 0); + try test_u32_intFromFloat_f64(-1.99, 0); + try test_u32_intFromFloat_f64(-2.0, 0); + try test_u32_intFromFloat_f64(-2.01, 0); + + try test_u32_intFromFloat_f64(0x1.000000p+31, 0x80000000); + try test_u32_intFromFloat_f64(0x1.000000p+32, 0xFFFFFFFF); + try test_u32_intFromFloat_f64(0x1.FFFFFEp+31, 0xFFFFFF00); + try test_u32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_u32_intFromFloat_f64(0x1.FFFFFCp+30, 0x7FFFFF00); + + try test_u32_intFromFloat_f64(-0x1.FFFFFEp+30, 0); + try test_u32_intFromFloat_f64(-0x1.FFFFFCp+30, 0); + + try test_u32_intFromFloat_f64(0x1.FFFFFFFEp+31, 0xFFFFFFFF); + try test_u32_intFromFloat_f64(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF); + try test_u32_intFromFloat_f64(0x1.FFFFFFF800000p+30, 0x7FFFFFFE); +} + +fn test_i64_intFromFloat_f64(a: f64, expected: i64) !void { + const x = i64_intFromFloat_f64(a); try testing.expect(x == expected); } -fn test__fixunsdfdi(a: f64, expected: u64) !void { - const x = __fixunsdfdi(a); +fn test_u64_intFromFloat_f64(a: f64, expected: u64) !void { + const x = u64_intFromFloat_f64(a); try testing.expect(x == expected); } -test "fixdfdi" { - try test__fixdfdi(-math.floatMax(f64), math.minInt(i64)); - - try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); - try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); - - try test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000); - try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); - try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); - - try test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000); - try test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); - try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); - - try test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); - try test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); - - try test__fixdfdi(-2.01, -2); - try test__fixdfdi(-2.0, -2); - try test__fixdfdi(-1.99, -1); - try test__fixdfdi(-1.0, -1); - try test__fixdfdi(-0.99, 0); - try test__fixdfdi(-0.5, 0); - try test__fixdfdi(-math.floatMin(f64), 0); - try test__fixdfdi(0.0, 0); - try test__fixdfdi(math.floatMin(f64), 0); - try test__fixdfdi(0.5, 0); - try test__fixdfdi(0.99, 0); - try test__fixdfdi(1.0, 1); - try test__fixdfdi(1.5, 1); - try test__fixdfdi(1.99, 1); - try test__fixdfdi(2.0, 2); - try test__fixdfdi(2.01, 2); - - try test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - - try test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - try test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); - try test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); - - try test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); - - try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); - try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); - - try test__fixdfdi(math.floatMax(f64), math.maxInt(i64)); -} - -test "fixunsdfdi" { - try test__fixunsdfdi(0.0, 0); - try test__fixunsdfdi(0.5, 0); - try test__fixunsdfdi(0.99, 0); - try test__fixunsdfdi(1.0, 1); - try test__fixunsdfdi(1.5, 1); - try test__fixunsdfdi(1.99, 1); - try test__fixunsdfdi(2.0, 2); - try test__fixunsdfdi(2.01, 2); - try test__fixunsdfdi(-0.5, 0); - try test__fixunsdfdi(-0.99, 0); - try test__fixunsdfdi(-1.0, 0); - try test__fixunsdfdi(-1.5, 0); - try test__fixunsdfdi(-1.99, 0); - try test__fixunsdfdi(-2.0, 0); - try test__fixunsdfdi(-2.01, 0); - - try test__fixunsdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixunsdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - - try test__fixunsdfdi(-0x1.FFFFFEp+62, 0); - try test__fixunsdfdi(-0x1.FFFFFCp+62, 0); - - try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); - try test__fixunsdfdi(0x1.0000000000000p+63, 0x8000000000000000); - try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixunsdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - - try test__fixunsdfdi(-0x1.FFFFFFFFFFFFFp+62, 0); - try test__fixunsdfdi(-0x1.FFFFFFFFFFFFEp+62, 0); -} - -fn test__fixdfti(a: f64, expected: i128) !void { - const x = __fixdfti(a); +test i64_intFromFloat_f64 { + try test_i64_intFromFloat_f64(-math.floatMax(f64), math.minInt(i64)); + + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); + + try test_i64_intFromFloat_f64(-0x1.0000000000000p+127, -0x8000000000000000); + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); + + try test_i64_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000000); + try test_i64_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); + + try test_i64_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000); + try test_i64_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000); + + try test_i64_intFromFloat_f64(-2.01, -2); + try test_i64_intFromFloat_f64(-2.0, -2); + try test_i64_intFromFloat_f64(-1.99, -1); + try test_i64_intFromFloat_f64(-1.0, -1); + try test_i64_intFromFloat_f64(-0.99, 0); + try test_i64_intFromFloat_f64(-0.5, 0); + try test_i64_intFromFloat_f64(-math.floatMin(f64), 0); + try test_i64_intFromFloat_f64(0.0, 0); + try test_i64_intFromFloat_f64(math.floatMin(f64), 0); + try test_i64_intFromFloat_f64(0.5, 0); + try test_i64_intFromFloat_f64(0.99, 0); + try test_i64_intFromFloat_f64(1.0, 1); + try test_i64_intFromFloat_f64(1.5, 1); + try test_i64_intFromFloat_f64(1.99, 1); + try test_i64_intFromFloat_f64(2.0, 2); + try test_i64_intFromFloat_f64(2.01, 2); + + try test_i64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_i64_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); + + try test_i64_intFromFloat_f64(math.floatMax(f64), math.maxInt(i64)); +} + +test u64_intFromFloat_f64 { + try test_u64_intFromFloat_f64(0.0, 0); + try test_u64_intFromFloat_f64(0.5, 0); + try test_u64_intFromFloat_f64(0.99, 0); + try test_u64_intFromFloat_f64(1.0, 1); + try test_u64_intFromFloat_f64(1.5, 1); + try test_u64_intFromFloat_f64(1.99, 1); + try test_u64_intFromFloat_f64(2.0, 2); + try test_u64_intFromFloat_f64(2.01, 2); + try test_u64_intFromFloat_f64(-0.5, 0); + try test_u64_intFromFloat_f64(-0.99, 0); + try test_u64_intFromFloat_f64(-1.0, 0); + try test_u64_intFromFloat_f64(-1.5, 0); + try test_u64_intFromFloat_f64(-1.99, 0); + try test_u64_intFromFloat_f64(-2.0, 0); + try test_u64_intFromFloat_f64(-2.01, 0); + + try test_u64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_u64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + + try test_u64_intFromFloat_f64(-0x1.FFFFFEp+62, 0); + try test_u64_intFromFloat_f64(-0x1.FFFFFCp+62, 0); + + try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); + try test_u64_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000); + try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + + try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0); + try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0); +} + +fn test_i128_intFromFloat_f64(a: f64, expected: i128) !void { + const x = i128_intFromFloat_f64(a); try testing.expect(x == expected); } -fn test__fixunsdfti(a: f64, expected: u128) !void { - const x = __fixunsdfti(a); +fn test_u128_intFromFloat_f64(a: f64, expected: u128) !void { + const x = u128_intFromFloat_f64(a); try testing.expect(x == expected); } -test "fixdfti" { - try test__fixdfti(-math.floatMax(f64), math.minInt(i128)); - - try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); - try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); - - try test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); - try test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); - try test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); - - try test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800); - try test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); - try test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); - - try test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); - try test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); - - try test__fixdfti(-2.01, -2); - try test__fixdfti(-2.0, -2); - try test__fixdfti(-1.99, -1); - try test__fixdfti(-1.0, -1); - try test__fixdfti(-0.99, 0); - try test__fixdfti(-0.5, 0); - try test__fixdfti(-math.floatMin(f64), 0); - try test__fixdfti(0.0, 0); - try test__fixdfti(math.floatMin(f64), 0); - try test__fixdfti(0.5, 0); - try test__fixdfti(0.99, 0); - try test__fixdfti(1.0, 1); - try test__fixdfti(1.5, 1); - try test__fixdfti(1.99, 1); - try test__fixdfti(2.0, 2); - try test__fixdfti(2.01, 2); - - try test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - - try test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - try test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000); - try test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800); - - try test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); - try test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); - try test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - - try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); - - try test__fixdfti(math.floatMax(f64), math.maxInt(i128)); -} - -test "fixunsdfti" { - try test__fixunsdfti(0.0, 0); - - try test__fixunsdfti(0.5, 0); - try test__fixunsdfti(0.99, 0); - try test__fixunsdfti(1.0, 1); - try test__fixunsdfti(1.5, 1); - try test__fixunsdfti(1.99, 1); - try test__fixunsdfti(2.0, 2); - try test__fixunsdfti(2.01, 2); - try test__fixunsdfti(-0.5, 0); - try test__fixunsdfti(-0.99, 0); - try test__fixunsdfti(-1.0, 0); - try test__fixunsdfti(-1.5, 0); - try test__fixunsdfti(-1.99, 0); - try test__fixunsdfti(-2.0, 0); - try test__fixunsdfti(-2.01, 0); - - try test__fixunsdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixunsdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - - try test__fixunsdfti(-0x1.FFFFFEp+62, 0); - try test__fixunsdfti(-0x1.FFFFFCp+62, 0); - - try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); - try test__fixunsdfti(0x1.0000000000000p+63, 0x8000000000000000); - try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - - try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000); - try test__fixunsdfti(0x1.0000000000000p+127, 0x80000000000000000000000000000000); - try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); - try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); - try test__fixunsdfti(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - - try test__fixunsdfti(-0x1.FFFFFFFFFFFFFp+62, 0); - try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0); -} - -fn test_fixdfei(comptime T: type, expected: T, a: f64) !void { +test i128_intFromFloat_f64 { + try test_i128_intFromFloat_f64(-math.floatMax(f64), math.minInt(i128)); + + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); + + try test_i128_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); + + try test_i128_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000800); + try test_i128_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); + + try test_i128_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000); + try test_i128_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000); + + try test_i128_intFromFloat_f64(-2.01, -2); + try test_i128_intFromFloat_f64(-2.0, -2); + try test_i128_intFromFloat_f64(-1.99, -1); + try test_i128_intFromFloat_f64(-1.0, -1); + try test_i128_intFromFloat_f64(-0.99, 0); + try test_i128_intFromFloat_f64(-0.5, 0); + try test_i128_intFromFloat_f64(-math.floatMin(f64), 0); + try test_i128_intFromFloat_f64(0.0, 0); + try test_i128_intFromFloat_f64(math.floatMin(f64), 0); + try test_i128_intFromFloat_f64(0.5, 0); + try test_i128_intFromFloat_f64(0.99, 0); + try test_i128_intFromFloat_f64(1.0, 1); + try test_i128_intFromFloat_f64(1.5, 1); + try test_i128_intFromFloat_f64(1.99, 1); + try test_i128_intFromFloat_f64(2.0, 2); + try test_i128_intFromFloat_f64(2.01, 2); + + try test_i128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_i128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000); + try test_i128_intFromFloat_f64(0x1.0000000000001p+63, 0x8000000000000800); + + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); + try test_i128_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); + + try test_i128_intFromFloat_f64(math.floatMax(f64), math.maxInt(i128)); +} + +test u128_intFromFloat_f64 { + try test_u128_intFromFloat_f64(0.0, 0); + + try test_u128_intFromFloat_f64(0.5, 0); + try test_u128_intFromFloat_f64(0.99, 0); + try test_u128_intFromFloat_f64(1.0, 1); + try test_u128_intFromFloat_f64(1.5, 1); + try test_u128_intFromFloat_f64(1.99, 1); + try test_u128_intFromFloat_f64(2.0, 2); + try test_u128_intFromFloat_f64(2.01, 2); + try test_u128_intFromFloat_f64(-0.5, 0); + try test_u128_intFromFloat_f64(-0.99, 0); + try test_u128_intFromFloat_f64(-1.0, 0); + try test_u128_intFromFloat_f64(-1.5, 0); + try test_u128_intFromFloat_f64(-1.99, 0); + try test_u128_intFromFloat_f64(-2.0, 0); + try test_u128_intFromFloat_f64(-2.01, 0); + + try test_u128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_u128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + + try test_u128_intFromFloat_f64(-0x1.FFFFFEp+62, 0); + try test_u128_intFromFloat_f64(-0x1.FFFFFCp+62, 0); + + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); + try test_u128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000); + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000); + try test_u128_intFromFloat_f64(0x1.0000000000000p+127, 0x80000000000000000000000000000000); + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); + try test_u128_intFromFloat_f64(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + + try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0); + try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0); +} + +fn test_intFromFloat_f64(comptime T: type, expected: T, a: f64) !void { const int = @typeInfo(T).int; var actual: T = undefined; _ = switch (int.signedness) { - .signed => __fixdfei, - .unsigned => __fixunsdfei, - }(@ptrCast(&actual), int.bits, a); + .signed => signed_intFromFloat_f64, + .unsigned => unsigned_intFromFloat_f64, + }(@ptrCast(&actual), a); try testing.expect(expected == actual); } -test "fixdfei" { - try test_fixdfei(i256, -1 << 255, -0x1p255); - try test_fixdfei(i256, -1 << 127, -0x1p127); - try test_fixdfei(i256, -1 << 100, -0x1p100); - try test_fixdfei(i256, -1 << 50, -0x1p50); - try test_fixdfei(i256, -1 << 1, -0x1p1); - try test_fixdfei(i256, -1 << 0, -0x1p0); - try test_fixdfei(i256, 0, 0); - try test_fixdfei(i256, 1 << 0, 0x1p0); - try test_fixdfei(i256, 1 << 1, 0x1p1); - try test_fixdfei(i256, 1 << 50, 0x1p50); - try test_fixdfei(i256, 1 << 100, 0x1p100); - try test_fixdfei(i256, 1 << 127, 0x1p127); - try test_fixdfei(i256, 1 << 254, 0x1p254); -} - -test "fixundfei" { - try test_fixdfei(u256, 0, 0); - try test_fixdfei(u256, 1 << 0, 0x1p0); - try test_fixdfei(u256, 1 << 1, 0x1p1); - try test_fixdfei(u256, 1 << 50, 0x1p50); - try test_fixdfei(u256, 1 << 100, 0x1p100); - try test_fixdfei(u256, 1 << 127, 0x1p127); - try test_fixdfei(u256, 1 << 255, 0x1p255); -} - -fn test__fixtfsi(a: f128, expected: i32) !void { - const x = __fixtfsi(a); - try testing.expect(x == expected); +test signed_intFromFloat_f64 { + try test_intFromFloat_f64(i256, -1 << 255, -0x1p255); + try test_intFromFloat_f64(i256, -1 << 127, -0x1p127); + try test_intFromFloat_f64(i256, -1 << 100, -0x1p100); + try test_intFromFloat_f64(i256, -1 << 50, -0x1p50); + try test_intFromFloat_f64(i256, -1 << 1, -0x1p1); + try test_intFromFloat_f64(i256, -1 << 0, -0x1p0); + try test_intFromFloat_f64(i256, 0, 0); + try test_intFromFloat_f64(i256, 1 << 0, 0x1p0); + try test_intFromFloat_f64(i256, 1 << 1, 0x1p1); + try test_intFromFloat_f64(i256, 1 << 50, 0x1p50); + try test_intFromFloat_f64(i256, 1 << 100, 0x1p100); + try test_intFromFloat_f64(i256, 1 << 127, 0x1p127); + try test_intFromFloat_f64(i256, 1 << 254, 0x1p254); } -fn test__fixunstfsi(a: f128, expected: u32) !void { - const x = __fixunstfsi(a); - try testing.expect(x == expected); +test unsigned_intFromFloat_f64 { + try test_intFromFloat_f64(u256, 0, 0); + try test_intFromFloat_f64(u256, 1 << 0, 0x1p0); + try test_intFromFloat_f64(u256, 1 << 1, 0x1p1); + try test_intFromFloat_f64(u256, 1 << 50, 0x1p50); + try test_intFromFloat_f64(u256, 1 << 100, 0x1p100); + try test_intFromFloat_f64(u256, 1 << 127, 0x1p127); + try test_intFromFloat_f64(u256, 1 << 255, 0x1p255); } -test "fixtfsi" { - try test__fixtfsi(-math.floatMax(f128), math.minInt(i32)); - - try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); - try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); - - try test__fixtfsi(-0x1.0000000000000p+127, -0x80000000); - try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); - try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); - - try test__fixtfsi(-0x1.0000000000001p+63, -0x80000000); - try test__fixtfsi(-0x1.0000000000000p+63, -0x80000000); - try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); - try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); - - try test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000); - try test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000); - - try test__fixtfsi(-0x1.000000p+31, -0x80000000); - try test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); - try test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); - try test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); - - try test__fixtfsi(-2.01, -2); - try test__fixtfsi(-2.0, -2); - try test__fixtfsi(-1.99, -1); - try test__fixtfsi(-1.0, -1); - try test__fixtfsi(-0.99, 0); - try test__fixtfsi(-0.5, 0); - try test__fixtfsi(-math.floatMin(f32), 0); - try test__fixtfsi(0.0, 0); - try test__fixtfsi(math.floatMin(f32), 0); - try test__fixtfsi(0.5, 0); - try test__fixtfsi(0.99, 0); - try test__fixtfsi(1.0, 1); - try test__fixtfsi(1.5, 1); - try test__fixtfsi(1.99, 1); - try test__fixtfsi(2.0, 2); - try test__fixtfsi(2.01, 2); - - try test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00); - try test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); - try test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF); - - try test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); - try test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); - - try test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); - try test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); - try test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF); - try test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF); - - try test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); - try test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); - try test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF); - - try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); - try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); - - try test__fixtfsi(math.floatMax(f128), math.maxInt(i32)); -} - -test "fixunstfsi" { - try test__fixunstfsi(math.inf(f128), 0xffffffff); - try test__fixunstfsi(0, 0x0); - try test__fixunstfsi(0x1.23456789abcdefp+5, 0x24); - try test__fixunstfsi(0x1.23456789abcdefp-3, 0x0); - try test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456); - try test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff); - try test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff); - try test__fixunstfsi(-0x1.23456789abcdefp+3, 0x0); - - try test__fixunstfsi(0x1p+32, 0xFFFFFFFF); -} - -fn test__fixtfdi(a: f128, expected: i64) !void { - const x = __fixtfdi(a); +fn test_i32_intFromFloat_f128(a: f128, expected: i32) !void { + const x = i32_intFromFloat_f128(a); try testing.expect(x == expected); } -fn test__fixunstfdi(a: f128, expected: u64) !void { - const x = __fixunstfdi(a); +fn test_u32_intFromFloat_f128(a: f128, expected: u32) !void { + const x = u32_intFromFloat_f128(a); try testing.expect(x == expected); } -test "fixtfdi" { - try test__fixtfdi(-math.floatMax(f128), math.minInt(i64)); - - try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); - try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); - - try test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000); - try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); - try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); - - try test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000); - try test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); - try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); - - try test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000); - try test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000); - - try test__fixtfdi(-0x1.000000p+31, -0x80000000); - try test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0); - try test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80); - try test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00); - - try test__fixtfdi(-2.01, -2); - try test__fixtfdi(-2.0, -2); - try test__fixtfdi(-1.99, -1); - try test__fixtfdi(-1.0, -1); - try test__fixtfdi(-0.99, 0); - try test__fixtfdi(-0.5, 0); - try test__fixtfdi(-math.floatMin(f64), 0); - try test__fixtfdi(0.0, 0); - try test__fixtfdi(math.floatMin(f64), 0); - try test__fixtfdi(0.5, 0); - try test__fixtfdi(0.99, 0); - try test__fixtfdi(1.0, 1); - try test__fixtfdi(1.5, 1); - try test__fixtfdi(1.99, 1); - try test__fixtfdi(2.0, 2); - try test__fixtfdi(2.01, 2); - - try test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00); - try test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0); - try test__fixtfdi(0x1.000000p+31, 0x80000000); - - try test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - - try test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - try test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); - try test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); - - try test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); - - try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); - try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); - - try test__fixtfdi(math.floatMax(f128), math.maxInt(i64)); -} - -test "fixunstfdi" { - try test__fixunstfdi(0.0, 0); - - try test__fixunstfdi(0.5, 0); - try test__fixunstfdi(0.99, 0); - try test__fixunstfdi(1.0, 1); - try test__fixunstfdi(1.5, 1); - try test__fixunstfdi(1.99, 1); - try test__fixunstfdi(2.0, 2); - try test__fixunstfdi(2.01, 2); - try test__fixunstfdi(-0.5, 0); - try test__fixunstfdi(-0.99, 0); - try test__fixunstfdi(-1.0, 0); - try test__fixunstfdi(-1.5, 0); - try test__fixunstfdi(-1.99, 0); - try test__fixunstfdi(-2.0, 0); - try test__fixunstfdi(-2.01, 0); - - try test__fixunstfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixunstfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - - try test__fixunstfdi(-0x1.FFFFFEp+62, 0); - try test__fixunstfdi(-0x1.FFFFFCp+62, 0); - - try test__fixunstfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixunstfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - - try test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0); - try test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0); - - try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF); - try test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001); - try test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000); - try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF); - try test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE); - try test__fixunstfdi(0x1p+64, 0xFFFFFFFFFFFFFFFF); - - try test__fixunstfdi(-0x1.0000000000000000p+63, 0); - try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0); - try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0); -} - -fn test__fixtfti(a: f128, expected: i128) !void { - const x = __fixtfti(a); - try testing.expect(x == expected); +test i32_intFromFloat_f128 { + try test_i32_intFromFloat_f128(-math.floatMax(f128), math.minInt(i32)); + + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); + + try test_i32_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); + + try test_i32_intFromFloat_f128(-0x1.0000000000001p+63, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.0000000000000p+63, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); + + try test_i32_intFromFloat_f128(-0x1.FFFFFEp+62, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFCp+62, -0x80000000); + + try test_i32_intFromFloat_f128(-0x1.000000p+31, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0); + try test_i32_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80); + try test_i32_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00); + + try test_i32_intFromFloat_f128(-2.01, -2); + try test_i32_intFromFloat_f128(-2.0, -2); + try test_i32_intFromFloat_f128(-1.99, -1); + try test_i32_intFromFloat_f128(-1.0, -1); + try test_i32_intFromFloat_f128(-0.99, 0); + try test_i32_intFromFloat_f128(-0.5, 0); + try test_i32_intFromFloat_f128(-math.floatMin(f32), 0); + try test_i32_intFromFloat_f128(0.0, 0); + try test_i32_intFromFloat_f128(math.floatMin(f32), 0); + try test_i32_intFromFloat_f128(0.5, 0); + try test_i32_intFromFloat_f128(0.99, 0); + try test_i32_intFromFloat_f128(1.0, 1); + try test_i32_intFromFloat_f128(1.5, 1); + try test_i32_intFromFloat_f128(1.99, 1); + try test_i32_intFromFloat_f128(2.0, 2); + try test_i32_intFromFloat_f128(2.01, 2); + + try test_i32_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00); + try test_i32_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_i32_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0); + try test_i32_intFromFloat_f128(0x1.000000p+31, 0x7FFFFFFF); + + try test_i32_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFFFF); + + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFF); + + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFF); + + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); + + try test_i32_intFromFloat_f128(math.floatMax(f128), math.maxInt(i32)); } -fn test__fixunstfti(a: f128, expected: u128) !void { - const x = __fixunstfti(a); - try testing.expect(x == expected); +test u32_intFromFloat_f128 { + try test_u32_intFromFloat_f128(math.inf(f128), 0xffffffff); + try test_u32_intFromFloat_f128(0, 0x0); + try test_u32_intFromFloat_f128(0x1.23456789abcdefp+5, 0x24); + try test_u32_intFromFloat_f128(0x1.23456789abcdefp-3, 0x0); + try test_u32_intFromFloat_f128(0x1.23456789abcdefp+20, 0x123456); + try test_u32_intFromFloat_f128(0x1.23456789abcdefp+40, 0xffffffff); + try test_u32_intFromFloat_f128(0x1.23456789abcdefp+256, 0xffffffff); + try test_u32_intFromFloat_f128(-0x1.23456789abcdefp+3, 0x0); + + try test_u32_intFromFloat_f128(0x1p+32, 0xFFFFFFFF); } -test "fixtfti" { - try test__fixtfti(-math.floatMax(f128), math.minInt(i128)); - - try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); - try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); - - try test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); - try test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); - try test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); - - try test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800); - try test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); - try test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); - - try test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); - try test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); +fn test_i64_intFromFloat_f128(a: f128, expected: i64) !void { + const x = i64_intFromFloat_f128(a); + try testing.expect(x == expected); +} - try test__fixtfti(-2.01, -2); - try test__fixtfti(-2.0, -2); - try test__fixtfti(-1.99, -1); - try test__fixtfti(-1.0, -1); - try test__fixtfti(-0.99, 0); - try test__fixtfti(-0.5, 0); - try test__fixtfti(-math.floatMin(f128), 0); - try test__fixtfti(0.0, 0); - try test__fixtfti(math.floatMin(f128), 0); - try test__fixtfti(0.5, 0); - try test__fixtfti(0.99, 0); - try test__fixtfti(1.0, 1); - try test__fixtfti(1.5, 1); - try test__fixtfti(1.99, 1); - try test__fixtfti(2.0, 2); - try test__fixtfti(2.01, 2); +fn test_u64_intFromFloat_f128(a: f128, expected: u64) !void { + const x = u64_intFromFloat_f128(a); + try testing.expect(x == expected); +} - try test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); +test i64_intFromFloat_f128 { + try test_i64_intFromFloat_f128(-math.floatMax(f128), math.minInt(i64)); + + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); + + try test_i64_intFromFloat_f128(-0x1.0000000000000p+127, -0x8000000000000000); + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); + + try test_i64_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000000); + try test_i64_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); + + try test_i64_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7FFFFF8000000000); + try test_i64_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7FFFFF0000000000); + + try test_i64_intFromFloat_f128(-0x1.000000p+31, -0x80000000); + try test_i64_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0); + try test_i64_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80); + try test_i64_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00); + + try test_i64_intFromFloat_f128(-2.01, -2); + try test_i64_intFromFloat_f128(-2.0, -2); + try test_i64_intFromFloat_f128(-1.99, -1); + try test_i64_intFromFloat_f128(-1.0, -1); + try test_i64_intFromFloat_f128(-0.99, 0); + try test_i64_intFromFloat_f128(-0.5, 0); + try test_i64_intFromFloat_f128(-math.floatMin(f64), 0); + try test_i64_intFromFloat_f128(0.0, 0); + try test_i64_intFromFloat_f128(math.floatMin(f64), 0); + try test_i64_intFromFloat_f128(0.5, 0); + try test_i64_intFromFloat_f128(0.99, 0); + try test_i64_intFromFloat_f128(1.0, 1); + try test_i64_intFromFloat_f128(1.5, 1); + try test_i64_intFromFloat_f128(1.99, 1); + try test_i64_intFromFloat_f128(2.0, 2); + try test_i64_intFromFloat_f128(2.01, 2); + + try test_i64_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00); + try test_i64_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_i64_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0); + try test_i64_intFromFloat_f128(0x1.000000p+31, 0x80000000); + + try test_i64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_i64_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); + + try test_i64_intFromFloat_f128(math.floatMax(f128), math.maxInt(i64)); +} - try test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - try test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000); - try test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800); +test u64_intFromFloat_f128 { + try test_u64_intFromFloat_f128(0.0, 0); + + try test_u64_intFromFloat_f128(0.5, 0); + try test_u64_intFromFloat_f128(0.99, 0); + try test_u64_intFromFloat_f128(1.0, 1); + try test_u64_intFromFloat_f128(1.5, 1); + try test_u64_intFromFloat_f128(1.99, 1); + try test_u64_intFromFloat_f128(2.0, 2); + try test_u64_intFromFloat_f128(2.01, 2); + try test_u64_intFromFloat_f128(-0.5, 0); + try test_u64_intFromFloat_f128(-0.99, 0); + try test_u64_intFromFloat_f128(-1.0, 0); + try test_u64_intFromFloat_f128(-1.5, 0); + try test_u64_intFromFloat_f128(-1.99, 0); + try test_u64_intFromFloat_f128(-2.0, 0); + try test_u64_intFromFloat_f128(-2.01, 0); + + try test_u64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_u64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + + try test_u64_intFromFloat_f128(-0x1.FFFFFEp+62, 0); + try test_u64_intFromFloat_f128(-0x1.FFFFFCp+62, 0); + + try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + + try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, 0); + try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, 0); + + try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF); + try test_u64_intFromFloat_f128(0x1.0000000000000002p+63, 0x8000000000000001); + try test_u64_intFromFloat_f128(0x1.0000000000000000p+63, 0x8000000000000000); + try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF); + try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE); + try test_u64_intFromFloat_f128(0x1p+64, 0xFFFFFFFFFFFFFFFF); + + try test_u64_intFromFloat_f128(-0x1.0000000000000000p+63, 0); + try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFFCp+62, 0); + try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFF8p+62, 0); +} - try test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); - try test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); - try test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); +fn test_i128_intFromFloat_f128(a: f128, expected: i128) !void { + const x = i128_intFromFloat_f128(a); + try testing.expect(x == expected); +} - try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); +fn test_u128_intFromFloat_f128(a: f128, expected: u128) !void { + const x = u128_intFromFloat_f128(a); + try testing.expect(x == expected); +} - try test__fixtfti(math.floatMax(f128), math.maxInt(i128)); +test i128_intFromFloat_f128 { + try test_i128_intFromFloat_f128(-math.floatMax(f128), math.minInt(i128)); + + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); + + try test_i128_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); + + try test_i128_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000800); + try test_i128_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); + + try test_i128_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7fffff8000000000); + try test_i128_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7fffff0000000000); + + try test_i128_intFromFloat_f128(-2.01, -2); + try test_i128_intFromFloat_f128(-2.0, -2); + try test_i128_intFromFloat_f128(-1.99, -1); + try test_i128_intFromFloat_f128(-1.0, -1); + try test_i128_intFromFloat_f128(-0.99, 0); + try test_i128_intFromFloat_f128(-0.5, 0); + try test_i128_intFromFloat_f128(-math.floatMin(f128), 0); + try test_i128_intFromFloat_f128(0.0, 0); + try test_i128_intFromFloat_f128(math.floatMin(f128), 0); + try test_i128_intFromFloat_f128(0.5, 0); + try test_i128_intFromFloat_f128(0.99, 0); + try test_i128_intFromFloat_f128(1.0, 1); + try test_i128_intFromFloat_f128(1.5, 1); + try test_i128_intFromFloat_f128(1.99, 1); + try test_i128_intFromFloat_f128(2.0, 2); + try test_i128_intFromFloat_f128(2.01, 2); + + try test_i128_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i128_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_i128_intFromFloat_f128(0x1.0000000000000p+63, 0x8000000000000000); + try test_i128_intFromFloat_f128(0x1.0000000000001p+63, 0x8000000000000800); + + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); + try test_i128_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); + + try test_i128_intFromFloat_f128(math.floatMax(f128), math.maxInt(i128)); } -test "fixunstfti" { - try test__fixunstfti(math.inf(f128), 0xffffffffffffffffffffffffffffffff); +test u128_intFromFloat_f128 { + try test_u128_intFromFloat_f128(math.inf(f128), 0xffffffffffffffffffffffffffffffff); - try test__fixunstfti(0.0, 0); + try test_u128_intFromFloat_f128(0.0, 0); - try test__fixunstfti(0.5, 0); - try test__fixunstfti(0.99, 0); - try test__fixunstfti(1.0, 1); - try test__fixunstfti(1.5, 1); - try test__fixunstfti(1.99, 1); - try test__fixunstfti(2.0, 2); - try test__fixunstfti(2.01, 2); - try test__fixunstfti(-0.01, 0); - try test__fixunstfti(-0.99, 0); + try test_u128_intFromFloat_f128(0.5, 0); + try test_u128_intFromFloat_f128(0.99, 0); + try test_u128_intFromFloat_f128(1.0, 1); + try test_u128_intFromFloat_f128(1.5, 1); + try test_u128_intFromFloat_f128(1.99, 1); + try test_u128_intFromFloat_f128(2.0, 2); + try test_u128_intFromFloat_f128(2.01, 2); + try test_u128_intFromFloat_f128(-0.01, 0); + try test_u128_intFromFloat_f128(-0.99, 0); - try test__fixunstfti(0x1p+128, 0xffffffffffffffffffffffffffffffff); + try test_u128_intFromFloat_f128(0x1p+128, 0xffffffffffffffffffffffffffffffff); - try test__fixunstfti(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000); - try test__fixunstfti(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000); - try test__fixunstfti(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff); - try test__fixunstfti(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff); + try test_u128_intFromFloat_f128(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000); + try test_u128_intFromFloat_f128(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000); + try test_u128_intFromFloat_f128(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff); + try test_u128_intFromFloat_f128(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff); } -fn test__fixunshfti(a: f16, expected: u128) !void { - const x = __fixunshfti(a); +fn test_u128_intFromFloat_f16(a: f16, expected: u128) !void { + const x = impl.u128_intFromFloat_f16(a); try testing.expect(x == expected); } -test "fixunshfti for f16" { - try test__fixunshfti(math.inf(f16), math.maxInt(u128)); - try test__fixunshfti(math.floatMax(f16), 65504); +test u128_intFromFloat_f16 { + try test_u128_intFromFloat_f16(math.inf(f16), math.maxInt(u128)); + try test_u128_intFromFloat_f16(math.floatMax(f16), 65504); } -fn test__fixunsxfti(a: f80, expected: u128) !void { - const x = __fixunsxfti(a); +fn test_u128_intFromFloat_f80(a: f80, expected: u128) !void { + const x = impl.u128_intFromFloat_f80(a); try testing.expect(x == expected); } -test "fixunsxfti for f80" { - try test__fixunsxfti(math.inf(f80), math.maxInt(u128)); - try test__fixunsxfti(math.floatMax(f80), math.maxInt(u128)); - try test__fixunsxfti(math.maxInt(u64), math.maxInt(u64)); +test u128_intFromFloat_f80 { + try test_u128_intFromFloat_f80(math.inf(f80), math.maxInt(u128)); + try test_u128_intFromFloat_f80(math.floatMax(f80), math.maxInt(u128)); + try test_u128_intFromFloat_f80(math.maxInt(u64), math.maxInt(u64)); } diff --git a/lib/compiler_rt/limb64.zig b/lib/compiler_rt/limb64.zig index bfe4c441f0525b2e7f5e858e3fa98f81a2e9c865..1d41c0ff1f673c4822b69ccbf0eee69faad19b51 100644 --- a/lib/compiler_rt/limb64.zig +++ b/lib/compiler_rt/limb64.zig @@ -6,7 +6,7 @@ const minInt = std.math.minInt; const builtin = @import("builtin"); const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; const endian = builtin.cpu.arch.endian(); diff --git a/lib/compiler_rt/log.zig b/lib/compiler_rt/log.zig index da3757d8224c2ab62e88affd269170b5c64cae6b..9f632f69ff93a9c05663104c5429c7c8e787e761 100644 --- a/lib/compiler_rt/log.zig +++ b/lib/compiler_rt/log.zig @@ -11,7 +11,7 @@ const expectEqual = std.testing.expectEqual; const expectApproxEqRel = std.testing.expectApproxEqRel; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { symbol(&__logh, "__logh"); @@ -25,12 +25,18 @@ comptime { symbol(&logl, "logl"); } -pub fn __logh(a: f16) callconv(.c) f16 { +fn __logh(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(log_f16(compiler_rt.f16.fromAbi(a))); +} +pub fn log_f16(a: f16) f16 { // TODO: more efficient implementation - return @floatCast(logf(a)); + return @floatCast(log_f32(a)); } -pub fn logf(x_: f32) callconv(.c) f32 { +fn logf(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(log_f32(compiler_rt.f32.fromAbi(a))); +} +pub fn log_f32(x_: f32) f32 { const ln2_hi: f32 = 6.9313812256e-01; const ln2_lo: f32 = 9.0580006145e-06; const Lg1: f32 = 0xaaaaaa.0p-24; @@ -82,7 +88,10 @@ pub fn logf(x_: f32) callconv(.c) f32 { return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi; } -pub fn log(x: f64) callconv(.c) f64 { +fn log(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(log_f64(compiler_rt.f64.fromAbi(a))); +} +pub fn log_f64(x: f64) f64 { const poly1 = [_]f64{ -0x1p-1, 0x1.5555555555577p-2, @@ -432,11 +441,17 @@ pub fn log(x: f64) callconv(.c) f64 { return @bitCast(y); } -pub fn __logx(a: f80) callconv(.c) f80 { +fn __logx(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(log_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn log_f80(a: f80) f80 { // TODO: more efficient implementation - return @floatCast(logq(a)); + return @floatCast(log_f128(a)); } +fn logq(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(log_f128(compiler_rt.f128.fromAbi(a))); +} /// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic" /// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990 /// @@ -449,7 +464,7 @@ pub fn __logx(a: f80) callconv(.c) f80 { /// /// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case): /// <= 0.5 ulp: 99.96%, worst case <= 0.528 ulp -pub fn logq(x: f128) callconv(.c) f128 { +pub fn log_f128(x: f128) f128 { const impl = @import("log_f128.zig"); if (impl.specialCases(x)) |y| @@ -626,123 +641,123 @@ pub fn logq(x: f128) callconv(.c) f128 { pub fn logl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return log(x), - 80 => return __logx(x), - 128 => return logq(x), - else => @compileError("unreachable"), + 64 => return log_f64(x), + 80 => return log_f80(x), + 128 => return log_f128(x), + else => comptime unreachable, } } test "logf() special" { - try expectEqual(logf(0.0), -math.inf(f32)); - try expectEqual(logf(-0.0), -math.inf(f32)); - try expect(math.isPositiveZero(logf(1.0))); - try expectEqual(logf(math.e), 1.0); - try expectEqual(logf(math.inf(f32)), math.inf(f32)); - try expect(math.isNan(logf(-1.0))); - try expect(math.isNan(logf(-math.inf(f32)))); - try expect(math.isNan(logf(math.nan(f32)))); - try expect(math.isNan(logf(math.snan(f32)))); + try expectEqual(log_f32(0.0), -math.inf(f32)); + try expectEqual(log_f32(-0.0), -math.inf(f32)); + try expect(math.isPositiveZero(log_f32(1.0))); + try expectEqual(log_f32(math.e), 1.0); + try expectEqual(log_f32(math.inf(f32)), math.inf(f32)); + try expect(math.isNan(log_f32(-1.0))); + try expect(math.isNan(log_f32(-math.inf(f32)))); + try expect(math.isNan(log_f32(math.nan(f32)))); + try expect(math.isNan(log_f32(math.snan(f32)))); } test "logf() sanity" { - try expect(math.isNan(logf(-0x1.0223a0p+3))); - try expectEqual(logf(0x1.161868p+2), 0x1.7815b0p+0); - try expect(math.isNan(logf(-0x1.0c34b4p+3))); - try expect(math.isNan(logf(-0x1.a206f0p+2))); - try expectEqual(logf(0x1.288bbcp+3), 0x1.1cfcd6p+1); - try expectEqual(logf(0x1.52efd0p-1), -0x1.a6694cp-2); - try expect(math.isNan(logf(-0x1.a05cc8p-2))); - try expectEqual(logf(0x1.1f9efap-1), -0x1.2742bap-1); - try expectEqual(logf(0x1.8c5db0p-1), -0x1.062160p-2); - try expect(math.isNan(logf(-0x1.5b86eap-1))); + try expect(math.isNan(log_f32(-0x1.0223a0p+3))); + try expectEqual(log_f32(0x1.161868p+2), 0x1.7815b0p+0); + try expect(math.isNan(log_f32(-0x1.0c34b4p+3))); + try expect(math.isNan(log_f32(-0x1.a206f0p+2))); + try expectEqual(log_f32(0x1.288bbcp+3), 0x1.1cfcd6p+1); + try expectEqual(log_f32(0x1.52efd0p-1), -0x1.a6694cp-2); + try expect(math.isNan(log_f32(-0x1.a05cc8p-2))); + try expectEqual(log_f32(0x1.1f9efap-1), -0x1.2742bap-1); + try expectEqual(log_f32(0x1.8c5db0p-1), -0x1.062160p-2); + try expect(math.isNan(log_f32(-0x1.5b86eap-1))); } test "logf() boundary" { - try expectEqual(logf(0x1.fffffep+127), 0x1.62e430p+6); // Max input value - try expectEqual(logf(0x1p-149), -0x1.9d1da0p+6); // Min positive input value - try expect(math.isNan(logf(-0x1p-149))); // Min negative input value - try expectEqual(logf(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0 - try expectEqual(logf(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0 - try expectEqual(logf(0x1p-126), -0x1.5d58a0p+6); // First subnormal - try expect(math.isNan(logf(-0x1p-126))); // First negative subnormal + try expectEqual(log_f32(0x1.fffffep+127), 0x1.62e430p+6); // Max input value + try expectEqual(log_f32(0x1p-149), -0x1.9d1da0p+6); // Min positive input value + try expect(math.isNan(log_f32(-0x1p-149))); // Min negative input value + try expectEqual(log_f32(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0 + try expectEqual(log_f32(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0 + try expectEqual(log_f32(0x1p-126), -0x1.5d58a0p+6); // First subnormal + try expect(math.isNan(log_f32(-0x1p-126))); // First negative subnormal } test "log() special" { - try expectEqual(log(0.0), -math.inf(f64)); - try expectEqual(log(-0.0), -math.inf(f64)); - try expect(math.isPositiveZero(log(1.0))); - try expectEqual(log(math.e), 1.0); - try expectEqual(log(math.inf(f64)), math.inf(f64)); - try expect(math.isNan(log(-1.0))); - try expect(math.isNan(log(-math.inf(f64)))); - try expect(math.isNan(log(math.nan(f64)))); - try expect(math.isNan(log(math.snan(f64)))); + try expectEqual(log_f64(0.0), -math.inf(f64)); + try expectEqual(log_f64(-0.0), -math.inf(f64)); + try expect(math.isPositiveZero(log_f64(1.0))); + try expectEqual(log_f64(math.e), 1.0); + try expectEqual(log_f64(math.inf(f64)), math.inf(f64)); + try expect(math.isNan(log_f64(-1.0))); + try expect(math.isNan(log_f64(-math.inf(f64)))); + try expect(math.isNan(log_f64(math.nan(f64)))); + try expect(math.isNan(log_f64(math.snan(f64)))); } test "log() sanity" { - try expect(math.isNan(log(-0x1.02239f3c6a8f1p+3))); - try expectEqual(log(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0); - try expect(math.isNan(log(-0x1.0c34b3e01e6e7p+3))); - try expect(math.isNan(log(-0x1.a206f0a19dcc4p+2))); - try expectEqual(log(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1); - try expectEqual(log(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2); - try expect(math.isNan(log(-0x1.a05cc754481d1p-2))); - try expectEqual(log(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1); - try expectEqual(log(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2); - try expect(math.isNan(log(-0x1.5b86ea8118a0ep-1))); + try expect(math.isNan(log_f64(-0x1.02239f3c6a8f1p+3))); + try expectEqual(log_f64(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0); + try expect(math.isNan(log_f64(-0x1.0c34b3e01e6e7p+3))); + try expect(math.isNan(log_f64(-0x1.a206f0a19dcc4p+2))); + try expectEqual(log_f64(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1); + try expectEqual(log_f64(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2); + try expect(math.isNan(log_f64(-0x1.a05cc754481d1p-2))); + try expectEqual(log_f64(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1); + try expectEqual(log_f64(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2); + try expect(math.isNan(log_f64(-0x1.5b86ea8118a0ep-1))); } test "log() boundary" { - try expectEqual(log(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value - try expectEqual(log(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value - try expect(math.isNan(log(-0x1p-1074))); // Min negative input value - try expectEqual(log(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0 - try expectEqual(log(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0 - try expectEqual(log(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal - try expect(math.isNan(log(-0x1p-1022))); // First negative subnormal + try expectEqual(log_f64(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value + try expectEqual(log_f64(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value + try expect(math.isNan(log_f64(-0x1p-1074))); // Min negative input value + try expectEqual(log_f64(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0 + try expectEqual(log_f64(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0 + try expectEqual(log_f64(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal + try expect(math.isNan(log_f64(-0x1p-1022))); // First negative subnormal } test "logq() special" { - try expectEqual(logq(0.0), -math.inf(f128)); - try expectEqual(logq(-0.0), -math.inf(f128)); - try expect(math.isPositiveZero(logq(1.0))); + try expectEqual(log_f128(0.0), -math.inf(f128)); + try expectEqual(log_f128(-0.0), -math.inf(f128)); + try expect(math.isPositiveZero(log_f128(1.0))); // Sadly, the rounding gods decided that 0.9999999999999999999999999999999999 - // is the correctly rounded value of logq(math.e) - try expectApproxEqRel(logq(math.e), 1.0, math.floatEpsAt(f128, 1.0)); - try expectEqual(logq(math.inf(f128)), math.inf(f128)); - try expect(math.isNan(logq(-1.0))); - try expect(math.isNan(logq(-math.inf(f128)))); - try expect(math.isNan(logq(math.nan(f128)))); - try expect(math.isNan(logq(math.snan(f128)))); + // is the correctly rounded value of log_f128(math.e) + try expectApproxEqRel(log_f128(math.e), 1.0, math.floatEpsAt(f128, 1.0)); + try expectEqual(log_f128(math.inf(f128)), math.inf(f128)); + try expect(math.isNan(log_f128(-1.0))); + try expect(math.isNan(log_f128(-math.inf(f128)))); + try expect(math.isNan(log_f128(math.nan(f128)))); + try expect(math.isNan(log_f128(math.snan(f128)))); } test "logq() boundary" { - try expectEqual(logq(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value - try expectEqual(logq(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value - try expect(math.isNan(logq(-0x1p-16494))); // Min negative input value - try expectEqual(logq(0x1.0000000000000000000000000001p0), 0x1.ffffffffffffffffffffffffffffp-113); // Last value before result reaches +0 - try expectEqual(logq(0x1.ffffffffffffffffffffffffffffp-1), -0x1p-113); // Last value before result reaches -0 - try expectEqual(logq(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal - try expect(math.isNan(logq(-0x1p-16382))); // First negative subnormal + try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value + try expectEqual(log_f128(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value + try expect(math.isNan(log_f128(-0x1p-16494))); // Min negative input value + try expectEqual(log_f128(0x1.0000000000000000000000000001p0), 0x1.ffffffffffffffffffffffffffffp-113); // Last value before result reaches +0 + try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1p-113); // Last value before result reaches -0 + try expectEqual(log_f128(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal + try expect(math.isNan(log_f128(-0x1p-16382))); // First negative subnormal } test "logq() sanity" { - try expectEqual(logq(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0); - try expectEqual(logq(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1); - try expectEqual(logq(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1); - try expectEqual(logq(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1); - try expectEqual(logq(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1); - try expectEqual(logq(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1); - try expectEqual(logq(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1); - try expectEqual(logq(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1); - try expectEqual(logq(1.200355637363589375e14), 3.2418809179272977400408325788186897e1); - try expectEqual(logq(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1); - try expectEqual(logq(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1); + try expectEqual(log_f128(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0); + try expectEqual(log_f128(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1); + try expectEqual(log_f128(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1); + try expectEqual(log_f128(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1); + try expectEqual(log_f128(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1); + try expectEqual(log_f128(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1); + try expectEqual(log_f128(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1); + try expectEqual(log_f128(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1); + try expectEqual(log_f128(1.200355637363589375e14), 3.2418809179272977400408325788186897e1); + try expectEqual(log_f128(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1); + try expectEqual(log_f128(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1); // testing near 1 - try expectEqual(logq(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2); - try expectEqual(logq(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2); - try expectEqual(logq(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2); - try expectEqual(logq(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2); - try expectEqual(logq(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2); + try expectEqual(log_f128(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2); + try expectEqual(log_f128(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2); + try expectEqual(log_f128(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2); + try expectEqual(log_f128(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2); + try expectEqual(log_f128(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2); } diff --git a/lib/compiler_rt/log10.zig b/lib/compiler_rt/log10.zig index 18479d534a347721c842b682228f29688213909c..6a554e0ea79ff597dfdeeea31477e1c6ebfbac1c 100644 --- a/lib/compiler_rt/log10.zig +++ b/lib/compiler_rt/log10.zig @@ -25,12 +25,18 @@ comptime { symbol(&log10l, "log10l"); } -pub fn __log10h(a: f16) callconv(.c) f16 { +fn __log10h(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(log10_f16(compiler_rt.f16.fromAbi(a))); +} +pub fn log10_f16(a: f16) f16 { // TODO: more efficient implementation - return @floatCast(log10f(a)); + return @floatCast(log10_f32(a)); } -pub fn log10f(x_: f32) callconv(.c) f32 { +fn log10f(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(log10_f32(compiler_rt.f32.fromAbi(a))); +} +pub fn log10_f32(x_: f32) f32 { const ivln10hi: f32 = 4.3432617188e-01; const ivln10lo: f32 = -3.1689971365e-05; const log10_2hi: f32 = 3.0102920532e-01; @@ -90,7 +96,10 @@ pub fn log10f(x_: f32) callconv(.c) f32 { return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi; } -pub fn log10(x_: f64) callconv(.c) f64 { +fn log10(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(log10_f64(compiler_rt.f64.fromAbi(a))); +} +pub fn log10_f64(x_: f64) f64 { const ivln10hi: f64 = 4.34294481878168880939e-01; const ivln10lo: f64 = 2.50829467116452752298e-11; const log10_2hi: f64 = 3.01029995663611771306e-01; @@ -165,11 +174,17 @@ pub fn log10(x_: f64) callconv(.c) f64 { return val_lo + val_hi; } -pub fn __log10x(a: f80) callconv(.c) f80 { +fn __log10x(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(log10_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn log10_f80(a: f80) f80 { // TODO: more efficient implementation - return @floatCast(log10q(a)); + return @floatCast(log10_f128(a)); } +fn log10q(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(log10_f128(compiler_rt.f128.fromAbi(a))); +} /// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic" /// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990 /// @@ -182,7 +197,7 @@ pub fn __log10x(a: f80) callconv(.c) f80 { /// /// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case): /// <= 0.5 ulp: 99.96%, worst case <= 0.565 ulp -pub fn log10q(x: f128) callconv(.c) f128 { +pub fn log10_f128(x: f128) f128 { const impl = @import("log_f128.zig"); if (impl.specialCases(x)) |y| @@ -359,124 +374,124 @@ pub fn log10q(x: f128) callconv(.c) f128 { pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return log10(x), - 80 => return __log10x(x), - 128 => return log10q(x), - else => @compileError("unreachable"), + 64 => return log10_f64(x), + 80 => return log10_f80(x), + 128 => return log10_f128(x), + else => comptime unreachable, } } test "log10f() special" { - try expectEqual(log10f(0.0), -math.inf(f32)); - try expectEqual(log10f(-0.0), -math.inf(f32)); - try expect(math.isPositiveZero(log10f(1.0))); - try expectEqual(log10f(10.0), 1.0); - try expectEqual(log10f(0.1), -1.0); - try expectEqual(log10f(math.inf(f32)), math.inf(f32)); - try expect(math.isNan(log10f(-1.0))); - try expect(math.isNan(log10f(-math.inf(f32)))); - try expect(math.isNan(log10f(math.nan(f32)))); - try expect(math.isNan(log10f(math.snan(f32)))); + try expectEqual(log10_f32(0.0), -math.inf(f32)); + try expectEqual(log10_f32(-0.0), -math.inf(f32)); + try expect(math.isPositiveZero(log10_f32(1.0))); + try expectEqual(log10_f32(10.0), 1.0); + try expectEqual(log10_f32(0.1), -1.0); + try expectEqual(log10_f32(math.inf(f32)), math.inf(f32)); + try expect(math.isNan(log10_f32(-1.0))); + try expect(math.isNan(log10_f32(-math.inf(f32)))); + try expect(math.isNan(log10_f32(math.nan(f32)))); + try expect(math.isNan(log10_f32(math.snan(f32)))); } test "log10f() sanity" { - try expect(math.isNan(log10f(-0x1.0223a0p+3))); - try expectEqual(log10f(0x1.161868p+2), 0x1.46a9bcp-1); - try expect(math.isNan(log10f(-0x1.0c34b4p+3))); - try expect(math.isNan(log10f(-0x1.a206f0p+2))); - try expectEqual(log10f(0x1.288bbcp+3), 0x1.ef1300p-1); - try expectEqual(log10f(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit - try expect(math.isNan(log10f(-0x1.a05cc8p-2))); - try expectEqual(log10f(0x1.1f9efap-1), -0x1.0075ccp-2); - try expectEqual(log10f(0x1.8c5db0p-1), -0x1.c75df8p-4); - try expect(math.isNan(log10f(-0x1.5b86eap-1))); + try expect(math.isNan(log10_f32(-0x1.0223a0p+3))); + try expectEqual(log10_f32(0x1.161868p+2), 0x1.46a9bcp-1); + try expect(math.isNan(log10_f32(-0x1.0c34b4p+3))); + try expect(math.isNan(log10_f32(-0x1.a206f0p+2))); + try expectEqual(log10_f32(0x1.288bbcp+3), 0x1.ef1300p-1); + try expectEqual(log10_f32(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit + try expect(math.isNan(log10_f32(-0x1.a05cc8p-2))); + try expectEqual(log10_f32(0x1.1f9efap-1), -0x1.0075ccp-2); + try expectEqual(log10_f32(0x1.8c5db0p-1), -0x1.c75df8p-4); + try expect(math.isNan(log10_f32(-0x1.5b86eap-1))); } test "log10f() boundary" { - try expectEqual(log10f(0x1.fffffep+127), 0x1.344136p+5); // Max input value - try expectEqual(log10f(0x1p-149), -0x1.66d3e8p+5); // Min positive input value - try expect(math.isNan(log10f(-0x1p-149))); // Min negative input value - try expectEqual(log10f(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0 - try expectEqual(log10f(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0 - try expectEqual(log10f(0x1p-126), -0x1.2f7030p+5); // First subnormal - try expect(math.isNan(log10f(-0x1p-126))); // First negative subnormal + try expectEqual(log10_f32(0x1.fffffep+127), 0x1.344136p+5); // Max input value + try expectEqual(log10_f32(0x1p-149), -0x1.66d3e8p+5); // Min positive input value + try expect(math.isNan(log10_f32(-0x1p-149))); // Min negative input value + try expectEqual(log10_f32(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0 + try expectEqual(log10_f32(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0 + try expectEqual(log10_f32(0x1p-126), -0x1.2f7030p+5); // First subnormal + try expect(math.isNan(log10_f32(-0x1p-126))); // First negative subnormal } test "log10() special" { - try expectEqual(log10(0.0), -math.inf(f64)); - try expectEqual(log10(-0.0), -math.inf(f64)); - try expect(math.isPositiveZero(log10(1.0))); - try expectEqual(log10(10.0), 1.0); - try expectEqual(log10(0.1), -1.0); - try expectEqual(log10(math.inf(f64)), math.inf(f64)); - try expect(math.isNan(log10(-1.0))); - try expect(math.isNan(log10(-math.inf(f64)))); - try expect(math.isNan(log10(math.nan(f64)))); - try expect(math.isNan(log10(math.snan(f64)))); + try expectEqual(log10_f64(0.0), -math.inf(f64)); + try expectEqual(log10_f64(-0.0), -math.inf(f64)); + try expect(math.isPositiveZero(log10_f64(1.0))); + try expectEqual(log10_f64(10.0), 1.0); + try expectEqual(log10_f64(0.1), -1.0); + try expectEqual(log10_f64(math.inf(f64)), math.inf(f64)); + try expect(math.isNan(log10_f64(-1.0))); + try expect(math.isNan(log10_f64(-math.inf(f64)))); + try expect(math.isNan(log10_f64(math.nan(f64)))); + try expect(math.isNan(log10_f64(math.snan(f64)))); } test "log10() sanity" { - try expect(math.isNan(log10(-0x1.02239f3c6a8f1p+3))); - try expectEqual(log10(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1); - try expect(math.isNan(log10(-0x1.0c34b3e01e6e7p+3))); - try expect(math.isNan(log10(-0x1.a206f0a19dcc4p+2))); - try expectEqual(log10(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1); - try expectEqual(log10(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3); - try expect(math.isNan(log10(-0x1.a05cc754481d1p-2))); - try expectEqual(log10(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2); - try expectEqual(log10(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4); - try expect(math.isNan(log10(-0x1.5b86ea8118a0ep-1))); + try expect(math.isNan(log10_f64(-0x1.02239f3c6a8f1p+3))); + try expectEqual(log10_f64(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1); + try expect(math.isNan(log10_f64(-0x1.0c34b3e01e6e7p+3))); + try expect(math.isNan(log10_f64(-0x1.a206f0a19dcc4p+2))); + try expectEqual(log10_f64(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1); + try expectEqual(log10_f64(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3); + try expect(math.isNan(log10_f64(-0x1.a05cc754481d1p-2))); + try expectEqual(log10_f64(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2); + try expectEqual(log10_f64(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4); + try expect(math.isNan(log10_f64(-0x1.5b86ea8118a0ep-1))); } test "log10() boundary" { - try expectEqual(log10(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value - try expectEqual(log10(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value - try expect(math.isNan(log10(-0x1p-1074))); // Min negative input value - try expectEqual(log10(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0 - try expectEqual(log10(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0 - try expectEqual(log10(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal - try expect(math.isNan(log10(-0x1p-1022))); // First negative subnormal + try expectEqual(log10_f64(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value + try expectEqual(log10_f64(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value + try expect(math.isNan(log10_f64(-0x1p-1074))); // Min negative input value + try expectEqual(log10_f64(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0 + try expectEqual(log10_f64(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0 + try expectEqual(log10_f64(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal + try expect(math.isNan(log10_f64(-0x1p-1022))); // First negative subnormal } test "log10q() special" { - try expectEqual(log10q(0.0), -math.inf(f128)); - try expectEqual(log10q(-0.0), -math.inf(f128)); - try expect(math.isPositiveZero(log10q(1.0))); - try expectEqual(log10q(10.0), 1.0); - try expectEqual(log10q(0.1), -1.0); - try expectEqual(log10q(math.inf(f128)), math.inf(f128)); - try expect(math.isNan(log10q(-1.0))); - try expect(math.isNan(log10q(-math.inf(f128)))); - try expect(math.isNan(log10q(math.nan(f128)))); - try expect(math.isNan(log10q(math.snan(f128)))); + try expectEqual(log10_f128(0.0), -math.inf(f128)); + try expectEqual(log10_f128(-0.0), -math.inf(f128)); + try expect(math.isPositiveZero(log10_f128(1.0))); + try expectEqual(log10_f128(10.0), 1.0); + try expectEqual(log10_f128(0.1), -1.0); + try expectEqual(log10_f128(math.inf(f128)), math.inf(f128)); + try expect(math.isNan(log10_f128(-1.0))); + try expect(math.isNan(log10_f128(-math.inf(f128)))); + try expect(math.isNan(log10_f128(math.nan(f128)))); + try expect(math.isNan(log10_f128(math.snan(f128)))); } test "log10q() sanity" { - try expectEqual(log10q(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3); - try expectEqual(log10q(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3); - try expectEqual(log10q(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2); - try expectEqual(log10q(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3); - try expectEqual(log10q(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3); - try expectEqual(log10q(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3); - try expectEqual(log10q(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3); - try expectEqual(log10q(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3); - try expectEqual(log10q(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3); - try expectEqual(log10q(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2); + try expectEqual(log10_f128(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3); + try expectEqual(log10_f128(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3); + try expectEqual(log10_f128(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2); + try expectEqual(log10_f128(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3); + try expectEqual(log10_f128(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3); + try expectEqual(log10_f128(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3); + try expectEqual(log10_f128(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3); + try expectEqual(log10_f128(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3); + try expectEqual(log10_f128(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3); + try expectEqual(log10_f128(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2); // testing near 1 - try expectEqual(log10q(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2); - try expectEqual(log10q(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2); - try expectEqual(log10q(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3); - try expectEqual(log10q(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2); - try expectEqual(log10q(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3); - try expectEqual(log10q(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2); + try expectEqual(log10_f128(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2); + try expectEqual(log10_f128(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2); + try expectEqual(log10_f128(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3); + try expectEqual(log10_f128(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2); + try expectEqual(log10_f128(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3); + try expectEqual(log10_f128(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2); } test "log10q() boundary" { - try expectEqual(log10q(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value - try expectEqual(log10q(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value - try expect(math.isNan(log10q(-0x1p-16494))); // Min negative input value - try expectEqual(log10q(0x1.0000000000000000000000000001p0), 0x1.bcb7b1526e50e32a6ab7555f5a67p-114); // Last value before result reaches +0 - try expectEqual(log10q(0x1.ffffffffffffffffffffffffffffp-1), -0x1.bcb7b1526e50e32a6ab7555f5a68p-115); // Last value before result reaches -0 - try expectEqual(log10q(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal - try expect(math.isNan(log10q(-0x1p-16382))); // First negative subnormal + try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value + try expectEqual(log10_f128(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value + try expect(math.isNan(log10_f128(-0x1p-16494))); // Min negative input value + try expectEqual(log10_f128(0x1.0000000000000000000000000001p0), 0x1.bcb7b1526e50e32a6ab7555f5a67p-114); // Last value before result reaches +0 + try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.bcb7b1526e50e32a6ab7555f5a68p-115); // Last value before result reaches -0 + try expectEqual(log10_f128(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal + try expect(math.isNan(log10_f128(-0x1p-16382))); // First negative subnormal } diff --git a/lib/compiler_rt/log2.zig b/lib/compiler_rt/log2.zig index 8db17aaf3f26f257482af43b7bc125d4747dbfe2..b748a0af826586065f1f5369a6f1c61492b4cf99 100644 --- a/lib/compiler_rt/log2.zig +++ b/lib/compiler_rt/log2.zig @@ -26,12 +26,18 @@ comptime { symbol(&log2l, "log2l"); } -pub fn __log2h(a: f16) callconv(.c) f16 { +fn __log2h(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(log2_f16(compiler_rt.f16.fromAbi(a))); +} +pub fn log2_f16(a: f16) f16 { // TODO: more efficient implementation - return @floatCast(log2f(a)); + return @floatCast(log2_f32(a)); } -pub fn log2f(x_: f32) callconv(.c) f32 { +fn log2f(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(log2_f32(compiler_rt.f32.fromAbi(a))); +} +pub fn log2_f32(x_: f32) f32 { const ivln2hi: f32 = 1.4428710938e+00; const ivln2lo: f32 = -1.7605285393e-04; const Lg1: f32 = 0xaaaaaa.0p-24; @@ -87,7 +93,10 @@ pub fn log2f(x_: f32) callconv(.c) f32 { return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + @as(f32, @floatFromInt(k)); } -pub fn log2(x_: f64) callconv(.c) f64 { +fn log2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(log2_f64(compiler_rt.f64.fromAbi(a))); +} +pub fn log2_f64(x_: f64) f64 { const ivln2hi: f64 = 1.44269504072144627571e+00; const ivln2lo: f64 = 1.67517131648865118353e-10; const Lg1: f64 = 6.666666666666735130e-01; @@ -158,11 +167,17 @@ pub fn log2(x_: f64) callconv(.c) f64 { return val_lo + val_hi; } -pub fn __log2x(a: f80) callconv(.c) f80 { +fn __log2x(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(log2_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn log2_f80(a: f80) f80 { // TODO: more efficient implementation - return @floatCast(log2q(a)); + return @floatCast(log2_f128(a)); } +fn log2q(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(log2_f128(compiler_rt.f128.fromAbi(a))); +} /// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic" /// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990 /// @@ -175,7 +190,7 @@ pub fn __log2x(a: f80) callconv(.c) f80 { /// /// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case): /// <= 0.5 ulp: 99.86%, worst case <= 0.546 ulp -pub fn log2q(x: f128) callconv(.c) f128 { +pub fn log2_f128(x: f128) f128 { const impl = @import("log_f128.zig"); if (impl.specialCases(x)) |y| @@ -351,117 +366,117 @@ pub fn log2q(x: f128) callconv(.c) f128 { pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return log2(x), - 80 => return __log2x(x), - 128 => return log2q(x), - else => @compileError("unreachable"), + 64 => return log2_f64(x), + 80 => return log2_f80(x), + 128 => return log2_f128(x), + else => comptime unreachable, } } test "log2f() special" { - try expectEqual(log2f(0.0), -math.inf(f32)); - try expectEqual(log2f(-0.0), -math.inf(f32)); - try expect(math.isPositiveZero(log2f(1.0))); - try expectEqual(log2f(2.0), 1.0); - try expectEqual(log2f(math.inf(f32)), math.inf(f32)); - try expect(math.isNan(log2f(-1.0))); - try expect(math.isNan(log2f(-math.inf(f32)))); - try expect(math.isNan(log2f(math.nan(f32)))); - try expect(math.isNan(log2f(math.snan(f32)))); + try expectEqual(log2_f32(0.0), -math.inf(f32)); + try expectEqual(log2_f32(-0.0), -math.inf(f32)); + try expect(math.isPositiveZero(log2_f32(1.0))); + try expectEqual(log2_f32(2.0), 1.0); + try expectEqual(log2_f32(math.inf(f32)), math.inf(f32)); + try expect(math.isNan(log2_f32(-1.0))); + try expect(math.isNan(log2_f32(-math.inf(f32)))); + try expect(math.isNan(log2_f32(math.nan(f32)))); + try expect(math.isNan(log2_f32(math.snan(f32)))); } test "log2f() sanity" { - try expect(math.isNan(log2f(-0x1.0223a0p+3))); - try expectEqual(log2f(0x1.161868p+2), 0x1.0f49acp+1); - try expect(math.isNan(log2f(-0x1.0c34b4p+3))); - try expect(math.isNan(log2f(-0x1.a206f0p+2))); - try expectEqual(log2f(0x1.288bbcp+3), 0x1.9b2676p+1); - try expectEqual(log2f(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit - try expect(math.isNan(log2f(-0x1.a05cc8p-2))); - try expectEqual(log2f(0x1.1f9efap-1), -0x1.a9f89ap-1); - try expectEqual(log2f(0x1.8c5db0p-1), -0x1.7a2c96p-2); - try expect(math.isNan(log2f(-0x1.5b86eap-1))); + try expect(math.isNan(log2_f32(-0x1.0223a0p+3))); + try expectEqual(log2_f32(0x1.161868p+2), 0x1.0f49acp+1); + try expect(math.isNan(log2_f32(-0x1.0c34b4p+3))); + try expect(math.isNan(log2_f32(-0x1.a206f0p+2))); + try expectEqual(log2_f32(0x1.288bbcp+3), 0x1.9b2676p+1); + try expectEqual(log2_f32(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit + try expect(math.isNan(log2_f32(-0x1.a05cc8p-2))); + try expectEqual(log2_f32(0x1.1f9efap-1), -0x1.a9f89ap-1); + try expectEqual(log2_f32(0x1.8c5db0p-1), -0x1.7a2c96p-2); + try expect(math.isNan(log2_f32(-0x1.5b86eap-1))); } test "log2f() boundary" { - try expectEqual(log2f(0x1.fffffep+127), 0x1p+7); // Max input value - try expectEqual(log2f(0x1p-149), -0x1.2ap+7); // Min positive input value - try expect(math.isNan(log2f(-0x1p-149))); // Min negative input value - try expectEqual(log2f(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0 - try expectEqual(log2f(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0 - try expectEqual(log2f(0x1p-126), -0x1.f8p+6); // First subnormal - try expect(math.isNan(log2f(-0x1p-126))); // First negative subnormal + try expectEqual(log2_f32(0x1.fffffep+127), 0x1p+7); // Max input value + try expectEqual(log2_f32(0x1p-149), -0x1.2ap+7); // Min positive input value + try expect(math.isNan(log2_f32(-0x1p-149))); // Min negative input value + try expectEqual(log2_f32(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0 + try expectEqual(log2_f32(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0 + try expectEqual(log2_f32(0x1p-126), -0x1.f8p+6); // First subnormal + try expect(math.isNan(log2_f32(-0x1p-126))); // First negative subnormal } test "log2() special" { - try expectEqual(log2(0.0), -math.inf(f64)); - try expectEqual(log2(-0.0), -math.inf(f64)); - try expect(math.isPositiveZero(log2(1.0))); - try expectEqual(log2(2.0), 1.0); - try expectEqual(log2(math.inf(f64)), math.inf(f64)); - try expect(math.isNan(log2(-1.0))); - try expect(math.isNan(log2(-math.inf(f64)))); - try expect(math.isNan(log2(math.nan(f64)))); - try expect(math.isNan(log2(math.snan(f64)))); + try expectEqual(log2_f64(0.0), -math.inf(f64)); + try expectEqual(log2_f64(-0.0), -math.inf(f64)); + try expect(math.isPositiveZero(log2_f64(1.0))); + try expectEqual(log2_f64(2.0), 1.0); + try expectEqual(log2_f64(math.inf(f64)), math.inf(f64)); + try expect(math.isNan(log2_f64(-1.0))); + try expect(math.isNan(log2_f64(-math.inf(f64)))); + try expect(math.isNan(log2_f64(math.nan(f64)))); + try expect(math.isNan(log2_f64(math.snan(f64)))); } test "log2() sanity" { - try expect(math.isNan(log2(-0x1.02239f3c6a8f1p+3))); - try expectEqual(log2(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1); - try expect(math.isNan(log2(-0x1.0c34b3e01e6e7p+3))); - try expect(math.isNan(log2(-0x1.a206f0a19dcc4p+2))); - try expectEqual(log2(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1); - try expectEqual(log2(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1); - try expect(math.isNan(log2(-0x1.a05cc754481d1p-2))); - try expectEqual(log2(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1); - try expectEqual(log2(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2); - try expect(math.isNan(log2(-0x1.5b86ea8118a0ep-1))); + try expect(math.isNan(log2_f64(-0x1.02239f3c6a8f1p+3))); + try expectEqual(log2_f64(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1); + try expect(math.isNan(log2_f64(-0x1.0c34b3e01e6e7p+3))); + try expect(math.isNan(log2_f64(-0x1.a206f0a19dcc4p+2))); + try expectEqual(log2_f64(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1); + try expectEqual(log2_f64(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1); + try expect(math.isNan(log2_f64(-0x1.a05cc754481d1p-2))); + try expectEqual(log2_f64(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1); + try expectEqual(log2_f64(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2); + try expect(math.isNan(log2_f64(-0x1.5b86ea8118a0ep-1))); } test "log2() boundary" { - try expectEqual(log2(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value - try expectEqual(log2(0x1p-1074), -0x1.0c8p+10); // Min positive input value - try expect(math.isNan(log2(-0x1p-1074))); // Min negative input value - try expectEqual(log2(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0 - try expectEqual(log2(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0 - try expectEqual(log2(0x1p-1022), -0x1.ffp+9); // First subnormal - try expect(math.isNan(log2(-0x1p-1022))); // First negative subnormal + try expectEqual(log2_f64(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value + try expectEqual(log2_f64(0x1p-1074), -0x1.0c8p+10); // Min positive input value + try expect(math.isNan(log2_f64(-0x1p-1074))); // Min negative input value + try expectEqual(log2_f64(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0 + try expectEqual(log2_f64(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0 + try expectEqual(log2_f64(0x1p-1022), -0x1.ffp+9); // First subnormal + try expect(math.isNan(log2_f64(-0x1p-1022))); // First negative subnormal } test "log2q() special" { - try expectEqual(log2q(0.0), -math.inf(f128)); - try expectEqual(log2q(-0.0), -math.inf(f128)); - try expect(math.isPositiveZero(log2q(1.0))); - try expectEqual(log2q(2.0), 1.0); - try expectEqual(log2q(math.inf(f128)), math.inf(f128)); - try expect(math.isNan(log2q(-1.0))); - try expect(math.isNan(log2q(-math.inf(f128)))); - try expect(math.isNan(log2q(math.nan(f128)))); - try expect(math.isNan(log2q(math.snan(f128)))); + try expectEqual(log2_f128(0.0), -math.inf(f128)); + try expectEqual(log2_f128(-0.0), -math.inf(f128)); + try expect(math.isPositiveZero(log2_f128(1.0))); + try expectEqual(log2_f128(2.0), 1.0); + try expectEqual(log2_f128(math.inf(f128)), math.inf(f128)); + try expect(math.isNan(log2_f128(-1.0))); + try expect(math.isNan(log2_f128(-math.inf(f128)))); + try expect(math.isNan(log2_f128(math.nan(f128)))); + try expect(math.isNan(log2_f128(math.snan(f128)))); } test "log2q() boundary" { - try expectEqual(log2q(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value - try expectEqual(log2q(0x1p-16494), -0x1.01b8p14); // Min positive input value - try expect(math.isNan(log2q(-0x1p-16494))); // Min negative input value - try expectEqual(log2q(0x1.0000000000000000000000000001p0), 0x1.71547652b82fe1777d0ffda0d23ap-112); // Last value before result reaches +0 - try expectEqual(log2q(0x1.ffffffffffffffffffffffffffffp-1), -0x1.71547652b82fe1777d0ffda0d23bp-113); // Last value before result reaches -0 - try expectEqual(log2q(0x1p-16382), -0x1.fffp13); // First subnormal - try expect(math.isNan(log2q(-0x1p-16382))); // First negative subnormal + try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value + try expectEqual(log2_f128(0x1p-16494), -0x1.01b8p14); // Min positive input value + try expect(math.isNan(log2_f128(-0x1p-16494))); // Min negative input value + try expectEqual(log2_f128(0x1.0000000000000000000000000001p0), 0x1.71547652b82fe1777d0ffda0d23ap-112); // Last value before result reaches +0 + try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.71547652b82fe1777d0ffda0d23bp-113); // Last value before result reaches -0 + try expectEqual(log2_f128(0x1p-16382), -0x1.fffp13); // First subnormal + try expect(math.isNan(log2_f128(-0x1p-16382))); // First negative subnormal } test "log2q() sanity" { - try expectEqual(log2q(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1); - try expectEqual(log2q(8.346531942223744e15), 5.28900982928636641107356163006646e1); - try expectEqual(log2q(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1); - try expectEqual(log2q(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1); - try expectEqual(log2q(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1); - try expectEqual(log2q(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1); + try expectEqual(log2_f128(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1); + try expectEqual(log2_f128(8.346531942223744e15), 5.28900982928636641107356163006646e1); + try expectEqual(log2_f128(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1); + try expectEqual(log2_f128(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1); + try expectEqual(log2_f128(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1); + try expectEqual(log2_f128(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1); // test near 1 - try expectEqual(log2q(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2); - try expectEqual(log2q(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4); - try expectEqual(log2q(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2); - try expectEqual(log2q(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2); - try expectEqual(log2q(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2); + try expectEqual(log2_f128(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2); + try expectEqual(log2_f128(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4); + try expectEqual(log2_f128(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2); + try expectEqual(log2_f128(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2); + try expectEqual(log2_f128(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2); } diff --git a/lib/compiler_rt/mulc3.zig b/lib/compiler_rt/mulc3.zig index eea753245f7687b2e3e9b65c12bdd278f1a3c757..fc0f2d24b4f603d9c933eb1328dbf5b73e4f41bc 100644 --- a/lib/compiler_rt/mulc3.zig +++ b/lib/compiler_rt/mulc3.zig @@ -3,19 +3,80 @@ const isNan = std.math.isNan; const isInf = std.math.isInf; const copysign = std.math.copysign; -pub fn Complex(comptime T: type) type { - return extern struct { - real: T, - imag: T, - }; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; +const Complex = compiler_rt.Complex; + +comptime { + if (@import("builtin").zig_backend != .stage2_c) { + symbol(&__mulhc3, "__mulhc3"); + symbol(&__mulsc3, "__mulsc3"); + symbol(&__muldc3, "__muldc3"); + symbol(&__mulxc3, "__mulxc3"); + if (compiler_rt.want_ppc_abi) { + symbol(&__multc3, "__mulkc3"); + } else { + symbol(&__multc3, "__multc3"); + } + } +} + +fn __mulhc3(lhs_real: compiler_rt.f16.Abi, lhs_imag: compiler_rt.f16.Abi, rhs_real: compiler_rt.f16.Abi, rhs_imag: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.complex.Abi { + return compiler_rt.f16.complex.toAbi(mul_cf16( + compiler_rt.f16.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f16.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn mul_cf16(a: Complex(f16), b: Complex(f16)) Complex(f16) { + return mulc3(f16, a, b); +} + +fn __mulsc3(lhs_real: compiler_rt.f32.Abi, lhs_imag: compiler_rt.f32.Abi, rhs_real: compiler_rt.f32.Abi, rhs_imag: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.complex.Abi { + return compiler_rt.f32.complex.toAbi(mul_cf32( + compiler_rt.f32.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f32.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn mul_cf32(a: Complex(f32), b: Complex(f32)) Complex(f32) { + return mulc3(f32, a, b); +} + +fn __muldc3(lhs_real: compiler_rt.f64.Abi, lhs_imag: compiler_rt.f64.Abi, rhs_real: compiler_rt.f64.Abi, rhs_imag: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.complex.Abi { + return compiler_rt.f64.complex.toAbi(mul_cf64( + compiler_rt.f64.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f64.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn mul_cf64(a: Complex(f64), b: Complex(f64)) Complex(f64) { + return mulc3(f64, a, b); +} + +fn __mulxc3(lhs_real: compiler_rt.f80.Abi, lhs_imag: compiler_rt.f80.Abi, rhs_real: compiler_rt.f80.Abi, rhs_imag: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.complex.Abi { + return compiler_rt.f80.complex.toAbi(mul_cf80( + compiler_rt.f80.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f80.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn mul_cf80(a: Complex(f80), b: Complex(f80)) Complex(f80) { + return mulc3(f80, a, b); +} + +fn __multc3(lhs_real: compiler_rt.f128.Abi, lhs_imag: compiler_rt.f128.Abi, rhs_real: compiler_rt.f128.Abi, rhs_imag: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.complex.Abi { + return compiler_rt.f128.complex.toAbi(mul_cf128( + compiler_rt.f128.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f128.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn mul_cf128(a: Complex(f128), b: Complex(f128)) Complex(f128) { + return mulc3(f128, a, b); } /// Implementation based on Annex G of C17 Standard (N2176) -pub inline fn mulc3(comptime T: type, a_in: T, b_in: T, c_in: T, d_in: T) Complex(T) { - var a = a_in; - var b = b_in; - var c = c_in; - var d = d_in; +inline fn mulc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) { + var a = lhs.real; + var b = lhs.imag; + var c = rhs.real; + var d = rhs.imag; const ac = a * c; const bd = b * d; @@ -77,3 +138,7 @@ pub inline fn mulc3(comptime T: type, a_in: T, b_in: T, c_in: T, d_in: T) Comple } return z; } + +test { + _ = @import("mulc3_test.zig"); +} diff --git a/lib/compiler_rt/mulc3_test.zig b/lib/compiler_rt/mulc3_test.zig index 3872cb34a6f9198dce4b482be03de720dce17696..748a3bc120ad6cfa3f82b2226f537a6bc63771b6 100644 --- a/lib/compiler_rt/mulc3_test.zig +++ b/lib/compiler_rt/mulc3_test.zig @@ -2,64 +2,45 @@ const std = @import("std"); const math = std.math; const expect = std.testing.expect; -const Complex = @import("./mulc3.zig").Complex; -const __mulhc3 = @import("./mulhc3.zig").__mulhc3; -const __mulsc3 = @import("./mulsc3.zig").__mulsc3; -const __muldc3 = @import("./muldc3.zig").__muldc3; -const __mulxc3 = @import("./mulxc3.zig").__mulxc3; -const __multc3 = @import("./multc3.zig").__multc3; +const Complex = @import("../compiler_rt.zig").Complex; +const impl = @import("mulc3.zig"); +const mul_cf16 = impl.mul_cf16; +const mul_cf32 = impl.mul_cf32; +const mul_cf64 = impl.mul_cf64; +const mul_cf80 = impl.mul_cf80; +const mul_cf128 = impl.mul_cf128; test "mulc3" { - try testMul(f16, __mulhc3); - try testMul(f32, __mulsc3); - try testMul(f64, __muldc3); - try testMul(f80, __mulxc3); - try testMul(f128, __multc3); + try testMul(f16, mul_cf16); + try testMul(f32, mul_cf32); + try testMul(f64, mul_cf64); + try testMul(f80, mul_cf80); + try testMul(f128, mul_cf128); } -fn testMul(comptime T: type, comptime f: fn (T, T, T, T) callconv(.c) Complex(T)) !void { +fn testMul(comptime T: type, comptime f: fn (Complex(T), Complex(T)) Complex(T)) !void { { - const a: T = 1.0; - const b: T = 0.0; - const c: T = -1.0; - const d: T = 0.0; - - const result = f(a, b, c, d); + const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.0 }); try expect(result.real == -1.0); - try expect(result.imag == 0.0); + try expect(math.isPositiveZero(result.imag)); } { - const a: T = 1.0; - const b: T = 0.0; - const c: T = -4.0; - const d: T = 0.0; - - const result = f(a, b, c, d); + const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.0 }); try expect(result.real == -4.0); - try expect(result.imag == 0.0); + try expect(math.isPositiveZero(result.imag)); } { // if one operand is an infinity and the other operand is a nonzero finite number or an infinity, // then the result of the * operator is an infinity; - const a: T = math.inf(T); - const b: T = -math.inf(T); - const c: T = 1.0; - const d: T = 0.0; - - const result = f(a, b, c, d); - try expect(result.real == math.inf(T)); - try expect(result.imag == -math.inf(T)); + const result = f(.{ .real = math.inf(T), .imag = -math.inf(T) }, .{ .real = 1.0, .imag = 0.0 }); + try expect(math.isPositiveInf(result.real)); + try expect(math.isNegativeInf(result.imag)); } { // if one operand is an infinity and the other operand is a nonzero finite number or an infinity, // then the result of the * operator is an infinity; - const a: T = math.inf(T); - const b: T = -1.0; - const c: T = 1.0; - const d: T = math.inf(T); - - const result = f(a, b, c, d); - try expect(result.real == math.inf(T)); - try expect(result.imag == math.inf(T)); + const result = f(.{ .real = math.inf(T), .imag = -1.0 }, .{ .real = 1.0, .imag = math.inf(T) }); + try expect(math.isPositiveInf(result.real)); + try expect(math.isPositiveInf(result.imag)); } } diff --git a/lib/compiler_rt/muldc3.zig b/lib/compiler_rt/muldc3.zig deleted file mode 100644 index d5facaa2b645670b6bf6e0953ec6b73342342329..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/muldc3.zig +++ /dev/null @@ -1,12 +0,0 @@ -const mulc3 = @import("./mulc3.zig"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__muldc3, "__muldc3"); - } -} - -pub fn __muldc3(a: f64, b: f64, c: f64, d: f64) callconv(.c) mulc3.Complex(f64) { - return mulc3.mulc3(f64, a, b, c, d); -} diff --git a/lib/compiler_rt/muldf3.zig b/lib/compiler_rt/muldf3.zig deleted file mode 100644 index b8809e76da8d11e04c181d9dea86911aaac1cb29..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/muldf3.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const mulf3 = @import("./mulf3.zig").mulf3; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dmul, "__aeabi_dmul"); - } else { - symbol(&__muldf3, "__muldf3"); - } -} - -pub fn __muldf3(a: f64, b: f64) callconv(.c) f64 { - return mulf3(f64, a, b); -} - -fn __aeabi_dmul(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { - return mulf3(f64, a, b); -} diff --git a/lib/compiler_rt/mulf3.zig b/lib/compiler_rt/mulf3.zig index d6b5a4719068cf2e27345f73e5f29994fc72e6d3..7367339dbc82f74dc99a9f6de7f842e8cbb71968 100644 --- a/lib/compiler_rt/mulf3.zig +++ b/lib/compiler_rt/mulf3.zig @@ -2,10 +2,76 @@ const std = @import("std"); const math = std.math; const builtin = @import("builtin"); const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; + +comptime { + symbol(&__mulhf3, "__mulhf3"); + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_fmul, "__aeabi_fmul"); + symbol(&__aeabi_dmul, "__aeabi_dmul"); + } else { + symbol(&__mulsf3, "__mulsf3"); + symbol(&__muldf3, "__muldf3"); + } + symbol(&__mulxf3, "__mulxf3"); + if (compiler_rt.want_ppc_abi) { + symbol(&__multf3, "__mulkf3"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_mul, "_Qp_mul"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__multf3, "_Q_mul"); + } else { + symbol(&__multf3, "__multf3"); + } +} + +fn __mulhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(mul_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); +} +pub fn mul_f16(a: f16, b: f16) f16 { + return mulf3(f16, a, b); +} + +fn __mulsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(mul_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); +} +fn __aeabi_fmul(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { + return mul_f32(a, b); +} +pub fn mul_f32(a: f32, b: f32) f32 { + return mulf3(f32, a, b); +} + +fn __muldf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(mul_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); +} +fn __aeabi_dmul(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { + return mul_f64(a, b); +} +pub fn mul_f64(a: f64, b: f64) f64 { + return mulf3(f64, a, b); +} + +fn __mulxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(mul_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} +pub fn mul_f80(a: f80, b: f80) f80 { + return mulf3(f80, a, b); +} + +fn __multf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(mul_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); +} +fn _Qp_mul(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { + c.* = mul_f128(a.*, b.*); +} +pub fn mul_f128(a: f128, b: f128) f128 { + return mulf3(f128, a, b); +} /// Ported from: /// https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc -pub inline fn mulf3(comptime T: type, a: T, b: T) T { +inline fn mulf3(comptime T: type, a: T, b: T) T { @setRuntimeSafety(compiler_rt.test_safety); const typeWidth = @typeInfo(T).float.bits; const significandBits = math.floatMantissaBits(T); diff --git a/lib/compiler_rt/mulf3_test.zig b/lib/compiler_rt/mulf3_test.zig index 751b8933f65bc20e4b630c125fa60f42d5e27529..a2595e21a6d1ca5dd44f1ce67e6dfb6b4ee4cd9f 100644 --- a/lib/compiler_rt/mulf3_test.zig +++ b/lib/compiler_rt/mulf3_test.zig @@ -7,10 +7,12 @@ const math = std.math; const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64); const inf128: f128 = @bitCast(@as(u128, 0x7fff000000000000) << 64); -const __multf3 = @import("multf3.zig").__multf3; -const __mulxf3 = @import("mulxf3.zig").__mulxf3; -const __muldf3 = @import("muldf3.zig").__muldf3; -const __mulsf3 = @import("mulsf3.zig").__mulsf3; +const impl = @import("mulf3.zig"); +const mul_f16 = impl.mul_f16; +const mul_f32 = impl.mul_f32; +const mul_f64 = impl.mul_f64; +const mul_f80 = impl.mul_f80; +const mul_f128 = impl.mul_f128; // return true if equal // use two 64-bit integers instead of one 128-bit integer @@ -34,8 +36,8 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool { return false; } -fn test__multf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { - const x = __multf3(a, b); +fn test_mul_f128(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { + const x = mul_f128(a, b); if (compareResultLD(x, expected_hi, expected_lo)) return; @@ -49,68 +51,68 @@ fn makeNaN128(rand: u64) f128 { } test "multf3" { // qNaN * any = qNaN - try test__multf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); + try test_mul_f128(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); // NaN * any = NaN const a = makeNaN128(0x800030000000); - try test__multf3(a, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); + try test_mul_f128(a, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); // inf * any = inf - try test__multf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); + try test_mul_f128(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); // any * any - try test__multf3( + try test_mul_f128( @as(f128, @bitCast(@as(u128, 0x40042eab345678439abcdefea5678234))), @as(f128, @bitCast(@as(u128, 0x3ffeedcb34a235253948765432134675))), 0x400423e7f9e3c9fc, 0xd906c2c2a85777c4, ); - try test__multf3( + try test_mul_f128( @as(f128, @bitCast(@as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50))), @as(f128, @bitCast(@as(u128, 0x3ff6ed8764648369535adf4be3214568))), 0x3fc52a163c6223fc, 0xc94c4bf0430768b4, ); - try test__multf3( + try test_mul_f128( 0x1.234425696abcad34a35eeffefdcbap+456, 0x451.ed98d76e5d46e5f24323dff21ffp+600, 0x44293a91de5e0e94, 0xe8ed17cc2cdf64ac, ); - try test__multf3( + try test_mul_f128( @as(f128, @bitCast(@as(u128, 0x3f154356473c82a9fabf2d22ace345df))), @as(f128, @bitCast(@as(u128, 0x3e38eda98765476743ab21da23d45679))), 0x3d4f37c1a3137cae, 0xfc6807048bc2836a, ); - try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0); + try test_mul_f128(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0); // Denormal operands. - try test__multf3( + try test_mul_f128( 0x0.0000000000000000000000000001p-16382, 0x1p16383, 0x3f90000000000000, 0x0, ); - try test__multf3( + try test_mul_f128( 0x1p16383, 0x0.0000000000000000000000000001p-16382, 0x3f90000000000000, 0x0, ); - try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002); - try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003); - try test__multf3(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002); + try test_mul_f128(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002); + try test_mul_f128(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003); + try test_mul_f128(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002); } const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1))); -fn test__mulxf3(a: f80, b: f80, expected: u80) !void { - const x = __mulxf3(a, b); +fn test_mul_f80(a: f80, b: f80, expected: u80) !void { + const x = mul_f80(a, b); const rep: u80 = @bitCast(x); if (rep == expected) @@ -124,47 +126,47 @@ fn test__mulxf3(a: f80, b: f80, expected: u80) !void { test "mulxf3" { // NaN * any = NaN - try test__mulxf3(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); - try test__mulxf3(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); + try test_mul_f80(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); + try test_mul_f80(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); // any * NaN = NaN - try test__mulxf3(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80))); - try test__mulxf3(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80))); + try test_mul_f80(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80))); + try test_mul_f80(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80))); // NaN * inf = NaN - try test__mulxf3(qnan80, math.inf(f80), @as(u80, @bitCast(qnan80))); + try test_mul_f80(qnan80, math.inf(f80), @as(u80, @bitCast(qnan80))); // inf * NaN = NaN - try test__mulxf3(math.inf(f80), qnan80, @as(u80, @bitCast(qnan80))); + try test_mul_f80(math.inf(f80), qnan80, @as(u80, @bitCast(qnan80))); // inf * inf = inf - try test__mulxf3(math.inf(f80), math.inf(f80), @as(u80, @bitCast(math.inf(f80)))); + try test_mul_f80(math.inf(f80), math.inf(f80), @as(u80, @bitCast(math.inf(f80)))); // inf * -inf = -inf - try test__mulxf3(math.inf(f80), -math.inf(f80), @as(u80, @bitCast(-math.inf(f80)))); + try test_mul_f80(math.inf(f80), -math.inf(f80), @as(u80, @bitCast(-math.inf(f80)))); // -inf + inf = -inf - try test__mulxf3(-math.inf(f80), math.inf(f80), @as(u80, @bitCast(-math.inf(f80)))); + try test_mul_f80(-math.inf(f80), math.inf(f80), @as(u80, @bitCast(-math.inf(f80)))); // inf * any = inf - try test__mulxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @as(u80, @bitCast(math.inf(f80)))); + try test_mul_f80(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @as(u80, @bitCast(math.inf(f80)))); // any * inf = inf - try test__mulxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @as(u80, @bitCast(math.inf(f80)))); + try test_mul_f80(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @as(u80, @bitCast(math.inf(f80)))); // any * any - try test__mulxf3(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800); - try test__mulxf3(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact + try test_mul_f80(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800); + try test_mul_f80(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact - try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact - try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down - try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even - try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up - try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact + try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact + try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down + try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even + try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up + try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact - try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even - try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up - try test__mulxf3(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal - try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal - try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal + try test_mul_f80(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even + try test_mul_f80(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up + try test_mul_f80(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal + try test_mul_f80(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal + try test_mul_f80(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal } diff --git a/lib/compiler_rt/mulhc3.zig b/lib/compiler_rt/mulhc3.zig deleted file mode 100644 index 4e0d3f875389ddf2f02bb7ddb3f75106e6d48513..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulhc3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulc3 = @import("./mulc3.zig"); - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__mulhc3, "__mulhc3"); - } -} - -pub fn __mulhc3(a: f16, b: f16, c: f16, d: f16) callconv(.c) mulc3.Complex(f16) { - return mulc3.mulc3(f16, a, b, c, d); -} diff --git a/lib/compiler_rt/mulhf3.zig b/lib/compiler_rt/mulhf3.zig deleted file mode 100644 index 46ce7a6b999005704db84280e3e83c7be05985b6..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulhf3.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulf3 = @import("./mulf3.zig").mulf3; - -comptime { - symbol(&__mulhf3, "__mulhf3"); -} - -pub fn __mulhf3(a: f16, b: f16) callconv(.c) f16 { - return mulf3(f16, a, b); -} diff --git a/lib/compiler_rt/mulsc3.zig b/lib/compiler_rt/mulsc3.zig deleted file mode 100644 index e735e65eade6a77f908abe8b4b25e8fc30af7f9f..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulsc3.zig +++ /dev/null @@ -1,12 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const mulc3 = @import("./mulc3.zig"); - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__mulsc3, "__mulsc3"); - } -} - -pub fn __mulsc3(a: f32, b: f32, c: f32, d: f32) callconv(.c) mulc3.Complex(f32) { - return mulc3.mulc3(f32, a, b, c, d); -} diff --git a/lib/compiler_rt/mulsf3.zig b/lib/compiler_rt/mulsf3.zig deleted file mode 100644 index 81f9eafae213d8cba10579b86f109bdfd361ba41..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulsf3.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulf3 = @import("./mulf3.zig").mulf3; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_fmul, "__aeabi_fmul"); - } else { - symbol(&__mulsf3, "__mulsf3"); - } -} - -pub fn __mulsf3(a: f32, b: f32) callconv(.c) f32 { - return mulf3(f32, a, b); -} - -fn __aeabi_fmul(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { - return mulf3(f32, a, b); -} diff --git a/lib/compiler_rt/multc3.zig b/lib/compiler_rt/multc3.zig deleted file mode 100644 index 4914735b10f63ec38d3487738e461769db6f8669..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/multc3.zig +++ /dev/null @@ -1,15 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const mulc3 = @import("./mulc3.zig"); - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - if (compiler_rt.want_ppc_abi) - symbol(&__multc3, "__mulkc3"); - symbol(&__multc3, "__multc3"); - } -} - -pub fn __multc3(a: f128, b: f128, c: f128, d: f128) callconv(.c) mulc3.Complex(f128) { - return mulc3.mulc3(f128, a, b, c, d); -} diff --git a/lib/compiler_rt/multf3.zig b/lib/compiler_rt/multf3.zig deleted file mode 100644 index 7d10c70777176e7a8580eb3b909546e42535785e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/multf3.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulf3 = @import("./mulf3.zig").mulf3; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__multf3, "__mulkf3"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_mul, "_Qp_mul"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__multf3, "_Q_mul"); - } - symbol(&__multf3, "__multf3"); -} - -pub fn __multf3(a: f128, b: f128) callconv(.c) f128 { - return mulf3(f128, a, b); -} - -fn _Qp_mul(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { - c.* = mulf3(f128, a.*, b.*); -} diff --git a/lib/compiler_rt/mulvsi3.zig b/lib/compiler_rt/mulvsi3.zig index 0935ea497afa52a46f515c83c40c2d8cc5bc02db..f2456fa7cb825a36a359d667d26e5f06eb2c95e4 100644 --- a/lib/compiler_rt/mulvsi3.zig +++ b/lib/compiler_rt/mulvsi3.zig @@ -1,7 +1,8 @@ const testing = @import("std").testing; const mulv = @import("mulo.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; comptime { symbol(&__mulvsi3, "__mulvsi3"); @@ -10,7 +11,7 @@ comptime { pub fn __mulvsi3(a: i32, b: i32) callconv(.c) i32 { var overflow: c_int = 0; const sum = mulv.__mulosi4(a, b, &overflow); - if (overflow != 0) @panic("compiler-rt: integer overflow"); + if (overflow != 0) @panic("integer overflow"); return sum; } diff --git a/lib/compiler_rt/mulxc3.zig b/lib/compiler_rt/mulxc3.zig deleted file mode 100644 index ac0e189f63ba4d4ce2f0a753c4f7409e0b551d23..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulxc3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulc3 = @import("./mulc3.zig"); - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__mulxc3, "__mulxc3"); - } -} - -pub fn __mulxc3(a: f80, b: f80, c: f80, d: f80) callconv(.c) mulc3.Complex(f80) { - return mulc3.mulc3(f80, a, b, c, d); -} diff --git a/lib/compiler_rt/mulxf3.zig b/lib/compiler_rt/mulxf3.zig deleted file mode 100644 index dcf783a4a6bc434275416e9da0079f65b3354277..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulxf3.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulf3 = @import("./mulf3.zig").mulf3; - -comptime { - symbol(&__mulxf3, "__mulxf3"); -} - -pub fn __mulxf3(a: f80, b: f80) callconv(.c) f80 { - return mulf3(f80, a, b); -} diff --git a/lib/compiler_rt/negv.zig b/lib/compiler_rt/negv.zig index 7c67a51c34ab72f9c3f0038024e45ca79413d955..c6d61611f1b24d3697dcdc4201f5ff2d8c1cf40c 100644 --- a/lib/compiler_rt/negv.zig +++ b/lib/compiler_rt/negv.zig @@ -33,8 +33,7 @@ inline fn negvXi(comptime ST: type, a: ST) ST { }; const N: UT = @bitSizeOf(ST); const min: ST = @as(ST, @bitCast((@as(UT, 1) << (N - 1)))); - if (a == min) - @panic("compiler_rt negv: overflow"); + if (a == min) @panic("integer overflow"); return -a; } diff --git a/lib/compiler_rt/os_version_check.zig b/lib/compiler_rt/os_version_check.zig index e575fef9ce553fee90cc9f7cc900689c5804cb20..96724a14e8092aae7693e4ab869ab3282a9ea762 100644 --- a/lib/compiler_rt/os_version_check.zig +++ b/lib/compiler_rt/os_version_check.zig @@ -3,7 +3,6 @@ const testing = std.testing; const builtin = @import("builtin"); const compiler_rt = @import("../compiler_rt.zig"); const symbol = compiler_rt.symbol; -const panic = @import("../compiler_rt.zig").panic; const have_availability_version_check = builtin.os.tag.isDarwin() and builtin.os.version_range.semver.min.order(.{ .major = 10, .minor = 15, .patch = 0 }).compare(.gte); diff --git a/lib/compiler_rt/parity.zig b/lib/compiler_rt/parity.zig index e3881699042fafc3fc0da7415e6fb2bb6d1aedde..9540cf49f629556b73f77067ddcf90944afdf21b 100644 --- a/lib/compiler_rt/parity.zig +++ b/lib/compiler_rt/parity.zig @@ -1,6 +1,7 @@ //! parity - if number of bits set is even => 0, else => 1 //! - pariytXi2_generic for big and little endian -const symbol = @import("../compiler_rt.zig").symbol; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; comptime { symbol(&__paritysi2, "__paritysi2"); diff --git a/lib/compiler_rt/popcount.zig b/lib/compiler_rt/popcount.zig index b1ef500ea117514d08b598e4209770bd4b879b1f..3b9d867548f62d9ab7da321786cb737effa2646d 100644 --- a/lib/compiler_rt/popcount.zig +++ b/lib/compiler_rt/popcount.zig @@ -6,7 +6,8 @@ //! TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques, //! subsubsection "Working with the rightmost bits" and "Sideways addition". -const symbol = @import("../compiler_rt.zig").symbol; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; comptime { symbol(&__popcountsi2, "__popcountsi2"); diff --git a/lib/compiler_rt/powiXf2.zig b/lib/compiler_rt/powiXf2.zig index b2a1e3e6989ba85538243483d14fd92ad0e3158d..dd8b477f152144ce7206f4ce54caa77c1a4ead36 100644 --- a/lib/compiler_rt/powiXf2.zig +++ b/lib/compiler_rt/powiXf2.zig @@ -4,16 +4,18 @@ //! error propagation and this method is optimized for performance, not accuracy. const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { symbol(&__powihf2, "__powihf2"); symbol(&__powisf2, "__powisf2"); symbol(&__powidf2, "__powidf2"); - if (compiler_rt.want_ppc_abi) - symbol(&__powitf2, "__powikf2"); - symbol(&__powitf2, "__powitf2"); symbol(&__powixf2, "__powixf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__powitf2, "__powikf2"); + } else { + symbol(&__powitf2, "__powitf2"); + } } inline fn powiXf2(comptime FT: type, a: FT, b: i32) FT { @@ -32,26 +34,41 @@ inline fn powiXf2(comptime FT: type, a: FT, b: i32) FT { return if (is_recip) 1 / r else r; } -pub fn __powihf2(a: f16, b: i32) callconv(.c) f16 { +fn __powihf2(a: compiler_rt.f16.Abi, b: i32) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(powi_f16(compiler_rt.f16.fromAbi(a), b)); +} +pub fn powi_f16(a: f16, b: i32) f16 { return powiXf2(f16, a, b); } -pub fn __powisf2(a: f32, b: i32) callconv(.c) f32 { +fn __powisf2(a: compiler_rt.f32.Abi, b: i32) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(powi_f32(compiler_rt.f32.fromAbi(a), b)); +} +pub fn powi_f32(a: f32, b: i32) f32 { return powiXf2(f32, a, b); } -pub fn __powidf2(a: f64, b: i32) callconv(.c) f64 { +fn __powidf2(a: compiler_rt.f64.Abi, b: i32) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(powi_f64(compiler_rt.f64.fromAbi(a), b)); +} +pub fn powi_f64(a: f64, b: i32) f64 { return powiXf2(f64, a, b); } -pub fn __powitf2(a: f128, b: i32) callconv(.c) f128 { - return powiXf2(f128, a, b); +fn __powixf2(a: compiler_rt.f80.Abi, b: i32) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(powi_f80(compiler_rt.f80.fromAbi(a), b)); } - -pub fn __powixf2(a: f80, b: i32) callconv(.c) f80 { +pub fn powi_f80(a: f80, b: i32) f80 { return powiXf2(f80, a, b); } +fn __powitf2(a: compiler_rt.f128.Abi, b: i32) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(powi_f128(compiler_rt.f128.fromAbi(a), b)); +} +pub fn powi_f128(a: f128, b: i32) f128 { + return powiXf2(f128, a, b); +} + test { _ = @import("powiXf2_test.zig"); } diff --git a/lib/compiler_rt/powiXf2_test.zig b/lib/compiler_rt/powiXf2_test.zig index 7bd43c73c3d2d1a379a6ef66977c55dff1fc8a00..1388a4e7250e7b418fee08cde6d165d2bce80adf 100644 --- a/lib/compiler_rt/powiXf2_test.zig +++ b/lib/compiler_rt/powiXf2_test.zig @@ -2,562 +2,568 @@ // powisf2_test.c, powidf2_test.c, powitf2_test.c, powixf2_test.c // powihf2 adapted from powisf2 tests -const powiXf2 = @import("powiXf2.zig"); const std = @import("std"); -const builtin = @import("builtin"); const testing = std.testing; const math = std.math; -fn test__powihf2(a: f16, b: i32, expected: f16) !void { - const result = powiXf2.__powihf2(a, b); +const impl = @import("powiXf2.zig"); + +const powi_f16 = impl.powi_f16; +const powi_f32 = impl.powi_f32; +const powi_f64 = impl.powi_f64; +const powi_f80 = impl.powi_f80; +const powi_f128 = impl.powi_f128; + +fn test_powi_f16(a: f16, b: i32, expected: f16) !void { + const result = powi_f16(a, b); try testing.expectEqual(expected, result); } -fn test__powisf2(a: f32, b: i32, expected: f32) !void { - const result = powiXf2.__powisf2(a, b); +fn test_powi_f32(a: f32, b: i32, expected: f32) !void { + const result = powi_f32(a, b); try testing.expectEqual(expected, result); } -fn test__powidf2(a: f64, b: i32, expected: f64) !void { - const result = powiXf2.__powidf2(a, b); +fn test_powi_f64(a: f64, b: i32, expected: f64) !void { + const result = powi_f64(a, b); try testing.expectEqual(expected, result); } -fn test__powitf2(a: f128, b: i32, expected: f128) !void { - const result = powiXf2.__powitf2(a, b); +fn test_powi_f80(a: f80, b: i32, expected: f80) !void { + const result = powi_f80(a, b); try testing.expectEqual(expected, result); } -fn test__powixf2(a: f80, b: i32, expected: f80) !void { - const result = powiXf2.__powixf2(a, b); +fn test_powi_f128(a: f128, b: i32, expected: f128) !void { + const result = powi_f128(a, b); try testing.expectEqual(expected, result); } -test "powihf2" { +test powi_f16 { const inf_f16 = math.inf(f16); - try test__powisf2(0, 0, 1); - try test__powihf2(1, 0, 1); - try test__powihf2(1.5, 0, 1); - try test__powihf2(2, 0, 1); - try test__powihf2(inf_f16, 0, 1); + try test_powi_f16(0, 0, 1); + try test_powi_f16(1, 0, 1); + try test_powi_f16(1.5, 0, 1); + try test_powi_f16(2, 0, 1); + try test_powi_f16(inf_f16, 0, 1); - try test__powihf2(-0.0, 0, 1); - try test__powihf2(-1, 0, 1); - try test__powihf2(-1.5, 0, 1); - try test__powihf2(-2, 0, 1); - try test__powihf2(-inf_f16, 0, 1); + try test_powi_f16(-0.0, 0, 1); + try test_powi_f16(-1, 0, 1); + try test_powi_f16(-1.5, 0, 1); + try test_powi_f16(-2, 0, 1); + try test_powi_f16(-inf_f16, 0, 1); - try test__powihf2(0, 1, 0); - try test__powihf2(0, 2, 0); - try test__powihf2(0, 3, 0); - try test__powihf2(0, 4, 0); - try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); + try test_powi_f16(0, 1, 0); + try test_powi_f16(0, 2, 0); + try test_powi_f16(0, 3, 0); + try test_powi_f16(0, 4, 0); + try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); - try test__powihf2(-0.0, 1, -0.0); - try test__powihf2(-0.0, 2, 0); - try test__powihf2(-0.0, 3, -0.0); - try test__powihf2(-0.0, 4, 0); - try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); + try test_powi_f16(-0.0, 1, -0.0); + try test_powi_f16(-0.0, 2, 0); + try test_powi_f16(-0.0, 3, -0.0); + try test_powi_f16(-0.0, 4, 0); + try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); - try test__powihf2(1, 1, 1); - try test__powihf2(1, 2, 1); - try test__powihf2(1, 3, 1); - try test__powihf2(1, 4, 1); - try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); - try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); + try test_powi_f16(1, 1, 1); + try test_powi_f16(1, 2, 1); + try test_powi_f16(1, 3, 1); + try test_powi_f16(1, 4, 1); + try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); + try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); - try test__powihf2(inf_f16, 1, inf_f16); - try test__powihf2(inf_f16, 2, inf_f16); - try test__powihf2(inf_f16, 3, inf_f16); - try test__powihf2(inf_f16, 4, inf_f16); - try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); - try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16); + try test_powi_f16(inf_f16, 1, inf_f16); + try test_powi_f16(inf_f16, 2, inf_f16); + try test_powi_f16(inf_f16, 3, inf_f16); + try test_powi_f16(inf_f16, 4, inf_f16); + try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); + try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16); - try test__powihf2(-inf_f16, 1, -inf_f16); - try test__powihf2(-inf_f16, 2, inf_f16); - try test__powihf2(-inf_f16, 3, -inf_f16); - try test__powihf2(-inf_f16, 4, inf_f16); - try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); - try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16); + try test_powi_f16(-inf_f16, 1, -inf_f16); + try test_powi_f16(-inf_f16, 2, inf_f16); + try test_powi_f16(-inf_f16, 3, -inf_f16); + try test_powi_f16(-inf_f16, 4, inf_f16); + try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); + try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16); // - try test__powihf2(0, -1, inf_f16); - try test__powihf2(0, -2, inf_f16); - try test__powihf2(0, -3, inf_f16); - try test__powihf2(0, -4, inf_f16); - try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf - try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16); - try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); + try test_powi_f16(0, -1, inf_f16); + try test_powi_f16(0, -2, inf_f16); + try test_powi_f16(0, -3, inf_f16); + try test_powi_f16(0, -4, inf_f16); + try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf + try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16); + try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); - try test__powihf2(-0.0, -1, -inf_f16); - try test__powihf2(-0.0, -2, inf_f16); - try test__powihf2(-0.0, -3, -inf_f16); - try test__powihf2(-0.0, -4, inf_f16); - try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf - try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f16); // -0 ^ anything odd = -inf - try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); + try test_powi_f16(-0.0, -1, -inf_f16); + try test_powi_f16(-0.0, -2, inf_f16); + try test_powi_f16(-0.0, -3, -inf_f16); + try test_powi_f16(-0.0, -4, inf_f16); + try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf + try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f16); // -0 ^ anything odd = -inf + try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); - try test__powihf2(1, -1, 1); - try test__powihf2(1, -2, 1); - try test__powihf2(1, -3, 1); - try test__powihf2(1, -4, 1); - try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1 - try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); - try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); + try test_powi_f16(1, -1, 1); + try test_powi_f16(1, -2, 1); + try test_powi_f16(1, -3, 1); + try test_powi_f16(1, -4, 1); + try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1 + try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); + try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); - try test__powihf2(inf_f16, -1, 0); - try test__powihf2(inf_f16, -2, 0); - try test__powihf2(inf_f16, -3, 0); - try test__powihf2(inf_f16, -4, 0); - try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); - try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + try test_powi_f16(inf_f16, -1, 0); + try test_powi_f16(inf_f16, -2, 0); + try test_powi_f16(inf_f16, -3, 0); + try test_powi_f16(inf_f16, -4, 0); + try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); + try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); // - try test__powihf2(-inf_f16, -1, -0.0); - try test__powihf2(-inf_f16, -2, 0); - try test__powihf2(-inf_f16, -3, -0.0); - try test__powihf2(-inf_f16, -4, 0); - try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); - try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + try test_powi_f16(-inf_f16, -1, -0.0); + try test_powi_f16(-inf_f16, -2, 0); + try test_powi_f16(-inf_f16, -3, -0.0); + try test_powi_f16(-inf_f16, -4, 0); + try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); + try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - try test__powihf2(2, 10, 1024.0); - try test__powihf2(-2, 10, 1024.0); - try test__powihf2(2, -10, 1.0 / 1024.0); - try test__powihf2(-2, -10, 1.0 / 1024.0); + try test_powi_f16(2, 10, 1024.0); + try test_powi_f16(-2, 10, 1024.0); + try test_powi_f16(2, -10, 1.0 / 1024.0); + try test_powi_f16(-2, -10, 1.0 / 1024.0); - try test__powihf2(2, 14, 16384.0); - try test__powihf2(-2, 14, 16384.0); - try test__powihf2(2, 15, 32768.0); - try test__powihf2(-2, 15, -32768.0); - try test__powihf2(2, 16, inf_f16); - try test__powihf2(-2, 16, inf_f16); + try test_powi_f16(2, 14, 16384.0); + try test_powi_f16(-2, 14, 16384.0); + try test_powi_f16(2, 15, 32768.0); + try test_powi_f16(-2, 15, -32768.0); + try test_powi_f16(2, 16, inf_f16); + try test_powi_f16(-2, 16, inf_f16); - try test__powihf2(2, -13, 1.0 / 8192.0); - try test__powihf2(-2, -13, -1.0 / 8192.0); - try test__powihf2(2, -15, 1.0 / 32768.0); - try test__powihf2(-2, -15, -1.0 / 32768.0); - try test__powihf2(2, -16, 0.0); // expected = 0.0 = 1/(-2**16) - try test__powihf2(-2, -16, 0.0); // expected = 0.0 = 1/(2**16) + try test_powi_f16(2, -13, 1.0 / 8192.0); + try test_powi_f16(-2, -13, -1.0 / 8192.0); + try test_powi_f16(2, -15, 1.0 / 32768.0); + try test_powi_f16(-2, -15, -1.0 / 32768.0); + try test_powi_f16(2, -16, 0.0); // expected = 0.0 = 1/(-2**16) + try test_powi_f16(-2, -16, 0.0); // expected = 0.0 = 1/(2**16) } -test "powisf2" { +test powi_f32 { const inf_f32 = math.inf(f32); - try test__powisf2(0, 0, 1); - try test__powisf2(1, 0, 1); - try test__powisf2(1.5, 0, 1); - try test__powisf2(2, 0, 1); - try test__powisf2(inf_f32, 0, 1); + try test_powi_f32(0, 0, 1); + try test_powi_f32(1, 0, 1); + try test_powi_f32(1.5, 0, 1); + try test_powi_f32(2, 0, 1); + try test_powi_f32(inf_f32, 0, 1); - try test__powisf2(-0.0, 0, 1); - try test__powisf2(-1, 0, 1); - try test__powisf2(-1.5, 0, 1); - try test__powisf2(-2, 0, 1); - try test__powisf2(-inf_f32, 0, 1); + try test_powi_f32(-0.0, 0, 1); + try test_powi_f32(-1, 0, 1); + try test_powi_f32(-1.5, 0, 1); + try test_powi_f32(-2, 0, 1); + try test_powi_f32(-inf_f32, 0, 1); - try test__powisf2(0, 1, 0); - try test__powisf2(0, 2, 0); - try test__powisf2(0, 3, 0); - try test__powisf2(0, 4, 0); - try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); + try test_powi_f32(0, 1, 0); + try test_powi_f32(0, 2, 0); + try test_powi_f32(0, 3, 0); + try test_powi_f32(0, 4, 0); + try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); - try test__powisf2(-0.0, 1, -0.0); - try test__powisf2(-0.0, 2, 0); - try test__powisf2(-0.0, 3, -0.0); - try test__powisf2(-0.0, 4, 0); - try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); + try test_powi_f32(-0.0, 1, -0.0); + try test_powi_f32(-0.0, 2, 0); + try test_powi_f32(-0.0, 3, -0.0); + try test_powi_f32(-0.0, 4, 0); + try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); - try test__powisf2(1, 1, 1); - try test__powisf2(1, 2, 1); - try test__powisf2(1, 3, 1); - try test__powisf2(1, 4, 1); - try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); - try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); + try test_powi_f32(1, 1, 1); + try test_powi_f32(1, 2, 1); + try test_powi_f32(1, 3, 1); + try test_powi_f32(1, 4, 1); + try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); + try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); - try test__powisf2(inf_f32, 1, inf_f32); - try test__powisf2(inf_f32, 2, inf_f32); - try test__powisf2(inf_f32, 3, inf_f32); - try test__powisf2(inf_f32, 4, inf_f32); - try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); - try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32); + try test_powi_f32(inf_f32, 1, inf_f32); + try test_powi_f32(inf_f32, 2, inf_f32); + try test_powi_f32(inf_f32, 3, inf_f32); + try test_powi_f32(inf_f32, 4, inf_f32); + try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); + try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32); - try test__powisf2(-inf_f32, 1, -inf_f32); - try test__powisf2(-inf_f32, 2, inf_f32); - try test__powisf2(-inf_f32, 3, -inf_f32); - try test__powisf2(-inf_f32, 4, inf_f32); - try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); - try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32); + try test_powi_f32(-inf_f32, 1, -inf_f32); + try test_powi_f32(-inf_f32, 2, inf_f32); + try test_powi_f32(-inf_f32, 3, -inf_f32); + try test_powi_f32(-inf_f32, 4, inf_f32); + try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); + try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32); - try test__powisf2(0, -1, inf_f32); - try test__powisf2(0, -2, inf_f32); - try test__powisf2(0, -3, inf_f32); - try test__powisf2(0, -4, inf_f32); - try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); - try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32); - try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); + try test_powi_f32(0, -1, inf_f32); + try test_powi_f32(0, -2, inf_f32); + try test_powi_f32(0, -3, inf_f32); + try test_powi_f32(0, -4, inf_f32); + try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); + try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32); + try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); - try test__powisf2(-0.0, -1, -inf_f32); - try test__powisf2(-0.0, -2, inf_f32); - try test__powisf2(-0.0, -3, -inf_f32); - try test__powisf2(-0.0, -4, inf_f32); - try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); - try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32); - try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); + try test_powi_f32(-0.0, -1, -inf_f32); + try test_powi_f32(-0.0, -2, inf_f32); + try test_powi_f32(-0.0, -3, -inf_f32); + try test_powi_f32(-0.0, -4, inf_f32); + try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); + try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32); + try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); - try test__powisf2(1, -1, 1); - try test__powisf2(1, -2, 1); - try test__powisf2(1, -3, 1); - try test__powisf2(1, -4, 1); - try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); - try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); - try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); + try test_powi_f32(1, -1, 1); + try test_powi_f32(1, -2, 1); + try test_powi_f32(1, -3, 1); + try test_powi_f32(1, -4, 1); + try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); + try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); + try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); - try test__powisf2(inf_f32, -1, 0); - try test__powisf2(inf_f32, -2, 0); - try test__powisf2(inf_f32, -3, 0); - try test__powisf2(inf_f32, -4, 0); - try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); - try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + try test_powi_f32(inf_f32, -1, 0); + try test_powi_f32(inf_f32, -2, 0); + try test_powi_f32(inf_f32, -3, 0); + try test_powi_f32(inf_f32, -4, 0); + try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); + try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - try test__powisf2(-inf_f32, -1, -0.0); - try test__powisf2(-inf_f32, -2, 0); - try test__powisf2(-inf_f32, -3, -0.0); - try test__powisf2(-inf_f32, -4, 0); - try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); - try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + try test_powi_f32(-inf_f32, -1, -0.0); + try test_powi_f32(-inf_f32, -2, 0); + try test_powi_f32(-inf_f32, -3, -0.0); + try test_powi_f32(-inf_f32, -4, 0); + try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); + try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - try test__powisf2(2.0, 10, 1024.0); - try test__powisf2(-2, 10, 1024.0); - try test__powisf2(2, -10, 1.0 / 1024.0); - try test__powisf2(-2, -10, 1.0 / 1024.0); + try test_powi_f32(2.0, 10, 1024.0); + try test_powi_f32(-2, 10, 1024.0); + try test_powi_f32(2, -10, 1.0 / 1024.0); + try test_powi_f32(-2, -10, 1.0 / 1024.0); // - try test__powisf2(2, 19, 524288.0); - try test__powisf2(-2, 19, -524288.0); - try test__powisf2(2, -19, 1.0 / 524288.0); - try test__powisf2(-2, -19, -1.0 / 524288.0); + try test_powi_f32(2, 19, 524288.0); + try test_powi_f32(-2, 19, -524288.0); + try test_powi_f32(2, -19, 1.0 / 524288.0); + try test_powi_f32(-2, -19, -1.0 / 524288.0); - try test__powisf2(2, 31, 2147483648.0); - try test__powisf2(-2, 31, -2147483648.0); - try test__powisf2(2, -31, 1.0 / 2147483648.0); - try test__powisf2(-2, -31, -1.0 / 2147483648.0); + try test_powi_f32(2, 31, 2147483648.0); + try test_powi_f32(-2, 31, -2147483648.0); + try test_powi_f32(2, -31, 1.0 / 2147483648.0); + try test_powi_f32(-2, -31, -1.0 / 2147483648.0); } -test "powidf2" { +test powi_f64 { const inf_f64 = math.inf(f64); - try test__powidf2(0, 0, 1); - try test__powidf2(1, 0, 1); - try test__powidf2(1.5, 0, 1); - try test__powidf2(2, 0, 1); - try test__powidf2(inf_f64, 0, 1); - - try test__powidf2(-0.0, 0, 1); - try test__powidf2(-1, 0, 1); - try test__powidf2(-1.5, 0, 1); - try test__powidf2(-2, 0, 1); - try test__powidf2(-inf_f64, 0, 1); - - try test__powidf2(0, 1, 0); - try test__powidf2(0, 2, 0); - try test__powidf2(0, 3, 0); - try test__powidf2(0, 4, 0); - try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); - - try test__powidf2(-0.0, 1, -0.0); - try test__powidf2(-0.0, 2, 0); - try test__powidf2(-0.0, 3, -0.0); - try test__powidf2(-0.0, 4, 0); - try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); - - try test__powidf2(1, 1, 1); - try test__powidf2(1, 2, 1); - try test__powidf2(1, 3, 1); - try test__powidf2(1, 4, 1); - try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); - try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); - - try test__powidf2(inf_f64, 1, inf_f64); - try test__powidf2(inf_f64, 2, inf_f64); - try test__powidf2(inf_f64, 3, inf_f64); - try test__powidf2(inf_f64, 4, inf_f64); - try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); - try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64); - - try test__powidf2(-inf_f64, 1, -inf_f64); - try test__powidf2(-inf_f64, 2, inf_f64); - try test__powidf2(-inf_f64, 3, -inf_f64); - try test__powidf2(-inf_f64, 4, inf_f64); - try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); - try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64); - - try test__powidf2(0, -1, inf_f64); - try test__powidf2(0, -2, inf_f64); - try test__powidf2(0, -3, inf_f64); - try test__powidf2(0, -4, inf_f64); - try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); - try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64); - try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); - - try test__powidf2(-0.0, -1, -inf_f64); - try test__powidf2(-0.0, -2, inf_f64); - try test__powidf2(-0.0, -3, -inf_f64); - try test__powidf2(-0.0, -4, inf_f64); - try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); - try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64); - try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); - - try test__powidf2(1, -1, 1); - try test__powidf2(1, -2, 1); - try test__powidf2(1, -3, 1); - try test__powidf2(1, -4, 1); - try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); - try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); - try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); - - try test__powidf2(inf_f64, -1, 0); - try test__powidf2(inf_f64, -2, 0); - try test__powidf2(inf_f64, -3, 0); - try test__powidf2(inf_f64, -4, 0); - try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); - try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powidf2(-inf_f64, -1, -0.0); - try test__powidf2(-inf_f64, -2, 0); - try test__powidf2(-inf_f64, -3, -0.0); - try test__powidf2(-inf_f64, -4, 0); - try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); - try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powidf2(2, 10, 1024.0); - try test__powidf2(-2, 10, 1024.0); - try test__powidf2(2, -10, 1.0 / 1024.0); - try test__powidf2(-2, -10, 1.0 / 1024.0); - - try test__powidf2(2, 19, 524288.0); - try test__powidf2(-2, 19, -524288.0); - try test__powidf2(2, -19, 1.0 / 524288.0); - try test__powidf2(-2, -19, -1.0 / 524288.0); - - try test__powidf2(2, 31, 2147483648.0); - try test__powidf2(-2, 31, -2147483648.0); - try test__powidf2(2, -31, 1.0 / 2147483648.0); - try test__powidf2(-2, -31, -1.0 / 2147483648.0); -} - -test "powitf2" { - const inf_f128 = math.inf(f128); - try test__powitf2(0, 0, 1); - try test__powitf2(1, 0, 1); - try test__powitf2(1.5, 0, 1); - try test__powitf2(2, 0, 1); - try test__powitf2(inf_f128, 0, 1); - - try test__powitf2(-0.0, 0, 1); - try test__powitf2(-1, 0, 1); - try test__powitf2(-1.5, 0, 1); - try test__powitf2(-2, 0, 1); - try test__powitf2(-inf_f128, 0, 1); - - try test__powitf2(0, 1, 0); - try test__powitf2(0, 2, 0); - try test__powitf2(0, 3, 0); - try test__powitf2(0, 4, 0); - try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powitf2(0, 0x7FFFFFFF, 0); - - try test__powitf2(-0.0, 1, -0.0); - try test__powitf2(-0.0, 2, 0); - try test__powitf2(-0.0, 3, -0.0); - try test__powitf2(-0.0, 4, 0); - try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); - - try test__powitf2(1, 1, 1); - try test__powitf2(1, 2, 1); - try test__powitf2(1, 3, 1); - try test__powitf2(1, 4, 1); - try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); - try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); - - try test__powitf2(inf_f128, 1, inf_f128); - try test__powitf2(inf_f128, 2, inf_f128); - try test__powitf2(inf_f128, 3, inf_f128); - try test__powitf2(inf_f128, 4, inf_f128); - try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); - try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128); - - try test__powitf2(-inf_f128, 1, -inf_f128); - try test__powitf2(-inf_f128, 2, inf_f128); - try test__powitf2(-inf_f128, 3, -inf_f128); - try test__powitf2(-inf_f128, 4, inf_f128); - try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); - try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128); - - try test__powitf2(0, -1, inf_f128); - try test__powitf2(0, -2, inf_f128); - try test__powitf2(0, -3, inf_f128); - try test__powitf2(0, -4, inf_f128); - try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); - try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128); - try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); - - try test__powitf2(-0.0, -1, -inf_f128); - try test__powitf2(-0.0, -2, inf_f128); - try test__powitf2(-0.0, -3, -inf_f128); - try test__powitf2(-0.0, -4, inf_f128); - try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); - try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128); - try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); - - try test__powitf2(1, -1, 1); - try test__powitf2(1, -2, 1); - try test__powitf2(1, -3, 1); - try test__powitf2(1, -4, 1); - try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); - try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); - try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); - - try test__powitf2(inf_f128, -1, 0); - try test__powitf2(inf_f128, -2, 0); - try test__powitf2(inf_f128, -3, 0); - try test__powitf2(inf_f128, -4, 0); - try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); - try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powitf2(-inf_f128, -1, -0.0); - try test__powitf2(-inf_f128, -2, 0); - try test__powitf2(-inf_f128, -3, -0.0); - try test__powitf2(-inf_f128, -4, 0); - try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); - try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powitf2(2, 10, 1024.0); - try test__powitf2(-2, 10, 1024.0); - try test__powitf2(2, -10, 1.0 / 1024.0); - try test__powitf2(-2, -10, 1.0 / 1024.0); - - try test__powitf2(2, 19, 524288.0); - try test__powitf2(-2, 19, -524288.0); - try test__powitf2(2, -19, 1.0 / 524288.0); - try test__powitf2(-2, -19, -1.0 / 524288.0); - - try test__powitf2(2, 31, 2147483648.0); - try test__powitf2(-2, 31, -2147483648.0); - try test__powitf2(2, -31, 1.0 / 2147483648.0); - try test__powitf2(-2, -31, -1.0 / 2147483648.0); + try test_powi_f64(0, 0, 1); + try test_powi_f64(1, 0, 1); + try test_powi_f64(1.5, 0, 1); + try test_powi_f64(2, 0, 1); + try test_powi_f64(inf_f64, 0, 1); + + try test_powi_f64(-0.0, 0, 1); + try test_powi_f64(-1, 0, 1); + try test_powi_f64(-1.5, 0, 1); + try test_powi_f64(-2, 0, 1); + try test_powi_f64(-inf_f64, 0, 1); + + try test_powi_f64(0, 1, 0); + try test_powi_f64(0, 2, 0); + try test_powi_f64(0, 3, 0); + try test_powi_f64(0, 4, 0); + try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); + + try test_powi_f64(-0.0, 1, -0.0); + try test_powi_f64(-0.0, 2, 0); + try test_powi_f64(-0.0, 3, -0.0); + try test_powi_f64(-0.0, 4, 0); + try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); + + try test_powi_f64(1, 1, 1); + try test_powi_f64(1, 2, 1); + try test_powi_f64(1, 3, 1); + try test_powi_f64(1, 4, 1); + try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); + try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); + + try test_powi_f64(inf_f64, 1, inf_f64); + try test_powi_f64(inf_f64, 2, inf_f64); + try test_powi_f64(inf_f64, 3, inf_f64); + try test_powi_f64(inf_f64, 4, inf_f64); + try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); + try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64); + + try test_powi_f64(-inf_f64, 1, -inf_f64); + try test_powi_f64(-inf_f64, 2, inf_f64); + try test_powi_f64(-inf_f64, 3, -inf_f64); + try test_powi_f64(-inf_f64, 4, inf_f64); + try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); + try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64); + + try test_powi_f64(0, -1, inf_f64); + try test_powi_f64(0, -2, inf_f64); + try test_powi_f64(0, -3, inf_f64); + try test_powi_f64(0, -4, inf_f64); + try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); + try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64); + try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); + + try test_powi_f64(-0.0, -1, -inf_f64); + try test_powi_f64(-0.0, -2, inf_f64); + try test_powi_f64(-0.0, -3, -inf_f64); + try test_powi_f64(-0.0, -4, inf_f64); + try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); + try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64); + try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); + + try test_powi_f64(1, -1, 1); + try test_powi_f64(1, -2, 1); + try test_powi_f64(1, -3, 1); + try test_powi_f64(1, -4, 1); + try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); + try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); + try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); + + try test_powi_f64(inf_f64, -1, 0); + try test_powi_f64(inf_f64, -2, 0); + try test_powi_f64(inf_f64, -3, 0); + try test_powi_f64(inf_f64, -4, 0); + try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); + try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f64(-inf_f64, -1, -0.0); + try test_powi_f64(-inf_f64, -2, 0); + try test_powi_f64(-inf_f64, -3, -0.0); + try test_powi_f64(-inf_f64, -4, 0); + try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); + try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f64(2, 10, 1024.0); + try test_powi_f64(-2, 10, 1024.0); + try test_powi_f64(2, -10, 1.0 / 1024.0); + try test_powi_f64(-2, -10, 1.0 / 1024.0); + + try test_powi_f64(2, 19, 524288.0); + try test_powi_f64(-2, 19, -524288.0); + try test_powi_f64(2, -19, 1.0 / 524288.0); + try test_powi_f64(-2, -19, -1.0 / 524288.0); + + try test_powi_f64(2, 31, 2147483648.0); + try test_powi_f64(-2, 31, -2147483648.0); + try test_powi_f64(2, -31, 1.0 / 2147483648.0); + try test_powi_f64(-2, -31, -1.0 / 2147483648.0); } -test "powixf2" { +test powi_f80 { const inf_f80 = math.inf(f80); - try test__powixf2(0, 0, 1); - try test__powixf2(1, 0, 1); - try test__powixf2(1.5, 0, 1); - try test__powixf2(2, 0, 1); - try test__powixf2(inf_f80, 0, 1); - - try test__powixf2(-0.0, 0, 1); - try test__powixf2(-1, 0, 1); - try test__powixf2(-1.5, 0, 1); - try test__powixf2(-2, 0, 1); - try test__powixf2(-inf_f80, 0, 1); - - try test__powixf2(0, 1, 0); - try test__powixf2(0, 2, 0); - try test__powixf2(0, 3, 0); - try test__powixf2(0, 4, 0); - try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); - - try test__powixf2(-0.0, 1, -0.0); - try test__powixf2(-0.0, 2, 0); - try test__powixf2(-0.0, 3, -0.0); - try test__powixf2(-0.0, 4, 0); - try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); - - try test__powixf2(1, 1, 1); - try test__powixf2(1, 2, 1); - try test__powixf2(1, 3, 1); - try test__powixf2(1, 4, 1); - try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); - try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); - - try test__powixf2(inf_f80, 1, inf_f80); - try test__powixf2(inf_f80, 2, inf_f80); - try test__powixf2(inf_f80, 3, inf_f80); - try test__powixf2(inf_f80, 4, inf_f80); - try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); - try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80); - - try test__powixf2(-inf_f80, 1, -inf_f80); - try test__powixf2(-inf_f80, 2, inf_f80); - try test__powixf2(-inf_f80, 3, -inf_f80); - try test__powixf2(-inf_f80, 4, inf_f80); - try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); - try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80); - - try test__powixf2(0, -1, inf_f80); - try test__powixf2(0, -2, inf_f80); - try test__powixf2(0, -3, inf_f80); - try test__powixf2(0, -4, inf_f80); - try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); - try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80); - try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); - - try test__powixf2(-0.0, -1, -inf_f80); - try test__powixf2(-0.0, -2, inf_f80); - try test__powixf2(-0.0, -3, -inf_f80); - try test__powixf2(-0.0, -4, inf_f80); - try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); - try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80); - try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); - - try test__powixf2(1, -1, 1); - try test__powixf2(1, -2, 1); - try test__powixf2(1, -3, 1); - try test__powixf2(1, -4, 1); - try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); - try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); - try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); - - try test__powixf2(inf_f80, -1, 0); - try test__powixf2(inf_f80, -2, 0); - try test__powixf2(inf_f80, -3, 0); - try test__powixf2(inf_f80, -4, 0); - try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); - try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powixf2(-inf_f80, -1, -0.0); - try test__powixf2(-inf_f80, -2, 0); - try test__powixf2(-inf_f80, -3, -0.0); - try test__powixf2(-inf_f80, -4, 0); - try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); - try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powixf2(2, 10, 1024.0); - try test__powixf2(-2, 10, 1024.0); - try test__powixf2(2, -10, 1.0 / 1024.0); - try test__powixf2(-2, -10, 1.0 / 1024.0); - - try test__powixf2(2, 19, 524288.0); - try test__powixf2(-2, 19, -524288.0); - try test__powixf2(2, -19, 1.0 / 524288.0); - try test__powixf2(-2, -19, -1.0 / 524288.0); - - try test__powixf2(2, 31, 2147483648.0); - try test__powixf2(-2, 31, -2147483648.0); - try test__powixf2(2, -31, 1.0 / 2147483648.0); - try test__powixf2(-2, -31, -1.0 / 2147483648.0); + try test_powi_f80(0, 0, 1); + try test_powi_f80(1, 0, 1); + try test_powi_f80(1.5, 0, 1); + try test_powi_f80(2, 0, 1); + try test_powi_f80(inf_f80, 0, 1); + + try test_powi_f80(-0.0, 0, 1); + try test_powi_f80(-1, 0, 1); + try test_powi_f80(-1.5, 0, 1); + try test_powi_f80(-2, 0, 1); + try test_powi_f80(-inf_f80, 0, 1); + + try test_powi_f80(0, 1, 0); + try test_powi_f80(0, 2, 0); + try test_powi_f80(0, 3, 0); + try test_powi_f80(0, 4, 0); + try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); + + try test_powi_f80(-0.0, 1, -0.0); + try test_powi_f80(-0.0, 2, 0); + try test_powi_f80(-0.0, 3, -0.0); + try test_powi_f80(-0.0, 4, 0); + try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); + + try test_powi_f80(1, 1, 1); + try test_powi_f80(1, 2, 1); + try test_powi_f80(1, 3, 1); + try test_powi_f80(1, 4, 1); + try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); + try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); + + try test_powi_f80(inf_f80, 1, inf_f80); + try test_powi_f80(inf_f80, 2, inf_f80); + try test_powi_f80(inf_f80, 3, inf_f80); + try test_powi_f80(inf_f80, 4, inf_f80); + try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); + try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80); + + try test_powi_f80(-inf_f80, 1, -inf_f80); + try test_powi_f80(-inf_f80, 2, inf_f80); + try test_powi_f80(-inf_f80, 3, -inf_f80); + try test_powi_f80(-inf_f80, 4, inf_f80); + try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); + try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80); + + try test_powi_f80(0, -1, inf_f80); + try test_powi_f80(0, -2, inf_f80); + try test_powi_f80(0, -3, inf_f80); + try test_powi_f80(0, -4, inf_f80); + try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); + try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80); + try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); + + try test_powi_f80(-0.0, -1, -inf_f80); + try test_powi_f80(-0.0, -2, inf_f80); + try test_powi_f80(-0.0, -3, -inf_f80); + try test_powi_f80(-0.0, -4, inf_f80); + try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); + try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80); + try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); + + try test_powi_f80(1, -1, 1); + try test_powi_f80(1, -2, 1); + try test_powi_f80(1, -3, 1); + try test_powi_f80(1, -4, 1); + try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); + try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); + try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); + + try test_powi_f80(inf_f80, -1, 0); + try test_powi_f80(inf_f80, -2, 0); + try test_powi_f80(inf_f80, -3, 0); + try test_powi_f80(inf_f80, -4, 0); + try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); + try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f80(-inf_f80, -1, -0.0); + try test_powi_f80(-inf_f80, -2, 0); + try test_powi_f80(-inf_f80, -3, -0.0); + try test_powi_f80(-inf_f80, -4, 0); + try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); + try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f80(2, 10, 1024.0); + try test_powi_f80(-2, 10, 1024.0); + try test_powi_f80(2, -10, 1.0 / 1024.0); + try test_powi_f80(-2, -10, 1.0 / 1024.0); + + try test_powi_f80(2, 19, 524288.0); + try test_powi_f80(-2, 19, -524288.0); + try test_powi_f80(2, -19, 1.0 / 524288.0); + try test_powi_f80(-2, -19, -1.0 / 524288.0); + + try test_powi_f80(2, 31, 2147483648.0); + try test_powi_f80(-2, 31, -2147483648.0); + try test_powi_f80(2, -31, 1.0 / 2147483648.0); + try test_powi_f80(-2, -31, -1.0 / 2147483648.0); +} + +test powi_f128 { + const inf_f128 = math.inf(f128); + try test_powi_f128(0, 0, 1); + try test_powi_f128(1, 0, 1); + try test_powi_f128(1.5, 0, 1); + try test_powi_f128(2, 0, 1); + try test_powi_f128(inf_f128, 0, 1); + + try test_powi_f128(-0.0, 0, 1); + try test_powi_f128(-1, 0, 1); + try test_powi_f128(-1.5, 0, 1); + try test_powi_f128(-2, 0, 1); + try test_powi_f128(-inf_f128, 0, 1); + + try test_powi_f128(0, 1, 0); + try test_powi_f128(0, 2, 0); + try test_powi_f128(0, 3, 0); + try test_powi_f128(0, 4, 0); + try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f128(0, 0x7FFFFFFF, 0); + + try test_powi_f128(-0.0, 1, -0.0); + try test_powi_f128(-0.0, 2, 0); + try test_powi_f128(-0.0, 3, -0.0); + try test_powi_f128(-0.0, 4, 0); + try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); + + try test_powi_f128(1, 1, 1); + try test_powi_f128(1, 2, 1); + try test_powi_f128(1, 3, 1); + try test_powi_f128(1, 4, 1); + try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); + try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); + + try test_powi_f128(inf_f128, 1, inf_f128); + try test_powi_f128(inf_f128, 2, inf_f128); + try test_powi_f128(inf_f128, 3, inf_f128); + try test_powi_f128(inf_f128, 4, inf_f128); + try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); + try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128); + + try test_powi_f128(-inf_f128, 1, -inf_f128); + try test_powi_f128(-inf_f128, 2, inf_f128); + try test_powi_f128(-inf_f128, 3, -inf_f128); + try test_powi_f128(-inf_f128, 4, inf_f128); + try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); + try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128); + + try test_powi_f128(0, -1, inf_f128); + try test_powi_f128(0, -2, inf_f128); + try test_powi_f128(0, -3, inf_f128); + try test_powi_f128(0, -4, inf_f128); + try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); + try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128); + try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); + + try test_powi_f128(-0.0, -1, -inf_f128); + try test_powi_f128(-0.0, -2, inf_f128); + try test_powi_f128(-0.0, -3, -inf_f128); + try test_powi_f128(-0.0, -4, inf_f128); + try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); + try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128); + try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); + + try test_powi_f128(1, -1, 1); + try test_powi_f128(1, -2, 1); + try test_powi_f128(1, -3, 1); + try test_powi_f128(1, -4, 1); + try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); + try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); + try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); + + try test_powi_f128(inf_f128, -1, 0); + try test_powi_f128(inf_f128, -2, 0); + try test_powi_f128(inf_f128, -3, 0); + try test_powi_f128(inf_f128, -4, 0); + try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); + try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f128(-inf_f128, -1, -0.0); + try test_powi_f128(-inf_f128, -2, 0); + try test_powi_f128(-inf_f128, -3, -0.0); + try test_powi_f128(-inf_f128, -4, 0); + try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); + try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f128(2, 10, 1024.0); + try test_powi_f128(-2, 10, 1024.0); + try test_powi_f128(2, -10, 1.0 / 1024.0); + try test_powi_f128(-2, -10, 1.0 / 1024.0); + + try test_powi_f128(2, 19, 524288.0); + try test_powi_f128(-2, 19, -524288.0); + try test_powi_f128(2, -19, 1.0 / 524288.0); + try test_powi_f128(-2, -19, -1.0 / 524288.0); + + try test_powi_f128(2, 31, 2147483648.0); + try test_powi_f128(-2, 31, -2147483648.0); + try test_powi_f128(2, -31, 1.0 / 2147483648.0); + try test_powi_f128(-2, -31, -1.0 / 2147483648.0); } diff --git a/lib/compiler_rt/round.zig b/lib/compiler_rt/round.zig index 590b957922efdbf33ac4fea2728390daad82ee38..6c86984605af2d246a4e582851a5d172a67d7c69 100644 --- a/lib/compiler_rt/round.zig +++ b/lib/compiler_rt/round.zig @@ -18,19 +18,23 @@ comptime { symbol(&roundf, "roundf"); symbol(&round, "round"); symbol(&__roundx, "__roundx"); - if (compiler_rt.want_ppc_abi) { - symbol(&roundq, "roundf128"); - } + if (compiler_rt.want_ppc_abi) symbol(&roundq, "roundf128"); symbol(&roundq, "roundq"); symbol(&roundl, "roundl"); } -pub fn __roundh(x: f16) callconv(.c) f16 { +fn __roundh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(round_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn round_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(roundf(x)); + return @floatCast(round_f32(x)); } -pub fn roundf(x_: f32) callconv(.c) f32 { +fn roundf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(round_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn round_f32(x_: f32) f32 { const f32_toint = 1.0 / math.floatEps(f32); var x = x_; @@ -65,7 +69,10 @@ pub fn roundf(x_: f32) callconv(.c) f32 { } } -pub fn round(x_: f64) callconv(.c) f64 { +fn round(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(round_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn round_f64(x_: f64) f64 { const f64_toint = 1.0 / math.floatEps(f64); var x = x_; @@ -100,12 +107,18 @@ pub fn round(x_: f64) callconv(.c) f64 { } } -pub fn __roundx(x: f80) callconv(.c) f80 { +fn __roundx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(round_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn round_f80(x: f80) f80 { // TODO: more efficient implementation - return @floatCast(roundq(x)); + return @floatCast(round_f128(x)); } -pub fn roundq(x_: f128) callconv(.c) f128 { +fn roundq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(round_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn round_f128(x_: f128) f128 { const f128_toint = 1.0 / math.floatEps(f128); var x = x_; @@ -142,54 +155,79 @@ pub fn roundq(x_: f128) callconv(.c) f128 { pub fn roundl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return round(x), - 80 => return __roundx(x), - 128 => return roundq(x), - else => @compileError("unreachable"), + 64 => return round_f64(x), + 80 => return round_f80(x), + 128 => return round_f128(x), + else => comptime unreachable, } } -test "round32" { - try expect(roundf(1.3) == 1.0); - try expect(roundf(-1.3) == -1.0); - try expect(roundf(0.2) == 0.0); - try expect(roundf(1.8) == 2.0); +test round_f16 { + try expect(round_f16(1.3) == 1.0); + try expect(round_f16(-1.3) == -1.0); + try expect(round_f16(1.8) == 2.0); + try expect(round_f16(-1.8) == -2.0); + try expect(math.isPositiveZero(round_f16(0.2))); + try expect(math.isNegativeZero(round_f16(-0.2))); + try expect(math.isPositiveZero(round_f16(0.0))); + try expect(math.isNegativeZero(round_f16(-0.0))); + try expect(math.isPositiveInf(round_f16(math.inf(f32)))); + try expect(math.isNegativeInf(round_f16(-math.inf(f32)))); + try expect(math.isNan(round_f16(math.nan(f32)))); } -test "round64" { - try expect(round(1.3) == 1.0); - try expect(round(-1.3) == -1.0); - try expect(round(0.2) == 0.0); - try expect(round(1.8) == 2.0); +test round_f32 { + try expect(round_f32(1.3) == 1.0); + try expect(round_f32(-1.3) == -1.0); + try expect(round_f32(1.8) == 2.0); + try expect(round_f32(-1.8) == -2.0); + try expect(math.isPositiveZero(round_f32(0.2))); + try expect(math.isNegativeZero(round_f32(-0.2))); + try expect(math.isPositiveZero(round_f32(0.0))); + try expect(math.isNegativeZero(round_f32(-0.0))); + try expect(math.isPositiveInf(round_f32(math.inf(f32)))); + try expect(math.isNegativeInf(round_f32(-math.inf(f32)))); + try expect(math.isNan(round_f32(math.nan(f32)))); } -test "round128" { - try expect(roundq(1.3) == 1.0); - try expect(roundq(-1.3) == -1.0); - try expect(roundq(0.2) == 0.0); - try expect(roundq(1.8) == 2.0); +test round_f64 { + try expect(round_f64(1.3) == 1.0); + try expect(round_f64(-1.3) == -1.0); + try expect(round_f64(1.8) == 2.0); + try expect(round_f64(-1.8) == -2.0); + try expect(math.isPositiveZero(round_f64(0.2))); + try expect(math.isNegativeZero(round_f64(-0.2))); + try expect(math.isPositiveZero(round_f64(0.0))); + try expect(math.isNegativeZero(round_f64(-0.0))); + try expect(math.isPositiveInf(round_f64(math.inf(f64)))); + try expect(math.isNegativeInf(round_f64(-math.inf(f64)))); + try expect(math.isNan(round_f64(math.nan(f64)))); } -test "round32.special" { - try expect(roundf(0.0) == 0.0); - try expect(roundf(-0.0) == -0.0); - try expect(math.isPositiveInf(roundf(math.inf(f32)))); - try expect(math.isNegativeInf(roundf(-math.inf(f32)))); - try expect(math.isNan(roundf(math.nan(f32)))); +test round_f80 { + try expect(round_f80(1.3) == 1.0); + try expect(round_f80(-1.3) == -1.0); + try expect(round_f80(1.8) == 2.0); + try expect(round_f80(-1.8) == -2.0); + try expect(math.isPositiveZero(round_f80(0.2))); + try expect(math.isNegativeZero(round_f80(-0.2))); + try expect(math.isPositiveZero(round_f80(0.0))); + try expect(math.isNegativeZero(round_f80(-0.0))); + try expect(math.isPositiveInf(round_f80(math.inf(f64)))); + try expect(math.isNegativeInf(round_f80(-math.inf(f64)))); + try expect(math.isNan(round_f80(math.nan(f64)))); } -test "round64.special" { - try expect(round(0.0) == 0.0); - try expect(round(-0.0) == -0.0); - try expect(math.isPositiveInf(round(math.inf(f64)))); - try expect(math.isNegativeInf(round(-math.inf(f64)))); - try expect(math.isNan(round(math.nan(f64)))); -} - -test "round128.special" { - try expect(roundq(0.0) == 0.0); - try expect(roundq(-0.0) == -0.0); - try expect(math.isPositiveInf(roundq(math.inf(f128)))); - try expect(math.isNegativeInf(roundq(-math.inf(f128)))); - try expect(math.isNan(roundq(math.nan(f128)))); +test round_f128 { + try expect(round_f128(1.3) == 1.0); + try expect(round_f128(-1.3) == -1.0); + try expect(round_f128(1.8) == 2.0); + try expect(round_f128(-1.8) == -2.0); + try expect(math.isPositiveZero(round_f128(0.2))); + try expect(math.isNegativeZero(round_f128(-0.2))); + try expect(math.isPositiveZero(round_f128(0.0))); + try expect(math.isNegativeZero(round_f128(-0.0))); + try expect(math.isPositiveInf(round_f128(math.inf(f128)))); + try expect(math.isNegativeInf(round_f128(-math.inf(f128)))); + try expect(math.isNan(round_f128(math.nan(f128)))); } diff --git a/lib/compiler_rt/sin.zig b/lib/compiler_rt/sin.zig index 040cba8cd3ef34e59f6bfd181a3c09036963fb4c..fe818922fe4af6542dc88fd682367860ae4908da 100644 --- a/lib/compiler_rt/sin.zig +++ b/lib/compiler_rt/sin.zig @@ -13,31 +13,37 @@ const expect = std.testing.expect; const expectApproxEqAbs = std.testing.expectApproxEqAbs; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; const trig = @import("trig.zig"); const rem_pio2 = @import("rem_pio2.zig").rem_pio2; const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; comptime { - symbol(&sinh, "__sinh"); - symbol(&sinl, "__sinl"); + symbol(&__sinh, "__sinh"); symbol(&sinf, "sinf"); symbol(&sin, "sin"); - symbol(&sinx, "__sinx"); + symbol(&__sinx, "__sinx"); if (compiler_rt.want_ppc_abi) { symbol(&sinq, "sinf128"); } symbol(&sinq, "sinq"); symbol(&sinl, "sinl"); + symbol(&sinl, "__sinl"); // required by musl } -pub fn sinh(x: f16) callconv(.c) f16 { +fn __sinh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(sin_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn sin_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(sinf(x)); + return @floatCast(sin_f32(x)); } -pub fn sinf(x: f32) callconv(.c) f32 { +fn sinf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(sin_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn sin_f32(x: f32) f32 { // Small multiples of pi/2 rounded to double precision. const s1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 const s2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 @@ -98,7 +104,10 @@ pub fn sinf(x: f32) callconv(.c) f32 { }; } -pub fn sin(x: f64) callconv(.c) f64 { +fn sin(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(sin_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn sin_f64(x: f64) f64 { var ix = @as(u64, @bitCast(x)) >> 32; ix &= 0x7fffffff; @@ -133,7 +142,10 @@ pub fn sin(x: f64) callconv(.c) f64 { }; } -fn sinx(x: f80) callconv(.c) f80 { +fn __sinx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(sin_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn sin_f80(x: f80) f80 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -160,7 +172,10 @@ fn sinx(x: f80) callconv(.c) f80 { }; } -pub fn sinq(x: f128) callconv(.c) f128 { +fn sinq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(sin_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn sin_f128(x: f128) f128 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -189,20 +204,21 @@ pub fn sinq(x: f128) callconv(.c) f128 { pub fn sinl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return sin(x), - 80 => return sinx(x), - 128 => return sinq(x), - else => @compileError("unreachable"), + 64 => return sin_f64(x), + 80 => return sin_f80(x), + 128 => return sin_f128(x), + else => comptime unreachable, } } fn testSinSpecial(comptime T: type) !void { const f = switch (T) { - f32 => sinf, - f64 => sin, - f80 => sinx, - f128 => sinq, - else => @compileError("unimplemented"), + f16 => sin_f16, + f32 => sin_f32, + f64 => sin_f64, + f80 => sin_f80, + f128 => sin_f128, + else => comptime unreachable, }; try expect(math.isPositiveZero(f(0.0))); @@ -214,13 +230,13 @@ fn testSinSpecial(comptime T: type) !void { test "sin32.normal" { const epsilon = math.floatEps(f32); - try expectApproxEqAbs(@as(f32, 0.0), sinf(0.0), epsilon); - try expectApproxEqAbs(@as(f32, 0.19866933), sinf(0.2), epsilon); - try expectApproxEqAbs(@as(f32, 0.77851737), sinf(0.8923), epsilon); - try expectApproxEqAbs(@as(f32, 0.997495), sinf(1.5), epsilon); - try expectApproxEqAbs(@as(f32, -0.997495), sinf(-1.5), epsilon); - try expectApproxEqAbs(@as(f32, -0.24654257), sinf(37.45), epsilon); - try expectApproxEqAbs(@as(f32, 0.9161657), sinf(89.123), epsilon); + try expectApproxEqAbs(@as(f32, 0.0), sin_f32(0.0), epsilon); + try expectApproxEqAbs(@as(f32, 0.19866933), sin_f32(0.2), epsilon); + try expectApproxEqAbs(@as(f32, 0.77851737), sin_f32(0.8923), epsilon); + try expectApproxEqAbs(@as(f32, 0.997495), sin_f32(1.5), epsilon); + try expectApproxEqAbs(@as(f32, -0.997495), sin_f32(-1.5), epsilon); + try expectApproxEqAbs(@as(f32, -0.24654257), sin_f32(37.45), epsilon); + try expectApproxEqAbs(@as(f32, 0.9161657), sin_f32(89.123), epsilon); } test "sin32.special" { @@ -229,13 +245,13 @@ test "sin32.special" { test "sin64.normal" { const epsilon = math.floatEps(f64); - try expectApproxEqAbs(@as(f64, 0.0), sin(0.0), epsilon); - try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin(0.2), epsilon); - try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin(0.8923), epsilon); - try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin(1.5), epsilon); - try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin(-1.5), epsilon); - try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin(37.45), epsilon); - try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin(89.123), epsilon); + try expectApproxEqAbs(@as(f64, 0.0), sin_f64(0.0), epsilon); + try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin_f64(0.2), epsilon); + try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin_f64(0.8923), epsilon); + try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin_f64(1.5), epsilon); + try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin_f64(-1.5), epsilon); + try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin_f64(37.45), epsilon); + try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin_f64(89.123), epsilon); } test "sin64.special" { @@ -244,13 +260,13 @@ test "sin64.special" { test "sin80.normal" { const epsilon = math.floatEps(f80); - try expectApproxEqAbs(@as(f80, 0.0), sinx(0.0), epsilon); - try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sinx(0.2), epsilon); - try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sinx(0.8923), epsilon); - try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sinx(1.5), epsilon); - try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sinx(-1.5), epsilon); - try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sinx(37.45), epsilon); - try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sinx(89.123), epsilon); + try expectApproxEqAbs(@as(f80, 0.0), sin_f80(0.0), epsilon); + try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sin_f80(0.2), epsilon); + try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sin_f80(0.8923), epsilon); + try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sin_f80(1.5), epsilon); + try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sin_f80(-1.5), epsilon); + try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sin_f80(37.45), epsilon); + try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sin_f80(89.123), epsilon); } test "sin80.special" { @@ -259,13 +275,13 @@ test "sin80.special" { test "sin128.normal" { const epsilon = math.floatEps(f128); - try expectApproxEqAbs(@as(f128, 0.0), sinq(0.0), epsilon); - try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sinq(0.2), epsilon); - try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sinq(0.8923), epsilon); - try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sinq(1.5), epsilon); - try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sinq(-1.5), epsilon); - try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sinq(37.45), epsilon); - try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sinq(89.123), epsilon); + try expectApproxEqAbs(@as(f128, 0.0), sin_f128(0.0), epsilon); + try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sin_f128(0.2), epsilon); + try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sin_f128(0.8923), epsilon); + try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sin_f128(1.5), epsilon); + try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sin_f128(-1.5), epsilon); + try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sin_f128(37.45), epsilon); + try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sin_f128(89.123), epsilon); } test "sin128.special" { @@ -274,10 +290,10 @@ test "sin128.special" { test "sin32 #9901" { const float: f32 = @bitCast(@as(u32, 0b11100011111111110000000000000000)); - _ = sinf(float); + _ = sin_f32(float); } test "sin64 #9901" { const float: f64 = @bitCast(@as(u64, 0b1111111101000001000000001111110111111111100000000000000000000001)); - _ = sin(float); + _ = sin_f64(float); } diff --git a/lib/compiler_rt/sincos.zig b/lib/compiler_rt/sincos.zig index 24bb751e76e7e93d32b05a4a801dec6d5d474709..6d2b9f007a90f94c158bb636d3fcd1d8e6b40a7c 100644 --- a/lib/compiler_rt/sincos.zig +++ b/lib/compiler_rt/sincos.zig @@ -25,16 +25,23 @@ comptime { symbol(&sincosl, "sincosl"); } -pub fn sincosh(x: f16, r_sin: *f16, r_cos: *f16) callconv(.c) void { +fn sincosh(x: compiler_rt.f16.Abi, r_sin: *compiler_rt.f16.Abi, r_cos: *compiler_rt.f16.Abi) callconv(.c) void { + const s, const c = sincos_f16(compiler_rt.f16.fromAbi(x)); + r_sin.* = compiler_rt.f16.toAbi(s); + r_cos.* = compiler_rt.f16.toAbi(c); +} +pub fn sincos_f16(x: f16) struct { f16, f16 } { // TODO: more efficient implementation - var big_sin: f32 = undefined; - var big_cos: f32 = undefined; - sincosf(x, &big_sin, &big_cos); - r_sin.* = @as(f16, @floatCast(big_sin)); - r_cos.* = @as(f16, @floatCast(big_cos)); + const s, const c = sincos_f32(x); + return .{ @floatCast(s), @floatCast(c) }; } -pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { +fn sincosf(x: compiler_rt.f32.Abi, r_sin: *compiler_rt.f32.Abi, r_cos: *compiler_rt.f32.Abi) callconv(.c) void { + const s, const c = sincos_f32(compiler_rt.f32.fromAbi(x)); + r_sin.* = compiler_rt.f32.toAbi(s); + r_cos.* = compiler_rt.f32.toAbi(c); +} +pub fn sincos_f32(x: f32) struct { f32, f32 } { const sc1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 const sc2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 const sc3pio2: f64 = 3.0 * math.pi / 2.0; // 0x4012D97C, 0x7F3321D2 @@ -56,13 +63,9 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { mem.doNotOptimizeAway(x + 0x1p120); } } - r_sin.* = x; - r_cos.* = 1.0; - return; + return .{ x, 1.0 }; } - r_sin.* = trig.sindf(x); - r_cos.* = trig.cosdf(x); - return; + return .{ trig.sindf(x), trig.cosdf(x) }; } // |x| ~<= 5*pi/4 @@ -70,18 +73,16 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { // |x| ~<= 3pi/4 if (ix <= 0x4016cbe3) { if (sign) { - r_sin.* = -trig.cosdf(x + sc1pio2); - r_cos.* = trig.sindf(x + sc1pio2); + return .{ -trig.cosdf(x + sc1pio2), trig.sindf(x + sc1pio2) }; } else { - r_sin.* = trig.cosdf(sc1pio2 - x); - r_cos.* = trig.sindf(sc1pio2 - x); + return .{ trig.cosdf(sc1pio2 - x), trig.sindf(sc1pio2 - x) }; } - return; } // -sin(x+c) is not correct if x+c could be 0: -0 vs +0 - r_sin.* = -trig.sindf(if (sign) x + sc2pio2 else x - sc2pio2); - r_cos.* = -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2); - return; + return .{ + -trig.sindf(if (sign) x + sc2pio2 else x - sc2pio2), + -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2), + }; } // |x| ~<= 9*pi/4 @@ -89,25 +90,21 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { // |x| ~<= 7*pi/4 if (ix <= 0x40afeddf) { if (sign) { - r_sin.* = trig.cosdf(x + sc3pio2); - r_cos.* = -trig.sindf(x + sc3pio2); + return .{ trig.cosdf(x + sc3pio2), -trig.sindf(x + sc3pio2) }; } else { - r_sin.* = -trig.cosdf(x - sc3pio2); - r_cos.* = trig.sindf(x - sc3pio2); + return .{ -trig.cosdf(x - sc3pio2), trig.sindf(x - sc3pio2) }; } - return; } - r_sin.* = trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2); - r_cos.* = trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2); - return; + return .{ + trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2), + trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2), + }; } // sin(Inf or NaN) is NaN if (ix >= 0x7f800000) { const result = x - x; - r_sin.* = result; - r_cos.* = result; - return; + return .{ result, result }; } // general argument reduction needed @@ -115,27 +112,20 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { const n = rem_pio2f(x, &y); const s = trig.sindf(y); const c = trig.cosdf(y); - switch (n & 3) { - 0 => { - r_sin.* = s; - r_cos.* = c; - }, - 1 => { - r_sin.* = c; - r_cos.* = -s; - }, - 2 => { - r_sin.* = -s; - r_cos.* = -c; - }, - else => { - r_sin.* = -c; - r_cos.* = s; - }, - } + return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { + 0 => .{ s, c }, + 1 => .{ c, -s }, + 2 => .{ -s, -c }, + 3 => .{ -c, s }, + }; } -pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void { +fn sincos(x: compiler_rt.f64.Abi, r_sin: *compiler_rt.f64.Abi, r_cos: *compiler_rt.f64.Abi) callconv(.c) void { + const s, const c = sincos_f64(compiler_rt.f64.fromAbi(x)); + r_sin.* = compiler_rt.f64.toAbi(s); + r_cos.* = compiler_rt.f64.toAbi(c); +} +pub fn sincos_f64(x: f64) struct { f64, f64 } { const ix = @as(u32, @truncate(@as(u64, @bitCast(x)) >> 32)) & 0x7fffffff; // |x| ~< pi/4 @@ -150,21 +140,15 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void { mem.doNotOptimizeAway(x + 0x1p120); } } - r_sin.* = x; - r_cos.* = 1.0; - return; + return .{ x, 1.0 }; } - r_sin.* = trig.sin(x, 0.0, 0); - r_cos.* = trig.cos(x, 0.0); - return; + return .{ trig.sin(x, 0.0, 0), trig.cos(x, 0.0) }; } // sincos(Inf or NaN) is NaN if (ix >= 0x7ff00000) { const result = x - x; - r_sin.* = result; - r_cos.* = result; - return; + return .{ result, result }; } // argument reduction needed @@ -172,33 +156,24 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void { const n = rem_pio2(x, &y); const s = trig.sin(y[0], y[1], 1); const c = trig.cos(y[0], y[1]); - switch (n & 3) { - 0 => { - r_sin.* = s; - r_cos.* = c; - }, - 1 => { - r_sin.* = c; - r_cos.* = -s; - }, - 2 => { - r_sin.* = -s; - r_cos.* = -c; - }, - else => { - r_sin.* = -c; - r_cos.* = s; - }, - } + return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { + 0 => .{ s, c }, + 1 => .{ c, -s }, + 2 => .{ -s, -c }, + 3 => .{ -c, s }, + }; } -pub fn sincosx(x: f80, r_sin: *f80, r_cos: *f80) callconv(.c) void { +fn sincosx(x: compiler_rt.f80.Abi, r_sin: *compiler_rt.f80.Abi, r_cos: *compiler_rt.f80.Abi) callconv(.c) void { + const s, const c = sincos_f80(compiler_rt.f80.fromAbi(x)); + r_sin.* = compiler_rt.f80.toAbi(s); + r_cos.* = compiler_rt.f80.toAbi(c); +} +pub fn sincos_f80(x: f80) struct { f80, f80 } { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { const result = x - x; - r_sin.* = result; - r_cos.* = result; - return; + return .{ result, result }; } if (@abs(x) < trig.pi_4) { @@ -207,47 +182,34 @@ pub fn sincosx(x: f80, r_sin: *f80, r_cos: *f80) callconv(.c) void { if (compiler_rt.want_float_exceptions and se == 0) { mem.doNotOptimizeAway(x * 0x1p-120); } - r_sin.* = x; // raise inexact if x!=0 - r_cos.* = 1.0 + x; - return; + return .{ x, 1.0 + x }; } - r_sin.* = trig.sinx(x, 0.0, 0); - r_cos.* = trig.cosx(x, 0.0); - return; + return .{ trig.sinx(x, 0.0, 0), trig.cosx(x, 0.0) }; } var y: [2]f80 = undefined; const n = rem_pio2l(f80, x, &y); const s = trig.sinx(y[0], y[1], 1); const c = trig.cosx(y[0], y[1]); - switch (n & 3) { - 0 => { - r_sin.* = s; - r_cos.* = c; - }, - 1 => { - r_sin.* = c; - r_cos.* = -s; - }, - 2 => { - r_sin.* = -s; - r_cos.* = -c; - }, - else => { - r_sin.* = -c; - r_cos.* = s; - }, - } + return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { + 0 => .{ s, c }, + 1 => .{ c, -s }, + 2 => .{ -s, -c }, + 3 => .{ -c, s }, + }; } -pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void { +fn sincosq(x: compiler_rt.f128.Abi, r_sin: *compiler_rt.f128.Abi, r_cos: *compiler_rt.f128.Abi) callconv(.c) void { + const s, const c = sincos_f128(compiler_rt.f128.fromAbi(x)); + r_sin.* = compiler_rt.f128.toAbi(s); + r_cos.* = compiler_rt.f128.toAbi(c); +} +pub fn sincos_f128(x: f128) struct { f128, f128 } { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { const result = x - x; - r_sin.* = result; - r_cos.* = result; - return; + return .{ result, result }; } if (@abs(x) < trig.pi_4) { @@ -256,78 +218,63 @@ pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void { if (compiler_rt.want_float_exceptions and se == 0) { mem.doNotOptimizeAway(x * 0x1p-120); } - r_sin.* = x; // raise inexact if x!=0 - r_cos.* = 1.0 + x; - return; + return .{ x, 1.0 + x }; } - r_sin.* = trig.sinq(x, 0.0, 0); - r_cos.* = trig.cosq(x, 0.0); - return; + return .{ trig.sinq(x, 0.0, 0), trig.cosq(x, 0.0) }; } var y: [2]f128 = undefined; const n = rem_pio2l(f128, x, &y); const s = trig.sinq(y[0], y[1], 1); const c = trig.cosq(y[0], y[1]); - switch (n & 3) { - 0 => { - r_sin.* = s; - r_cos.* = c; - }, - 1 => { - r_sin.* = c; - r_cos.* = -s; - }, - 2 => { - r_sin.* = -s; - r_cos.* = -c; - }, - else => { - r_sin.* = -c; - r_cos.* = s; - }, - } + return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { + 0 => .{ s, c }, + 1 => .{ c, -s }, + 2 => .{ -s, -c }, + 3 => .{ -c, s }, + }; } pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) callconv(.c) void { - switch (@typeInfo(c_longdouble).float.bits) { - 64 => return sincos(x, r_sin, r_cos), - 80 => return sincosx(x, r_sin, r_cos), - 128 => return sincosq(x, r_sin, r_cos), - else => @compileError("unreachable"), - } + r_sin.*, r_cos.* = switch (@typeInfo(c_longdouble).float.bits) { + 64 => sincos_f64(x), + 80 => sincos_f80(x), + 128 => sincos_f128(x), + else => comptime unreachable, + }; } fn testSincosSpecial(comptime T: type) !void { const f = switch (T) { - f32 => sincosf, - f64 => sincos, - f80 => sincosx, - f128 => sincosq, + f16 => sincos_f16, + f32 => sincos_f32, + f64 => sincos_f64, + f80 => sincos_f80, + f128 => sincos_f128, else => @compileError("unimplemented"), }; var s: T = undefined; var c: T = undefined; - f(0.0, &s, &c); + s, c = f(0.0); try expect(math.isPositiveZero(s)); try expect(c == 1.0); - f(-0.0, &s, &c); + s, c = f(-0.0); try expect(math.isNegativeZero(s)); try expect(c == 1.0); - f(math.inf(T), &s, &c); + s, c = f(math.inf(T)); try expect(math.isNan(s)); try expect(math.isNan(c)); - f(-math.inf(T), &s, &c); + s, c = f(-math.inf(T)); try expect(math.isNan(s)); try expect(math.isNan(c)); - f(math.nan(T), &s, &c); + s, c = f(math.nan(T)); try expect(math.isNan(s)); try expect(math.isNan(c)); } @@ -337,31 +284,31 @@ test "sincos32.normal" { var s: f32 = undefined; var c: f32 = undefined; - sincosf(0.0, &s, &c); + s, c = sincos_f32(0.0); try expectApproxEqAbs(@as(f32, 0.0), s, epsilon); try expectApproxEqAbs(@as(f32, 1.0), c, epsilon); - sincosf(0.2, &s, &c); + s, c = sincos_f32(0.2); try expectApproxEqAbs(@as(f32, 0.19866933), s, epsilon); try expectApproxEqAbs(@as(f32, 0.9800666), c, epsilon); - sincosf(0.8923, &s, &c); + s, c = sincos_f32(0.8923); try expectApproxEqAbs(@as(f32, 0.77851737), s, epsilon); try expectApproxEqAbs(@as(f32, 0.6276231), c, epsilon); - sincosf(1.5, &s, &c); + s, c = sincos_f32(1.5); try expectApproxEqAbs(@as(f32, 0.997495), s, epsilon); try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon); - sincosf(-1.5, &s, &c); + s, c = sincos_f32(-1.5); try expectApproxEqAbs(@as(f32, -0.997495), s, epsilon); try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon); - sincosf(37.45, &s, &c); + s, c = sincos_f32(37.45); try expectApproxEqAbs(@as(f32, -0.24654257), s, epsilon); try expectApproxEqAbs(@as(f32, 0.96913195), c, epsilon); - sincosf(89.123, &s, &c); + s, c = sincos_f32(89.123); try expectApproxEqAbs(@as(f32, 0.9161657), s, epsilon); try expectApproxEqAbs(@as(f32, 0.40079966), c, epsilon); } @@ -375,31 +322,31 @@ test "sincos64.normal" { var s: f64 = undefined; var c: f64 = undefined; - sincos(0.0, &s, &c); + s, c = sincos_f64(0.0); try expectApproxEqAbs(@as(f64, 0.0), s, epsilon); try expectApproxEqAbs(@as(f64, 1.0), c, epsilon); - sincos(0.2, &s, &c); + s, c = sincos_f64(0.2); try expectApproxEqAbs(@as(f64, 0.19866933079506122), s, epsilon); try expectApproxEqAbs(@as(f64, 0.9800665778412416), c, epsilon); - sincos(0.8923, &s, &c); + s, c = sincos_f64(0.8923); try expectApproxEqAbs(@as(f64, 0.7785173385577349), s, epsilon); try expectApproxEqAbs(@as(f64, 0.6276230983360804), c, epsilon); - sincos(1.5, &s, &c); + s, c = sincos_f64(1.5); try expectApproxEqAbs(@as(f64, 0.9974949866040544), s, epsilon); try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon); - sincos(-1.5, &s, &c); + s, c = sincos_f64(-1.5); try expectApproxEqAbs(@as(f64, -0.9974949866040544), s, epsilon); try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon); - sincos(37.45, &s, &c); + s, c = sincos_f64(37.45); try expectApproxEqAbs(@as(f64, -0.24654331551411082), s, epsilon); try expectApproxEqAbs(@as(f64, 0.9691317730707778), c, epsilon); - sincos(89.123, &s, &c); + s, c = sincos_f64(89.123); try expectApproxEqAbs(@as(f64, 0.9161652766622714), s, epsilon); try expectApproxEqAbs(@as(f64, 0.4008006809354791), c, epsilon); } @@ -413,31 +360,31 @@ test "sincos80.normal" { var s: f80 = undefined; var c: f80 = undefined; - sincosx(0.0, &s, &c); + s, c = sincos_f80(0.0); try expectApproxEqAbs(@as(f80, 0.0), s, epsilon); try expectApproxEqAbs(@as(f80, 1.0), c, epsilon); - sincosx(0.2, &s, &c); + s, c = sincos_f80(0.2); try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), s, epsilon); try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), c, epsilon); - sincosx(0.8923, &s, &c); + s, c = sincos_f80(0.8923); try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), s, epsilon); try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), c, epsilon); - sincosx(1.5, &s, &c); + s, c = sincos_f80(1.5); try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), s, epsilon); try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon); - sincosx(-1.5, &s, &c); + s, c = sincos_f80(-1.5); try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), s, epsilon); try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon); - sincosx(37.45, &s, &c); + s, c = sincos_f80(37.45); try expectApproxEqAbs(@as(f80, -0.24654331551411356504), s, epsilon); try expectApproxEqAbs(@as(f80, 0.9691317730707771246), c, epsilon); - sincosx(89.123, &s, &c); + s, c = sincos_f80(89.123); try expectApproxEqAbs(@as(f80, 0.91616527666226951006), s, epsilon); try expectApproxEqAbs(@as(f80, 0.4008006809354834001), c, epsilon); } @@ -451,31 +398,31 @@ test "sincos128.normal" { var s: f128 = undefined; var c: f128 = undefined; - sincosq(0.0, &s, &c); + s, c = sincos_f128(0.0); try expectApproxEqAbs(@as(f128, 0.0), s, epsilon); try expectApproxEqAbs(@as(f128, 1.0), c, epsilon); - sincosq(0.2, &s, &c); + s, c = sincos_f128(0.2); try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), s, epsilon); try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), c, epsilon); - sincosq(0.8923, &s, &c); + s, c = sincos_f128(0.8923); try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), s, epsilon); try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), c, epsilon); - sincosq(1.5, &s, &c); + s, c = sincos_f128(1.5); try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), s, epsilon); try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon); - sincosq(-1.5, &s, &c); + s, c = sincos_f128(-1.5); try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), s, epsilon); try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon); - sincosq(37.45, &s, &c); + s, c = sincos_f128(37.45); try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), s, epsilon); try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), c, epsilon); - sincosq(89.123, &s, &c); + s, c = sincos_f128(89.123); try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), s, epsilon); try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), c, epsilon); } diff --git a/lib/compiler_rt/sqrt.zig b/lib/compiler_rt/sqrt.zig index 739285af0eaa66af2cf6ed31a3dcc142a708b590..56e43a42fcdd437811ad00d7290de45d5cee82f3 100644 --- a/lib/compiler_rt/sqrt.zig +++ b/lib/compiler_rt/sqrt.zig @@ -28,7 +28,10 @@ comptime { symbol(&sqrtl, "sqrtl"); } -pub fn __sqrth(x: f16) callconv(.c) f16 { +fn __sqrth(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(sqrt_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn sqrt_f16(x: f16) f16 { var ix: u16 = @bitCast(x); var top = ix >> 10; @@ -93,7 +96,10 @@ pub fn __sqrth(x: f16) callconv(.c) f16 { return y; } -pub fn sqrtf(x: f32) callconv(.c) f32 { +fn sqrtf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(sqrt_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn sqrt_f32(x: f32) f32 { var ix: u32 = @bitCast(x); if (ix < @as(u32, @bitCast(@as(f32, 0x1p-126))) or @as(u32, @bitCast(std.math.inf(f32))) <= ix) { @@ -147,7 +153,10 @@ pub fn sqrtf(x: f32) callconv(.c) f32 { return y + t; } -pub fn sqrt(x: f64) callconv(.c) f64 { +fn sqrt(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(sqrt_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn sqrt_f64(x: f64) f64 { var ix: u64 = @bitCast(x); var top = ix >> 52; @@ -284,7 +293,10 @@ pub fn sqrt(x: f64) callconv(.c) f64 { return y; } -pub fn __sqrtx(x: f80) callconv(.c) f80 { +fn __sqrtx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(sqrt_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn sqrt_f80(x: f80) f80 { var ix: u80 = @bitCast(x); var top = ix >> 64; @@ -381,7 +393,10 @@ pub fn __sqrtx(x: f80) callconv(.c) f80 { return y; } -pub fn sqrtq(x: f128) callconv(.c) f128 { +fn sqrtq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(sqrt_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn sqrt_f128(x: f128) f128 { var ix: u128 = @bitCast(x); var top = ix >> 112; @@ -483,10 +498,10 @@ fn _Qp_sqrt(c: *f128, a: *f128) callconv(.c) void { pub fn sqrtl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return sqrt(x), - 80 => return __sqrtx(x), - 128 => return sqrtq(x), - else => @compileError("unreachable"), + 64 => return sqrt_f64(x), + 80 => return sqrt_f80(x), + 128 => return sqrt_f128(x), + else => comptime unreachable, } } @@ -545,187 +560,187 @@ inline fn mul80_tail(a: u80, b: u80) u80 { return alo * blo +% ((ahi * blo) << 40) +% ((alo * bhi) << 40); } -test "__sqrth" { +test "sqrt_f16" { // sqrt(±0) is ±0 - try std.testing.expectEqual(__sqrth(0x0.0p0), 0x0.0p0); - try std.testing.expectEqual(__sqrth(-0x0.0p0), -0x0.0p0); + try std.testing.expectEqual(sqrt_f16(0x0.0p0), 0x0.0p0); + try std.testing.expectEqual(sqrt_f16(-0x0.0p0), -0x0.0p0); // sqrt(+max) is finite - try std.testing.expectEqual(__sqrth(0x1.FFCp15), 0x1.FFCp7); + try std.testing.expectEqual(sqrt_f16(0x1.FFCp15), 0x1.FFCp7); // sqrt(4)=2 - try std.testing.expectEqual(__sqrth(0x1p2), 0x1p1); + try std.testing.expectEqual(sqrt_f16(0x1p2), 0x1p1); // sqrt(x) for x=1, 1±ulp - try std.testing.expectEqual(__sqrth(0x1p0), 0x1p0); - try std.testing.expectEqual(__sqrth(0x1.004p0), 0x1p0); - try std.testing.expectEqual(__sqrth(0x1.FF8p-1), 0x1.FFCp-1); + try std.testing.expectEqual(sqrt_f16(0x1p0), 0x1p0); + try std.testing.expectEqual(sqrt_f16(0x1.004p0), 0x1p0); + try std.testing.expectEqual(sqrt_f16(0x1.FF8p-1), 0x1.FFCp-1); // sqrt(+min) is non-zero - try std.testing.expectEqual(__sqrth(0x1p-14), 0x1p-7); + try std.testing.expectEqual(sqrt_f16(0x1p-14), 0x1p-7); // sqrt(min subnormal) is non-zero - try std.testing.expectEqual(__sqrth(0x0.004p-14), 0x1p-12); + try std.testing.expectEqual(sqrt_f16(0x0.004p-14), 0x1p-12); // sqrt(inf) is inf - try std.testing.expect(math.isInf(__sqrth(math.inf(f16)))); + try std.testing.expect(math.isInf(sqrt_f16(math.inf(f16)))); // sqrt(nan) is nan - try std.testing.expect(math.isNan(__sqrth(math.nan(f16)))); + try std.testing.expect(math.isNan(sqrt_f16(math.nan(f16)))); // sqrt(-ve) is nan - try std.testing.expect(math.isNan(__sqrth(-0x1p-14))); - try std.testing.expect(math.isNan(__sqrth(-0x1p+0))); - try std.testing.expect(math.isNan(__sqrth(-math.inf(f16)))); + try std.testing.expect(math.isNan(sqrt_f16(-0x1p-14))); + try std.testing.expect(math.isNan(sqrt_f16(-0x1p+0))); + try std.testing.expect(math.isNan(sqrt_f16(-math.inf(f16)))); // random arguments - try std.testing.expectEqual(__sqrth(0x1.1p14), 0x1.08p7); - try std.testing.expectEqual(__sqrth(0x1.C9p-12), 0x1.56p-6); - try std.testing.expectEqual(__sqrth(0x1.CE8p-7), 0x1.E68p-4); - try std.testing.expectEqual(__sqrth(0x1.134p-7), 0x1.778p-4); - try std.testing.expectEqual(__sqrth(0x1.E9Cp-10), 0x1.62p-5); - try std.testing.expectEqual(__sqrth(0x1.3Dp9), 0x1.92Cp4); - try std.testing.expectEqual(__sqrth(0x1.AA4p8), 0x1.4A4p4); - try std.testing.expectEqual(__sqrth(0x1.8A8p4), 0x1.3DCp2); - try std.testing.expectEqual(__sqrth(0x1.8Fp-7), 0x1.C4p-4); - try std.testing.expectEqual(__sqrth(0x1.584p-11), 0x1.A3Cp-6); + try std.testing.expectEqual(sqrt_f16(0x1.1p14), 0x1.08p7); + try std.testing.expectEqual(sqrt_f16(0x1.C9p-12), 0x1.56p-6); + try std.testing.expectEqual(sqrt_f16(0x1.CE8p-7), 0x1.E68p-4); + try std.testing.expectEqual(sqrt_f16(0x1.134p-7), 0x1.778p-4); + try std.testing.expectEqual(sqrt_f16(0x1.E9Cp-10), 0x1.62p-5); + try std.testing.expectEqual(sqrt_f16(0x1.3Dp9), 0x1.92Cp4); + try std.testing.expectEqual(sqrt_f16(0x1.AA4p8), 0x1.4A4p4); + try std.testing.expectEqual(sqrt_f16(0x1.8A8p4), 0x1.3DCp2); + try std.testing.expectEqual(sqrt_f16(0x1.8Fp-7), 0x1.C4p-4); + try std.testing.expectEqual(sqrt_f16(0x1.584p-11), 0x1.A3Cp-6); } -test "sqrtf" { +test "sqrt_f32" { // sqrt(±0) is ±0 - try std.testing.expectEqual(sqrtf(0x0.0p0), 0x0.0p0); - try std.testing.expectEqual(sqrtf(-0x0.0p0), -0x0.0p0); + try std.testing.expectEqual(sqrt_f32(0x0.0p0), 0x0.0p0); + try std.testing.expectEqual(sqrt_f32(-0x0.0p0), -0x0.0p0); // sqrt(+max) is finite - try std.testing.expectEqual(sqrtf(0x1.FFFFFEp127), 0x1.FFFFFEp63); + try std.testing.expectEqual(sqrt_f32(0x1.FFFFFEp127), 0x1.FFFFFEp63); // sqrt(4)=2 - try std.testing.expectEqual(sqrtf(0x1p2), 0x1p1); + try std.testing.expectEqual(sqrt_f32(0x1p2), 0x1p1); // sqrt(x) for x=1, 1±ulp - try std.testing.expectEqual(sqrtf(0x1p0), 0x1p0); - try std.testing.expectEqual(sqrtf(0x1.000002p0), 0x1p0); - try std.testing.expectEqual(sqrtf(0x1.FFFFFEp-1), 0x1.FFFFFEp-1); + try std.testing.expectEqual(sqrt_f32(0x1p0), 0x1p0); + try std.testing.expectEqual(sqrt_f32(0x1.000002p0), 0x1p0); + try std.testing.expectEqual(sqrt_f32(0x1.FFFFFEp-1), 0x1.FFFFFEp-1); // sqrt(+min) is non-zero - try std.testing.expectEqual(sqrtf(0x1p-126), 0x1p-63); + try std.testing.expectEqual(sqrt_f32(0x1p-126), 0x1p-63); // sqrt(min subnormal) is non-zero - try std.testing.expectEqual(sqrtf(0x0.000002p-126), 0x1.6a09e6p-75); + try std.testing.expectEqual(sqrt_f32(0x0.000002p-126), 0x1.6a09e6p-75); // sqrt(inf) is inf - try std.testing.expect(math.isInf(sqrtf(math.inf(f32)))); + try std.testing.expect(math.isInf(sqrt_f32(math.inf(f32)))); // sqrt(nan) is nan - try std.testing.expect(math.isNan(sqrtf(math.nan(f32)))); + try std.testing.expect(math.isNan(sqrt_f32(math.nan(f32)))); // sqrt(-ve) is nan - try std.testing.expect(math.isNan(sqrtf(-0x1p-149))); - try std.testing.expect(math.isNan(sqrtf(-0x1p0))); - try std.testing.expect(math.isNan(sqrtf(-math.inf(f32)))); + try std.testing.expect(math.isNan(sqrt_f32(-0x1p-149))); + try std.testing.expect(math.isNan(sqrt_f32(-0x1p0))); + try std.testing.expect(math.isNan(sqrt_f32(-math.inf(f32)))); // random arguments - try std.testing.expectEqual(sqrtf(0x1.4DD57Ep77), 0x1.9D6DA8p38); - try std.testing.expectEqual(sqrtf(0x1.871848p102), 0x1.3C6AFAp51); - try std.testing.expectEqual(sqrtf(0x1.A1D748p-112), 0x1.470EFCp-56); - try std.testing.expectEqual(sqrtf(0x1.E626C2p18), 0x1.60C80Ep9); - try std.testing.expectEqual(sqrtf(0x1.E80E66p-29), 0x1.F3E282p-15); - try std.testing.expectEqual(sqrtf(0x1.B47204p89), 0x1.D8B732p44); - try std.testing.expectEqual(sqrtf(0x1.77F45p15), 0x1.B6BC3Ap7); - try std.testing.expectEqual(sqrtf(0x1.AD5F5p-48), 0x1.4B8A72p-24); - try std.testing.expectEqual(sqrtf(0x1.91A39p-76), 0x1.40A7A8p-38); - try std.testing.expectEqual(sqrtf(0x1.DAE088p79), 0x1.ED16DCp39); + try std.testing.expectEqual(sqrt_f32(0x1.4DD57Ep77), 0x1.9D6DA8p38); + try std.testing.expectEqual(sqrt_f32(0x1.871848p102), 0x1.3C6AFAp51); + try std.testing.expectEqual(sqrt_f32(0x1.A1D748p-112), 0x1.470EFCp-56); + try std.testing.expectEqual(sqrt_f32(0x1.E626C2p18), 0x1.60C80Ep9); + try std.testing.expectEqual(sqrt_f32(0x1.E80E66p-29), 0x1.F3E282p-15); + try std.testing.expectEqual(sqrt_f32(0x1.B47204p89), 0x1.D8B732p44); + try std.testing.expectEqual(sqrt_f32(0x1.77F45p15), 0x1.B6BC3Ap7); + try std.testing.expectEqual(sqrt_f32(0x1.AD5F5p-48), 0x1.4B8A72p-24); + try std.testing.expectEqual(sqrt_f32(0x1.91A39p-76), 0x1.40A7A8p-38); + try std.testing.expectEqual(sqrt_f32(0x1.DAE088p79), 0x1.ED16DCp39); } -test "sqrt" { +test "sqrt_f64" { // sqrt(±0) is ±0 - try std.testing.expectEqual(sqrt(0x0.0p0), 0x0.0p0); - try std.testing.expectEqual(sqrt(-0x0.0p0), -0x0.0p0); + try std.testing.expectEqual(sqrt_f64(0x0.0p0), 0x0.0p0); + try std.testing.expectEqual(sqrt_f64(-0x0.0p0), -0x0.0p0); // sqrt(+max) is finite - try std.testing.expectEqual(sqrt(math.floatMax(f64)), 0x1.FFFFFFFFFFFFFp511); + try std.testing.expectEqual(sqrt_f64(math.floatMax(f64)), 0x1.FFFFFFFFFFFFFp511); // sqrt(4)=2 - try std.testing.expectEqual(sqrt(0x1p2), 0x1p1); + try std.testing.expectEqual(sqrt_f64(0x1p2), 0x1p1); // sqrt(x) for x=1, 1±ulp - try std.testing.expectEqual(sqrt(0x1p0), 0x1p0); - try std.testing.expectEqual(sqrt(0x1p0 + math.floatEps(f64)), 0x1p0); - try std.testing.expectEqual(sqrt(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1); + try std.testing.expectEqual(sqrt_f64(0x1p0), 0x1p0); + try std.testing.expectEqual(sqrt_f64(0x1p0 + math.floatEps(f64)), 0x1p0); + try std.testing.expectEqual(sqrt_f64(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1); // sqrt(+min) is non-zero - try std.testing.expectEqual(sqrt(math.floatMin(f64)), 0x1p-511); + try std.testing.expectEqual(sqrt_f64(math.floatMin(f64)), 0x1p-511); // sqrt(min subnormal) is non-zero - try std.testing.expectEqual(sqrt(math.floatTrueMin(f64)), 0x1p-537); + try std.testing.expectEqual(sqrt_f64(math.floatTrueMin(f64)), 0x1p-537); // sqrt(inf) is inf - try std.testing.expect(math.isInf(sqrt(math.inf(f64)))); + try std.testing.expect(math.isInf(sqrt_f64(math.inf(f64)))); // sqrt(nan) is nan - try std.testing.expect(math.isNan(sqrt(math.nan(f64)))); + try std.testing.expect(math.isNan(sqrt_f64(math.nan(f64)))); // sqrt(-ve) is nan - try std.testing.expect(math.isNan(sqrt(-0x1p-1074))); - try std.testing.expect(math.isNan(sqrt(-0x1p0))); - try std.testing.expect(math.isNan(sqrt(-math.inf(f64)))); + try std.testing.expect(math.isNan(sqrt_f64(-0x1p-1074))); + try std.testing.expect(math.isNan(sqrt_f64(-0x1p0))); + try std.testing.expect(math.isNan(sqrt_f64(-math.inf(f64)))); // random arguments - try std.testing.expectEqual(sqrt(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235); - try std.testing.expectEqual(sqrt(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395); - try std.testing.expectEqual(sqrt(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69); - try std.testing.expectEqual(sqrt(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139); - try std.testing.expectEqual(sqrt(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458); - try std.testing.expectEqual(sqrt(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125); - try std.testing.expectEqual(sqrt(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243); - try std.testing.expectEqual(sqrt(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169); - try std.testing.expectEqual(sqrt(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133); - try std.testing.expectEqual(sqrt(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178); + try std.testing.expectEqual(sqrt_f64(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235); + try std.testing.expectEqual(sqrt_f64(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395); + try std.testing.expectEqual(sqrt_f64(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69); + try std.testing.expectEqual(sqrt_f64(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139); + try std.testing.expectEqual(sqrt_f64(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458); + try std.testing.expectEqual(sqrt_f64(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125); + try std.testing.expectEqual(sqrt_f64(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243); + try std.testing.expectEqual(sqrt_f64(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169); + try std.testing.expectEqual(sqrt_f64(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133); + try std.testing.expectEqual(sqrt_f64(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178); } test "__sqrtx" { // sqrt(±0) is ±0 - try std.testing.expectEqual(__sqrtx(0x0.0p0), 0x0.0p0); - try std.testing.expectEqual(__sqrtx(-0x0.0p0), -0x0.0p0); + try std.testing.expectEqual(sqrt_f80(0x0.0p0), 0x0.0p0); + try std.testing.expectEqual(sqrt_f80(-0x0.0p0), -0x0.0p0); // sqrt(+max) is finite - try std.testing.expectEqual(__sqrtx(math.floatMax(f80)), 0x1.FFFFFFFFFFFFFFFEp8191); + try std.testing.expectEqual(sqrt_f80(math.floatMax(f80)), 0x1.FFFFFFFFFFFFFFFEp8191); // sqrt(4)=2 - try std.testing.expectEqual(__sqrtx(0x1p2), 0x1p1); + try std.testing.expectEqual(sqrt_f80(0x1p2), 0x1p1); // sqrt(x) for x=1, 1±ulp - try std.testing.expectEqual(__sqrtx(0x1p0), 0x1p0); - try std.testing.expectEqual(__sqrtx(0x1p0 + math.floatEps(f80)), 0x1p0); - try std.testing.expectEqual(__sqrtx(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1); + try std.testing.expectEqual(sqrt_f80(0x1p0), 0x1p0); + try std.testing.expectEqual(sqrt_f80(0x1p0 + math.floatEps(f80)), 0x1p0); + try std.testing.expectEqual(sqrt_f80(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1); // sqrt(+min) is non-zero - try std.testing.expectEqual(__sqrtx(math.floatMin(f80)), 0x1p-8191); + try std.testing.expectEqual(sqrt_f80(math.floatMin(f80)), 0x1p-8191); // sqrt(min subnormal) is non-zero - try std.testing.expectEqual(__sqrtx(math.floatTrueMin(f80)), 0x1.6A09E667F3BCC908p-8223); + try std.testing.expectEqual(sqrt_f80(math.floatTrueMin(f80)), 0x1.6A09E667F3BCC908p-8223); // sqrt(inf) is inf - try std.testing.expect(math.isInf(__sqrtx(math.inf(f80)))); + try std.testing.expect(math.isInf(sqrt_f80(math.inf(f80)))); // sqrt(nan) is nan - try std.testing.expect(math.isNan(__sqrtx(math.nan(f80)))); + try std.testing.expect(math.isNan(sqrt_f80(math.nan(f80)))); // sqrt(-ve) is nan - try std.testing.expect(math.isNan(__sqrtx(-0x1p-16442))); - try std.testing.expect(math.isNan(__sqrtx(-0x1p0))); - try std.testing.expect(math.isNan(__sqrtx(-math.inf(f80)))); + try std.testing.expect(math.isNan(sqrt_f80(-0x1p-16442))); + try std.testing.expect(math.isNan(sqrt_f80(-0x1p0))); + try std.testing.expect(math.isNan(sqrt_f80(-math.inf(f80)))); // random arguments - try std.testing.expectEqual(__sqrtx(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741); - try std.testing.expectEqual(__sqrtx(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165); - try std.testing.expectEqual(__sqrtx(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856); - try std.testing.expectEqual(__sqrtx(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432); - try std.testing.expectEqual(__sqrtx(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591); - try std.testing.expectEqual(__sqrtx(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315); - try std.testing.expectEqual(__sqrtx(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517); - try std.testing.expectEqual(__sqrtx(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706); - try std.testing.expectEqual(__sqrtx(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760); - try std.testing.expectEqual(__sqrtx(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685); + try std.testing.expectEqual(sqrt_f80(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741); + try std.testing.expectEqual(sqrt_f80(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165); + try std.testing.expectEqual(sqrt_f80(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856); + try std.testing.expectEqual(sqrt_f80(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432); + try std.testing.expectEqual(sqrt_f80(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591); + try std.testing.expectEqual(sqrt_f80(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315); + try std.testing.expectEqual(sqrt_f80(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517); + try std.testing.expectEqual(sqrt_f80(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706); + try std.testing.expectEqual(sqrt_f80(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760); + try std.testing.expectEqual(sqrt_f80(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685); } -test "sqrtq" { +test "sqrt_f128" { // sqrt(±0) is ±0 - try std.testing.expectEqual(sqrtq(0x0.0p0), 0x0.0p0); - try std.testing.expectEqual(sqrtq(-0x0.0p0), -0x0.0p0); + try std.testing.expectEqual(sqrt_f128(0x0.0p0), 0x0.0p0); + try std.testing.expectEqual(sqrt_f128(-0x0.0p0), -0x0.0p0); // sqrt(+max) is finite - try std.testing.expectEqual(sqrtq(math.floatMax(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp8191); + try std.testing.expectEqual(sqrt_f128(math.floatMax(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp8191); // sqrt(4)=2 - try std.testing.expectEqual(sqrtq(0x1p2), 0x1p1); + try std.testing.expectEqual(sqrt_f128(0x1p2), 0x1p1); // sqrt(x) for x=1, 1±ulp - try std.testing.expectEqual(sqrtq(0x1p0), 0x1p0); - try std.testing.expectEqual(sqrtq(0x1p0 + math.floatEps(f128)), 0x1p0); - try std.testing.expectEqual(sqrtq(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1); + try std.testing.expectEqual(sqrt_f128(0x1p0), 0x1p0); + try std.testing.expectEqual(sqrt_f128(0x1p0 + math.floatEps(f128)), 0x1p0); + try std.testing.expectEqual(sqrt_f128(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1); // sqrt(+min) is non-zero - try std.testing.expectEqual(sqrtq(math.floatMin(f128)), 0x1p-8191); + try std.testing.expectEqual(sqrt_f128(math.floatMin(f128)), 0x1p-8191); // sqrt(min subnormal) is non-zero - try std.testing.expectEqual(sqrtq(math.floatTrueMin(f128)), 0x1p-8247); + try std.testing.expectEqual(sqrt_f128(math.floatTrueMin(f128)), 0x1p-8247); // sqrt(inf) is inf - try std.testing.expect(math.isInf(sqrtq(math.inf(f128)))); + try std.testing.expect(math.isInf(sqrt_f128(math.inf(f128)))); // sqrt(nan) is nan - try std.testing.expect(math.isNan(sqrtq(math.nan(f128)))); + try std.testing.expect(math.isNan(sqrt_f128(math.nan(f128)))); // sqrt(-ve) is nan - try std.testing.expect(math.isNan(sqrtq(-0x1p-16442))); - try std.testing.expect(math.isNan(sqrtq(-0x1p0))); - try std.testing.expect(math.isNan(sqrtq(-math.inf(f128)))); + try std.testing.expect(math.isNan(sqrt_f128(-0x1p-16442))); + try std.testing.expect(math.isNan(sqrt_f128(-0x1p0))); + try std.testing.expect(math.isNan(sqrt_f128(-math.inf(f128)))); // random arguments - try std.testing.expectEqual(sqrtq(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681); - try std.testing.expectEqual(sqrtq(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882); - try std.testing.expectEqual(sqrtq(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812); - try std.testing.expectEqual(sqrtq(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031); - try std.testing.expectEqual(sqrtq(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513); - try std.testing.expectEqual(sqrtq(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917); - try std.testing.expectEqual(sqrtq(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256); - try std.testing.expectEqual(sqrtq(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476); - try std.testing.expectEqual(sqrtq(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446); - try std.testing.expectEqual(sqrtq(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976); + try std.testing.expectEqual(sqrt_f128(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681); + try std.testing.expectEqual(sqrt_f128(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882); + try std.testing.expectEqual(sqrt_f128(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812); + try std.testing.expectEqual(sqrt_f128(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031); + try std.testing.expectEqual(sqrt_f128(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513); + try std.testing.expectEqual(sqrt_f128(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917); + try std.testing.expectEqual(sqrt_f128(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256); + try std.testing.expectEqual(sqrt_f128(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476); + try std.testing.expectEqual(sqrt_f128(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446); + try std.testing.expectEqual(sqrt_f128(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976); } diff --git a/lib/compiler_rt/subdf3.zig b/lib/compiler_rt/subdf3.zig deleted file mode 100644 index 4d00a7f03ae71c4f9bf2ffecbcd1123216dff6b6..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/subdf3.zig +++ /dev/null @@ -1,24 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const addf3 = @import("./addf3.zig").addf3; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dsub, "__aeabi_dsub"); - } else { - symbol(&__subdf3, "__subdf3"); - } -} - -fn __subdf3(a: f64, b: f64) callconv(.c) f64 { - return sub(a, b); -} - -fn __aeabi_dsub(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { - return sub(a, b); -} - -inline fn sub(a: f64, b: f64) f64 { - const neg_b = @as(f64, @bitCast(@as(u64, @bitCast(b)) ^ (@as(u64, 1) << 63))); - return addf3(f64, a, neg_b); -} diff --git a/lib/compiler_rt/subhf3.zig b/lib/compiler_rt/subhf3.zig deleted file mode 100644 index 258401d2957a6d3aafcd0aa02c6de63ca0211952..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/subhf3.zig +++ /dev/null @@ -1,12 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - symbol(&__subhf3, "__subhf3"); -} - -fn __subhf3(a: f16, b: f16) callconv(.c) f16 { - const neg_b = @as(f16, @bitCast(@as(u16, @bitCast(b)) ^ (@as(u16, 1) << 15))); - return addf3(f16, a, neg_b); -} diff --git a/lib/compiler_rt/subsf3.zig b/lib/compiler_rt/subsf3.zig deleted file mode 100644 index 94d47220166aff38656455d3f50fa2b061df3f61..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/subsf3.zig +++ /dev/null @@ -1,24 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_fsub, "__aeabi_fsub"); - } else { - symbol(&__subsf3, "__subsf3"); - } -} - -fn __subsf3(a: f32, b: f32) callconv(.c) f32 { - return sub(a, b); -} - -fn __aeabi_fsub(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { - return sub(a, b); -} - -inline fn sub(a: f32, b: f32) f32 { - const neg_b = @as(f32, @bitCast(@as(u32, @bitCast(b)) ^ (@as(u32, 1) << 31))); - return addf3(f32, a, neg_b); -} diff --git a/lib/compiler_rt/subtf3.zig b/lib/compiler_rt/subtf3.zig deleted file mode 100644 index 46580f1728d70b85c83259dce39cb860e46ac10e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/subtf3.zig +++ /dev/null @@ -1,27 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__subtf3, "__subkf3"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_sub, "_Qp_sub"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__subtf3, "_Q_sub"); - } - symbol(&__subtf3, "__subtf3"); -} - -pub fn __subtf3(a: f128, b: f128) callconv(.c) f128 { - return sub(a, b); -} - -fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { - c.* = sub(a.*, b.*); -} - -inline fn sub(a: f128, b: f128) f128 { - const neg_b = @as(f128, @bitCast(@as(u128, @bitCast(b)) ^ (@as(u128, 1) << 127))); - return addf3(f128, a, neg_b); -} diff --git a/lib/compiler_rt/subvdi3.zig b/lib/compiler_rt/subvdi3.zig index 62bb1b406835c1a72588cd9c1d08705f6663bbd2..2fedc77ee2c07fe42ded5f5da11191a41fc17a0f 100644 --- a/lib/compiler_rt/subvdi3.zig +++ b/lib/compiler_rt/subvdi3.zig @@ -1,5 +1,6 @@ -const symbol = @import("../compiler_rt.zig").symbol; const testing = @import("std").testing; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; comptime { symbol(&__subvdi3, "__subvdi3"); @@ -9,7 +10,7 @@ pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 { const sum = a -% b; // Overflow occurred iff the operands have opposite signs, and the sign of the // sum is the opposite of the lhs sign. - if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow"); + if (((a ^ b) & (sum ^ a)) < 0) @panic("integer overflow"); return sum; } diff --git a/lib/compiler_rt/subvsi3.zig b/lib/compiler_rt/subvsi3.zig index 0744585770237d034f35947a927155efe23eaef9..0d2a47e7cbfa8beb25cbeedc1809e549481db97e 100644 --- a/lib/compiler_rt/subvsi3.zig +++ b/lib/compiler_rt/subvsi3.zig @@ -10,7 +10,7 @@ pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 { const sum = a -% b; // Overflow occurred iff the operands have opposite signs, and the sign of the // sum is the opposite of the lhs sign. - if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow"); + if (((a ^ b) & (sum ^ a)) < 0) @panic("integer overflow"); return sum; } diff --git a/lib/compiler_rt/subxf3.zig b/lib/compiler_rt/subxf3.zig deleted file mode 100644 index 1c2dcd65429596c975937432aae6eaefb89c2f72..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/subxf3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const std = @import("std"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__subxf3, "__subxf3"); -} - -fn __subxf3(a: f80, b: f80) callconv(.c) f80 { - var b_rep = std.math.F80.fromFloat(b); - b_rep.exp ^= 0x8000; - const neg_b = b_rep.toFloat(); - return a + neg_b; -} diff --git a/lib/compiler_rt/tan.zig b/lib/compiler_rt/tan.zig index 6cbc3cb098acd1f6a719451d103574b935a8bb2c..038ac85b6dc2dd9e7d742936bd0df3095dc4b9ec 100644 --- a/lib/compiler_rt/tan.zig +++ b/lib/compiler_rt/tan.zig @@ -21,13 +21,13 @@ const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; const arch = builtin.cpu.arch; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { - symbol(&tanh, "__tanh"); + symbol(&__tanh, "__tanh"); symbol(&tanf, "tanf"); symbol(&tan, "tan"); - symbol(&tanx, "__tanx"); + symbol(&__tanx, "__tanx"); if (compiler_rt.want_ppc_abi) { symbol(&tanq, "tanf128"); } @@ -35,12 +35,18 @@ comptime { symbol(&tanl, "tanl"); } -pub fn tanh(x: f16) callconv(.c) f16 { +fn __tanh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(tan_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn tan_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(tanf(x)); + return @floatCast(tan_f32(x)); } -pub fn tanf(x: f32) callconv(.c) f32 { +fn tanf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(tan_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn tan_f32(x: f32) f32 { // Small multiples of pi/2 rounded to double precision. const t1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 const t2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 @@ -90,7 +96,10 @@ pub fn tanf(x: f32) callconv(.c) f32 { return kernel.tandf(y, n & 1 != 0); } -pub fn tan(x: f64) callconv(.c) f64 { +fn tan(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(tan_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn tan_f64(x: f64) f64 { var ix = @as(u64, @bitCast(x)) >> 32; ix &= 0x7fffffff; @@ -120,7 +129,10 @@ pub fn tan(x: f64) callconv(.c) f64 { return kernel.tan(y[0], y[1], n & 1 != 0); } -pub fn tanx(x: f80) callconv(.c) f80 { +fn __tanx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(tan_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn tan_f80(x: f80) f80 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -141,7 +153,10 @@ pub fn tanx(x: f80) callconv(.c) f80 { return kernel.tanx(y[0], y[1], n & 1); } -pub fn tanq(x: f128) callconv(.c) f128 { +fn tanq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(tan_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn tan_f128(x: f128) f128 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -164,18 +179,21 @@ pub fn tanq(x: f128) callconv(.c) f128 { pub fn tanl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return tan(x), - 80 => return tanx(x), - 128 => return tanq(x), - else => @compileError("unreachable"), + 64 => return tan_f64(x), + 80 => return tan_f80(x), + 128 => return tan_f128(x), + else => comptime unreachable, } } fn testTanNormal(comptime T: type) !void { const f = switch (T) { - f32 => tanf, - f64 => tan, - else => @compileError("unimplemented"), + f16 => tan_f16, + f32 => tan_f32, + f64 => tan_f64, + f80 => tan_f80, + f128 => tan_f128, + else => comptime unreachable, }; const epsilon = 0.00001; @@ -189,11 +207,12 @@ fn testTanNormal(comptime T: type) !void { fn testTanSpecial(comptime T: type) !void { const f = switch (T) { - f32 => tanf, - f64 => tan, - f80 => tanx, - f128 => tanq, - else => @compileError("unimplemented"), + f16 => tan_f16, + f32 => tan_f32, + f64 => tan_f64, + f80 => tan_f80, + f128 => tan_f128, + else => comptime unreachable, }; try expect(math.isPositiveZero(f(0.0))); @@ -214,23 +233,23 @@ test "tan64.normal" { test "tan80.normal" { const epsilon = math.floatEps(f80); - try expectApproxEqAbs(@as(f80, 0.0), tanx(0.0), epsilon); - try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tanx(0.2), epsilon); - try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tanx(0.8923), epsilon); - try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tanx(1.5), epsilon); - try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tanx(37.45), epsilon); - try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tanx(89.123), epsilon); + try expectApproxEqAbs(@as(f80, 0.0), tan_f80(0.0), epsilon); + try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tan_f80(0.2), epsilon); + try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tan_f80(0.8923), epsilon); + try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tan_f80(1.5), epsilon); + try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tan_f80(37.45), epsilon); + try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tan_f80(89.123), epsilon); } test "tan128.normal" { const epsilon = math.floatEps(f128); - try expectApproxEqAbs(@as(f128, 0.0), tanq(0.0), epsilon); - try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tanq(0.2), epsilon); - try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tanq(0.8923), epsilon); - try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tanq(1.5), epsilon); - try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tanq(37.45), epsilon); - try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tanq(89.123), epsilon); + try expectApproxEqAbs(@as(f128, 0.0), tan_f128(0.0), epsilon); + try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tan_f128(0.2), epsilon); + try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tan_f128(0.8923), epsilon); + try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tan_f128(1.5), epsilon); + try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tan_f128(37.45), epsilon); + try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tan_f128(89.123), epsilon); } test "tan32.special" { diff --git a/lib/compiler_rt/trunc.zig b/lib/compiler_rt/trunc.zig index aa2eb560dfd8035f14aa07c8e51c5c117daad042..0653178b54b50256e43168d377f59377f34dcc14 100644 --- a/lib/compiler_rt/trunc.zig +++ b/lib/compiler_rt/trunc.zig @@ -24,12 +24,18 @@ comptime { symbol(&truncl, "truncl"); } -pub fn __trunch(x: f16) callconv(.c) f16 { +fn __trunch(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(trunc_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn trunc_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(truncf(x)); + return @floatCast(trunc_f32(x)); } -pub fn truncf(x: f32) callconv(.c) f32 { +fn truncf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(trunc_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn trunc_f32(x: f32) f32 { const u: u32 = @bitCast(x); var e = @as(i32, @intCast(((u >> 23) & 0xFF))) - 0x7F + 9; var m: u32 = undefined; @@ -50,7 +56,10 @@ pub fn truncf(x: f32) callconv(.c) f32 { } } -pub fn trunc(x: f64) callconv(.c) f64 { +fn trunc(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(trunc_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn trunc_f64(x: f64) f64 { const u: u64 = @bitCast(x); var e = @as(i32, @intCast(((u >> 52) & 0x7FF))) - 0x3FF + 12; var m: u64 = undefined; @@ -71,12 +80,18 @@ pub fn trunc(x: f64) callconv(.c) f64 { } } -pub fn __truncx(x: f80) callconv(.c) f80 { +fn __truncx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(trunc_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn trunc_f80(x: f80) f80 { // TODO: more efficient implementation - return @floatCast(truncq(x)); + return @floatCast(trunc_f128(x)); } -pub fn truncq(x: f128) callconv(.c) f128 { +fn truncq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(trunc_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn trunc_f128(x: f128) f128 { const u: u128 = @bitCast(x); var e = @as(i32, @intCast(((u >> 112) & 0x7FFF))) - 0x3FFF + 16; var m: u128 = undefined; @@ -99,51 +114,69 @@ pub fn truncq(x: f128) callconv(.c) f128 { pub fn truncl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return trunc(x), - 80 => return __truncx(x), - 128 => return truncq(x), - else => @compileError("unreachable"), + 64 => return trunc_f64(x), + 80 => return trunc_f80(x), + 128 => return trunc_f128(x), + else => comptime unreachable, } } -test "trunc32" { - try expect(truncf(1.3) == 1.0); - try expect(truncf(-1.3) == -1.0); - try expect(truncf(0.2) == 0.0); +test trunc_f16 { + try expect(trunc_f16(1.3) == 1.0); + try expect(trunc_f16(-1.3) == -1.0); + try expect(math.isPositiveZero(trunc_f16(0.2))); + try expect(math.isNegativeZero(trunc_f16(-0.2))); + try expect(math.isPositiveZero(trunc_f16(0.0))); + try expect(math.isNegativeZero(trunc_f16(-0.0))); + try expect(math.isPositiveInf(trunc_f16(math.inf(f32)))); + try expect(math.isNegativeInf(trunc_f16(-math.inf(f32)))); + try expect(math.isNan(trunc_f16(math.nan(f32)))); } -test "trunc64" { - try expect(trunc(1.3) == 1.0); - try expect(trunc(-1.3) == -1.0); - try expect(trunc(0.2) == 0.0); +test trunc_f32 { + try expect(trunc_f32(1.3) == 1.0); + try expect(trunc_f32(-1.3) == -1.0); + try expect(math.isPositiveZero(trunc_f32(0.2))); + try expect(math.isNegativeZero(trunc_f32(-0.2))); + try expect(math.isPositiveZero(trunc_f32(0.0))); + try expect(math.isNegativeZero(trunc_f32(-0.0))); + try expect(math.isPositiveInf(trunc_f32(math.inf(f32)))); + try expect(math.isNegativeInf(trunc_f32(-math.inf(f32)))); + try expect(math.isNan(trunc_f32(math.nan(f32)))); } -test "trunc128" { - try expect(truncq(1.3) == 1.0); - try expect(truncq(-1.3) == -1.0); - try expect(truncq(0.2) == 0.0); +test trunc_f64 { + try expect(trunc_f64(1.3) == 1.0); + try expect(trunc_f64(-1.3) == -1.0); + try expect(math.isPositiveZero(trunc_f64(0.2))); + try expect(math.isNegativeZero(trunc_f64(-0.2))); + try expect(math.isPositiveZero(trunc_f64(0.0))); + try expect(math.isNegativeZero(trunc_f64(-0.0))); + try expect(math.isPositiveInf(trunc_f64(math.inf(f64)))); + try expect(math.isNegativeInf(trunc_f64(-math.inf(f64)))); + try expect(math.isNan(trunc_f64(math.nan(f64)))); } -test "trunc32.special" { - try expect(truncf(0.0) == 0.0); // 0x3F800000 - try expect(truncf(-0.0) == -0.0); - try expect(math.isPositiveInf(truncf(math.inf(f32)))); - try expect(math.isNegativeInf(truncf(-math.inf(f32)))); - try expect(math.isNan(truncf(math.nan(f32)))); +test trunc_f80 { + try expect(trunc_f80(1.3) == 1.0); + try expect(trunc_f80(-1.3) == -1.0); + try expect(math.isPositiveZero(trunc_f80(0.2))); + try expect(math.isNegativeZero(trunc_f80(-0.2))); + try expect(math.isPositiveZero(trunc_f80(0.0))); + try expect(math.isNegativeZero(trunc_f80(-0.0))); + try expect(math.isPositiveInf(trunc_f80(math.inf(f64)))); + try expect(math.isNegativeInf(trunc_f80(-math.inf(f64)))); + try expect(math.isNan(trunc_f80(math.nan(f64)))); } -test "trunc64.special" { - try expect(trunc(0.0) == 0.0); - try expect(trunc(-0.0) == -0.0); - try expect(math.isPositiveInf(trunc(math.inf(f64)))); - try expect(math.isNegativeInf(trunc(-math.inf(f64)))); - try expect(math.isNan(trunc(math.nan(f64)))); -} - -test "trunc128.special" { - try expect(truncq(0.0) == 0.0); - try expect(truncq(-0.0) == -0.0); - try expect(math.isPositiveInf(truncq(math.inf(f128)))); - try expect(math.isNegativeInf(truncq(-math.inf(f128)))); - try expect(math.isNan(truncq(math.nan(f128)))); +test trunc_f128 { + try expect(trunc_f128(1.3) == 1.0); + try expect(trunc_f128(-1.3) == -1.0); + try expect(math.isPositiveZero(trunc_f128(0.2))); + try expect(math.isNegativeZero(trunc_f128(-0.2))); + try expect(math.isPositiveZero(trunc_f128(0.0))); + try expect(math.isNegativeZero(trunc_f128(-0.0))); + try expect(math.isPositiveInf(trunc_f128(math.inf(f128)))); + try expect(math.isNegativeInf(trunc_f128(-math.inf(f128)))); + try expect(math.isNan(trunc_f128(math.nan(f128)))); } diff --git a/lib/compiler_rt/truncdfhf2.zig b/lib/compiler_rt/truncdfhf2.zig deleted file mode 100644 index e01e1877633eee7077c64ef42e6cde56a0a17aee..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncdfhf2.zig +++ /dev/null @@ -1,18 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const truncf = @import("./truncf.zig").truncf; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2h, "__aeabi_d2h"); - } - symbol(&__truncdfhf2, "__truncdfhf2"); -} - -pub fn __truncdfhf2(a: f64) callconv(.c) compiler_rt.F16T(f64) { - return @bitCast(truncf(f16, f64, a)); -} - -fn __aeabi_d2h(a: f64) callconv(.{ .arm_aapcs = .{} }) u16 { - return @bitCast(truncf(f16, f64, a)); -} diff --git a/lib/compiler_rt/truncdfsf2.zig b/lib/compiler_rt/truncdfsf2.zig deleted file mode 100644 index f1bada18449130344f213ad0f8272794d38f23bf..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncdfsf2.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const truncf = @import("./truncf.zig").truncf; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2f, "__aeabi_d2f"); - } else { - symbol(&__truncdfsf2, "__truncdfsf2"); - } -} - -pub fn __truncdfsf2(a: f64) callconv(.c) f32 { - return truncf(f32, f64, a); -} - -fn __aeabi_d2f(a: f64) callconv(.{ .arm_aapcs = .{} }) f32 { - return truncf(f32, f64, a); -} diff --git a/lib/compiler_rt/truncf.zig b/lib/compiler_rt/truncf.zig index a03f3b67113028ba8a69c4fc72023b9d26f87e23..9a1cb491e27bc214a2c5c7a4a91f8f236efae1ef 100644 --- a/lib/compiler_rt/truncf.zig +++ b/lib/compiler_rt/truncf.zig @@ -1,6 +1,204 @@ const std = @import("std"); -pub inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; + +comptime { + if (compiler_rt.want_aeabi) { + if (compiler_rt.gnu_f16_abi) { + symbol(&__aeabi_f2h, "__gnu_f2h_ieee"); + } else { + symbol(&__aeabi_f2h, "__aeabi_f2h"); + } + symbol(&__aeabi_d2h, "__aeabi_d2h"); + } else if (compiler_rt.gnu_f16_abi) { + symbol(&__truncsfhf2, "__gnu_f2h_ieee"); + } + symbol(&__truncsfhf2, "__truncsfhf2"); + symbol(&__truncdfhf2, "__truncdfhf2"); + symbol(&__truncxfhf2, "__truncxfhf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__trunctfhf2, "__trunckfhf2"); + } else { + symbol(&__trunctfhf2, "__trunctfhf2"); + } + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_d2f, "__aeabi_d2f"); + } else { + symbol(&__truncdfsf2, "__truncdfsf2"); + } + symbol(&__truncxfsf2, "__truncxfsf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__trunctfsf2, "__trunckfsf2"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_qtos, "_Qp_qtos"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__trunctfsf2, "_Q_qtos"); + } else { + symbol(&__trunctfsf2, "__trunctfsf2"); + } + + symbol(&__truncxfdf2, "__truncxfdf2"); + + if (compiler_rt.want_ppc_abi) { + symbol(&__trunctfdf2, "__trunckfdf2"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_qtod, "_Qp_qtod"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__trunctfdf2, "_Q_qtod"); + } else { + symbol(&__trunctfdf2, "__trunctfdf2"); + } + + if (compiler_rt.want_ppc_abi) { + symbol(&__trunctfxf2, "__trunckfxf2"); + } else { + symbol(&__trunctfxf2, "__trunctfxf2"); + } +} + +fn __truncsfhf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f16Conv(f32).Abi { + return compiler_rt.f16Conv(f32).toAbi(f16_floatCast_f32(compiler_rt.f32.fromAbi(a))); +} +fn __aeabi_f2h(a: u32) callconv(.{ .arm_aapcs = .{} }) u16 { + return @bitCast(f16_floatCast_f32(@bitCast(a))); +} +pub fn f16_floatCast_f32(a: f32) f16 { + return truncf(f16, f32, a); +} + +fn __truncdfhf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f16Conv(f64).Abi { + return compiler_rt.f16Conv(f64).toAbi(f16_floatCast_f64(compiler_rt.f64.fromAbi(a))); +} +fn __aeabi_d2h(a: u64) callconv(.{ .arm_aapcs = .{} }) u16 { + return @bitCast(f16_floatCast_f64(@bitCast(a))); +} +pub fn f16_floatCast_f64(a: f64) f16 { + return truncf(f16, f64, a); +} + +fn __truncxfhf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f16Conv(f80).Abi { + return compiler_rt.f16Conv(f80).toAbi(f16_floatCast_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn f16_floatCast_f80(a: f80) f16 { + return trunc_f80(f16, a); +} + +fn __trunctfhf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f16Conv(f128).Abi { + return compiler_rt.f16Conv(f128).toAbi(f16_floatCast_f128(compiler_rt.f128.fromAbi(a))); +} +pub fn f16_floatCast_f128(a: f128) f16 { + return truncf(f16, f128, a); +} + +fn __truncdfsf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatCast_f64(compiler_rt.f64.fromAbi(a))); +} +fn __aeabi_d2f(a: f64) callconv(.{ .arm_aapcs = .{} }) f32 { + return f32_floatCast_f64(a); +} +pub fn f32_floatCast_f64(a: f64) f32 { + return truncf(f32, f64, a); +} + +fn __truncxfsf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatCast_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn f32_floatCast_f80(a: f80) f32 { + return trunc_f80(f32, a); +} + +fn __trunctfsf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatCast_f128(compiler_rt.f128.fromAbi(a))); +} +fn _Qp_qtos(a: *const f128) callconv(.c) f32 { + return f32_floatCast_f128(a.*); +} +pub fn f32_floatCast_f128(a: f128) f32 { + return truncf(f32, f128, a); +} + +fn __truncxfdf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatCast_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn f64_floatCast_f80(a: f80) f64 { + return trunc_f80(f64, a); +} + +fn __trunctfdf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatCast_f128(compiler_rt.f128.fromAbi(a))); +} +fn _Qp_qtod(a: *const f128) callconv(.c) f64 { + return f64_floatCast_f128(a.*); +} +pub fn f64_floatCast_f128(a: f128) f64 { + return truncf(f64, f128, a); +} + +fn __trunctfxf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatCast_f128(compiler_rt.f128.fromAbi(a))); +} +pub fn f80_floatCast_f128(a: f128) f80 { + const src_sig_bits = std.math.floatMantissaBits(f128); + const dst_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit + + // Various constants whose values follow from the type parameters. + // Any reasonable optimizer will fold and propagate all of these. + const src_bits = @typeInfo(f128).float.bits; + const src_exp_bits = src_bits - src_sig_bits - 1; + const src_inf_exp = 0x7FFF; + + const src_inf = src_inf_exp << src_sig_bits; + const src_sign_mask = 1 << (src_sig_bits + src_exp_bits); + const src_abs_mask = src_sign_mask - 1; + const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1; + const halfway = 1 << (src_sig_bits - dst_sig_bits - 1); + + // Break a into a sign and representation of the absolute value + const a_rep: u128 = @bitCast(a); + const a_abs = a_rep & src_abs_mask; + const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0; + const integer_bit = 1 << 63; + + var res: std.math.F80 = undefined; + + if (a_abs > src_inf) { + // a is NaN. + // Conjure the result by beginning with infinity, setting the qNaN + // bit and inserting the (truncated) trailing NaN field. + res.exp = 0x7fff; + res.fraction = 0x8000000000000000; + res.fraction |= @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))); + } else { + // The exponent of a is within the range of normal numbers in the + // destination format. We can convert by simply right-shifting with + // rounding, adding the explicit integer bit, and adjusting the exponent + res.fraction = @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))) | integer_bit; + res.exp = @truncate(a_abs >> src_sig_bits); + + const round_bits = a_abs & round_mask; + if (round_bits > halfway) { + // Round to nearest + const ov = @addWithOverflow(res.fraction, 1); + res.fraction = ov[0]; + res.exp += ov[1]; + res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry + } else if (round_bits == halfway) { + // Ties to even + const ov = @addWithOverflow(res.fraction, res.fraction & 1); + res.fraction = ov[0]; + res.exp += ov[1]; + res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry + } + if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals + } + + res.exp |= sign; + return res.toFloat(); +} + +inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits); const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits); const srcSigBits = std.math.floatMantissaBits(src_t); @@ -99,7 +297,7 @@ pub inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t return @bitCast(result); } -pub inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t { +inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t { const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits); const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit const dst_sig_bits = std.math.floatMantissaBits(dst_t); diff --git a/lib/compiler_rt/truncf_test.zig b/lib/compiler_rt/truncf_test.zig index 8da6fe0a19456e9898f32ea4dec4c7b8ccb221b4..6595c47b52d8f868d019c1728ae3d57735e12323 100644 --- a/lib/compiler_rt/truncf_test.zig +++ b/lib/compiler_rt/truncf_test.zig @@ -1,79 +1,82 @@ const std = @import("std"); const testing = std.testing; -const __truncsfhf2 = @import("truncsfhf2.zig").__truncsfhf2; -const __truncdfhf2 = @import("truncdfhf2.zig").__truncdfhf2; -const __truncdfsf2 = @import("truncdfsf2.zig").__truncdfsf2; -const __trunctfhf2 = @import("trunctfhf2.zig").__trunctfhf2; -const __trunctfsf2 = @import("trunctfsf2.zig").__trunctfsf2; -const __trunctfdf2 = @import("trunctfdf2.zig").__trunctfdf2; -const __trunctfxf2 = @import("trunctfxf2.zig").__trunctfxf2; - -fn test__truncsfhf2(a: u32, expected: u16) !void { - const actual: u16 = @bitCast(__truncsfhf2(@bitCast(a))); - - if (actual == expected) { - return; - } - - return error.TestFailure; +const impl = @import("truncf.zig"); + +const f16_floatCast_f32 = impl.f16_floatCast_f32; +const f16_floatCast_f64 = impl.f16_floatCast_f64; +const f16_floatCast_f80 = impl.f16_floatCast_f80; +const f16_floatCast_f128 = impl.f16_floatCast_f128; + +const f32_floatCast_f64 = impl.f32_floatCast_f64; +const f32_floatCast_f80 = impl.f32_floatCast_f80; +const f32_floatCast_f128 = impl.f32_floatCast_f128; + +const f64_floatCast_f80 = impl.f64_floatCast_f80; +const f64_floatCast_f128 = impl.f64_floatCast_f128; + +const f80_floatCast_f128 = impl.f80_floatCast_f128; + +fn test_f16_floatCast_f32(a: u32, expected: u16) !void { + const actual: u16 = @bitCast(f16_floatCast_f32(@bitCast(a))); + try testing.expect(actual == expected); } -test "truncsfhf2" { - try test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN - try test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN +test f16_floatCast_f32 { + try test_f16_floatCast_f32(0x7fc00000, 0x7e00); // qNaN + try test_f16_floatCast_f32(0x7fe00000, 0x7f00); // sNaN - try test__truncsfhf2(0, 0); // 0 - try test__truncsfhf2(0x80000000, 0x8000); // -0 + try test_f16_floatCast_f32(0, 0); // 0 + try test_f16_floatCast_f32(0x80000000, 0x8000); // -0 - try test__truncsfhf2(0x7f800000, 0x7c00); // inf - try test__truncsfhf2(0xff800000, 0xfc00); // -inf + try test_f16_floatCast_f32(0x7f800000, 0x7c00); // inf + try test_f16_floatCast_f32(0xff800000, 0xfc00); // -inf - try test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf - try test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf + try test_f16_floatCast_f32(0x477ff000, 0x7c00); // 65520 -> inf + try test_f16_floatCast_f32(0xc77ff000, 0xfc00); // -65520 -> -inf - try test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf - try test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf + try test_f16_floatCast_f32(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf + try test_f16_floatCast_f32(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf - try test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-14 - try test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-14 + try test_f16_floatCast_f32(0x38800000, 0x0400); // normal (min), 2**-14 + try test_f16_floatCast_f32(0xb8800000, 0x8400); // normal (min), -2**-14 - try test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 65504 - try test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -65504 + try test_f16_floatCast_f32(0x477fe000, 0x7bff); // normal (max), 65504 + try test_f16_floatCast_f32(0xc77fe000, 0xfbff); // normal (max), -65504 - try test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 65504 - try test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -65504 + try test_f16_floatCast_f32(0x477fe100, 0x7bff); // normal, 65505 -> 65504 + try test_f16_floatCast_f32(0xc77fe100, 0xfbff); // normal, -65505 -> -65504 - try test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 65504 - try test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -65504 + try test_f16_floatCast_f32(0x477fef00, 0x7bff); // normal, 65519 -> 65504 + try test_f16_floatCast_f32(0xc77fef00, 0xfbff); // normal, -65519 -> -65504 - try test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-10 - try test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-10 + try test_f16_floatCast_f32(0x3f802000, 0x3c01); // normal, 1 + 2**-10 + try test_f16_floatCast_f32(0xbf802000, 0xbc01); // normal, -1 - 2**-10 - try test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/3 - try test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/3 + try test_f16_floatCast_f32(0x3eaaa000, 0x3555); // normal, approx. 1/3 + try test_f16_floatCast_f32(0xbeaaa000, 0xb555); // normal, approx. -1/3 - try test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.1415926535 - try test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.1415926535 + try test_f16_floatCast_f32(0x40490fdb, 0x4248); // normal, 3.1415926535 + try test_f16_floatCast_f32(0xc0490fdb, 0xc248); // normal, -3.1415926535 - try test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12 + try test_f16_floatCast_f32(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12 - try test__truncsfhf2(0x3f800000, 0x3c00); // normal, 1 - try test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-14 + try test_f16_floatCast_f32(0x3f800000, 0x3c00); // normal, 1 + try test_f16_floatCast_f32(0x38800000, 0x0400); // normal, 0x1.0p-14 - try test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-24 - try test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-24 + try test_f16_floatCast_f32(0x33800000, 0x0001); // denormal (min), 2**-24 + try test_f16_floatCast_f32(0xb3800000, 0x8001); // denormal (min), -2**-24 - try test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24 - try test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24 + try test_f16_floatCast_f32(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24 + try test_f16_floatCast_f32(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24 - try test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-20 - try test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24 - try test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero + try test_f16_floatCast_f32(0x35800000, 0x0010); // denormal, 0x1.0p-20 + try test_f16_floatCast_f32(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24 + try test_f16_floatCast_f32(0x33000000, 0x0000); // 0x1.0p-25 -> zero } -fn test__truncdfhf2(a: f64, expected: u16) void { - const rep: u16 = @bitCast(__truncdfhf2(a)); +fn test_f16_floatCast_f64(a: f64, expected: u16) !void { + const rep: u16 = @bitCast(f16_floatCast_f64(a)); if (rep == expected) { return; @@ -84,62 +87,56 @@ fn test__truncdfhf2(a: f64, expected: u16) void { return; } } - - @panic("__truncdfhf2 test failure"); + return error.TestFailure; } -fn test__truncdfhf2_raw(a: u64, expected: u16) void { - const actual: u16 = @bitCast(__truncdfhf2(@bitCast(a))); - - if (actual == expected) { - return; - } - - @panic("__truncdfhf2 test failure"); +fn test_f16_floatCast_f64_raw(a: u64, expected: u16) !void { + const actual: u16 = @bitCast(f16_floatCast_f64(@bitCast(a))); + try testing.expect(actual == expected); } -test "truncdfhf2" { - test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN - test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN +test f16_floatCast_f64 { + try test_f16_floatCast_f64_raw(0x7ff8000000000000, 0x7e00); // qNaN + try test_f16_floatCast_f64_raw(0x7ff0000000008000, 0x7e00); // NaN - test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf - test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf + try test_f16_floatCast_f64_raw(0x7ff0000000000000, 0x7c00); //inf + try test_f16_floatCast_f64_raw(0xfff0000000000000, 0xfc00); // -inf - test__truncdfhf2(0.0, 0x0); // zero - test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero + try test_f16_floatCast_f64(0.0, 0x0); // zero + try test_f16_floatCast_f64_raw(0x80000000 << 32, 0x8000); // -zero - test__truncdfhf2(3.1415926535, 0x4248); - test__truncdfhf2(-3.1415926535, 0xc248); + try test_f16_floatCast_f64(3.1415926535, 0x4248); + try test_f16_floatCast_f64(-3.1415926535, 0xc248); - test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00); - test__truncdfhf2(0x1.987124876876324p+12, 0x6e62); - test__truncdfhf2(0x1.0p+0, 0x3c00); - test__truncdfhf2(0x1.0p-14, 0x0400); + try test_f16_floatCast_f64(0x1.987124876876324p+1000, 0x7c00); + try test_f16_floatCast_f64(0x1.987124876876324p+12, 0x6e62); + try test_f16_floatCast_f64(0x1.0p+0, 0x3c00); + try test_f16_floatCast_f64(0x1.0p-14, 0x0400); // denormal - test__truncdfhf2(0x1.0p-20, 0x0010); - test__truncdfhf2(0x1.0p-24, 0x0001); - test__truncdfhf2(-0x1.0p-24, 0x8001); - test__truncdfhf2(0x1.5p-25, 0x0001); + try test_f16_floatCast_f64(0x1.0p-20, 0x0010); + try test_f16_floatCast_f64(0x1.0p-24, 0x0001); + try test_f16_floatCast_f64(-0x1.0p-24, 0x8001); + try test_f16_floatCast_f64(0x1.5p-25, 0x0001); // and back to zero - test__truncdfhf2(0x1.0p-25, 0x0000); - test__truncdfhf2(-0x1.0p-25, 0x8000); + try test_f16_floatCast_f64(0x1.0p-25, 0x0000); + try test_f16_floatCast_f64(-0x1.0p-25, 0x8000); // max (precise) - test__truncdfhf2(65504.0, 0x7bff); + try test_f16_floatCast_f64(65504.0, 0x7bff); // max (rounded) - test__truncdfhf2(65519.0, 0x7bff); + try test_f16_floatCast_f64(65519.0, 0x7bff); // max (to +inf) - test__truncdfhf2(65520.0, 0x7c00); - test__truncdfhf2(-65520.0, 0xfc00); - test__truncdfhf2(65536.0, 0x7c00); + try test_f16_floatCast_f64(65520.0, 0x7c00); + try test_f16_floatCast_f64(-65520.0, 0xfc00); + try test_f16_floatCast_f64(65536.0, 0x7c00); } -fn test__trunctfsf2(a: f128, expected: u32) void { - const x = __trunctfsf2(a); +fn test_f32_floatCast_f128(a: f128, expected: u32) !void { + const x = f32_floatCast_f128(a); const rep: u32 = @bitCast(x); if (rep == expected) { @@ -151,28 +148,27 @@ fn test__trunctfsf2(a: f128, expected: u32) void { return; } } - - @panic("__trunctfsf2 test failure"); + return error.TestFailure; } -test "trunctfsf2" { +test f32_floatCast_f128 { // qnan - test__trunctfsf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000); + try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000); // nan - test__trunctfsf2(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000); + try test_f32_floatCast_f128(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000); // inf - test__trunctfsf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000); + try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000); // zero - test__trunctfsf2(0.0, 0x0); + try test_f32_floatCast_f128(0.0, 0x0); - test__trunctfsf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156); - test__trunctfsf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2); - test__trunctfsf2(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000); - test__trunctfsf2(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0); + try test_f32_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156); + try test_f32_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2); + try test_f32_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000); + try test_f32_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0); } -fn test__trunctfdf2(a: f128, expected: u64) void { - const x = __trunctfdf2(a); +fn test_f64_floatCast_f128(a: f128, expected: u64) !void { + const x = f64_floatCast_f128(a); const rep: u64 = @bitCast(x); if (rep == expected) { @@ -184,28 +180,27 @@ fn test__trunctfdf2(a: f128, expected: u64) void { return; } } - - @panic("__trunctfsf2 test failure"); + return error.TestFailure; } -test "trunctfdf2" { +test f64_floatCast_f128 { // qnan - test__trunctfdf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000); + try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000); // nan - test__trunctfdf2(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000); + try test_f64_floatCast_f128(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000); // inf - test__trunctfdf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000); + try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000); // zero - test__trunctfdf2(0.0, 0x0); + try test_f64_floatCast_f128(0.0, 0x0); - test__trunctfdf2(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb); - test__trunctfdf2(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7); - test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000); - test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab); + try test_f64_floatCast_f128(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb); + try test_f64_floatCast_f128(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7); + try test_f64_floatCast_f128(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000); + try test_f64_floatCast_f128(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab); } -fn test__truncdfsf2(a: f64, expected: u32) void { - const x = __truncdfsf2(a); +fn test_f32_floatCast_f64(a: f64, expected: u32) !void { + const x = f32_floatCast_f64(a); const rep: u32 = @bitCast(x); if (rep == expected) { @@ -217,90 +212,81 @@ fn test__truncdfsf2(a: f64, expected: u32) void { return; } } - - std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected }); - - @panic("__trunctfsf2 test failure"); + return error.TestFailure; } -test "truncdfsf2" { +test f32_floatCast_f64 { // nan & qnan - test__truncdfsf2(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000); - test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000); + try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000); + try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000); // inf - test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000); - test__truncdfsf2(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000); + try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000); + try test_f32_floatCast_f64(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000); - test__truncdfsf2(0.0, 0x0); - test__truncdfsf2(1.0, 0x3f800000); - test__truncdfsf2(-1.0, 0xbf800000); + try test_f32_floatCast_f64(0.0, 0x0); + try test_f32_floatCast_f64(1.0, 0x3f800000); + try test_f32_floatCast_f64(-1.0, 0xbf800000); // huge number becomes inf - test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000); + try test_f32_floatCast_f64(340282366920938463463374607431768211456.0, 0x7f800000); } -fn test__trunctfhf2(a: f128, expected: u16) void { - const x = __trunctfhf2(a); +fn test_f16_floatCast_f128(a: f128, expected: u16) !void { + const x = f16_floatCast_f128(a); const rep: u16 = @bitCast(x); - if (rep == expected) { - return; - } - - std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected }); - - @panic("__trunctfhf2 test failure"); + try testing.expect(rep == expected); } -test "trunctfhf2" { +test f16_floatCast_f128 { // qNaN - test__trunctfhf2(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00); + try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00); // NaN - test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00); + try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00); // inf - test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00); - test__trunctfhf2(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00); + try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00); + try test_f16_floatCast_f128(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00); // zero - test__trunctfhf2(0.0, 0x0); - test__trunctfhf2(-0.0, 0x8000); + try test_f16_floatCast_f128(0.0, 0x0); + try test_f16_floatCast_f128(-0.0, 0x8000); - test__trunctfhf2(3.1415926535, 0x4248); - test__trunctfhf2(-3.1415926535, 0xc248); - test__trunctfhf2(0x1.987124876876324p+100, 0x7c00); - test__trunctfhf2(0x1.987124876876324p+12, 0x6e62); - test__trunctfhf2(0x1.0p+0, 0x3c00); - test__trunctfhf2(0x1.0p-14, 0x0400); + try test_f16_floatCast_f128(3.1415926535, 0x4248); + try test_f16_floatCast_f128(-3.1415926535, 0xc248); + try test_f16_floatCast_f128(0x1.987124876876324p+100, 0x7c00); + try test_f16_floatCast_f128(0x1.987124876876324p+12, 0x6e62); + try test_f16_floatCast_f128(0x1.0p+0, 0x3c00); + try test_f16_floatCast_f128(0x1.0p-14, 0x0400); // denormal - test__trunctfhf2(0x1.0p-20, 0x0010); - test__trunctfhf2(0x1.0p-24, 0x0001); - test__trunctfhf2(-0x1.0p-24, 0x8001); - test__trunctfhf2(0x1.5p-25, 0x0001); + try test_f16_floatCast_f128(0x1.0p-20, 0x0010); + try test_f16_floatCast_f128(0x1.0p-24, 0x0001); + try test_f16_floatCast_f128(-0x1.0p-24, 0x8001); + try test_f16_floatCast_f128(0x1.5p-25, 0x0001); // and back to zero - test__trunctfhf2(0x1.0p-25, 0x0000); - test__trunctfhf2(-0x1.0p-25, 0x8000); + try test_f16_floatCast_f128(0x1.0p-25, 0x0000); + try test_f16_floatCast_f128(-0x1.0p-25, 0x8000); // max (precise) - test__trunctfhf2(65504.0, 0x7bff); + try test_f16_floatCast_f128(65504.0, 0x7bff); // max (rounded) - test__trunctfhf2(65519.0, 0x7bff); + try test_f16_floatCast_f128(65519.0, 0x7bff); // max (to +inf) - test__trunctfhf2(65520.0, 0x7c00); - test__trunctfhf2(65536.0, 0x7c00); - test__trunctfhf2(-65520.0, 0xfc00); + try test_f16_floatCast_f128(65520.0, 0x7c00); + try test_f16_floatCast_f128(65536.0, 0x7c00); + try test_f16_floatCast_f128(-65520.0, 0xfc00); - test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f); - test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f); - test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00); - test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0); + try test_f16_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f); + try test_f16_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f); + try test_f16_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00); + try test_f16_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0); } -test "trunctfxf2" { - try test__trunctfxf2(1.5, 1.5); - try test__trunctfxf2(2.5, 2.5); - try test__trunctfxf2(-2.5, -2.5); - try test__trunctfxf2(0.0, 0.0); -} - -fn test__trunctfxf2(a: f128, expected: f80) !void { - const x = __trunctfxf2(a); +fn test_f80_floatCast_f128(a: f128, expected: f80) !void { + const x = f80_floatCast_f128(a); try testing.expect(x == expected); } + +test f80_floatCast_f128 { + try test_f80_floatCast_f128(1.5, 1.5); + try test_f80_floatCast_f128(2.5, 2.5); + try test_f80_floatCast_f128(-2.5, -2.5); + try test_f80_floatCast_f128(0.0, 0.0); +} diff --git a/lib/compiler_rt/truncsfhf2.zig b/lib/compiler_rt/truncsfhf2.zig deleted file mode 100644 index e0b2b1e4bf2f15400c568f1c1656c8cb70bc03c8..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncsfhf2.zig +++ /dev/null @@ -1,24 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const truncf = @import("./truncf.zig").truncf; - -comptime { - if (compiler_rt.gnu_f16_abi) { - symbol(&__gnu_f2h_ieee, "__gnu_f2h_ieee"); - } else if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2h, "__aeabi_f2h"); - } - symbol(&__truncsfhf2, "__truncsfhf2"); -} - -pub fn __truncsfhf2(a: f32) callconv(.c) compiler_rt.F16T(f32) { - return @bitCast(truncf(f16, f32, a)); -} - -fn __gnu_f2h_ieee(a: f32) callconv(.c) compiler_rt.F16T(f32) { - return @bitCast(truncf(f16, f32, a)); -} - -fn __aeabi_f2h(a: f32) callconv(.{ .arm_aapcs = .{} }) u16 { - return @bitCast(truncf(f16, f32, a)); -} diff --git a/lib/compiler_rt/trunctfdf2.zig b/lib/compiler_rt/trunctfdf2.zig deleted file mode 100644 index ba909de73bf144b2f023e4f6366dac5a4ad0ea40..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/trunctfdf2.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const truncf = @import("./truncf.zig").truncf; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__trunctfdf2, "__trunckfdf2"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtod, "_Qp_qtod"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__trunctfdf2, "_Q_qtod"); - } - symbol(&__trunctfdf2, "__trunctfdf2"); -} - -pub fn __trunctfdf2(a: f128) callconv(.c) f64 { - return truncf(f64, f128, a); -} - -fn _Qp_qtod(a: *const f128) callconv(.c) f64 { - return truncf(f64, f128, a.*); -} diff --git a/lib/compiler_rt/trunctfhf2.zig b/lib/compiler_rt/trunctfhf2.zig deleted file mode 100644 index 5af87f9c127180b49a15b8f3906252d7da162d26..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/trunctfhf2.zig +++ /dev/null @@ -1,14 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const truncf = @import("./truncf.zig").truncf; - -comptime { - symbol(&__trunctfhf2, "__trunctfhf2"); - if (compiler_rt.want_ppc_abi) { - symbol(&__trunctfhf2, "__trunckfhf2"); - } -} - -pub fn __trunctfhf2(a: f128) callconv(.c) compiler_rt.F16T(f128) { - return @bitCast(truncf(f16, f128, a)); -} diff --git a/lib/compiler_rt/trunctfsf2.zig b/lib/compiler_rt/trunctfsf2.zig deleted file mode 100644 index 8af51ca82f95b1dd36c7f27df20e6756b8e15396..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/trunctfsf2.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const truncf = @import("./truncf.zig").truncf; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__trunctfsf2, "__trunckfsf2"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtos, "_Qp_qtos"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__trunctfsf2, "_Q_qtos"); - } - symbol(&__trunctfsf2, "__trunctfsf2"); -} - -pub fn __trunctfsf2(a: f128) callconv(.c) f32 { - return truncf(f32, f128, a); -} - -fn _Qp_qtos(a: *const f128) callconv(.c) f32 { - return truncf(f32, f128, a.*); -} diff --git a/lib/compiler_rt/trunctfxf2.zig b/lib/compiler_rt/trunctfxf2.zig deleted file mode 100644 index dfb9ef80402cda0360a111e436ba1f7c460bbc1f..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/trunctfxf2.zig +++ /dev/null @@ -1,67 +0,0 @@ -const math = @import("std").math; -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const trunc_f80 = @import("./truncf.zig").trunc_f80; - -comptime { - symbol(&__trunctfxf2, "__trunctfxf2"); -} - -pub fn __trunctfxf2(a: f128) callconv(.c) f80 { - const src_sig_bits = math.floatMantissaBits(f128); - const dst_sig_bits = math.floatMantissaBits(f80) - 1; // -1 for the integer bit - - // Various constants whose values follow from the type parameters. - // Any reasonable optimizer will fold and propagate all of these. - const src_bits = @typeInfo(f128).float.bits; - const src_exp_bits = src_bits - src_sig_bits - 1; - const src_inf_exp = 0x7FFF; - - const src_inf = src_inf_exp << src_sig_bits; - const src_sign_mask = 1 << (src_sig_bits + src_exp_bits); - const src_abs_mask = src_sign_mask - 1; - const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1; - const halfway = 1 << (src_sig_bits - dst_sig_bits - 1); - - // Break a into a sign and representation of the absolute value - const a_rep = @as(u128, @bitCast(a)); - const a_abs = a_rep & src_abs_mask; - const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0; - const integer_bit = 1 << 63; - - var res: math.F80 = undefined; - - if (a_abs > src_inf) { - // a is NaN. - // Conjure the result by beginning with infinity, setting the qNaN - // bit and inserting the (truncated) trailing NaN field. - res.exp = 0x7fff; - res.fraction = 0x8000000000000000; - res.fraction |= @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))); - } else { - // The exponent of a is within the range of normal numbers in the - // destination format. We can convert by simply right-shifting with - // rounding, adding the explicit integer bit, and adjusting the exponent - res.fraction = @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))) | integer_bit; - res.exp = @truncate(a_abs >> src_sig_bits); - - const round_bits = a_abs & round_mask; - if (round_bits > halfway) { - // Round to nearest - const ov = @addWithOverflow(res.fraction, 1); - res.fraction = ov[0]; - res.exp += ov[1]; - res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry - } else if (round_bits == halfway) { - // Ties to even - const ov = @addWithOverflow(res.fraction, res.fraction & 1); - res.fraction = ov[0]; - res.exp += ov[1]; - res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry - } - if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals - } - - res.exp |= sign; - return res.toFloat(); -} diff --git a/lib/compiler_rt/truncxfdf2.zig b/lib/compiler_rt/truncxfdf2.zig deleted file mode 100644 index 6140d94181fbe10a5e83e880dff805e87b34fae8..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncxfdf2.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const trunc_f80 = @import("./truncf.zig").trunc_f80; - -comptime { - symbol(&__truncxfdf2, "__truncxfdf2"); -} - -fn __truncxfdf2(a: f80) callconv(.c) f64 { - return trunc_f80(f64, a); -} diff --git a/lib/compiler_rt/truncxfhf2.zig b/lib/compiler_rt/truncxfhf2.zig deleted file mode 100644 index 4c3e951bfe9b67ff88818e6a89f210851ddfcfb0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncxfhf2.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const trunc_f80 = @import("./truncf.zig").trunc_f80; - -comptime { - symbol(&__truncxfhf2, "__truncxfhf2"); -} - -fn __truncxfhf2(a: f80) callconv(.c) compiler_rt.F16T(f80) { - return @bitCast(trunc_f80(f16, a)); -} diff --git a/lib/compiler_rt/truncxfsf2.zig b/lib/compiler_rt/truncxfsf2.zig deleted file mode 100644 index 8aaf7e6906a9da938835d2c36e931bfb21d07037..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncxfsf2.zig +++ /dev/null @@ -1,10 +0,0 @@ -const trunc_f80 = @import("./truncf.zig").trunc_f80; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__truncxfsf2, "__truncxfsf2"); -} - -fn __truncxfsf2(a: f80) callconv(.c) f32 { - return trunc_f80(f32, a); -} diff --git a/lib/compiler_rt/udivmodei4.zig b/lib/compiler_rt/udivmodei4.zig index 41ba32cdbef1532de8b77e0f91db4bbf4b39f29a..e7c4f52cd1f0360307c5e0ab2232c8925b0b1792 100644 --- a/lib/compiler_rt/udivmodei4.zig +++ b/lib/compiler_rt/udivmodei4.zig @@ -6,7 +6,7 @@ const shr = std.math.shr; const shl = std.math.shl; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; const max_limbs = @divCeil(65535, 32); // max supported type is u65535 diff --git a/lib/compiler_rt/unorddf2.zig b/lib/compiler_rt/unorddf2.zig deleted file mode 100644 index 90da7451992ab5f8b003e5e2f85f93947f932197..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/unorddf2.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const comparef = @import("./comparef.zig"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dcmpun, "__aeabi_dcmpun"); - } else { - symbol(&__unorddf2, "__unorddf2"); - } -} - -pub fn __unorddf2(a: f64, b: f64) callconv(.c) i32 { - return comparef.unordcmp(f64, a, b); -} - -fn __aeabi_dcmpun(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return comparef.unordcmp(f64, a, b); -} diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig index 33502074f661d86b2b6778361e85ab89172242d9..aa36b73ac3e36e51bea58c59fea780d1cc222ae8 100644 --- a/lib/std/crypto/Certificate.zig +++ b/lib/std/crypto/Certificate.zig @@ -1211,7 +1211,7 @@ pub const rsa = struct { 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40, }, - else => @compileError("unreachable"), + else => comptime unreachable, }; em_index -= hash_der.len; @memcpy(em[em_index..][0..hash_der.len], hash_der); diff --git a/lib/std/math.zig b/lib/std/math.zig index b43bc8f5981ec9083596a17ac90df631fc31d33f..0beb62ae6a9eb10cdb78e887f900bebcde0612f4 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -75,7 +75,7 @@ pub const snan = float.snan; /// /// NaN values are never considered equal to any value. pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool { - assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float); + comptime assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float); assert(tolerance >= 0); // Fast path for equal values (and signed zeros and infinites). @@ -103,7 +103,7 @@ pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool { /// /// NaN values are never considered equal to any value. pub fn approxEqRel(comptime T: type, x: T, y: T, tolerance: T) bool { - assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float); + comptime assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float); assert(tolerance > 0); // Fast path for equal values (and signed zeros and infinites). diff --git a/lib/std/math/atan2.zig b/lib/std/math/atan2.zig index f0c8aa0792046a94b900fba216dde87724ec8e1c..7c7bb4bb78e34d8d3b2c3403eba2e63d3ed1d3ce 100644 --- a/lib/std/math/atan2.zig +++ b/lib/std/math/atan2.zig @@ -252,8 +252,8 @@ test "atan2_32.special" { try expect(math.isNan(atan2_32(1.0, math.nan(f32)))); try expect(math.isNan(atan2_32(math.nan(f32), 1.0))); - try expect(atan2_32(0.0, 5.0) == 0.0); - try expect(atan2_32(-0.0, 5.0) == -0.0); + try expect(math.isPositiveZero(atan2_32(0.0, 5.0))); + try expect(math.isNegativeZero(atan2_32(-0.0, 5.0))); try expect(math.approxEqAbs(f32, atan2_32(0.0, -5.0), math.pi, epsilon)); //expect(math.approxEqAbs(f32, atan2_32(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero? try expect(math.approxEqAbs(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon)); @@ -276,8 +276,8 @@ test "atan2_64.special" { try expect(math.isNan(atan2_64(1.0, math.nan(f64)))); try expect(math.isNan(atan2_64(math.nan(f64), 1.0))); - try expect(atan2_64(0.0, 5.0) == 0.0); - try expect(atan2_64(-0.0, 5.0) == -0.0); + try expect(math.isPositiveZero(atan2_64(0.0, 5.0))); + try expect(math.isNegativeZero(atan2_64(-0.0, 5.0))); try expect(math.approxEqAbs(f64, atan2_64(0.0, -5.0), math.pi, epsilon)); //expect(math.approxEqAbs(f64, atan2_64(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero? try expect(math.approxEqAbs(f64, atan2_64(1.0, 0.0), math.pi / 2.0, epsilon)); diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index 0ac83c50dc57047ff1a937182b717960b14e8f82..2315405a9e89549e26a875b00b51390fc3bc1b3d 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -527,6 +527,20 @@ pub fn intAlignment(target: *const std.Target, bits: u16) u16 { }; } +pub fn compilerRtFloatAbi(target: *const std.Target, bits: u16) std.Target.Abi.Float { + if (target.cpu.has(.x86, .soft_float)) return .soft; + // Marks targets where clang does not even provide a usable C type. + const no_c_type_available = .soft; + switch (bits) { + else => unreachable, + 16 => if (target.cpu.arch.isMIPS() or target.cpu.arch.isPowerPC()) return no_c_type_available, + 32, 64 => {}, + 80 => if (target.cTypeBitSize(.longdouble) != 80) return no_c_type_available, + 128 => if (target.cTypeBitSize(.longdouble) <= 64) return no_c_type_available, + } + return .hard; +} + const std = @import("std"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; diff --git a/src/link.zig b/src/link.zig index 84cbcbdcb78ea45a0e9e93242686f7f8f0f01748..7ce8363a3d77d9191b813cc86f2896e0285bec4e 100644 --- a/src/link.zig +++ b/src/link.zig @@ -2127,7 +2127,7 @@ pub fn resolveInputs( continue; }, } - @compileError("unreachable"); + comptime unreachable; } if (failed_libs.items.len > 0) { diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index d13fc8e83d36590bb20b329f3accd39eae411a4d..0117c647880eb21fb9226abfc816a22ad2bcd2a7 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1845,7 +1845,7 @@ test "coerce between pointers of compatible differently-named floats" { 64 => f64, 80 => f80, 128 => f128, - else => @compileError("unreachable"), + else => comptime unreachable, }; var f1: F = 12.34; const f2: *c_longdouble = &f1; diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 76b21b6f15316a95c3ee6d98a759ff06e8c03715..74a71249c65f6c2f839356c99bbd8416d5df1cd5 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -431,9 +431,9 @@ fn testSqrt(comptime T: type) !void { var inf: T = math.inf(T); try expect(math.isPositiveInf(@sqrt(inf))); var zero: T = 0.0; - try expect(@sqrt(zero) == 0.0); + try expect(math.isPositiveZero(@sqrt(zero))); var neg_zero: T = -0.0; - try expect(@sqrt(neg_zero) == 0.0); + try expect(math.isNegativeZero(@sqrt(neg_zero))); var neg_one: T = -1.0; try expect(math.isNan(@sqrt(neg_one))); var nan: T = math.nan(T); @@ -1501,9 +1501,9 @@ fn testNeg(comptime T: type) !void { // subnormals var zero: T = 0.0; - try expect(-zero == -0.0); + try expect(math.isNegativeZero(-zero)); var neg_zero: T = -0.0; - try expect(-neg_zero == 0.0); + try expect(math.isPositiveZero(-neg_zero)); var true_min: T = math.floatTrueMin(T); try expect(-true_min == -math.floatTrueMin(T)); var neg_true_min: T = -math.floatTrueMin(T); diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 6a44290f859261ad1c2f02974eb8525022fc0b25..c5ffdfa3e1872bfa58edb53b414b523660e9a9bb 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -1267,7 +1267,7 @@ test "switch with complex item expressions" { test "switch evaluation order" { const eu: anyerror!u32 = 0; _ = eu catch |err| switch (err) { - if (true) @compileError("unreachable") => unreachable, + if (true) comptime unreachable => unreachable, else => unreachable, }; } diff --git a/test/behavior/switch_on_captured_error.zig b/test/behavior/switch_on_captured_error.zig index c4353cd5df381e080489b9b5594df9d356277cc0..a57e93d0d1ca4bd502123b9e13ddcaeb7cbd9b68 100644 --- a/test/behavior/switch_on_captured_error.zig +++ b/test/behavior/switch_on_captured_error.zig @@ -243,7 +243,7 @@ test "switch on error union catch capture" { var a: error{}!u64 = 0; _ = &a; const b = a catch |err| switch (err) { - undefined => @compileError("unreachable"), + undefined => comptime unreachable, }; try expectEqual(@as(u64, 0), b); } @@ -829,7 +829,7 @@ test "switch on error union if else capture" { var a: error{}!u64 = 0; _ = &a; const b = if (a) |x| x else |err| switch (err) { - undefined => @compileError("unreachable"), + undefined => comptime unreachable, }; try expectEqual(@as(u64, 0), b); } @@ -840,7 +840,7 @@ test "switch on error union if else capture" { var a: error{}!u64 = 0; _ = &a; const b = if (a) |*x| x.* else |err| switch (err) { - undefined => @compileError("unreachable"), + undefined => comptime unreachable, }; try expectEqual(@as(u64, 0), b); } -- 2.54.0 From 3e26b9e957887e55e99046e908bc07200140d3f8 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Mon, 29 Jun 2026 09:48:37 -0400 Subject: [PATCH 09/22] codegen: change libc f128 suffix to match llvm --- lib/compiler_rt/cos.zig | 3 +- lib/compiler_rt/exp.zig | 5 +- lib/compiler_rt/exp2.zig | 5 +- lib/compiler_rt/fabs.zig | 5 +- lib/compiler_rt/floor_ceil.zig | 10 +- lib/compiler_rt/fma.zig | 5 +- lib/compiler_rt/fmax.zig | 5 +- lib/compiler_rt/fmin.zig | 5 +- lib/compiler_rt/fmod.zig | 5 +- lib/compiler_rt/log.zig | 5 +- lib/compiler_rt/log10.zig | 5 +- lib/compiler_rt/log2.zig | 5 +- lib/compiler_rt/round.zig | 3 +- lib/compiler_rt/sin.zig | 5 +- lib/compiler_rt/sincos.zig | 5 +- lib/compiler_rt/sqrt.zig | 6 +- lib/compiler_rt/tan.zig | 5 +- lib/compiler_rt/trunc.zig | 5 +- lib/zig.h | 2 +- src/codegen/aarch64/Select.zig | 38 ++--- src/codegen/wasm/CodeGen.zig | 32 ++-- src/codegen/wasm/Mir.zig | 36 ++-- src/codegen/x86_64/CodeGen.zig | 296 ++++++++++++++++----------------- src/target.zig | 2 +- stage1/zig.h | 2 +- test/behavior/floatop.zig | 1 + test/behavior/x86_64/unary.zig | 2 +- 27 files changed, 226 insertions(+), 277 deletions(-) diff --git a/lib/compiler_rt/cos.zig b/lib/compiler_rt/cos.zig index 612698b1e9efb080804656c50e68cd6e0a2e8680..72ea9026472a1f8e31bca5cddc9e106cfd66155b 100644 --- a/lib/compiler_rt/cos.zig +++ b/lib/compiler_rt/cos.zig @@ -24,8 +24,7 @@ comptime { symbol(&cosf, "cosf"); symbol(&cos, "cos"); symbol(&__cosx, "__cosx"); - if (compiler_rt.want_ppc_abi) symbol(&cosq, "cosf128"); - symbol(&cosq, "cosq"); + symbol(&cosq, "cosf128"); symbol(&cosl, "cosl"); symbol(&cosl, "__cosl"); // required by musl } diff --git a/lib/compiler_rt/exp.zig b/lib/compiler_rt/exp.zig index ddec21869f166538e3497bb84050e55eba3ff33c..6f9d19ddb3adbfe743fd278ce9e458ae45341502 100644 --- a/lib/compiler_rt/exp.zig +++ b/lib/compiler_rt/exp.zig @@ -21,10 +21,7 @@ comptime { symbol(&expf, "expf"); symbol(&exp, "exp"); symbol(&__expx, "__expx"); - if (compiler_rt.want_ppc_abi) { - symbol(&expq, "expf128"); - } - symbol(&expq, "expq"); + symbol(&expq, "expf128"); symbol(&expl, "expl"); } diff --git a/lib/compiler_rt/exp2.zig b/lib/compiler_rt/exp2.zig index 36ee7c14c90be2c13dd0e09ca91d656a19a539a7..4f25cdec63332788d1bdda417503901b02ce6154 100644 --- a/lib/compiler_rt/exp2.zig +++ b/lib/compiler_rt/exp2.zig @@ -19,10 +19,7 @@ comptime { symbol(&exp2f, "exp2f"); symbol(&exp2, "exp2"); symbol(&__exp2x, "__exp2x"); - if (compiler_rt.want_ppc_abi) { - symbol(&exp2q, "exp2f128"); - } - symbol(&exp2q, "exp2q"); + symbol(&exp2q, "exp2f128"); symbol(&exp2l, "exp2l"); } diff --git a/lib/compiler_rt/fabs.zig b/lib/compiler_rt/fabs.zig index 50d2cc17d590a11615bdc471e6926af6c1f7bc6c..2238e65e61292668cb2e7bc2e2be3f090470b2e9 100644 --- a/lib/compiler_rt/fabs.zig +++ b/lib/compiler_rt/fabs.zig @@ -9,10 +9,7 @@ comptime { symbol(&fabsf, "fabsf"); symbol(&fabs, "fabs"); symbol(&__fabsx, "__fabsx"); - if (compiler_rt.want_ppc_abi) { - symbol(&fabsq, "fabsf128"); - } - symbol(&fabsq, "fabsq"); + symbol(&fabsq, "fabsf128"); symbol(&fabsl, "fabsl"); } diff --git a/lib/compiler_rt/floor_ceil.zig b/lib/compiler_rt/floor_ceil.zig index f31c352d026c549bd230c9d7d5f15677a85968ce..8bd82275e3787ae52587eb84c1391ee5949f616b 100644 --- a/lib/compiler_rt/floor_ceil.zig +++ b/lib/compiler_rt/floor_ceil.zig @@ -23,10 +23,7 @@ comptime { symbol(&floorf, "floorf"); symbol(&floor, "floor"); symbol(&__floorx, "__floorx"); - if (compiler_rt.want_ppc_abi) { - symbol(&floorq, "floorf128"); - } - symbol(&floorq, "floorq"); + symbol(&floorq, "floorf128"); symbol(&floorl, "floorl"); // ceil @@ -34,10 +31,7 @@ comptime { symbol(&ceilf, "ceilf"); symbol(&ceil, "ceil"); symbol(&__ceilx, "__ceilx"); - if (compiler_rt.want_ppc_abi) { - symbol(&ceilq, "ceilf128"); - } - symbol(&ceilq, "ceilq"); + symbol(&ceilq, "ceilf128"); symbol(&ceill, "ceill"); } diff --git a/lib/compiler_rt/fma.zig b/lib/compiler_rt/fma.zig index f10d08fc63f2038fa98cd4b28c5d4ee8a2ca0a84..97bb57d4aae5aebe74c34925abacdb84f3aeef82 100644 --- a/lib/compiler_rt/fma.zig +++ b/lib/compiler_rt/fma.zig @@ -16,10 +16,7 @@ comptime { symbol(&fmaf, "fmaf"); symbol(&fma, "fma"); symbol(&__fmax, "__fmax"); - if (compiler_rt.want_ppc_abi) { - symbol(&fmaq, "fmaf128"); - } - symbol(&fmaq, "fmaq"); + symbol(&fmaq, "fmaf128"); symbol(&fmal, "fmal"); } diff --git a/lib/compiler_rt/fmax.zig b/lib/compiler_rt/fmax.zig index cf323533952e542e126e11f69ec5a8352c37bcdb..f69912472044f62c50733968b382fec866d069c7 100644 --- a/lib/compiler_rt/fmax.zig +++ b/lib/compiler_rt/fmax.zig @@ -10,10 +10,7 @@ comptime { symbol(&fmaxf, "fmaxf"); symbol(&fmax, "fmax"); symbol(&__fmaxx, "__fmaxx"); - if (compiler_rt.want_ppc_abi) { - symbol(&fmaxq, "fmaxf128"); - } - symbol(&fmaxq, "fmaxq"); + symbol(&fmaxq, "fmaxf128"); symbol(&fmaxl, "fmaxl"); } diff --git a/lib/compiler_rt/fmin.zig b/lib/compiler_rt/fmin.zig index 48b5dcdc225118ce3a2096b15c98b0b534f75ae3..bece9262f2a673919e33260576c2ce7d8730cdee 100644 --- a/lib/compiler_rt/fmin.zig +++ b/lib/compiler_rt/fmin.zig @@ -10,10 +10,7 @@ comptime { symbol(&fminf, "fminf"); symbol(&fmin, "fmin"); symbol(&__fminx, "__fminx"); - if (compiler_rt.want_ppc_abi) { - symbol(&fminq, "fminf128"); - } - symbol(&fminq, "fminq"); + symbol(&fminq, "fminf128"); symbol(&fminl, "fminl"); } diff --git a/lib/compiler_rt/fmod.zig b/lib/compiler_rt/fmod.zig index 636138516bf1f13d2a15b597d21fd6a617e7ee0d..951b90d06e529e8a3a2606d7fe0eff1dcd9d667a 100644 --- a/lib/compiler_rt/fmod.zig +++ b/lib/compiler_rt/fmod.zig @@ -12,10 +12,7 @@ comptime { symbol(&fmodf, "fmodf"); symbol(&fmod, "fmod"); symbol(&__fmodx, "__fmodx"); - if (compiler_rt.want_ppc_abi) { - symbol(&fmodq, "fmodf128"); - } - symbol(&fmodq, "fmodq"); + symbol(&fmodq, "fmodf128"); symbol(&fmodl, "fmodl"); } diff --git a/lib/compiler_rt/log.zig b/lib/compiler_rt/log.zig index 9f632f69ff93a9c05663104c5429c7c8e787e761..8b2937921d5998941e7731ac8decce71f60c85cb 100644 --- a/lib/compiler_rt/log.zig +++ b/lib/compiler_rt/log.zig @@ -18,10 +18,7 @@ comptime { symbol(&logf, "logf"); symbol(&log, "log"); symbol(&__logx, "__logx"); - if (compiler_rt.want_ppc_abi) { - symbol(&logq, "logf128"); - } - symbol(&logq, "logq"); + symbol(&logq, "logf128"); symbol(&logl, "logl"); } diff --git a/lib/compiler_rt/log10.zig b/lib/compiler_rt/log10.zig index 6a554e0ea79ff597dfdeeea31477e1c6ebfbac1c..0813c1ae7c0dc6d71ae7aa2699f17e05bdffe039 100644 --- a/lib/compiler_rt/log10.zig +++ b/lib/compiler_rt/log10.zig @@ -18,10 +18,7 @@ comptime { symbol(&log10f, "log10f"); symbol(&log10, "log10"); symbol(&__log10x, "__log10x"); - if (compiler_rt.want_ppc_abi) { - symbol(&log10q, "log10f128"); - } - symbol(&log10q, "log10q"); + symbol(&log10q, "log10f128"); symbol(&log10l, "log10l"); } diff --git a/lib/compiler_rt/log2.zig b/lib/compiler_rt/log2.zig index b748a0af826586065f1f5369a6f1c61492b4cf99..0806fb079419787d33dd3b825b4057aac51f1397 100644 --- a/lib/compiler_rt/log2.zig +++ b/lib/compiler_rt/log2.zig @@ -19,10 +19,7 @@ comptime { symbol(&log2f, "log2f"); symbol(&log2, "log2"); symbol(&__log2x, "__log2x"); - if (compiler_rt.want_ppc_abi) { - symbol(&log2q, "log2f128"); - } - symbol(&log2q, "log2q"); + symbol(&log2q, "log2f128"); symbol(&log2l, "log2l"); } diff --git a/lib/compiler_rt/round.zig b/lib/compiler_rt/round.zig index 6c86984605af2d246a4e582851a5d172a67d7c69..ffcaed60774e70e5067ff107380a8af5a057d718 100644 --- a/lib/compiler_rt/round.zig +++ b/lib/compiler_rt/round.zig @@ -18,8 +18,7 @@ comptime { symbol(&roundf, "roundf"); symbol(&round, "round"); symbol(&__roundx, "__roundx"); - if (compiler_rt.want_ppc_abi) symbol(&roundq, "roundf128"); - symbol(&roundq, "roundq"); + symbol(&roundq, "roundf128"); symbol(&roundl, "roundl"); } diff --git a/lib/compiler_rt/sin.zig b/lib/compiler_rt/sin.zig index fe818922fe4af6542dc88fd682367860ae4908da..3e0b8f0cbd823b0e57fe0172217c7726955c7fd1 100644 --- a/lib/compiler_rt/sin.zig +++ b/lib/compiler_rt/sin.zig @@ -24,10 +24,7 @@ comptime { symbol(&sinf, "sinf"); symbol(&sin, "sin"); symbol(&__sinx, "__sinx"); - if (compiler_rt.want_ppc_abi) { - symbol(&sinq, "sinf128"); - } - symbol(&sinq, "sinq"); + symbol(&sinq, "sinf128"); symbol(&sinl, "sinl"); symbol(&sinl, "__sinl"); // required by musl } diff --git a/lib/compiler_rt/sincos.zig b/lib/compiler_rt/sincos.zig index 6d2b9f007a90f94c158bb636d3fcd1d8e6b40a7c..d43f55b623954f602edf850b75d409931b1aaee6 100644 --- a/lib/compiler_rt/sincos.zig +++ b/lib/compiler_rt/sincos.zig @@ -18,10 +18,7 @@ comptime { symbol(&sincosf, "sincosf"); symbol(&sincos, "sincos"); symbol(&sincosx, "__sincosx"); - if (compiler_rt.want_ppc_abi) { - symbol(&sincosq, "sincosf128"); - } - symbol(&sincosq, "sincosq"); + symbol(&sincosq, "sincosf128"); symbol(&sincosl, "sincosl"); } diff --git a/lib/compiler_rt/sqrt.zig b/lib/compiler_rt/sqrt.zig index 56e43a42fcdd437811ad00d7290de45d5cee82f3..a37fe429c1458153dded08805982d118dedb8ebb 100644 --- a/lib/compiler_rt/sqrt.zig +++ b/lib/compiler_rt/sqrt.zig @@ -17,14 +17,12 @@ comptime { symbol(&sqrtf, "sqrtf"); symbol(&sqrt, "sqrt"); symbol(&__sqrtx, "__sqrtx"); - if (compiler_rt.want_ppc_abi) { - symbol(&sqrtq, "sqrtf128"); - } else if (compiler_rt.want_sparc64_abi) { + symbol(&sqrtq, "sqrtf128"); + if (compiler_rt.want_sparc64_abi) { symbol(&_Qp_sqrt, "_Qp_sqrt"); } else if (compiler_rt.want_sparc32_abi) { symbol(&sqrtq, "_Q_sqrt"); } - symbol(&sqrtq, "sqrtq"); symbol(&sqrtl, "sqrtl"); } diff --git a/lib/compiler_rt/tan.zig b/lib/compiler_rt/tan.zig index 038ac85b6dc2dd9e7d742936bd0df3095dc4b9ec..4ee4440dd6c5cd7417842de27084cab36ae85907 100644 --- a/lib/compiler_rt/tan.zig +++ b/lib/compiler_rt/tan.zig @@ -28,10 +28,7 @@ comptime { symbol(&tanf, "tanf"); symbol(&tan, "tan"); symbol(&__tanx, "__tanx"); - if (compiler_rt.want_ppc_abi) { - symbol(&tanq, "tanf128"); - } - symbol(&tanq, "tanq"); + symbol(&tanq, "tanf128"); symbol(&tanl, "tanl"); } diff --git a/lib/compiler_rt/trunc.zig b/lib/compiler_rt/trunc.zig index 0653178b54b50256e43168d377f59377f34dcc14..0dbacf0e9d822385a8dc558a29bf0401f6d97e21 100644 --- a/lib/compiler_rt/trunc.zig +++ b/lib/compiler_rt/trunc.zig @@ -17,10 +17,7 @@ comptime { symbol(&truncf, "truncf"); symbol(&trunc, "trunc"); symbol(&__truncx, "__truncx"); - if (compiler_rt.want_ppc_abi) { - symbol(&truncq, "truncf128"); - } - symbol(&truncq, "truncq"); + symbol(&truncq, "truncf128"); symbol(&truncl, "truncl"); } diff --git a/lib/zig.h b/lib/zig.h index fbc924ca334e99eb12d2f37e3ebffa970ced7b9d..fc2f9479bea2bf9599dfcaebe35294fed98b4db4 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -3835,7 +3835,7 @@ typedef zig_u128 zig_f80; #endif #define zig_has_f128 1 -#define zig_libc_name_f128(name) name##q +#define zig_libc_name_f128(name) name##f128 #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) #if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 typedef float zig_f128; diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 30387bfe8a37719577b57391f6f270e71e8238e2..73cd6ea1e357e38497633fbcbb5af744f1815e1a 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -2099,7 +2099,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "truncf", 64 => "trunc", 80 => "__truncx", - 128 => "truncq", + 128 => "truncf128", }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, }); @@ -2113,7 +2113,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "floorf", 64 => "floor", 80 => "__floorx", - 128 => "floorq", + 128 => "floorf128", }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, }); @@ -2431,7 +2431,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "fmodf", 64 => "fmod", 80 => "__fmodx", - 128 => "fmodq", + 128 => "fmodf128", }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, }); @@ -2599,7 +2599,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "fmaxf", 64 => "fmax", 80 => "__fmaxx", - 128 => "fmaxq", + 128 => "fmaxf128", }, .min => switch (bits) { else => unreachable, @@ -2607,7 +2607,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "fminf", 64 => "fmin", 80 => "__fminx", - 128 => "fminq", + 128 => "fminf128", }, }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, @@ -4055,7 +4055,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "sqrtf", 64 => "sqrt", 80 => "__sqrtx", - 128 => "sqrtq", + 128 => "sqrtf128", }, .floor => switch (bits) { else => unreachable, @@ -4063,7 +4063,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "floorf", 64 => "floor", 80 => "__floorx", - 128 => "floorq", + 128 => "floorf128", }, .ceil => switch (bits) { else => unreachable, @@ -4071,7 +4071,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "ceilf", 64 => "ceil", 80 => "__ceilx", - 128 => "ceilq", + 128 => "ceilf128", }, .round => switch (bits) { else => unreachable, @@ -4079,7 +4079,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "roundf", 64 => "round", 80 => "__roundx", - 128 => "roundq", + 128 => "roundf128", }, .trunc_float => switch (bits) { else => unreachable, @@ -4087,7 +4087,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "truncf", 64 => "trunc", 80 => "__truncx", - 128 => "truncq", + 128 => "truncf128", }, }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, @@ -4147,7 +4147,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "sinf", 64 => "sin", 80 => "__sinx", - 128 => "sinq", + 128 => "sinf128", }, .cos => switch (bits) { else => unreachable, @@ -4155,7 +4155,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "cosf", 64 => "cos", 80 => "__cosx", - 128 => "cosq", + 128 => "cosf128", }, .tan => switch (bits) { else => unreachable, @@ -4163,7 +4163,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "tanf", 64 => "tan", 80 => "__tanx", - 128 => "tanq", + 128 => "tanf128", }, .exp => switch (bits) { else => unreachable, @@ -4171,7 +4171,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "expf", 64 => "exp", 80 => "__expx", - 128 => "expq", + 128 => "expf128", }, .exp2 => switch (bits) { else => unreachable, @@ -4179,7 +4179,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "exp2f", 64 => "exp2", 80 => "__exp2x", - 128 => "exp2q", + 128 => "exp2f128", }, .log => switch (bits) { else => unreachable, @@ -4187,7 +4187,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "logf", 64 => "log", 80 => "__logx", - 128 => "logq", + 128 => "logf128", }, .log2 => switch (bits) { else => unreachable, @@ -4195,7 +4195,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "log2f", 64 => "log2", 80 => "__log2x", - 128 => "log2q", + 128 => "log2f128", }, .log10 => switch (bits) { else => unreachable, @@ -4203,7 +4203,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "log10f", 64 => "log10", 80 => "__log10x", - 128 => "log10q", + 128 => "log10f128", }, }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, @@ -7118,7 +7118,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "fmaf", 64 => "fma", 80 => "__fmax", - 128 => "fmaq", + 128 => "fmaf128", }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, }); diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index e0e73040cab9dedecaaca4c4f843e647e87edcd5..3dc36619686e53a6112e3cc81ec9ccd3f902e0c6 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -4340,7 +4340,7 @@ fn floatRem(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV .f32 => return cg.callIntrinsic(.fmodf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }), .f64 => return cg.callIntrinsic(.fmod, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }), .f80 => return cg.callIntrinsic(.__fmodx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }), - .f128 => return cg.callIntrinsic(.fmodq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), + .f128 => return cg.callIntrinsic(.fmodf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), } } @@ -4376,7 +4376,7 @@ fn floatMax(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV .f32 => return cg.callIntrinsic(.fmaxf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }), .f64 => return cg.callIntrinsic(.fmax, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }), .f80 => return cg.callIntrinsic(.__fmaxx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }), - .f128 => return cg.callIntrinsic(.fmaxq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), + .f128 => return cg.callIntrinsic(.fmaxf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), } } @@ -4387,7 +4387,7 @@ fn floatMin(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV .f32 => return cg.callIntrinsic(.fminf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }), .f64 => return cg.callIntrinsic(.fmin, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }), .f80 => return cg.callIntrinsic(.__fminx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }), - .f128 => return cg.callIntrinsic(.fminq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), + .f128 => return cg.callIntrinsic(.fminf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), } } @@ -4405,7 +4405,7 @@ fn floatSqrt(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { return .stack; }, .f80 => return cg.callIntrinsic(.__sqrtx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.sqrtq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.sqrtf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4415,7 +4415,7 @@ fn floatSin(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.sinf, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.sin, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__sinx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.sinq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.sinf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4425,7 +4425,7 @@ fn floatCos(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.cosf, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.cos, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__cosx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.cosq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.cosf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4435,7 +4435,7 @@ fn floatTan(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.tanf, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.tan, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__tanx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.tanq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.tanf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4445,7 +4445,7 @@ fn floatExp(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.expf, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.exp, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__expx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.expq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.expf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4455,7 +4455,7 @@ fn floatExp2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.exp2f, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.exp2, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__exp2x, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.exp2q, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.exp2f128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4465,7 +4465,7 @@ fn floatLog(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.logf, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.log, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__logx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.logq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.logf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4475,7 +4475,7 @@ fn floatLog2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.log2f, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.log2, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__log2x, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.log2q, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.log2f128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4485,7 +4485,7 @@ fn floatLog10(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.log10f, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.log10, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__log10x, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.log10q, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.log10f128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4503,7 +4503,7 @@ fn floatFloor(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { return .stack; }, .f80 => return cg.callIntrinsic(.__floorx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.floorq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.floorf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4521,7 +4521,7 @@ fn floatCeil(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { return .stack; }, .f80 => return cg.callIntrinsic(.__ceilx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.ceilq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.ceilf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4539,7 +4539,7 @@ fn floatRound(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { return .stack; }, .f80 => return cg.callIntrinsic(.__roundx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.roundq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.roundf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4557,7 +4557,7 @@ fn floatTrunc(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { return .stack; }, .f80 => return cg.callIntrinsic(.__truncx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.truncq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.truncf128, &.{.f128_type}, Type.f128, &.{arg}), } } diff --git a/src/codegen/wasm/Mir.zig b/src/codegen/wasm/Mir.zig index 8e5f1c32f958d8ea2403ea2260a421da08e153c9..bbb41312990a836c336b6a3aa303ba2f0e363521 100644 --- a/src/codegen/wasm/Mir.zig +++ b/src/codegen/wasm/Mir.zig @@ -991,48 +991,48 @@ pub const Intrinsic = enum(u32) { __udivti3, __umodei5, __umodti3, - ceilq, + ceilf128, cos, cosf, - cosq, + cosf128, exp, exp2, exp2f, - exp2q, + exp2f128, expf, - expq, - fabsq, - floorq, + expf128, + fabsf128, + floorf128, fma, fmaf, - fmaq, + fmaf128, fmax, fmaxf, - fmaxq, + fmaxf128, fmin, fminf, - fminq, + fminf128, fmod, fmodf, - fmodq, + fmodf128, log, log10, log10f, - log10q, + log10f128, log2, log2f, - log2q, + log2f128, logf, - logq, - roundq, + logf128, + roundf128, sin, sinf, - sinq, - sqrtq, + sinf128, + sqrtf128, tan, tanf, - tanq, - truncq, + tanf128, + truncf128, memcpy, memmove, memset, diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index d499ef406fc67f0a7a4fe8c81390b6ad434a36a5..da82d324608abdc1a1dabc4c691c41b4f9c470d5 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -34436,7 +34436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34470,7 +34470,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34505,7 +34505,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34540,7 +34540,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34575,7 +34575,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34612,7 +34612,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34649,7 +34649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34688,7 +34688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34727,7 +34727,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34766,7 +34766,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -35960,8 +35960,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -35998,8 +35998,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .mem }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36037,8 +36037,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .mem }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36076,8 +36076,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .mem }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36115,8 +36115,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36156,8 +36156,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36197,8 +36197,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36240,8 +36240,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36283,8 +36283,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36326,8 +36326,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -37691,7 +37691,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37725,7 +37725,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37760,7 +37760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37795,7 +37795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37830,7 +37830,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37867,7 +37867,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37904,7 +37904,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37943,7 +37943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37982,7 +37982,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -38021,7 +38021,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -39558,7 +39558,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .unused, .unused, .unused, @@ -39590,7 +39590,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .unused, .unused, .unused, @@ -39623,7 +39623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .unused, .unused, .unused, @@ -39659,7 +39659,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .unused, .unused, .unused, @@ -39695,7 +39695,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .unused, .unused, .unused, @@ -39731,7 +39731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -39767,7 +39767,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -39803,7 +39803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -42803,7 +42803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .u64, .kind = .{ .reg = .rcx } }, .{ .type = .u64, .kind = .{ .reg = .rdx } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -42849,7 +42849,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .u64, .kind = .{ .reg = .rcx } }, .{ .type = .u64, .kind = .{ .reg = .rdx } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -42895,7 +42895,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .u64, .kind = .{ .reg = .rcx } }, .{ .type = .u64, .kind = .{ .reg = .rdx } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -42942,7 +42942,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .u64, .kind = .{ .reg = .rdx } }, .{ .type = .f128, .kind = .mem }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -42984,7 +42984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .reg = .xmm1 } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -43029,7 +43029,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .reg = .xmm1 } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -43074,7 +43074,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .reg = .xmm1 } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -43120,7 +43120,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .usize, .kind = .{ .reg = .rax } }, .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } }, @@ -43164,7 +43164,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .reg = .rcx } }, .{ .type = .f128, .kind = .{ .reg = .rdx } }, .{ .type = .f128, .kind = .{ .reg = .rax } }, @@ -43211,7 +43211,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .reg = .rcx } }, .{ .type = .f128, .kind = .{ .reg = .rdx } }, .{ .type = .f128, .kind = .{ .reg = .rax } }, @@ -43258,7 +43258,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .reg = .rcx } }, .{ .type = .f128, .kind = .{ .reg = .rdx } }, .{ .type = .f128, .kind = .{ .reg = .rax } }, @@ -43306,7 +43306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .reg = .rdx } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .reg = .rax } }, @@ -47623,7 +47623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -47655,7 +47655,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -47688,7 +47688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -47724,7 +47724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -47760,7 +47760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -47796,7 +47796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -47832,7 +47832,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -47868,7 +47868,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -51926,7 +51926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -51958,7 +51958,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -51991,7 +51991,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -52027,7 +52027,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -52063,7 +52063,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -52099,7 +52099,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -52135,7 +52135,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -52171,7 +52171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -76457,7 +76457,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .unused, .unused, .unused, @@ -76484,7 +76484,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .unused, .unused, .unused, @@ -76512,7 +76512,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .unused, .unused, .unused, @@ -76543,7 +76543,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .unused, .unused, .unused, @@ -76574,7 +76574,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .unused, .unused, .unused, @@ -76605,7 +76605,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -76636,7 +76636,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -76667,7 +76667,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -77306,7 +77306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .unused, .unused, .unused, @@ -77333,7 +77333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .unused, .unused, .unused, @@ -77361,7 +77361,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .unused, .unused, .unused, @@ -77392,7 +77392,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .unused, .unused, .unused, @@ -77423,7 +77423,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .unused, .unused, .unused, @@ -77454,7 +77454,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -77485,7 +77485,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -77516,7 +77516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -80155,9 +80155,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .unused, .unused, @@ -80187,9 +80187,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .unused, .unused, @@ -80220,9 +80220,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .unused, .unused, @@ -80256,9 +80256,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .unused, .unused, @@ -80292,9 +80292,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .unused, .unused, @@ -80328,9 +80328,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, @@ -80364,9 +80364,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, @@ -80400,9 +80400,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, @@ -142552,7 +142552,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -142584,7 +142584,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -142616,7 +142616,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -142649,7 +142649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -142683,7 +142683,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -142717,7 +142717,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -152785,7 +152785,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -152817,7 +152817,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -152849,7 +152849,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -152882,7 +152882,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -152916,7 +152916,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -152950,7 +152950,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -163019,7 +163019,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -163051,7 +163051,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -163083,7 +163083,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -163116,7 +163116,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -163150,7 +163150,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -163184,7 +163184,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -164816,7 +164816,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -164848,7 +164848,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -164880,7 +164880,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -164913,7 +164913,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -164947,7 +164947,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -164981,7 +164981,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -172785,7 +172785,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .unused, .unused, .unused, @@ -172818,7 +172818,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .unused, .unused, .unused, @@ -172852,7 +172852,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .unused, .unused, .unused, @@ -172889,7 +172889,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .unused, .unused, .unused, @@ -172926,7 +172926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .unused, .unused, .unused, @@ -172963,7 +172963,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -173000,7 +173000,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -173037,7 +173037,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, diff --git a/src/target.zig b/src/target.zig index 0ed4053701fd696db7540b42dbf5aaf890e47921..e249be39947d8d99f6f9eef6bd15b271887625fe 100644 --- a/src/target.zig +++ b/src/target.zig @@ -876,7 +876,7 @@ pub fn libcFloatSuffix(float_bits: u16) []const u8 { 32 => "f", 64 => "", 80 => "x", // Non-standard - 128 => "q", // Non-standard (mimics convention in GCC libquadmath) + 128 => "f128", else => unreachable, }; } diff --git a/stage1/zig.h b/stage1/zig.h index fbc924ca334e99eb12d2f37e3ebffa970ced7b9d..fc2f9479bea2bf9599dfcaebe35294fed98b4db4 100644 --- a/stage1/zig.h +++ b/stage1/zig.h @@ -3835,7 +3835,7 @@ typedef zig_u128 zig_f80; #endif #define zig_has_f128 1 -#define zig_libc_name_f128(name) name##q +#define zig_libc_name_f128(name) name##f128 #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) #if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 typedef float zig_f128; diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 74a71249c65f6c2f839356c99bbd8416d5df1cd5..f8fbab0aaefd3d3d4b39d472eb84e41b9382dc8f 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -381,6 +381,7 @@ test "@sqrt f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.os.tag == .freebsd) { // TODO https://github.com/ziglang/zig/issues/10875 diff --git a/test/behavior/x86_64/unary.zig b/test/behavior/x86_64/unary.zig index 2b2a9e288b30c1c0a1d0ab1de61b23522582b6e8..263505f090d09aa3b76eddb309b0d6bd531057dc 100644 --- a/test/behavior/x86_64/unary.zig +++ b/test/behavior/x86_64/unary.zig @@ -56,7 +56,7 @@ fn unary(comptime op: anytype, comptime opts: struct { f32 => libc_name ++ "f", f64 => libc_name, f80 => "__" ++ libc_name ++ "x", - f128 => libc_name ++ "q", + f128 => libc_name ++ "f128", else => break :libc, }, .library_name = switch (@import("builtin").object_format) { -- 2.54.0 From 69dd10144fc723d8006f2e563fc3edd82ee4b368 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 17 Jul 2026 11:33:42 -0400 Subject: [PATCH 10/22] Type: make `f80` not extern compatible on targets lacking such a type Closes #35802 --- src/Sema.zig | 2 +- src/Type.zig | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 129b9104d385499e8443b4fc45dcf6c2e26497e8..bb2cd4eff32547c659ec0e7f14fddf3cc4b07d18 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -25675,7 +25675,6 @@ pub fn explainWhyTypeIsNotExtern( .@"opaque", .bool, - .float, .@"anyframe", => unreachable, // these *are* allowed @@ -25684,6 +25683,7 @@ pub fn explainWhyTypeIsNotExtern( try sema.errNote(src_loc, msg, "SPIR-V runtime arrays must be the last field of an extern struct", .{}); }, + .float => try sema.errNote(src_loc, msg, "'{f}' is not extern compatible on this target", .{ty.fmt(pt)}), .pointer => if (ty.isSlice(zcu)) { try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); } else { diff --git a/src/Type.zig b/src/Type.zig index 32e49a05c26a8ee5459164c02f987c92704f0f65..56b2388710b2b919a2a429fd3afa0dfa515bcf66 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -3122,7 +3122,6 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool .@"opaque", .bool, - .float, .@"anyframe", => true, @@ -3144,6 +3143,10 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool 24, 48 => zcu.getTarget().cpu.arch == .ez80, else => false, }, + .float => switch (ty.floatBits(zcu.getTarget())) { + else => true, + 80 => zcu.getTarget().cTypeBitSize(.longdouble) == 80, + }, .@"fn" => { if (position != .other) return false; return validateExternCallconv(ty.fnCallingConvention(zcu)); -- 2.54.0 From 865f329e4f9fd097bb9739566045f9b7179521c4 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 25 Jun 2026 01:53:50 -0400 Subject: [PATCH 11/22] cbe: update for compiler_rt abi changes * `tools/generate_c_size_and_align_checks.zig`: superceded by any cbe output artifact * `cTypePreferredAlignment`: no uses, if brought back, cbe should be updated to verify `__alignof` Closes #19991 Closes #20881 Closes #35523 --- lib/compiler/test_runner.zig | 1 + lib/std/Io/Semaphore.zig | 2 - lib/std/Io/Writer.zig | 6 +- lib/std/Random/RomuTrio.zig | 1 - lib/std/Random/Xoshiro256.zig | 2 - lib/std/Target.zig | 114 - lib/std/bit_set.zig | 2 - lib/std/crypto/aes.zig | 4 +- lib/std/crypto/aes_ocb.zig | 10 - lib/std/crypto/ecdsa.zig | 21 - lib/std/crypto/ff.zig | 4 - lib/std/crypto/pcurves/p384.zig | 10 +- lib/std/crypto/pcurves/secp256k1.zig | 12 +- lib/std/debug/cpu_context.zig | 2 + lib/std/fmt.zig | 2 - lib/std/fmt/float.zig | 2 +- lib/std/fs/test.zig | 5 +- lib/std/hash/auto_hash.zig | 2 +- lib/std/hash/xxhash.zig | 4 - lib/std/math.zig | 3 +- lib/std/math/big/int_test.zig | 39 +- lib/std/math/log10.zig | 5 - lib/std/math/signbit.zig | 1 + lib/std/mem.zig | 88 +- lib/std/os/linux/aarch64.zig | 2 +- lib/std/os/linux/s390x.zig | 36 +- lib/std/testing/Smith.zig | 2 +- lib/std/zon/parse.zig | 7 +- lib/std/zon/stringify.zig | 3 - lib/zig.h | 3933 +++++++++++++++----- src/codegen/c.zig | 1207 +++--- src/codegen/c/type/render_defs.zig | 182 +- src/link.zig | 2 +- src/link/C.zig | 49 +- test/behavior/abs.zig | 2 - test/behavior/align.zig | 2 - test/behavior/basic.zig | 1 - test/behavior/bit_shifting.zig | 1 - test/behavior/bitcast.zig | 7 +- test/behavior/cast.zig | 11 +- test/behavior/cast_int.zig | 1 - test/behavior/eval.zig | 1 - test/behavior/extern.zig | 1 - test/behavior/field_parent_ptr.zig | 2 - test/behavior/floatop.zig | 8 - test/behavior/fn.zig | 1 - test/behavior/math.zig | 29 - test/behavior/maximum_minimum.zig | 1 - test/behavior/muladd.zig | 4 - test/behavior/packed-struct.zig | 4 - test/behavior/pointers.zig | 2 +- test/behavior/saturating_arithmetic.zig | 7 - test/behavior/struct.zig | 8 +- test/behavior/switch_loop.zig | 3 +- test/behavior/truncate.zig | 1 - test/behavior/union.zig | 6 - test/behavior/vector.zig | 5 - test/standalone/build.zig | 1 - test/tests.zig | 64 +- tools/generate_c_size_and_align_checks.zig | 62 - 60 files changed, 3993 insertions(+), 2007 deletions(-) delete mode 100644 tools/generate_c_size_and_align_checks.zig diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index 62c09fe22800abc8aeb462dbd8c8beffe0ef7925..4e9502656c56f1e8cc43a03529d5d2599abbace5 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -377,6 +377,7 @@ pub fn mainSimple() anyerror!void { else => false, }; + testing.allocator_instance = .init(std.heap.page_allocator, .{}); testing.io_instance = .init(testing.allocator, .{}); var passed: u64 = 0; diff --git a/lib/std/Io/Semaphore.zig b/lib/std/Io/Semaphore.zig index 1f486750487ed8cd66c39306998d7434e8cd4df7..8f2137b80220fa26c19173d8a3db1098eb24f570 100644 --- a/lib/std/Io/Semaphore.zig +++ b/lib/std/Io/Semaphore.zig @@ -4,8 +4,6 @@ //! This API supports static initialization and does not require deinitialization. const Semaphore = @This(); -const builtin = @import("builtin"); - const std = @import("../std.zig"); const Io = std.Io; const testing = std.testing; diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index ca9564edff39fe329f5114aa2a2fba41c4a6fe02..c243c8551f4917ef210159743f0d55ba749d1e6a 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -874,7 +874,7 @@ pub fn splatBytes(w: *Writer, bytes: []const u8, n: usize) Error!usize { } /// Asserts the `buffer` was initialized with a capacity of at least `@sizeOf(T)` bytes. -pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.builtin.Endian) Error!void { +pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.lang.Endian) Error!void { var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined; std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian); return w.writeAll(&bytes); @@ -882,7 +882,7 @@ pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.built /// The function is inline to avoid the dead code in case `endian` is /// comptime-known and matches host endianness. -pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian) Error!void { +pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.lang.Endian) Error!void { switch (@typeInfo(@TypeOf(value))) { .@"struct" => |info| switch (info.layout) { .auto => @compileError("ill-defined memory layout"), @@ -907,7 +907,7 @@ pub inline fn writeSliceEndian( w: *Writer, Elem: type, slice: []const Elem, - endian: std.builtin.Endian, + endian: std.lang.Endian, ) Error!void { switch (@typeInfo(Elem)) { .@"struct" => |info| comptime assert(info.layout != .auto), diff --git a/lib/std/Random/RomuTrio.zig b/lib/std/Random/RomuTrio.zig index 9f005bf2f9fac8082eb4e71355dc90c73280d2b9..7352308f0d18eb6ccbe0b506bdfd4138443c89de 100644 --- a/lib/std/Random/RomuTrio.zig +++ b/lib/std/Random/RomuTrio.zig @@ -122,7 +122,6 @@ test fill { } test "buf seeding test" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const buf0: [24]u8 = @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 }); const resulting_state = .{ .x = 16294208416658607535, .y = 13964609475759908645, .z = 4703697494102998476 }; var r = RomuTrio.init(0); diff --git a/lib/std/Random/Xoshiro256.zig b/lib/std/Random/Xoshiro256.zig index 6cb0583d982622b3f7df21b94368b03ddeb80c17..9c1ea9cfec6843cf2b9151ac08cb44aebd810936 100644 --- a/lib/std/Random/Xoshiro256.zig +++ b/lib/std/Random/Xoshiro256.zig @@ -89,8 +89,6 @@ pub fn fill(self: *Xoshiro256, buf: []u8) void { } test "sequence" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - var r = Xoshiro256.init(0); const seq1 = [_]u64{ diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 6124ffd96597d33dbd1027ae8b5757989b536c7a..5dc5075bada694841849a65904acdaa60471a23b 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3575,120 +3575,6 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { ); } -pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { - // Overrides for unusual alignments - switch (target.cpu.arch) { - .arc, .arceb => switch (c_type) { - .longdouble => return 4, - else => {}, - }, - .avr, - .ez80, - => return 1, - .x86 => switch (target.os.tag) { - .windows, .uefi => switch (c_type) { - .longdouble => switch (target.abi) { - .gnu => return 4, - else => return 8, - }, - else => {}, - }, - else => switch (c_type) { - .longdouble => return 4, - else => {}, - }, - }, - .m68k => switch (c_type) { - .int, .uint, .long, .ulong => return 2, - else => {}, - }, - .wasm32, .wasm64 => switch (target.os.tag) { - .emscripten => switch (c_type) { - .longdouble => return 8, - else => {}, - }, - else => {}, - }, - else => {}, - } - - // Next-power-of-two-aligned, up to a maximum. - return @min( - std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8), - @as(u16, switch (target.cpu.arch) { - .x86_16, - .msp430, - => 2, - - .arc, - .arceb, - .csky, - .kalimba, - .microblaze, - .microblazeel, - .or1k, - .propeller, - .sh, - .sheb, - .xcore, - .xtensa, - .xtensaeb, - => 4, - - .amdgcn, - .arm, - .armeb, - .bpfeb, - .bpfel, - .hexagon, - .hppa, - .lanai, - .m68k, - .m88k, - .mips, - .mipsel, - .nvptx, - .nvptx64, - .s390x, - .sparc, - .thumb, - .thumbeb, - .x86, - => 8, - - .aarch64, - .aarch64_be, - .alpha, - .hppa64, - .kvx, - .loongarch32, - .loongarch64, - .mips64, - .mips64el, - .powerpc, - .powerpcle, - .powerpc64, - .powerpc64le, - .riscv32, - .riscv32be, - .riscv64, - .riscv64be, - .sparc64, - .spirv32, - .spirv64, - .ve, - .wasm32, - .wasm64, - .x86_64, - => 16, - - .avr, - .ez80, - => unreachable, // Handled above. - }), - ); -} - pub fn cMaxIntAlignment(target: *const Target) u16 { return switch (target.cpu.arch) { .avr, diff --git a/lib/std/bit_set.zig b/lib/std/bit_set.zig index b7920e20124d4e04f78662a14861ed7f9f6ae711..1a31e3b1a50b55cb8f26aa63789c1a04e9f6bc84 100644 --- a/lib/std/bit_set.zig +++ b/lib/std/bit_set.zig @@ -1707,8 +1707,6 @@ fn testStaticBitSet(comptime Set: type) !void { } test Integer { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - try testStaticBitSet(Integer(0)); try testStaticBitSet(Integer(1)); try testStaticBitSet(Integer(2)); diff --git a/lib/std/crypto/aes.zig b/lib/std/crypto/aes.zig index acf3a72e1fd2616a6074f896c3cf53da02364c48..54d1bd0dc8474d9eb299ca823864fdc9a1a001ea 100644 --- a/lib/std/crypto/aes.zig +++ b/lib/std/crypto/aes.zig @@ -6,9 +6,9 @@ const has_aesni = builtin.cpu.has(.x86, .aes); const has_avx = builtin.cpu.has(.x86, .avx); const has_armaes = builtin.cpu.has(.aarch64, .aes); // C backend doesn't currently support passing vectors to inline asm. -const impl = if (builtin.cpu.arch == .x86_64 and builtin.zig_backend != .stage2_c and has_aesni and has_avx) impl: { +const impl = if (builtin.cpu.arch == .x86_64 and has_aesni and has_avx) impl: { break :impl @import("aes/aesni.zig"); -} else if (builtin.cpu.arch == .aarch64 and builtin.zig_backend != .stage2_c and has_armaes) impl: { +} else if (builtin.cpu.arch == .aarch64 and (builtin.zig_backend != .stage2_c or !builtin.os.tag.isDarwin()) and has_armaes) impl: { break :impl @import("aes/armcrypto.zig"); } else impl: { break :impl @import("aes/soft.zig"); diff --git a/lib/std/crypto/aes_ocb.zig b/lib/std/crypto/aes_ocb.zig index 36e2aaa84cbb852ab0dc8b20ccf4aca8ecfea710..5c3af0615112822c58c892fa373150e23050dfcc 100644 --- a/lib/std/crypto/aes_ocb.zig +++ b/lib/std/crypto/aes_ocb.zig @@ -262,8 +262,6 @@ const hexToBytes = std.fmt.hexToBytes; const testing = std.testing; test "AesOcb test vector 1" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -281,8 +279,6 @@ test "AesOcb test vector 1" { } test "AesOcb test vector 2" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -303,8 +299,6 @@ test "AesOcb test vector 2" { } test "AesOcb test vector 3" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -329,8 +323,6 @@ test "AesOcb test vector 3" { } test "AesOcb test vector 4" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -356,8 +348,6 @@ test "AesOcb test vector 4" { } test "AesOcb in-place encryption-decryption" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; diff --git a/lib/std/crypto/ecdsa.zig b/lib/std/crypto/ecdsa.zig index b111b8e52a706b7b869a8091747934291912eff6..8977851b44ea04596ff686ec46fa576aa9b9693f 100644 --- a/lib/std/crypto/ecdsa.zig +++ b/lib/std/crypto/ecdsa.zig @@ -1,4 +1,3 @@ -const builtin = @import("builtin"); const std = @import("std"); const crypto = std.crypto; const fmt = std.fmt; @@ -415,8 +414,6 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { } test "Basic operations over EcdsaP384Sha384" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaP384Sha384; const kp = Scheme.KeyPair.generate(io); @@ -432,8 +429,6 @@ test "Basic operations over EcdsaP384Sha384" { } test "Basic operations over Secp256k1" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaSecp256k1Sha256oSha256; const kp = Scheme.KeyPair.generate(io); @@ -449,8 +444,6 @@ test "Basic operations over Secp256k1" { } test "Basic operations over EcdsaP384Sha256" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256); const kp = Scheme.KeyPair.generate(io); @@ -466,8 +459,6 @@ test "Basic operations over EcdsaP384Sha256" { } test "Verifying a existing signature with EcdsaP384Sha256" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256); // zig fmt: off const sk_bytes = [_]u8{ @@ -503,8 +494,6 @@ test "Verifying a existing signature with EcdsaP384Sha256" { } test "Prehashed message operations" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaP256Sha256; @@ -539,8 +528,6 @@ const TestVector = struct { }; test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // well-formed DER encoding -> expected valid .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76" }, @@ -711,8 +698,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" { } test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // S encoded with negative sign -> expected invalid .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180220b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db" }, @@ -1026,8 +1011,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" { } test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // canonical sign-bit padding on R; canonical sign-bit padding on S -> expected valid .{ .key = "0429bdb76d5fa741bfd70233cb3a66cc7d44beb3b0663d92a8136650478bcefb61ef182e155a54345a5e8e5e88f064e5bc9a525ab7f764dad3dae1468c2b419f3b62b9ba917d5e8c4fb1ec47404a3fc76474b2713081be9db4c00e043ada9fc4a3", .msg = "4d7367", .sig = "3066023100d7143a836608b25599a7f28dec6635494c2992ad1e2bbeecb7ef601a9c01746e710ce0d9c48accb38a79ede5b9638f3402310080f9e165e8c61035bf8aa7b5533960e46dd0e211c904a064edb6de41f797c0eae4e327612ee3f816f4157272bb4fabc9" }, @@ -1243,8 +1226,6 @@ test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" { } test "Test vectors from Project Wycheproof - EcdsaP384Sha384 invalid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // S encoded with negative sign -> expected invalid .{ .key = "042da57dda1089276a543f9ffdac0bff0d976cad71eb7280e7d9bfd9fee4bdb2f20f47ff888274389772d98cc5752138aa4b6d054d69dcf3e25ec49df870715e34883b1836197d76f8ad962e78f6571bbc7407b0d6091f9e4d88f014274406174f", .msg = "313233343030", .sig = "3064023012b30abef6b5476fe6b612ae557c0425661e26b44b1bfe19daf2ca28e3113083ba8e4ae4cc45a0320abd3394f1c548d70230e7bf25603e2d07076ff30b7a2abec473da8b11c572b35fc631991d5de62ddca7525aaba89325dfd04fecc47bff426f82" }, @@ -1631,8 +1612,6 @@ fn tvTry(comptime Scheme: type, vector: TestVector) !void { } test "Sec1 encoding/decoding" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaP384Sha384; const kp = Scheme.KeyPair.generate(io); diff --git a/lib/std/crypto/ff.zig b/lib/std/crypto/ff.zig index bf9584dfa3ad033652130705937972171370669c..c59dc92c61d66a457aabd11175f9ee0c5f83e582 100644 --- a/lib/std/crypto/ff.zig +++ b/lib/std/crypto/ff.zig @@ -966,8 +966,6 @@ const ct_unprotected = struct { }; test "finite field arithmetic" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const M = Modulus(256); const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233); var x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733); @@ -1066,8 +1064,6 @@ test "finite field arithmetic" { } fn testCt(ct_: anytype) !void { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const l0: Limb = 0; const l1: Limb = 1; try testing.expectEqual(l1, ct_.select(true, l1, l0)); diff --git a/lib/std/crypto/pcurves/p384.zig b/lib/std/crypto/pcurves/p384.zig index 8bc0ec36f2d64e3c6d73e5d782b6df143c6a859f..7b97bf92b1b5ab138659e1348822d06885017fc5 100644 --- a/lib/std/crypto/pcurves/p384.zig +++ b/lib/std/crypto/pcurves/p384.zig @@ -56,7 +56,7 @@ pub const P384 = struct { } /// Create a point from serialized affine coordinates. - pub fn fromSerializedAffineCoordinates(xs: [48]u8, ys: [48]u8, endian: std.builtin.Endian) (NonCanonicalError || EncodingError)!P384 { + pub fn fromSerializedAffineCoordinates(xs: [48]u8, ys: [48]u8, endian: std.lang.Endian) (NonCanonicalError || EncodingError)!P384 { const x = try Fe.fromBytes(xs, endian); const y = try Fe.fromBytes(ys, endian); return fromAffineCoordinates(.{ .x = x, .y = y }); @@ -395,7 +395,7 @@ pub const P384 = struct { /// Multiply an elliptic curve point by a scalar. /// Return error.IdentityElement if the result is the identity element. - pub fn mul(p: P384, s_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 { + pub fn mul(p: P384, s_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); if (p.is_base) { return pcMul16(&basePointPc, s, false); @@ -407,7 +407,7 @@ pub const P384 = struct { /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulPublic(p: P384, s_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 { + pub fn mulPublic(p: P384, s_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); if (p.is_base) { return pcMul16(&basePointPc, s, true); @@ -419,7 +419,7 @@ pub const P384 = struct { /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulDoubleBasePublic(p1: P384, s1_: [48]u8, p2: P384, s2_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 { + pub fn mulDoubleBasePublic(p1: P384, s1_: [48]u8, p2: P384, s2_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 { const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_); const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_); try p1.rejectIdentity(); @@ -478,7 +478,5 @@ pub const AffineCoordinates = struct { }; test { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - _ = @import("tests/p384.zig"); } diff --git a/lib/std/crypto/pcurves/secp256k1.zig b/lib/std/crypto/pcurves/secp256k1.zig index 9ce8b944ebbffc071bcdd3be90fa47463525289e..3c36b9b2ed49d45dc1a13c0d9aab2a69d6dd3398 100644 --- a/lib/std/crypto/pcurves/secp256k1.zig +++ b/lib/std/crypto/pcurves/secp256k1.zig @@ -51,7 +51,7 @@ pub const Secp256k1 = struct { }; /// Compute r1 and r2 so that k = r1 + r2*lambda (mod L). - pub fn splitScalar(s: [32]u8, endian: std.builtin.Endian) NonCanonicalError!SplitScalar { + pub fn splitScalar(s: [32]u8, endian: std.lang.Endian) NonCanonicalError!SplitScalar { const b1_neg_s = comptime s: { var buf: [32]u8 = undefined; mem.writeInt(u256, &buf, 303414439467246543595250775667605759171, .little); @@ -109,7 +109,7 @@ pub const Secp256k1 = struct { } /// Create a point from serialized affine coordinates. - pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: std.builtin.Endian) (NonCanonicalError || EncodingError)!Secp256k1 { + pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: std.lang.Endian) (NonCanonicalError || EncodingError)!Secp256k1 { const x = try Fe.fromBytes(xs, endian); const y = try Fe.fromBytes(ys, endian); return fromAffineCoordinates(.{ .x = x, .y = y }); @@ -423,7 +423,7 @@ pub const Secp256k1 = struct { /// Multiply an elliptic curve point by a scalar. /// Return error.IdentityElement if the result is the identity element. - pub fn mul(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 { + pub fn mul(p: Secp256k1, s_: [32]u8, endian: std.lang.Endian) IdentityElementError!Secp256k1 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); if (p.is_base) { return pcMul16(&basePointPc, s, false); @@ -435,7 +435,7 @@ pub const Secp256k1 = struct { /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulPublic(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) (IdentityElementError || NonCanonicalError)!Secp256k1 { + pub fn mulPublic(p: Secp256k1, s_: [32]u8, endian: std.lang.Endian) (IdentityElementError || NonCanonicalError)!Secp256k1 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); const zero = comptime scalar.Scalar.zero.toBytes(.little); if (mem.eql(u8, &zero, &s)) { @@ -497,7 +497,7 @@ pub const Secp256k1 = struct { /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulDoubleBasePublic(p1: Secp256k1, s1_: [32]u8, p2: Secp256k1, s2_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 { + pub fn mulDoubleBasePublic(p1: Secp256k1, s1_: [32]u8, p2: Secp256k1, s2_: [32]u8, endian: std.lang.Endian) IdentityElementError!Secp256k1 { const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_); const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_); try p1.rejectIdentity(); @@ -556,7 +556,5 @@ pub const AffineCoordinates = struct { }; test { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - _ = @import("tests/secp256k1.zig"); } diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 36be9fe60e0ebe084ab2e045702bc91628ff9bf6..ab90b9b2c27e374ef56148334eb83fcc13d6ba75 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -2020,6 +2020,8 @@ const signal_ucontext_t = switch (native_os) { .mips64el, .or1k, .s390x, + .sh, + .sheb, .x86, .x86_64, .xtensa, diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 7cdc44269cdc95b492eb8ac718a53d7fe721af55..0c3dba4a7a95ff9a68f8d9f64d082c35565134a7 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -1082,8 +1082,6 @@ test "float.libc.sanity" { } test "union" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const TU = union(enum) { float: f32, int: u32, diff --git a/lib/std/fmt/float.zig b/lib/std/fmt/float.zig index 25bf97f22ae52df136be9dbbdeab2e0fdedfdc18..e055959825832e1889d6d2c0fb6cfd131d06d50b 100644 --- a/lib/std/fmt/float.zig +++ b/lib/std/fmt/float.zig @@ -65,7 +65,7 @@ pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 { const DT = if (@bitSizeOf(T) <= 64) u64 else u128; const tables = switch (DT) { - u64 => if (@import("builtin").mode == .small) &Backend64_TablesSmall else &Backend64_TablesFull, + u64 => if (builtin.mode == .small) &Backend64_TablesSmall else &Backend64_TablesFull, u128 => &Backend128_Tables, else => unreachable, }; diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index fc613ccdaa313d46dab643f849149293f422a9a5..e9c2d5f8f8e167b7556ec5eaec20d994cc2f5d73 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -2205,7 +2205,7 @@ test "'.' and '..' in absolute functions" { } test "chmod" { - if (native_os == .windows or native_os == .wasi) return; + if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; const io = testing.io; @@ -2228,8 +2228,7 @@ test "chmod" { } test "change ownership" { - if (native_os == .windows or native_os == .wasi) - return error.SkipZigTest; + if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; const io = testing.io; diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig index 3964ad5f946f899a51cbfdefb38cb42d2973b74d..1cb8e93092ec55534810432e78e896d88ffa881a 100644 --- a/lib/std/hash/auto_hash.zig +++ b/lib/std/hash/auto_hash.zig @@ -225,7 +225,7 @@ fn testHashDeepRecursive(key: anytype) u64 { test "typeContainsSlice" { comptime { - try testing.expect(!typeContainsSlice(std.meta.Tag(std.builtin.Type))); + try testing.expect(!typeContainsSlice(std.meta.Tag(std.lang.Type))); try testing.expect(typeContainsSlice([]const u8)); try testing.expect(!typeContainsSlice(u8)); diff --git a/lib/std/hash/xxhash.zig b/lib/std/hash/xxhash.zig index 27f2701443cc919a9cd2686165ecc8ae087ae002..72c8bff280548134abcb34a71857c7c101683dae 100644 --- a/lib/std/hash/xxhash.zig +++ b/lib/std/hash/xxhash.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const builtin = @import("builtin"); const mem = std.mem; const expectEqual = std.testing.expectEqual; @@ -788,7 +787,6 @@ fn testExpect(comptime H: type, seed: anytype, input: []const u8, expected: u64) } test "xxhash3" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const H = XxHash3; // Non-Seeded Tests try testExpect(H, 0, "", 0x2d06800538d394c2); @@ -820,7 +818,6 @@ test "xxhash3" { } test "xxhash3 smhasher" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const Test = struct { fn do() !void { try expectEqual(verify.smhasher(XxHash3.hash), 0x9a636405); @@ -832,7 +829,6 @@ test "xxhash3 smhasher" { } test "xxhash3 iterative api" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const Test = struct { fn do() !void { try verify.iterativeApi(XxHash3); diff --git a/lib/std/math.zig b/lib/std/math.zig index 0beb62ae6a9eb10cdb78e887f900bebcde0612f4..ae644d6fceff795c5cb1864acada365867a19521 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -1385,7 +1385,8 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) { } test lerp { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884 + if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isX86()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and !comptime builtin.cpu.has(.x86, .fma)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884 try testing.expectEqual(@as(f64, 75), lerp(50, 100, 0.5)); diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index 485ae4918cce7545119b5b014f7c8133656aaf0b..271041e761a1d6f089c7733aa2964913c771dc0d 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -1,5 +1,4 @@ const std = @import("../../std.zig"); -const builtin = @import("builtin"); const mem = std.mem; const testing = std.testing; const Managed = std.math.big.int.Managed; @@ -276,8 +275,6 @@ fn setFloat(comptime Float: type) !void { try expectNormalized(1 << 10, res.toConst()); } test setFloat { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - try setFloat(f16); try setFloat(f32); try setFloat(f64); @@ -484,7 +481,6 @@ fn toFloat(comptime Float: type) !void { ); } test toFloat { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; try toFloat(f16); try toFloat(f32); try toFloat(f64); @@ -1391,8 +1387,6 @@ test "mul multi-single" { } test "mul multi-multi" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var op1: u256 = 0x998888efefefefefefefef; var op2: u256 = 0x333000abababababababab; _ = .{ &op1, &op2 }; @@ -1514,8 +1508,6 @@ test "mulWrap single-single signed" { } test "mulWrap multi-multi unsigned" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var op1: u256 = 0x998888efefefefefefefef; var op2: u256 = 0x333000abababababababab; _ = .{ &op1, &op2 }; @@ -1533,11 +1525,6 @@ test "mulWrap multi-multi unsigned" { } test "mulWrap multi-multi signed" { - switch (builtin.zig_backend) { - .stage2_c => return error.SkipZigTest, - else => {}, - } - var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb) - 1); defer a.deinit(); var b = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb)); @@ -1744,8 +1731,6 @@ test "div q=0 alias" { } test "div multi-multi q < r" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const op1 = 0x1ffffffff0078f432; const op2 = 0x1ffffffff01000000; var a = try Managed.initSet(testing.allocator, op1); @@ -2166,8 +2151,6 @@ test "div ceil multi-limb" { } test "div multi-multi with rem" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x99990000111122223333); @@ -2184,8 +2167,6 @@ test "div multi-multi with rem" { } test "div multi-multi no rem" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeedb4fec200ee3a4286361); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x99990000111122223333); @@ -2202,8 +2183,6 @@ test "div multi-multi no rem" { } test "div multi-multi (2 branch)" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x866666665555555588888887777777761111111111111111); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x86666666555555554444444433333333); @@ -2220,8 +2199,6 @@ test "div multi-multi (2 branch)" { } test "div multi-multi (3.1/3.3 branch)" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x11111111111111111111111111111111111111111111111111111111111111); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x1111111111111111111111111111111111111111171); @@ -2238,8 +2215,6 @@ test "div multi-multi (3.1/3.3 branch)" { } test "div multi-single zero-limb trailing" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x60000000000000000000000000000000000000000000000000000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x10000000000000000); @@ -2258,8 +2233,6 @@ test "div multi-single zero-limb trailing" { } test "div multi-multi zero-limb trailing (with rem)" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000); @@ -2279,8 +2252,6 @@ test "div multi-multi zero-limb trailing (with rem)" { } test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x8666666655555555888888877777777611111111111111110000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000); @@ -2300,8 +2271,6 @@ test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count } test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x866666665555555544444444333333330000000000000000); @@ -2832,10 +2801,6 @@ test "bitNotWrap signed multi" { } test "bitNotWrap more than two limbs" { - // This test requires int sizes greater than 128 bits. - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - var a = try Managed.initSet(testing.allocator, maxInt(Limb)); defer a.deinit(); @@ -3179,8 +3144,6 @@ test "gcd non-one large" { } test "gcd large multi-limb result" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x12345678123456781234567812345678123456781234567812345678); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x12345671234567123456712345671234567123456712345671234567); @@ -3431,7 +3394,7 @@ test "big int conversion read/write twos complement" { var buffer1 = try testing.allocator.alloc(u8, 64); defer testing.allocator.free(buffer1); - const endians = [_]std.builtin.Endian{ .little, .big }; + const endians = [_]std.lang.Endian{ .little, .big }; const abi_size = 64; for (endians) |endian| { diff --git a/lib/std/math/log10.zig b/lib/std/math/log10.zig index a46948cac54dddf2dd7a822a68188f219086a9af..0dc5b2a8be90cd88276ec344c9de51a492b6430a 100644 --- a/lib/std/math/log10.zig +++ b/lib/std/math/log10.zig @@ -1,5 +1,4 @@ const std = @import("../std.zig"); -const builtin = @import("builtin"); const testing = std.testing; /// Returns the base-10 logarithm of x. @@ -135,10 +134,6 @@ inline fn less_than_5(x: u32) u32 { } test log10_int { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - inline for ( .{ u8, u16, u32, u64, u128, u256, u512 }, .{ 2, 4, 9, 19, 38, 77, 154 }, diff --git a/lib/std/math/signbit.zig b/lib/std/math/signbit.zig index 115aaa26eb056e31c423695cd2a2cde79050d0a1..36a933e641ce35985523b25bb403f234143c20bc 100644 --- a/lib/std/math/signbit.zig +++ b/lib/std/math/signbit.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const std = @import("../std.zig"); const math = std.math; const expect = std.testing.expect; diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 8353c0ca8e209dd1516371926e0fbfd00f874ded..9529f73b93586014b6338eef2ecd780461b9cd37 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -4780,62 +4780,47 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize { pub fn doNotOptimizeAway(val: anytype) void { if (@inComptime()) return; + if (builtin.zig_backend == .stage2_c and builtin.abi == .msvc) { + _ = @atomicRmw(*const anyopaque, @as(*volatile *const anyopaque, &struct { + var escape: *const anyopaque = undefined; + }.escape), .Xchg, &val, .acq_rel); // TODO: syncscope("singlethreaded") + return; + } + const max_gp_register_bits = @bitSizeOf(c_long); - const t = @typeInfo(@TypeOf(val)); - switch (t) { + switch (@typeInfo(@TypeOf(val))) { .void, .null, .comptime_int, .comptime_float => return, .@"enum" => doNotOptimizeAway(@backingInt(val)), .bool => doNotOptimizeAway(@intFromBool(val)), - .int => { - const bits = t.int.bits; - if (bits <= max_gp_register_bits and builtin.zig_backend != .stage2_c) { - const val2 = @as( - @Int(t.int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, bits))), - val, - ); - asm volatile ("" - : - : [_] "r" (val2), - ); - } else doNotOptimizeAway(&val); - }, - .float => { - if ((t.float.bits == 32 or t.float.bits == 64) and builtin.zig_backend != .stage2_c) { - asm volatile ("" - : - : [_] "rm" (val), - ); - } else doNotOptimizeAway(&val); - }, - .pointer => { - if (builtin.zig_backend == .stage2_c) { - doNotOptimizeAwayC(val); - } else { - asm volatile ("" - : - : [_] "m" (val), - : .{ .memory = true }); - } - }, - .array => { - if (t.array.len * @sizeOf(t.array.child) <= 64) { - for (val) |v| doNotOptimizeAway(v); - } else doNotOptimizeAway(&val); + .int => |int| if (int.bits <= max_gp_register_bits) { + const val2 = @as( + @Int(int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, int.bits))), + val, + ); + asm volatile ("" + : + : [_] "r" (val2), + ); + } else doNotOptimizeAway(&val), + .float => |float| switch (float.bits) { + else => comptime unreachable, + 16, 80, 128 => doNotOptimizeAway(&val), + 32, 64 => asm volatile ("" + : + : [_] "rm" (val), + ), }, + .pointer => asm volatile ("" + : + : [_] "m" (val), + : .{ .memory = true }), + .array => |array| if (array.len * @sizeOf(array.child) <= 64) { + for (val) |v| doNotOptimizeAway(v); + } else doNotOptimizeAway(&val), else => doNotOptimizeAway(&val), } } -/// .stage2_c doesn't support asm blocks yet, so use volatile stores instead -var deopt_target: if (builtin.zig_backend == .stage2_c) u8 else void = undefined; -fn doNotOptimizeAwayC(ptr: anytype) void { - const dest = @as(*volatile u8, @ptrCast(&deopt_target)); - for (asBytes(ptr)) |b| { - dest.* = b; - } - dest.* = 0; -} - test doNotOptimizeAway { comptime doNotOptimizeAway("test"); @@ -4994,12 +4979,9 @@ pub fn alignInSlice(slice: anytype, comptime new_alignment: usize) ?AlignedSlice } test "read/write(Var)PackedInt" { - switch (builtin.cpu.arch) { - // This test generates too much code to execute on WASI. - // LLVM backend fails with "too many locals: locals exceed maximum" - .wasm32, .wasm64 => return error.SkipZigTest, - else => {}, - } + // This test generates too much code to execute on WASI. + // LLVM backend fails with "too many locals: locals exceed maximum" + if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; const foreign_endian: Endian = if (native_endian == .big) .little else .big; const expect = std.testing.expect; diff --git a/lib/std/os/linux/aarch64.zig b/lib/std/os/linux/aarch64.zig index a49c1d48bedd05331da4a7a25c6f1006797aa251..431097feccf104eba84a3f347fac6fe29ae1eb57 100644 --- a/lib/std/os/linux/aarch64.zig +++ b/lib/std/os/linux/aarch64.zig @@ -154,7 +154,7 @@ pub const restore = restore_rt; pub fn restore_rt() callconv(.naked) noreturn { switch (builtin.zig_backend) { .stage2_c => asm volatile ( - \\ mov x8, %[number] + \\ mov w8, %[number] \\ svc #0 : : [number] "i" (@backingInt(SYS.rt_sigreturn)), diff --git a/lib/std/os/linux/s390x.zig b/lib/std/os/linux/s390x.zig index 9b9ca0cd0327c93c1260128f42a497e8d96a3094..3c44beeb8df7bb5d7f0d7d7fb13f3c35c840da01 100644 --- a/lib/std/os/linux/s390x.zig +++ b/lib/std/os/linux/s390x.zig @@ -174,19 +174,35 @@ pub fn clone() callconv(.naked) u64 { } pub fn restore() callconv(.naked) noreturn { - asm volatile ( - \\svc 0 - : - : [number] "{r1}" (@backingInt(SYS.sigreturn)), - ); + switch (builtin.zig_backend) { + .stage2_c => asm volatile ( + \\lghi %%r1, %[number] + \\svc 0 + : + : [number] "K" (@backingInt(SYS.sigreturn)), + ), + else => asm volatile ( + \\svc 0 + : + : [number] "{r1}" (@backingInt(SYS.sigreturn)), + ), + } } pub fn restore_rt() callconv(.naked) noreturn { - asm volatile ( - \\svc 0 - : - : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)), - ); + switch (builtin.zig_backend) { + .stage2_c => asm volatile ( + \\lghi %%r1, %[number] + \\svc 0 + : + : [number] "K" (@backingInt(SYS.rt_sigreturn)), + ), + else => asm volatile ( + \\svc 0 + : + : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)), + ), + } } pub const time_t = i64; diff --git a/lib/std/testing/Smith.zig b/lib/std/testing/Smith.zig index 7e3235fe0e5ffd1163a2cc7bf46f7583eb0a06ae..a60a9802391078fe6ca400fb4409216bd73ff345 100644 --- a/lib/std/testing/Smith.zig +++ b/lib/std/testing/Smith.zig @@ -708,7 +708,7 @@ fn constructInput(comptime values: []const union(enum) { } test value { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const S = struct { v: void = {}, diff --git a/lib/std/zon/parse.zig b/lib/std/zon/parse.zig index b22de08eacccf9c75e24a6f32e85ce7d795e12a8..16294f3df6d763df2587b48fbb99e3b6615d478f 100644 --- a/lib/std/zon/parse.zig +++ b/lib/std/zon/parse.zig @@ -9,7 +9,6 @@ //! For lower level control over parsing, see `std.zig.Zoir`. const std = @import("std"); -const builtin = @import("builtin"); const Allocator = std.mem.Allocator; const Ast = std.zig.Ast; const Zoir = std.zig.Zoir; @@ -1868,8 +1867,6 @@ test "std.zon tuples" { // Test sizes 0 to 3 since small sizes get parsed differently test "std.zon arrays and slices" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/20881 - const gpa = std.testing.allocator; // Literals @@ -2802,8 +2799,6 @@ test "std.zon negative char" { } test "std.zon parse float" { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; - const gpa = std.testing.allocator; // Test decimals @@ -3135,7 +3130,7 @@ test "std.zon free on error" { } test "std.zon vector" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15330 + const builtin = @import("builtin"); if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25957 const gpa = std.testing.allocator; diff --git a/lib/std/zon/stringify.zig b/lib/std/zon/stringify.zig index 57b62d41cac6c3f9aa0e442bd276edb33f2679c2..a1c6b39ebe25a350d08eba57008fbd3522c16f76 100644 --- a/lib/std/zon/stringify.zig +++ b/lib/std/zon/stringify.zig @@ -1151,9 +1151,6 @@ test "std.zon depth limits" { } test "std.zon stringify primitives" { - // Issue: https://github.com/ziglang/zig/issues/20880 - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - try expectSerializeEqual( \\.{ \\ .a = 1.5, diff --git a/lib/zig.h b/lib/zig.h index fc2f9479bea2bf9599dfcaebe35294fed98b4db4..139263d11132833d2c64539c2b39cf44b3bd0b89 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -166,6 +166,12 @@ #endif #define zig_expand_has_builtin(b) zig_has_builtin(b) +#if defined(__has_feature) +#define zig_has_feature(feature) __has_feature(feature) +#else +#define zig_has_feature(feature) 0 +#endif + #if defined(__has_attribute) #define zig_has_attribute(attribute) __has_attribute(attribute) #else @@ -175,9 +181,9 @@ #if __STDC_VERSION__ >= 201112L #define zig_static_assert(cond, msg) _Static_assert(cond, msg) #elif zig_has_attribute(unused) -#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused)) +#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] __attribute__((unused)) #else -#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] +#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] #endif #if __STDC_VERSION__ >= 202311L @@ -267,12 +273,20 @@ #if __STDC_VERSION__ >= 202311L #define zig_align(alignment) alignas(alignment) -#elif __STDC_VERSION__ >= 201112L +#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas) #define zig_align(alignment) _Alignas(alignment) #else #define zig_align(alignment) zig_under_align(alignment) #endif +#if __STDC_VERSION__ >= 202311L +#define zig_alignOf(Type) alignof(Type) +#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignof) +#define zig_alignOf(Type) _Alignof(Type) +#else +#define zig_alignOf(Type) (sizeof(struct { char c; Type t; }) - sizeof(Type)) +#endif + #if zig_has_attribute(aligned) || defined(zig_tinyc) #define zig_align_fn(alignment) __attribute__((aligned(alignment))) #elif defined(zig_msvc) @@ -350,11 +364,9 @@ #define zig_export(symbol, name) __attribute__((alias(symbol))) #else #define zig_export(symbol, name) ; \ - __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol)) + __asm("\t.globl\t" zig_mangle_c(name) "\n" zig_mangle_c(name) " = " zig_mangle_c(symbol)) #endif -#define zig_mangled_tentative zig_mangled -#define zig_mangled_final zig_mangled #if defined(zig_msvc) #define zig_mangled(mangled, unmangled) ; \ zig_export(#mangled, unmangled) @@ -364,7 +376,7 @@ #else /* zig_msvc */ #define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled)) #define zig_mangled_export(mangled, unmangled, symbol) \ - zig_mangled_final(mangled, unmangled) \ + zig_mangled(mangled, unmangled) \ zig_export(symbol, unmangled) #endif /* zig_msvc */ @@ -550,6 +562,9 @@ #define zig_noreturn #endif +#define zig_has_always 1 +#define zig_has_never 0 + #define zig_compiler_rt_abbrev_uint32_t si #define zig_compiler_rt_abbrev_int32_t si #define zig_compiler_rt_abbrev_uint64_t di @@ -560,7 +575,11 @@ #define zig_compiler_rt_abbrev_zig_f32 sf #define zig_compiler_rt_abbrev_zig_f64 df #define zig_compiler_rt_abbrev_zig_f80 xf +#ifdef zig_powerpc +#define zig_compiler_rt_abbrev_zig_f128 kf +#else #define zig_compiler_rt_abbrev_zig_f128 tf +#endif zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t); zig_extern void *memset (void *, int, size_t); @@ -645,16 +664,6 @@ typedef signed long long int16_t; #define INT16_MAX ( INT16_C(0x7FFF)) #define UINT16_MAX ( INT16_C(0xFFFF)) -#if defined(zig_ez80) -typedef unsigned int uint24_t; -typedef signed int int24_t; -#define INT24_C(c) c -#define UINT24_C(c) c##U -#endif -#define INT24_MIN (~INT24_C(0x7FFF)) -#define INT24_MAX ( INT24_C(0x7FFF)) -#define UINT24_MAX ( INT24_C(0xFFFF)) - #if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF typedef unsigned char uint32_t; typedef signed char int32_t; @@ -685,17 +694,6 @@ typedef signed long long int32_t; #define INT32_MAX ( INT32_C(0x7FFFFFFF)) #define UINT32_MAX ( INT32_C(0xFFFFFFFF)) -#if defined(zig_ez80) -typedef unsigned __int48 uint48_t; -typedef signed __int48 int48_t; -#define INT48_C(c) c -/* no suffix */ -#define UINT48_C(c) ((uint48_t)(c)) -#endif -#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF)) -#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF)) -#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF)) - #if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF typedef unsigned char uint64_t; typedef signed char int64_t; @@ -726,6 +724,27 @@ typedef signed long long int64_t; #define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF)) #define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF)) +#if defined(zig_ez80) + +typedef unsigned int uint24_t; +typedef signed int int24_t; +#define INT24_C(c) c +#define UINT24_C(c) c##U +#define INT24_MIN (~INT24_C(0x7FFF)) +#define INT24_MAX ( INT24_C(0x7FFF)) +#define UINT24_MAX ( INT24_C(0xFFFF)) + +typedef unsigned __int48 uint48_t; +typedef signed __int48 int48_t; +#define INT48_C(c) c +/* no suffix */ +#define UINT48_C(c) ((uint48_t)(c)) +#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF)) +#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF)) +#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF)) + +#endif + typedef size_t uintptr_t; typedef ptrdiff_t intptr_t; @@ -739,23 +758,145 @@ typedef ptrdiff_t intptr_t; #define zig_maxInt_i16 INT16_MAX #define zig_minInt_u16 UINT16_C(0) #define zig_maxInt_u16 UINT16_MAX -#define zig_minInt_i24 INT24_MIN -#define zig_maxInt_i24 INT24_MAX -#define zig_minInt_u24 UINT24_C(0) -#define zig_maxInt_u24 UINT24_MAX #define zig_minInt_i32 INT32_MIN #define zig_maxInt_i32 INT32_MAX #define zig_minInt_u32 UINT32_C(0) #define zig_maxInt_u32 UINT32_MAX -#define zig_minInt_i48 INT48_MIN -#define zig_maxInt_i48 INT48_MAX -#define zig_minInt_u48 UINT48_C(0) -#define zig_maxInt_u48 UINT48_MAX #define zig_minInt_i64 INT64_MIN #define zig_maxInt_i64 INT64_MAX #define zig_minInt_u64 UINT64_C(0) #define zig_maxInt_u64 UINT64_MAX +// zig_promoted_T implements C integral promotions except with signedness preserved, which +// allows wrapping operations to avoid the ub that would be caused by the normal promotion. + +#if INT8_MAX <= INT_MAX +typedef unsigned int zig_promoted_i8; +#elif INT8_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i8; +#elif INT8_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i8; +#else +typedef int8_t zig_promoted_i8; +#endif +#if UINT8_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u8; +#elif UINT8_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u8; +#elif UINT8_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u8; +#else +typedef uint8_t zig_promoted_u8; +#endif + +#if INT16_MAX <= INT_MAX +typedef unsigned int zig_promoted_i16; +#elif INT16_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i16; +#elif INT16_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i16; +#else +typedef int16_t zig_promoted_i16; +#endif +#if UINT16_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u16; +#elif UINT16_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u16; +#elif UINT16_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u16; +#else +typedef uint16_t zig_promoted_u16; +#endif + +#if INT32_MAX <= INT_MAX +typedef unsigned int zig_promoted_i32; +#elif INT32_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i32; +#elif INT32_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i32; +#else +typedef int32_t zig_promoted_i32; +#endif +#if UINT32_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u32; +#elif UINT32_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u32; +#elif UINT32_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u32; +#else +typedef uint32_t zig_promoted_u32; +#endif + +#if INT64_MAX <= INT_MAX +typedef unsigned int zig_promoted_i64; +#elif INT64_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i64; +#elif INT64_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i64; +#else +typedef int64_t zig_promoted_i64; +#endif +#if UINT64_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u64; +#elif UINT64_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u64; +#elif UINT64_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u64; +#else +typedef uint64_t zig_promoted_u64; +#endif + +#ifdef zig_ez80 + +#define zig_minInt_i24 INT24_MIN +#define zig_maxInt_i24 INT24_MAX +#define zig_minInt_u24 UINT24_C(0) +#define zig_maxInt_u24 UINT24_MAX +#define zig_minInt_i48 INT48_MIN +#define zig_maxInt_i48 INT48_MAX +#define zig_minInt_u48 UINT48_C(0) +#define zig_maxInt_u48 UINT48_MAX + +#if INT24_MAX <= INT_MAX +typedef unsigned int zig_promoted_i24; +#elif INT24_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i24; +#elif INT24_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i24; +#else +typedef int24_t zig_promoted_i24; +#endif +#if UINT24_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u24; +#elif UINT24_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u24; +#elif UINT24_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u24; +#else +typedef uint24_t zig_promoted_u24; +#endif + +#if INT48_MAX <= INT_MAX +typedef unsigned int zig_promoted_i48; +#elif INT48_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i48; +#elif INT48_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i48; +#else +typedef int48_t zig_promoted_i48; +#endif +#if UINT48_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u48; +#elif UINT48_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u48; +#elif UINT48_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u48; +#else +typedef uint48_t zig_promoted_u48; +#endif + +#endif + #define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits)) #define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits) #define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits) @@ -770,7 +911,33 @@ typedef ptrdiff_t intptr_t; zig_operator(Type, Type, operation, operator) #define zig_shift_operator(Type, operation, operator) \ zig_operator(Type, uint8_t, operation, operator) -#define zig_int_helpers(w, PromotedUnsigned) \ + +#define zig_int_casts_common(bw, sw) \ + static inline uint##bw##_t zig_u##bw##_intCast_u##sw(uint##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline uint##bw##_t zig_u##bw##_intCast_i##sw(int##sw##_t arg) { \ + return (uint##bw##_t)arg; \ + } \ +\ + static inline int##bw##_t zig_i##bw##_intCast_u##sw(uint##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline int##bw##_t zig_i##bw##_intCast_i##sw(int##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline uint##sw##_t zig_u##sw##_truncate_u##bw(uint##bw##_t arg, uint8_t bits) { \ + return (uint##sw##_t)arg & zig_maxInt_u(sw, bits); \ + } \ +\ + static inline int##sw##_t zig_i##sw##_truncate_i##bw(int##bw##_t arg, uint8_t bits) { \ + return ((uint##sw##_t)arg & UINT##sw##_C(1) << (bits - UINT8_C(1))) != UINT##sw##_C(0) \ + ? (int##sw##_t)arg | zig_minInt_i(sw, bits) : (int##sw##_t)arg & zig_maxInt_i(sw, bits); \ + } +#define zig_int_operators(w) \ zig_basic_operator(uint##w##_t, and_u##w, &) \ zig_basic_operator( int##w##_t, and_i##w, &) \ zig_basic_operator(uint##w##_t, or_u##w, |) \ @@ -786,44 +953,48 @@ typedef ptrdiff_t intptr_t; return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \ } \ \ - static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \ - return val ^ zig_maxInt_u(w, bits); \ + static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \ + return arg ^ zig_maxInt_u(w, bits); \ } \ \ - static inline int##w##_t zig_not_i##w(int##w##_t val, uint8_t bits) { \ + static inline int##w##_t zig_not_i##w(int##w##_t arg, uint8_t bits) { \ (void)bits; \ - return ~val; \ + return ~arg; \ } \ \ - static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \ - return val & zig_maxInt_u(w, bits); \ - } \ -\ - static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \ - return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \ - ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \ - } \ -\ - static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \ - return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \ - } \ -\ - zig_basic_operator(uint##w##_t, div_floor_u##w, /) \ + zig_basic_operator(uint##w##_t, divFloor_u##w, /) \ \ - static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \ + static inline int##w##_t zig_divFloor_i##w(int##w##_t lhs, int##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \ } \ \ - static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \ } \ \ - static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \ + static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != INT##w##_C(0) \ ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \ } \ \ zig_basic_operator(uint##w##_t, mod_u##w, %) \ + zig_int_casts_common(w, w) \ +\ + static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_u##w##_truncate_u##w(arg, bits); \ + } \ +\ + static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_i##w##_truncate_i##w(arg, bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_i##w##_bitCast_i##w((int##w##_t)arg, bits); \ + } \ \ static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \ int##w##_t rem = lhs % rhs; \ @@ -831,100 +1002,102 @@ typedef ptrdiff_t intptr_t; } \ \ static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \ + return zig_u##w##_truncate_u##w(zig_shl_u##w(lhs, rhs), bits); \ } \ \ static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_shl_u##w(zig_u##w##_bitCast_i##w(lhs, bits), rhs), bits); \ } \ \ static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(lhs + rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs + rhs, bits); \ } \ \ static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_addw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ } \ \ static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(lhs - rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs - rhs, bits); \ } \ \ static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_subw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ } \ \ static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w((PromotedUnsigned)lhs * rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs * rhs, bits); \ } \ \ static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_mulw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ + } \ +\ + static inline uint##w##_t zig_abs_i##w(int##w##_t arg) { \ + int##w##_t tmp = zig_shr_i##w(arg, UINT8_C(w) - UINT8_C(1)); \ + return zig_u##w##_bitCast_i##w(zig_subw_i##w(zig_xor_i##w(arg, tmp), tmp, UINT8_C(w)), UINT8_C(w)); \ + } \ +\ + static inline uint##w##_t zig_min_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + return lhs < rhs ? lhs : rhs; \ + } \ +\ + static inline int##w##_t zig_min_i##w(int##w##_t lhs, int##w##_t rhs) { \ + return lhs < rhs ? lhs : rhs; \ + } \ +\ + static inline uint##w##_t zig_max_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + return lhs >= rhs ? lhs : rhs; \ + } \ +\ + static inline int##w##_t zig_max_i##w(int##w##_t lhs, int##w##_t rhs) { \ + return lhs >= rhs ? lhs : rhs; \ } -#if UINT8_MAX <= UINT_MAX -zig_int_helpers(8, unsigned int) -#elif UINT8_MAX <= ULONG_MAX -zig_int_helpers(8, unsigned long) -#elif UINT8_MAX <= ULLONG_MAX -zig_int_helpers(8, unsigned long long) -#else -zig_int_helpers(8, uint8_t) +zig_int_operators(8) +zig_int_operators(16) +zig_int_operators(32) +zig_int_operators(64) +#ifdef zig_ez80 +zig_int_operators(24) +zig_int_operators(48) #endif -#if UINT16_MAX <= UINT_MAX -zig_int_helpers(16, unsigned int) -#elif UINT16_MAX <= ULONG_MAX -zig_int_helpers(16, unsigned long) -#elif UINT16_MAX <= ULLONG_MAX -zig_int_helpers(16, unsigned long long) -#else -zig_int_helpers(16, uint16_t) -#endif -#if defined(zig_ez80) -#if UINT24_MAX <= UINT_MAX -zig_int_helpers(24, unsigned int) -#elif UINT24_MAX <= ULONG_MAX -zig_int_helpers(24, unsigned long) -#elif UINT24_MAX <= ULLONG_MAX -zig_int_helpers(24, unsigned long long) -#else -zig_int_helpers(24, uint24_t) -#endif -#endif -#if UINT32_MAX <= UINT_MAX -zig_int_helpers(32, unsigned int) -#elif UINT32_MAX <= ULONG_MAX -zig_int_helpers(32, unsigned long) -#elif UINT32_MAX <= ULLONG_MAX -zig_int_helpers(32, unsigned long long) -#else -zig_int_helpers(32, uint32_t) -#endif -#if defined(zig_ez80) -#if UINT24_MAX <= UINT_MAX -zig_int_helpers(48, unsigned int) -#elif UINT24_MAX <= ULONG_MAX -zig_int_helpers(48, unsigned long) -#elif UINT24_MAX <= ULLONG_MAX -zig_int_helpers(48, unsigned long long) -#else -zig_int_helpers(48, uint48_t) -#endif -#endif -#if UINT64_MAX <= UINT_MAX -zig_int_helpers(64, unsigned int) -#elif UINT64_MAX <= ULONG_MAX -zig_int_helpers(64, unsigned long) -#elif UINT64_MAX <= ULLONG_MAX -zig_int_helpers(64, unsigned long long) -#else -zig_int_helpers(64, uint64_t) + +#define zig_int_casts(bw, sw) \ + static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \ + return (uint##sw##_t)arg; \ + } \ +\ + static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \ + return (uint##sw##_t)arg; \ + } \ +\ + static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \ + return (int##sw##_t)arg; \ + } \ +\ + static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \ + return (int##sw##_t)arg; \ + } \ +\ + zig_int_casts_common(bw, sw) +zig_int_casts(16, 8) +zig_int_casts(32, 8) +zig_int_casts(64, 8) +zig_int_casts(32, 16) +zig_int_casts(64, 16) +zig_int_casts(64, 32) +#ifdef zig_ez80 +zig_int_casts(32, 24) +zig_int_casts(48, 24) +zig_int_casts(64, 24) +zig_int_casts(64, 48) #endif static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_addw_u32(lhs, rhs, bits); @@ -936,19 +1109,19 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_i32_truncate_i32(full_res, bits); + return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); #else - int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs); - bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; + *res = zig_addw_i32(lhs, rhs, bits); + return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0); #endif - *res = zig_wrap_i32(full_res, bits); - return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_addw_u64(lhs, rhs, bits); @@ -960,24 +1133,24 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_i64_truncate_i64(full_res, bits); + return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); #else - int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs); - bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; + *res = zig_addw_i64(lhs, rhs, bits); + return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0); #endif - *res = zig_wrap_i64(full_res, bits); - return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -986,12 +1159,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(add_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1000,12 +1173,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1014,27 +1187,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1043,28 +1217,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1073,22 +1245,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_subw_u32(lhs, rhs, bits); @@ -1100,20 +1273,19 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_i32_truncate_i32(full_res, bits); + return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); #else - int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs); - bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; + *res = zig_subw_i32(lhs, rhs, bits); + return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0); #endif - *res = zig_wrap_i32(full_res, bits); - return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } - static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_subw_u64(lhs, rhs, bits); @@ -1125,24 +1297,24 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_i64_truncate_i64(full_res, bits); + return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); #else - int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs); - bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; + *res = zig_subw_i64(lhs, rhs, bits); + return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0); #endif - *res = zig_wrap_i64(full_res, bits); - return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -1151,12 +1323,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1165,12 +1337,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1179,27 +1351,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1208,28 +1381,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1238,22 +1409,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_mulw_u32(lhs, rhs, bits); @@ -1261,8 +1433,8 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8 #endif } -zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) { + zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -1271,7 +1443,7 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t int32_t full_res = __mulosi4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i32(full_res, bits); + *res = zig_i32_truncate_i32(full_res, bits); return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } @@ -1279,7 +1451,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_mulw_u64(lhs, rhs, bits); @@ -1287,8 +1459,8 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #endif } -zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) { + zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -1297,7 +1469,7 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t int64_t full_res = __mulodi4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i64(full_res, bits); + *res = zig_i64_truncate_i64(full_res, bits); return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } @@ -1305,12 +1477,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -1319,12 +1491,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1333,12 +1505,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1347,27 +1519,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1376,28 +1549,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1406,18 +1577,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif -#define zig_int_builtins(w) \ +#define zig_shls_builtins(lw, rw) \ + static inline uint##lw##_t zig_shls_u##lw##_u##rw(uint##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \ + uint##lw##_t res; \ + if (rhs < bits && !zig_shlo_u##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + return lhs == INT##lw##_C(0) ? zig_minInt_u(lw, bits) : zig_maxInt_u(lw, bits); \ + } \ +\ + static inline int##lw##_t zig_shls_i##lw##_u##rw(int##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \ + int##lw##_t res; \ + if (rhs < bits && !zig_shlo_i##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + return lhs == INT##lw##_C(0) ? INT##lw##_C(0) : \ + lhs < INT##lw##_C(0) ? zig_minInt_i(lw, bits) : zig_maxInt_i(lw, bits); \ + } +#define zig_int_sat_builtins(w) \ static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ *res = zig_shlw_u##w(lhs, rhs, bits); \ return lhs > zig_maxInt_u(w, bits) >> rhs; \ @@ -1429,18 +1614,10 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \ } \ \ - static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - uint##w##_t res; \ - if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \ - return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \ - } \ -\ - static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - int##w##_t res; \ - if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \ - return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ - lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ - } \ + zig_shls_builtins(w, 8) \ + zig_shls_builtins(w, 16) \ + zig_shls_builtins(w, 32) \ + zig_shls_builtins(w, 64) \ \ static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ uint##w##_t res; \ @@ -1474,332 +1651,321 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \ return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ } -zig_int_builtins(8) -zig_int_builtins(16) +zig_int_sat_builtins(8) +zig_int_sat_builtins(16) +zig_int_sat_builtins(32) +zig_int_sat_builtins(64) #if defined(zig_ez80) -zig_int_builtins(24) +zig_int_sat_builtins(24) +zig_int_sat_builtins(48) #endif -zig_int_builtins(32) -#if defined(zig_ez80) -zig_int_builtins(48) -#endif -zig_int_builtins(64) -#define zig_builtin8(name, val) __builtin_##name(val) +#define zig_builtin8(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin8; -#define zig_builtin16(name, val) __builtin_##name(val) +#define zig_builtin16(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin16; -#if defined(zig_ez80) -#define zig_builtin24(name, val) __builtin_##name(val) -typedef unsigned int zig_Builtin24; -#endif - #if INT_MIN <= INT32_MIN -#define zig_builtin32(name, val) __builtin_##name(val) +#define zig_builtin32(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin32; #elif LONG_MIN <= INT32_MIN -#define zig_builtin32(name, val) __builtin_##name##l(val) +#define zig_builtin32(name, arg) __builtin_##name##l(arg) typedef unsigned long zig_Builtin32; #endif -#if defined(zig_ez80) -#define zig_builtin48(name, val) __builtin_##name(val) -typedef unsigned long long zig_Builtin48; -#endif - #if INT_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name(val) +#define zig_builtin64(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin64; #elif LONG_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name##l(val) +#define zig_builtin64(name, arg) __builtin_##name##l(arg) typedef unsigned long zig_Builtin64; #elif LLONG_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name##ll(val) +#define zig_builtin64(name, arg) __builtin_##name##ll(arg) typedef unsigned long long zig_Builtin64; #endif -static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) { - return zig_wrap_u8(val >> (8 - bits), bits); +#if defined(zig_ez80) +#define zig_builtin24(name, arg) __builtin_##name(arg) +typedef unsigned int zig_Builtin24; +#define zig_builtin48(name, arg) __builtin_##name(arg) +typedef unsigned long long zig_Builtin48; +#endif + +static inline uint8_t zig_byteSwap_u8(uint8_t arg, uint8_t bits) { + return zig_u8_truncate_u8(arg >> (8 - bits), bits); } -static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) { - return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits); +static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) { + return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits); } -static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) { +static inline uint16_t zig_byteSwap_u16(uint16_t arg, uint8_t bits) { uint16_t full_res; #if zig_has_builtin(bswap16) || defined(zig_gcc) - full_res = __builtin_bswap16(val); + full_res = __builtin_bswap16(arg); #else - full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 | - (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0; + full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 | + (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0; #endif - return zig_wrap_u16(full_res >> (16 - bits), bits); + return zig_u16_truncate_u16(full_res >> (16 - bits), bits); } -static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) { - return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits); +static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) { + return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) { +static inline uint16_t zig_byteSwap_u24(uint24_t arg, uint8_t bits) { uint24_t full_res; #if zig_has_builtin(bswap24) || defined(zig_gcc) - full_res = __builtin_bswap24(val); + full_res = __builtin_bswap24(arg); #else - full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 | - (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0; + full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 | + (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0; #endif - return zig_wrap_u24(full_res >> (24 - bits), bits); + return zig_u24_truncate_u24(full_res >> (24 - bits), bits); } -static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) { - return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits); +static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) { + return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits); } #endif -static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) { +static inline uint32_t zig_byteSwap_u32(uint32_t arg, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bswap32) || defined(zig_gcc) - full_res = __builtin_bswap32(val); + full_res = __builtin_bswap32(arg); #else - full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 | - (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0; + full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 | + (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0; #endif - return zig_wrap_u32(full_res >> (32 - bits), bits); + return zig_u32_truncate_u32(full_res >> (32 - bits), bits); } -static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) { - return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits); +static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) { + return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) { +static inline uint32_t zig_byteSwap_u48(uint48_t arg, uint8_t bits) { uint48_t full_res; #if zig_has_builtin(bswap48) || defined(zig_gcc) - full_res = __builtin_bswap48(val); + full_res = __builtin_bswap48(arg); #else - full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 | - (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0; + full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 | + (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0; #endif - return zig_wrap_u48(full_res >> (48 - bits), bits); + return zig_u48_truncate_u48(full_res >> (48 - bits), bits); } -static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) { - return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits); +static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) { + return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits); } #endif -static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) { +static inline uint64_t zig_byteSwap_u64(uint64_t arg, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bswap64) || defined(zig_gcc) - full_res = __builtin_bswap64(val); + full_res = __builtin_bswap64(arg); #else - full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 | - (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0; + full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 | + (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0; #endif - return zig_wrap_u64(full_res >> (64 - bits), bits); + return zig_u64_truncate_u64(full_res >> (64 - bits), bits); } -static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) { - return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits); +static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) { + return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits); } -static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) { +static inline uint8_t zig_bitReverse_u8(uint8_t arg, uint8_t bits) { uint8_t full_res; #if zig_has_builtin(bitreverse8) - full_res = __builtin_bitreverse8(val); + full_res = __builtin_bitreverse8(arg); #else static uint8_t const lut[0x10] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; - full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0; + full_res = lut[arg >> 0 & 0xF] << 4 | lut[arg >> 4 & 0xF] << 0; #endif - return zig_wrap_u8(full_res >> (8 - bits), bits); + return zig_u8_truncate_u8(full_res >> (8 - bits), bits); } -static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) { - return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits); +static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) { + return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits); } -static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) { +static inline uint16_t zig_bitReverse_u16(uint16_t arg, uint8_t bits) { uint16_t full_res; #if zig_has_builtin(bitreverse16) - full_res = __builtin_bitreverse16(val); + full_res = __builtin_bitreverse16(arg); #else - full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 | - (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0; + full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 | + (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0; #endif - return zig_wrap_u16(full_res >> (16 - bits), bits); + return zig_u16_truncate_u16(full_res >> (16 - bits), bits); } -static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) { - return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits); +static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) { + return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) { +static inline uint24_t zig_bitReverse_u24(uint24_t arg, uint8_t bits) { uint24_t full_res; #if zig_has_builtin(bitreverse24) - full_res = __builtin_bitreverse24(val); + full_res = __builtin_bitreverse24(arg); #else - full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 | - (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0; + full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 | + (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0; #endif - return zig_wrap_u24(full_res >> (24 - bits), bits); + return zig_u24_truncate_u24(full_res >> (24 - bits), bits); } -static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) { - return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits); +static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) { + return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits); } #endif -static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) { +static inline uint32_t zig_bitReverse_u32(uint32_t arg, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bitreverse32) - full_res = __builtin_bitreverse32(val); + full_res = __builtin_bitreverse32(arg); #else - full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 | - (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0; + full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 | + (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0; #endif - return zig_wrap_u32(full_res >> (32 - bits), bits); + return zig_u32_truncate_u32(full_res >> (32 - bits), bits); } -static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) { - return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits); +static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) { + return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) { +static inline uint32_t zig_bitReverse_u48(uint48_t arg, uint8_t bits) { uint48_t full_res; #if zig_has_builtin(bitreverse48) - full_res = __builtin_bitreverse48(val); + full_res = __builtin_bitreverse48(arg); #else - full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 | - (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0; + full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 | + (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0; #endif - return zig_wrap_u32(full_res >> (48 - bits), bits); + return zig_u48_truncate_u48(full_res >> (48 - bits), bits); } -static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) { - return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits); +static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) { + return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits); } #endif -static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) { +static inline uint64_t zig_bitReverse_u64(uint64_t arg, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bitreverse64) - full_res = __builtin_bitreverse64(val); + full_res = __builtin_bitreverse64(arg); #else - full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 | - (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0; + full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 | + (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0; #endif - return zig_wrap_u64(full_res >> (64 - bits), bits); + return zig_u64_truncate_u64(full_res >> (64 - bits), bits); } -static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) { - return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits); +static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) { + return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits); } -#define zig_builtin_popcount_common(w) \ - static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \ - return zig_popcount_u##w((uint##w##_t)val, bits); \ +#define zig_builtin_popCount_common(w) \ + static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_popCount_u##w((uint##w##_t)arg, bits); \ } -#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc) -#define zig_builtin_popcount(w) \ - static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ +#if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc) +#define zig_builtin_popCount(w) \ + static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ (void)bits; \ - return zig_builtin##w(popcount, val); \ + return zig_builtin##w(popcount, arg); \ } \ \ - zig_builtin_popcount_common(w) + zig_builtin_popCount_common(w) #else -#define zig_builtin_popcount(w) \ - static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ +#define zig_builtin_popCount(w) \ + static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ (void)bits; \ - uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \ + uint##w##_t temp = arg - ((arg >> 1) & (UINT##w##_MAX / 3)); \ temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \ temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \ return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \ } \ \ - zig_builtin_popcount_common(w) + zig_builtin_popCount_common(w) #endif -zig_builtin_popcount(8) -zig_builtin_popcount(16) +zig_builtin_popCount(8) +zig_builtin_popCount(16) +zig_builtin_popCount(32) +zig_builtin_popCount(64) #if defined(zig_ez80) -zig_builtin_popcount(24) +zig_builtin_popCount(24) +zig_builtin_popCount(48) #endif -zig_builtin_popcount(32) -#if defined(zig_ez80) -zig_builtin_popcount(48) -#endif -zig_builtin_popcount(64) #define zig_builtin_ctz_common(w) \ - static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \ - return zig_ctz_u##w((uint##w##_t)val, bits); \ + static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_ctz_u##w((uint##w##_t)arg, bits); \ } #if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_ctz(w) \ - static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ - if (val == 0) return bits; \ - return zig_builtin##w(ctz, val); \ + static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ + if (arg == 0) return bits; \ + return zig_builtin##w(ctz, arg); \ } \ \ zig_builtin_ctz_common(w) #else #define zig_builtin_ctz(w) \ - static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ - return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \ + static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \ } \ \ zig_builtin_ctz_common(w) #endif zig_builtin_ctz(8) zig_builtin_ctz(16) -#if defined(zig_ez80) -zig_builtin_ctz(24) -#endif zig_builtin_ctz(32) -#if defined(zig_ez80) -zig_builtin_ctz(48) -#endif zig_builtin_ctz(64) +#if defined(zig_ez80) +zig_builtin_ctz(24) +zig_builtin_ctz(48) +#endif #define zig_builtin_clz_common(w) \ - static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \ - return zig_clz_u##w((uint##w##_t)val, bits); \ + static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_clz_u##w((uint##w##_t)arg, bits); \ } #if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_clz(w) \ - static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ - if (val == 0) return bits; \ - return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ + static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ + if (arg == 0) return bits; \ + return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ } \ \ zig_builtin_clz_common(w) #else #define zig_builtin_clz(w) \ - static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ - return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \ + static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \ } \ \ zig_builtin_clz_common(w) #endif zig_builtin_clz(8) zig_builtin_clz(16) -#if defined(zig_ez80) -zig_builtin_clz(24) -#endif zig_builtin_clz(32) -#if defined(zig_ez80) -zig_builtin_clz(48) -#endif zig_builtin_clz(64) +#if defined(zig_ez80) +zig_builtin_clz(24) +zig_builtin_clz(48) +#endif /* ======================== 128-bit Integer Support ========================= */ @@ -1816,16 +1982,14 @@ zig_builtin_clz(64) typedef unsigned __int128 zig_u128; typedef signed __int128 zig_i128; -#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) -#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) -#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) -#define zig_hi_u128(val) ((uint64_t)((val) >> 64)) -#define zig_lo_u128(val) ((uint64_t)((val) >> 0)) -#define zig_hi_i128(val) (( int64_t)((val) >> 64)) -#define zig_lo_i128(val) ((uint64_t)((val) >> 0)) -#define zig_bitCast_u128(val) ((zig_u128)(val)) -#define zig_bitCast_i128(val) ((zig_i128)(val)) +#define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) +#define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) +#define zig_make_u128(hi, lo) zig_init_u128(hi, lo) +#define zig_make_i128(hi, lo) zig_init_i128(hi, lo) +#define zig_hi_u128(arg) ((uint64_t)((arg) >> 64)) +#define zig_lo_u128(arg) ((uint64_t)((arg) >> 0)) +#define zig_hi_i128(arg) (( int64_t)((arg) >> 64)) +#define zig_lo_i128(arg) ((uint64_t)((arg) >> 0)) #define zig_cmp_int128(Type) \ static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ return (lhs > rhs) - (lhs < rhs); \ @@ -1835,32 +1999,49 @@ typedef signed __int128 zig_i128; return lhs operator rhs; \ } +static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { + return lhs << rhs; +} + +static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { + return lhs >> rhs; +} + +static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { + return lhs << rhs; +} + +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + // This works around a GCC miscompilation, but it has the side benefit of + // emitting better code. It is behind the `#if` because it depends on + // arithmetic right shift, which is implementation-defined in C, but should + // be guaranteed on any GCC-compatible compiler. +#if defined(zig_gnuc) + return lhs >> rhs; +#else + zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); + return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; +#endif +} + #else /* zig_has_int128 */ #if zig_little_endian -typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128; -typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128; #else -typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128; -typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128; #endif -#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) }) -#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) }) - -#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */ -#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) } -#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) } -#else /* But non-MSVC doesn't like the unprotected commas */ -#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) -#endif -#define zig_hi_u128(val) ((val).hi) -#define zig_lo_u128(val) ((val).lo) -#define zig_hi_i128(val) ((val).hi) -#define zig_lo_i128(val) ((val).lo) -#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo) -#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo) +#define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo) +#define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo) +#define zig_hi_u128(arg) (arg).hi +#define zig_lo_u128(arg) (arg).lo +#define zig_hi_i128(arg) (arg).hi +#define zig_lo_i128(arg) (arg).lo #define zig_cmp_int128(Type) \ static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ return (lhs.hi == rhs.hi) \ @@ -1872,6 +2053,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \ } +static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; + return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +} + +static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) }; + return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs }; +} + +static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; + return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +} + +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) }; + return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) }; +} + #endif /* zig_has_int128 */ #define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64) @@ -1891,42 +2096,177 @@ zig_bit_int128(i128, or, |) zig_bit_int128(u128, xor, ^) zig_bit_int128(i128, xor, ^) -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs); +static inline uint8_t zig_u8_intCast_u128(zig_u128 arg) { + return (uint8_t)zig_lo_u128(arg); +} +static inline uint8_t zig_u8_intCast_i128(zig_i128 arg) { + return (uint8_t)zig_lo_i128(arg); +} +static inline int8_t zig_i8_intCast_i128(zig_i128 arg) { + return (int8_t)zig_lo_i128(arg); +} +static inline int8_t zig_i8_intCast_u128(zig_u128 arg) { + return (int8_t)zig_lo_u128(arg); +} -#if zig_has_int128 +static inline uint16_t zig_u16_intCast_u128(zig_u128 arg) { + return (uint16_t)zig_lo_u128(arg); +} +static inline uint16_t zig_u16_intCast_i128(zig_i128 arg) { + return (uint16_t)zig_lo_i128(arg); +} +static inline int16_t zig_i16_intCast_i128(zig_i128 arg) { + return (int16_t)zig_lo_i128(arg); +} +static inline int16_t zig_i16_intCast_u128(zig_u128 arg) { + return (int16_t)zig_lo_u128(arg); +} -static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { - return val ^ zig_maxInt_u(128, bits); +static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) { + return (uint32_t)zig_lo_u128(arg); +} +static inline uint32_t zig_u32_intCast_i128(zig_i128 arg) { + return (uint32_t)zig_lo_i128(arg); +} +static inline int32_t zig_i32_intCast_i128(zig_i128 arg) { + return (int32_t)zig_lo_i128(arg); +} +static inline int32_t zig_i32_intCast_u128(zig_u128 arg) { + return (int32_t)zig_lo_u128(arg); } -static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { - (void)bits; - return ~val; +static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) { + return zig_lo_u128(arg); +} +static inline uint64_t zig_u64_intCast_i128(zig_i128 arg) { + return zig_lo_i128(arg); +} +static inline int64_t zig_i64_intCast_i128(zig_i128 arg) { + return (int64_t)zig_lo_i128(arg); +} +static inline int64_t zig_i64_intCast_u128(zig_u128 arg) { + return (int64_t)zig_lo_u128(arg); +} + +static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) { + return zig_make_u128(UINT8_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i8(int8_t arg) { + return zig_make_u128(UINT8_C(0), (uint8_t)arg); +} +static inline zig_i128 zig_i128_intCast_i8(int8_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint8_t)arg); +} +static inline zig_i128 zig_i128_intCast_u8(uint8_t arg) { + return zig_make_i128(INT8_C(0), arg); } -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { - return lhs >> rhs; +static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) { + return zig_make_u128(UINT16_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i16(int16_t arg) { + return zig_make_u128(UINT16_C(0), (uint16_t)arg); +} +static inline zig_i128 zig_i128_intCast_i16(int16_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint16_t)arg); +} +static inline zig_i128 zig_i128_intCast_u16(uint16_t arg) { + return zig_make_i128(INT16_C(0), arg); } -static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { - return lhs << rhs; +static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) { + return zig_make_u128(UINT32_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i32(int32_t arg) { + return zig_make_u128(UINT32_C(0), (uint32_t)arg); +} +static inline zig_i128 zig_i128_intCast_i32(int32_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint32_t)arg); +} +static inline zig_i128 zig_i128_intCast_u32(uint32_t arg) { + return zig_make_i128(INT32_C(0), arg); } -static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { - // This works around a GCC miscompilation, but it has the side benefit of - // emitting better code. It is behind the `#if` because it depends on - // arithmetic right shift, which is implementation-defined in C, but should - // be guaranteed on any GCC-compatible compiler. -#if defined(zig_gnuc) - return lhs >> rhs; +static inline zig_u128 zig_u128_intCast_u64(uint64_t arg) { + return zig_make_u128(UINT64_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i64(int64_t arg) { + return zig_make_u128(UINT64_C(0), (uint64_t)arg); +} +static inline zig_i128 zig_i128_intCast_i64(int64_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint64_t)arg); +} +static inline zig_i128 zig_i128_intCast_u64(uint64_t arg) { + return zig_make_i128(INT64_C(0), arg); +} + +static inline zig_u128 zig_u128_intCast_u128(zig_u128 arg) { + return arg; +} +static inline zig_u128 zig_u128_intCast_i128(zig_i128 arg) { +#if zig_has_int128 + return (zig_u128)arg; +#else + return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); +#endif +} +static inline zig_i128 zig_i128_intCast_i128(zig_i128 arg) { + return arg; +} +static inline zig_i128 zig_i128_intCast_u128(zig_u128 arg) { +#if zig_has_int128 + return (zig_i128)arg; #else - zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); - return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; + return zig_make_i128(zig_i64_bitCast_u64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); #endif } -static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { - return lhs << rhs; +#define zig_int128_cast_builtins(w) \ + static inline uint##w##_t zig_u##w##_truncate_u128(zig_u128 arg, uint8_t bits) { \ + return zig_u##w##_truncate_u##w((uint##w##_t)zig_lo_u128(arg), bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_truncate_i128(zig_i128 arg, uint8_t bits) { \ + return zig_i##w##_truncate_i##w((int##w##_t)zig_lo_i128(arg), bits); \ + } +zig_int128_cast_builtins(8) +zig_int128_cast_builtins(16) +zig_int128_cast_builtins(32) +zig_int128_cast_builtins(64) + +static inline zig_u128 zig_u128_truncate_u128(zig_u128 arg, uint8_t bits) { + return zig_and_u128(arg, zig_maxInt_u(128, bits)); +} +static inline zig_i128 zig_i128_truncate_i128(zig_i128 arg, uint8_t bits) { + if (bits > UINT8_C(64)) return zig_make_i128(zig_i64_truncate_i64(zig_hi_i128(arg), bits - UINT8_C(64)), zig_lo_i128(arg)); + int64_t lo = zig_i64_truncate_i128(arg, bits); + return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); +} + +static inline zig_u128 zig_u128_bitCast_u128(zig_u128 arg, uint8_t bits) { + (void)bits; + return arg; +} +static inline zig_u128 zig_u128_bitCast_i128(zig_i128 arg, uint8_t bits) { + return zig_u128_truncate_u128(zig_u128_intCast_i128(arg), bits); +} +static inline zig_i128 zig_i128_bitCast_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return arg; +} +static inline zig_i128 zig_i128_bitCast_u128(zig_u128 arg, uint8_t bits) { + return zig_i128_truncate_i128(zig_i128_intCast_u128(arg), bits); +} + +#if zig_has_int128 + +static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { + return arg ^ zig_maxInt_u(128, bits); +} + +static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return ~arg; } static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { @@ -1953,11 +2293,11 @@ static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { return lhs * rhs; } -static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { +static inline zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { return lhs / rhs; } -static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { return lhs / rhs; } @@ -1971,36 +2311,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { #else /* zig_has_int128 */ -static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { - return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; +static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { + if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) }; + return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) }; } -static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { - return (zig_i128){ .hi = zig_not_i64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; -} - -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) }; - return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs }; -} - -static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; - return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; -} - -static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) }; - return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) }; -} - -static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; - return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo }; } static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { @@ -2027,59 +2345,59 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) { return res; } -zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); return __multi3(lhs, rhs); } static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) { - return zig_bitCast_u128(zig_mul_i128(zig_bitCast_i128(lhs), zig_bitCast_i128(rhs))); + return zig_u128_bitCast_i128(zig_mul_i128(zig_i128_bitCast_u128(lhs, UINT8_C(128)), zig_i128_bitCast_u128(rhs, UINT8_C(128))), UINT8_C(128)); } -zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); -static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { +static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { + zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); return __udivti3(lhs, rhs); } -zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); -static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { +static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); return __divti3(lhs, rhs); } -zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) { + zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); return __umodti3(lhs, rhs); } -zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); return __modti3(lhs, rhs); } #endif /* zig_has_int128 */ -#define zig_div_floor_u128 zig_div_trunc_u128 +#define zig_divFloor_u128 zig_divTrunc_u128 -static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divFloor_i128(zig_i128 lhs, zig_i128 rhs) { zig_i128 rem = zig_rem_i128(lhs, rhs); int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0); - return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask)); + return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask)); } -static inline zig_u128 zig_div_ceil_u128(zig_u128 lhs, zig_u128 rhs) { +static inline zig_u128 zig_divCeil_u128(zig_u128 lhs, zig_u128 rhs) { zig_u128 rem = zig_rem_u128(lhs, rhs); uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0) ? UINT64_C(1) : UINT64_C(0); - return zig_add_u128(zig_div_trunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask)); + return zig_add_u128(zig_divTrunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask)); } -static inline zig_i128 zig_div_ceil_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divCeil_i128(zig_i128 lhs, zig_i128 rhs) { zig_i128 rem = zig_rem_i128(lhs, rhs); int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1) : INT64_C(0); - return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask)); + return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask)); } #define zig_mod_u128 zig_rem_u128 @@ -2107,51 +2425,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) { return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs; } -static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) { - return zig_and_u128(val, zig_maxInt_u(128, bits)); -} - -static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) { - if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val)); - int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits); - return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); -} - static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) { - return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_shl_u128(lhs, rhs), bits); } static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_shl_u128(zig_bitCast_u128(lhs), rhs)), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_shl_u128(zig_u128_bitCast_i128(lhs, bits), rhs), bits), bits); } static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_add_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_add_u128(lhs, rhs), bits); } static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_add_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_add_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_sub_u128(lhs, rhs), bits); } static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_sub_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_sub_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_mul_u128(lhs, rhs), bits); } static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_mul_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } -static inline zig_u128 zig_abs_i128(zig_i128 val) { - zig_i128 tmp = zig_shr_i128(val, 127); - return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp)); +static inline zig_u128 zig_abs_i128(zig_i128 arg) { + zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128)); + return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp); } #if zig_has_int128 @@ -2160,7 +2468,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(add_overflow) zig_u128 full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_addw_u128(lhs, rhs, bits); @@ -2176,7 +2484,7 @@ static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs); bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } @@ -2184,7 +2492,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(sub_overflow) zig_u128 full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_subw_u128(lhs, rhs, bits); @@ -2200,7 +2508,7 @@ static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs); bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } @@ -2208,7 +2516,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(mul_overflow) zig_u128 full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_mulw_u128(lhs, rhs, bits); @@ -2216,8 +2524,8 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #endif } -zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { + zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); #if zig_has_builtin(mul_overflow) zig_i128 full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -2226,50 +2534,78 @@ static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } #else /* zig_has_int128 */ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - uint64_t hi; - bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + uint64_t lo; + bool overflow = zig_addo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); + *res = zig_u128_intCast_u64(lo); + return overflow; + } else { + uint64_t hi; + bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int64_t hi; - bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + int64_t lo; + bool overflow = zig_addo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); + *res = zig_i128_intCast_i64(lo); + return overflow; + } else { + int64_t hi; + bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - uint64_t hi; - bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + uint64_t lo; + bool overflow = zig_subo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); + *res = zig_u128_intCast_u64(lo); + return overflow; + } else { + uint64_t hi; + bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int64_t hi; - bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + int64_t lo; + bool overflow = zig_subo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); + *res = zig_i128_intCast_i64(lo); + return overflow; + } else { + int64_t hi; + bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { *res = zig_mulw_u128(lhs, rhs, bits); - return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) && - zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); + return zig_cmp_u128(rhs, zig_make_u128(0, 0)) != INT32_C(0) && + zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); } -zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { + zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); int overflow_int; zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0 || zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) || zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0); - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow; } @@ -2282,28 +2618,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8 static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) { *res = zig_shlw_i128(lhs, rhs, bits); - zig_i128 mask = zig_bitCast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1))); + zig_i128 mask = zig_i128_bitCast_u128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)), bits); return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) && zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0); } -static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { +#define zig_int128_shls_builtins(rw) \ + static inline zig_u128 zig_shls_u128_u##rw(zig_u128 lhs, uint##rw##_t rhs, uint8_t bits) { \ + zig_u128 res; \ + if (rhs < bits && !zig_shlo_u128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + switch (zig_cmp_u128(lhs, zig_make_u128(UINT64_C(0), UINT64_C(0)))) { \ + case 0: return zig_minInt_u(128, bits); \ + case 1: return zig_maxInt_u(128, bits); \ + default: zig_unreachable(); \ + } \ + } \ +\ + static inline zig_i128 zig_shls_i128_u##rw(zig_i128 lhs, uint##rw##_t rhs, uint8_t bits) { \ + zig_i128 res; \ + if (rhs < bits && !zig_shlo_i128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + switch (zig_cmp_i128(lhs, zig_make_i128(INT64_C(0), UINT64_C(0)))) { \ + case -1: return zig_minInt_i(128, bits); \ + case 0: return zig_make_i128(INT64_C(0), UINT64_C(0)); \ + case 1: return zig_maxInt_i(128, bits); \ + default: zig_unreachable(); \ + } \ + } +zig_int128_shls_builtins(8) +zig_int128_shls_builtins(16) +zig_int128_shls_builtins(32) +zig_int128_shls_builtins(64) + +static inline zig_u128 zig_shls_u128_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { zig_u128 res; if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) { - case 0: return zig_make_u128(0, 0); - case 1: return zig_maxInt_u(128, bits); + case INT32_C(0): return zig_make_u128(0, 0); + case INT32_C(1): return zig_maxInt_u(128, bits); default: zig_unreachable(); } } -static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { +static inline zig_i128 zig_shls_i128_u128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { zig_i128 res; if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) { - case -1: return zig_minInt_i(128, bits); - case 0: return zig_make_i128(0, 0); - case 1: return zig_maxInt_i(128, bits); + case -INT32_C(1): return zig_minInt_i(128, bits); + case INT32_C(0): return zig_make_i128(0, 0); + case INT32_C(1): return zig_maxInt_i(128, bits); default: zig_unreachable(); } } @@ -2341,57 +2703,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits); } -static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) { - if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits); - if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64)); - return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64)); +static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) { + if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits); + if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64)); + return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64)); } -static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) { - return zig_clz_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) { + return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) { - if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64)); - return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64); +static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) { + if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64)); + return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64); } -static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) { - return zig_ctz_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) { + return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) { - return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) + - zig_popcount_u64(zig_lo_u128(val), UINT8_C(64)); +static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) { + return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) + + zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64)); } -static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) { - return zig_popcount_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) { + return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) { +static inline zig_u128 zig_byteSwap_u128(zig_u128 arg, uint8_t bits) { zig_u128 full_res; #if zig_has_builtin(bswap128) - full_res = __builtin_bswap128(val); + full_res = __builtin_bswap128(arg); #else - full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)), - zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64))); + full_res = zig_make_u128( + zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)), + zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64)) + ); #endif return zig_shr_u128(full_res, UINT8_C(128) - bits); } -static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) { - return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits)); +static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) { + return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); } -static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) { - return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)), - zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))), - UINT8_C(128) - bits); +static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) { + return zig_shr_u128(zig_make_u128( + zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)), + zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64)) + ), UINT8_C(128) - bits); } -static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { - return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits)); +static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) { + return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); } #if zig_has_int128 @@ -2411,12 +2776,378 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { /* ========================== Big Integer Support =========================== */ static inline uint16_t zig_int_bytes(uint16_t bits) { - uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT; + uint16_t bytes = (bits - UINT16_C(1)) / CHAR_BIT + UINT16_C(1); uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT; + while (alignment / 2 >= bytes) alignment /= 2; return (bytes + alignment - 1) / alignment * alignment; } +static inline void zig_minInt_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + + if (is_signed) { + int8_t signed_sign_byte = zig_minInt_i(8, remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_minInt_u(8, remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memset(&res_bytes[0], zig_minInt_u8, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + byte_offset = size - UINT16_C(1) - byte_offset; + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], zig_minInt_u8, size - byte_offset); +#endif +} + +static inline void zig_maxInt_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + + if (is_signed) { + int8_t signed_sign_byte = zig_maxInt_i(8, remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_maxInt_u(8, remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memset(&res_bytes[0], zig_maxInt_u8, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + byte_offset = size - UINT16_C(1) - byte_offset; + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], zig_maxInt_u8, size - byte_offset); +#endif +} + +static inline int8_t zig_signFill_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + + if (!is_signed) return INT8_C(0); +#if zig_little_endian + byte_offset = zig_int_bytes(bits) - 1; +#endif + return zig_shr_i8(zig_i8_bitCast_u8(arg_bytes[byte_offset], UINT8_C(8)), UINT8_C(7)); +} + +static inline void zig_big_intCast_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_size = zig_int_bytes(res_bits); + uint16_t arg_size = zig_int_bytes(arg_bits); + uint16_t copy_size = zig_min_u16(res_size, arg_size); + uint8_t sign_fill = zig_u8_bitCast_i8(zig_signFill_big(arg, arg_is_signed, arg_bits), UINT8_C(8)); + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], copy_size); + memset(&res_bytes[copy_size], sign_fill, res_size - copy_size); +#else + memset(&res_bytes[0], sign_fill, res_size - copy_size); + memcpy(&res_bytes[res_size - copy_size], &arg_bytes[arg_size - copy_size], copy_size); +#endif +} + +static inline void zig_big_truncate_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_size = zig_int_bytes(res_bits); + + if (res_is_signed != arg_is_signed) zig_unreachable(); + if (res_bits > arg_bits) zig_unreachable(); + + if (res_is_signed) { + uint16_t arg_byte_offset = UINT16_C(0); + +#if zig_big_endian + arg_byte_offset = zig_int_bytes(arg_bits) - res_size; +#endif + + memcpy(&res_bytes[0], &arg_bytes[arg_byte_offset], res_size); + } else { + uint16_t res_byte_offset = zig_shr_u16(res_bits - UINT16_C(1), UINT8_C(3)); + uint16_t arg_byte_offset = res_byte_offset; + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], res_byte_offset); +#else + res_byte_offset = res_size - UINT16_C(1) - res_byte_offset; + arg_byte_offset = zig_int_bytes(arg_bits) - UINT16_C(1) - arg_byte_offset; + + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#endif + + res_bytes[res_byte_offset] = zig_u8_truncate_u8( + arg_bytes[arg_byte_offset], + zig_u8_truncate_u8(res_bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1) + ); + res_byte_offset += UINT16_C(1); + arg_byte_offset += UINT16_C(1); + +#if zig_little_endian + memset(&res_bytes[res_byte_offset], zig_minInt_u8, res_size - res_byte_offset); +#else + memcpy(&res_bytes[res_byte_offset], &arg_bytes[arg_byte_offset], res_size - res_byte_offset); +#endif + } +} + +#define zig_big_casts(is, s, w, IntType) \ + static inline IntType zig_##s##w##_intCast_big(const void *arg, bool arg_is_signed, uint16_t arg_bits) { \ + IntType res; \ + zig_big_intCast_big(&res, arg, is, w, arg_is_signed, arg_bits); \ + return res; \ + } \ +\ + static inline void zig_big_intCast_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \ + zig_big_intCast_big(res, &arg, res_is_signed, res_bits, is, w); \ + } \ +\ + static inline IntType zig_##s##w##_truncate_big(const void *arg, uint8_t res_bits, bool arg_is_signed, uint16_t arg_bits) { \ + IntType res; \ + zig_big_truncate_big(&res, arg, is, res_bits, arg_is_signed, arg_bits); \ + return res; \ + } \ +\ + static inline void zig_big_truncate_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \ + zig_big_truncate_big(res, &arg, res_is_signed, res_bits, is, w); \ + } +zig_big_casts(false, u, 8, uint8_t) +zig_big_casts(true , i, 8, int8_t) +zig_big_casts(false, u, 16, uint16_t) +zig_big_casts(true , i, 16, int16_t) +zig_big_casts(false, u, 32, uint32_t) +zig_big_casts(true , i, 32, int32_t) +zig_big_casts(false, u, 64, uint64_t) +zig_big_casts(true , i, 64, int64_t) +zig_big_casts(false, u, 128, zig_u128) +zig_big_casts(true , i, 128, zig_i128) + +static inline void zig_big_bitCast_big(void *res, const void *arg, bool res_is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + +#if zig_big_endian + byte_offset = size - UINT16_C(1) - byte_offset; +#endif + + if (res_is_signed) { + int8_t signed_sign_byte = zig_i8_bitCast_u8(arg_bytes[byte_offset], remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_u8_bitCast_u8(arg_bytes[byte_offset], remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memcpy(&res_bytes[byte_offset], &arg_bytes[byte_offset], size - byte_offset); +#endif +} + +static inline int32_t zig_cmp_big_u8(const void *lhs, uint8_t rhs, bool is_signed, uint16_t bits) { + const uint8_t *lhs_bytes = lhs; + uint16_t byte_offset = 0; + bool do_signed = is_signed; + uint16_t remaining_bytes = zig_int_bytes(bits); + +#if zig_little_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0); + int32_t limb_cmp; + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (do_signed) { + zig_i128 lhs_limb; + zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb); + do_signed = false; + } else { + zig_u128 lhs_limb; + zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb); + } + + if (limb_cmp != 0) return limb_cmp; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (do_signed) { + int64_t lhs_limb; + int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint64_t lhs_limb; + uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (do_signed) { + int32_t lhs_limb; + int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint32_t lhs_limb; + uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (do_signed) { + int16_t lhs_limb; + int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint16_t lhs_limb; + uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (do_signed) { + int8_t lhs_limb; + int16_t lhs_cmp_limb; + int16_t rhs_cmp_limb = zig_i16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb); + if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb); + do_signed = false; + } else { + uint8_t lhs_limb; + uint8_t rhs_limb = rhs_byte; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return 0; +} + static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { const uint8_t *lhs_bytes = lhs; const uint8_t *rhs_bytes = rhs; @@ -2579,6 +3310,168 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign return 0; } +static inline void zig_not_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (remaining_bytes != 128 / CHAR_BIT || is_signed) { + zig_i128 res_limb; + zig_i128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i128(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + zig_u128 res_limb; + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u128(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (remaining_bytes != 64 / CHAR_BIT || is_signed) { + int64_t res_limb; + int64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i64(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint64_t res_limb; + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u64(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (remaining_bytes != 32 / CHAR_BIT || is_signed) { + int32_t res_limb; + int32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i32(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint32_t res_limb; + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u32(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (remaining_bytes != 16 / CHAR_BIT || is_signed) { + int16_t res_limb; + int16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i16(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint16_t res_limb; + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u16(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (remaining_bytes != 8 / CHAR_BIT || is_signed) { + int8_t res_limb; + int8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i8(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint8_t res_limb; + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u8(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { uint8_t *res_bytes = res; const uint8_t *lhs_bytes = lhs; @@ -2816,13 +3709,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool } } +static inline void zig_increment_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_decrement_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_abs_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + if (zig_signFill_big(arg, is_signed, bits) >= INT8_C(0)) { + memcpy(res, arg, remaining_bytes); + return; + } + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + bool overflow = true; + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u128(&res_limb, zig_not_u128(arg_limb, UINT8_C(128)), zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u64(&res_limb, zig_not_u64(arg_limb, UINT8_C(64)), overflow ? UINT64_C(1) : UINT64_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u32(&res_limb, zig_not_u32(arg_limb, UINT8_C(32)), overflow ? UINT32_C(1) : UINT32_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u16(&res_limb, zig_not_u16(arg_limb, UINT8_C(16)), overflow ? UINT16_C(1) : UINT16_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u8(&res_limb, zig_not_u8(arg_limb, UINT8_C(8)), overflow ? UINT8_C(1) : UINT8_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_min_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) < INT32_C(0) ? lhs : rhs, zig_int_bytes(bits)); +} + +static inline void zig_max_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) >= INT32_C(0) ? lhs : rhs, zig_int_bytes(bits)); +} + static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { uint8_t *res_bytes = res; const uint8_t *lhs_bytes = lhs; const uint8_t *rhs_bytes = rhs; uint16_t byte_offset = 0; uint16_t remaining_bytes = zig_int_bytes(bits); - uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); bool overflow = false; #if zig_big_endian @@ -3038,7 +4333,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo const uint8_t *rhs_bytes = rhs; uint16_t byte_offset = 0; uint16_t remaining_bytes = zig_int_bytes(bits); - uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); bool overflow = false; #if zig_big_endian @@ -3248,323 +4543,755 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo return overflow; } +static inline void zig_add_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_addo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow +} + static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { (void)zig_addo_big(res, lhs, rhs, is_signed, bits); } +static inline void zig_adds_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits); + + if (!zig_addo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); + } +} + +static inline void zig_sub_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_subo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow +} + static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { (void)zig_subo_big(res, lhs, rhs, is_signed, bits); } -zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); -static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - __udivei4(res, lhs, rhs, bits); - return; - } +static inline void zig_subs_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = is_signed ? zig_signFill_big(lhs, is_signed, bits) : -INT8_C(1); - zig_trap(); + if (!zig_subo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); + } } -static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - zig_div_trunc_big(res, lhs, rhs, is_signed, bits); - return; +static inline bool zig_mulo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + const uint8_t *rhs_bytes = rhs; + uint16_t size = zig_int_bytes(bits); + uint16_t sign_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8)); + uint8_t rhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(rhs, is_signed, bits), UINT8_C(8)); + uint16_t lhs_byte_offset = sign_byte_offset; + uint16_t lhs_end_byte_offset = UINT16_C(0); + bool overflow = false; + +#if zig_big_endian + lhs_byte_offset = size - lhs_byte_offset; + lhs_end_byte_offset = size - lhs_end_byte_offset; +#endif + + while (lhs_byte_offset != lhs_end_byte_offset) { + uint16_t rhs_byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint16_t res_byte_offset; + uint16_t lhs_byte; + uint8_t res_byte = UINT8_C(0); + uint16_t mul_res = UINT16_C(0); + uint8_t carry = UINT8_C(0); + +#if zig_little_endian + lhs_byte_offset -= UINT16_C(1); +#else + rhs_byte_offset = size - rhs_byte_offset; + end_byte_offset = size - end_byte_offset; +#endif + + lhs_byte = zig_u16_intCast_u8(lhs_bytes[lhs_byte_offset]) ^ lhs_sign_fill; + +#if zig_big_endian + lhs_byte_offset += UINT16_C(1); +#endif + + res_byte_offset = lhs_byte_offset; + + while (res_byte_offset != end_byte_offset) { + bool res_byte_initialized = res_byte_offset != lhs_byte_offset; + +#if zig_big_endian + rhs_byte_offset -= UINT16_C(1); + res_byte_offset -= UINT16_C(1); +#endif + + if (res_byte_initialized) res_byte = res_bytes[res_byte_offset]; + carry = zig_addo_u8(&res_byte, res_byte, carry, UINT8_C(8)); + carry += zig_addo_u8(&res_byte, res_byte, zig_u8_intCast_u16( + zig_shr_u16(mul_res, UINT8_C(8)) + ), UINT8_C(8)); + mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill); + carry += zig_addo_u8(&res_bytes[res_byte_offset], res_byte, zig_u8_truncate_u16( + mul_res, + UINT8_C(8) + ), UINT8_C(8)); + +#if zig_little_endian + rhs_byte_offset += UINT16_C(1); + res_byte_offset += UINT16_C(1); +#endif + } + + while (rhs_byte_offset != end_byte_offset) { +#if zig_big_endian + rhs_byte_offset -= UINT16_C(1); +#endif + + carry = zig_addo_u8( + &res_byte, + zig_u8_intCast_u16(zig_shr_u16(mul_res, UINT8_C(8))), + carry, + UINT8_C(8) + ); + mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill); + carry += zig_addo_u8(&res_byte, res_byte, zig_u8_truncate_u16( + mul_res, + UINT8_C(8) + ), UINT8_C(8)); + overflow |= res_byte != UINT8_C(0); + +#if zig_little_endian + rhs_byte_offset += UINT16_C(1); +#endif + } + + overflow |= zig_shr_u16(mul_res, UINT8_C(8)) != UINT16_C(0); + overflow |= carry != UINT8_C(0); } - zig_trap(); +#if zig_little_endian + sign_byte_offset -= UINT64_C(1); +#else + sign_byte_offset = size - sign_byte_offset; +#endif + + if (lhs_sign_fill != rhs_sign_fill) { + uint16_t byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint8_t res_byte; + int8_t signed_res_byte; + uint8_t carry = UINT8_C(0); + +#if zig_big_endian + byte_offset = size - byte_offset; + end_byte_offset += UINT16_C(1); +#endif + + while (byte_offset != end_byte_offset) { +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + carry = zig_subo_u8(&res_byte, UINT8_C(0), carry, UINT8_C(8)); + carry += zig_subo_u8(&res_byte, res_byte, res_bytes[byte_offset], UINT8_C(8)); + carry += zig_subo_u8( + &res_bytes[byte_offset], + res_byte, + (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset], + UINT8_C(8) + ); + +#if zig_little_endian + byte_offset += UINT16_C(1); +#endif + } + +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8)); + overflow |= signed_res_byte < INT8_C(0); + overflow |= zig_subo_i8(&signed_res_byte, INT8_C(0), signed_res_byte, UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8)); + } else if (lhs_sign_fill != UINT8_C(0)) { + uint16_t byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint8_t res_byte; + int8_t signed_res_byte; + uint8_t carry = UINT8_C(1); + +#if zig_big_endian + byte_offset = size - byte_offset; + end_byte_offset += UINT16_C(1); +#endif + + while (byte_offset != end_byte_offset) { +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + carry = zig_subo_u8(&res_byte, res_bytes[byte_offset], carry, UINT8_C(8)); + carry += zig_subo_u8(&res_byte, res_byte, lhs_bytes[byte_offset], UINT8_C(8)); + carry += zig_subo_u8(&res_bytes[byte_offset], res_byte, rhs_bytes[byte_offset], UINT8_C(8)); + +#if zig_little_endian + byte_offset += UINT16_C(1); +#endif + } + +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8)); + overflow |= signed_res_byte < INT8_C(0); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + lhs_bytes[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + rhs_bytes[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8)); + } else if (is_signed) { + int8_t signed_res_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8)); + + overflow |= signed_res_byte < INT8_C(0); + } + + { + uint8_t truncate_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t fill_byte = UINT8_C(0); + + if (is_signed) { + int8_t sign_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8)); + int8_t truncated = zig_i8_truncate_i8(sign_byte, truncate_bits); + + overflow |= sign_byte != truncated; + res_bytes[sign_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8)); + } else { + uint8_t sign_byte = res_bytes[sign_byte_offset]; + uint8_t truncated = zig_u8_truncate_u8(sign_byte, truncate_bits); + + overflow |= sign_byte != truncated; + res_bytes[sign_byte_offset] = truncated; + } + +#if zig_little_endian + sign_byte_offset += UINT16_C(1); + memset(&res_bytes[sign_byte_offset], fill_byte, size - sign_byte_offset); +#else + memset(&res_bytes[0], fill_byte, sign_byte_offset); +#endif + } + + return overflow; +} + +static inline void zig_mul_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_mulo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow } -static inline void zig_div_ceil_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - zig_trap(); +static inline void zig_mulw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + (void)zig_mulo_big(res, lhs, rhs, is_signed, bits); } -zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); -static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - __umodei4(res, lhs, rhs, bits); - return; +static inline void zig_muls_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits) ^ zig_signFill_big(rhs, is_signed, bits); + + if (!zig_mulo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); } +} + +static inline void zig_divTrunc_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + if (is_signed) { + zig_extern void __divei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __divei5(res, lhs, rhs, temp, bits); + } else { + zig_extern void __udivei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __udivei5(res, lhs, rhs, temp, bits); + } +} - zig_trap(); +static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + if (is_signed) { + zig_extern void __modei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __modei5(res, lhs, rhs, temp, bits); + } else { + zig_extern void __umodei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __umodei5(res, lhs, rhs, temp, bits); + } } -static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - zig_rem_big(res, lhs, rhs, is_signed, bits); - return; +static inline void zig_divFloor_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool decrement = false; + + if (is_signed) { + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + decrement = zig_u32_bitCast_i32(zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32)); } + zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits); + if (decrement) zig_decrement_big(res, is_signed, bits); +} - zig_trap(); +static inline void zig_divCeil_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool increment = false; + + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + increment = zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ) > INT32_C(0); + zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits); + if (increment) zig_increment_big(res, is_signed, bits); } -static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; - uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); - uint16_t skip_bits = remaining_bytes * 8 - bits; - uint16_t total_lz = 0; - uint16_t limb_lz; - (void)is_signed; +static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool fixup = false; -#if zig_little_endian - byte_offset = remaining_bytes; + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + if (is_signed && zig_u32_bitCast_i32(zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32))) zig_add_big(res, res, rhs, is_signed, bits); +} + +static inline void zig_shr_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = UINT16_C(0); + uint16_t lhs_byte_offset = zig_shr_u16(rhs, UINT8_C(3)); + uint16_t end_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t lhs_prev_byte; + uint8_t byte_shift = zig_u8_truncate_u16(rhs, UINT8_C(3)); + +#if zig_big_endian + res_byte_offset = size - res_byte_offset; + lhs_byte_offset = size - lhs_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - while (remaining_bytes >= 128 / CHAR_BIT) { + { +#if zig_big_endian + lhs_byte_offset -= UINT16_C(1); +#endif + + lhs_prev_byte = lhs_bytes[lhs_byte_offset]; + #if zig_little_endian - byte_offset -= 128 / CHAR_BIT; + lhs_byte_offset += UINT16_C(1); +#endif + } + + while (lhs_byte_offset != end_byte_offset) { +#if zig_big_endian + res_byte_offset -= UINT16_C(1); + lhs_byte_offset -= UINT16_C(1); #endif { - zig_u128 val_limb; + uint8_t lhs_byte = lhs_bytes[lhs_byte_offset]; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u128(val_limb, 128 - skip_bits); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_prev_byte) + ), byte_shift)); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 128 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 128 / CHAR_BIT; - -#if zig_big_endian - byte_offset += 128 / CHAR_BIT; +#if zig_little_endian + res_byte_offset += UINT16_C(1); + lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 64 / CHAR_BIT) { -#if zig_little_endian - byte_offset -= 64 / CHAR_BIT; + { + uint8_t lhs_sign_fill = UINT8_C(0); + +#if zig_big_endian + res_byte_offset -= UINT16_C(1); #endif - { - uint64_t val_limb; + if (is_signed) { + int8_t signed_byte = zig_i8_bitCast_u8(lhs_prev_byte, UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u64(val_limb, 64 - skip_bits); + res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift); + lhs_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8)); + } else { + res_bytes[res_byte_offset] = zig_shr_u8(lhs_prev_byte, byte_shift); } - total_lz += limb_lz; - if (limb_lz < 64 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 64 / CHAR_BIT; - -#if zig_big_endian - byte_offset += 64 / CHAR_BIT; +#if zig_little_endian + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], lhs_sign_fill, size - res_byte_offset); +#else + memset(&res_bytes[0], lhs_sign_fill, res_byte_offset); #endif } +} + +static inline bool zig_shlo_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8)); + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t lhs_byte_offset = UINT16_C(0); + uint16_t end_byte_offset = res_byte_offset - UINT16_C(1) - zig_shr_u16(rhs, UINT8_C(3)); + uint8_t lhs_prev_byte = lhs_sign_fill; + uint8_t byte_shift = UINT8_C(8) - zig_u8_truncate_u16(rhs, UINT8_C(3)); + bool overflow = false; - while (remaining_bytes >= 32 / CHAR_BIT) { #if zig_little_endian - byte_offset -= 32 / CHAR_BIT; + lhs_byte_offset = size - lhs_byte_offset; +#else + res_byte_offset = size - res_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - { - uint32_t val_limb; - - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u32(val_limb, 32 - skip_bits); - } + while (lhs_byte_offset != end_byte_offset) { +#if zig_little_endian + lhs_byte_offset -= UINT16_C(1); +#endif - total_lz += limb_lz; - if (limb_lz < 32 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 32 / CHAR_BIT; + overflow |= lhs_prev_byte != lhs_sign_fill; + lhs_prev_byte = lhs_bytes[lhs_byte_offset]; #if zig_big_endian - byte_offset += 32 / CHAR_BIT; + lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 16 / CHAR_BIT) { #if zig_little_endian - byte_offset -= 16 / CHAR_BIT; + end_byte_offset = UINT16_C(0); +#else + end_byte_offset = size; +#endif + + { + bool lhs_more_bytes = lhs_byte_offset != end_byte_offset; + +#if zig_little_endian + if (lhs_more_bytes) lhs_byte_offset -= UINT16_C(1); #endif { - uint16_t val_limb; + uint8_t lhs_byte = UINT8_C(0); + + if (lhs_more_bytes) lhs_byte = lhs_bytes[lhs_byte_offset]; + + if (is_signed) { + int16_t shifted = zig_shr_i16(zig_or_i16( + zig_shl_i16(zig_i16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_i16_intCast_u8(lhs_byte) + ), byte_shift); + int8_t truncated = zig_i8_truncate_i16( + shifted, + zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1) + ); + uint8_t fill = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8)); + + overflow |= zig_i16_intCast_i8(truncated) != shifted; +#if zig_little_endian + memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); + res_byte_offset -= UINT16_C(1); +#else + memset(&res_bytes[0], fill, res_byte_offset); +#endif + res_bytes[res_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8)); + } else { + uint16_t shifted = zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_byte) + ), byte_shift); + uint8_t truncated = zig_u8_truncate_u16( + shifted, + zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1) + ); + + overflow |= zig_u16_intCast_u8(truncated) != shifted; +#if zig_little_endian + memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset); + res_byte_offset -= UINT16_C(1); +#else + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#endif + res_bytes[res_byte_offset] = truncated; + } - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u16(val_limb, 16 - skip_bits); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 16 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 16 / CHAR_BIT; - #if zig_big_endian - byte_offset += 16 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + if (lhs_more_bytes) lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 8 / CHAR_BIT) { + while (lhs_byte_offset != end_byte_offset) { #if zig_little_endian - byte_offset -= 8 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); + lhs_byte_offset -= UINT16_C(1); #endif { - uint8_t val_limb; + uint8_t lhs_byte = lhs_bytes[lhs_byte_offset]; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u8(val_limb, 8 - skip_bits); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_byte) + ), byte_shift)); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 8 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 8 / CHAR_BIT; - #if zig_big_endian - byte_offset += 8 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + lhs_byte_offset += UINT16_C(1); #endif } - return total_lz; -} + { +#if zig_little_endian + res_byte_offset -= UINT16_C(1); +#endif -static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; - uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); - uint16_t total_tz = 0; - uint16_t limb_tz; - (void)is_signed; + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + byte_shift + )); #if zig_big_endian - byte_offset = remaining_bytes; + res_byte_offset += UINT16_C(1); #endif + } - while (remaining_bytes >= 128 / CHAR_BIT) { -#if zig_big_endian - byte_offset -= 128 / CHAR_BIT; +#if zig_little_endian + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#else + memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset); #endif - { - zig_u128 val_limb; + return overflow; +} - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u128(val_limb, 128); - } +static inline void zig_shl_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + if (zig_shlo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: left shift overflowed bits +} - total_tz += limb_tz; - if (limb_tz < 128) return total_tz; - remaining_bytes -= 128 / CHAR_BIT; +static inline void zig_shlw_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + (void)zig_shlo_big(res, lhs, rhs, is_signed, bits); +} -#if zig_little_endian - byte_offset += 128 / CHAR_BIT; -#endif +#define zig_big_shls_builtin(w) \ + static inline uint##w##_t zig_shls_u##w##_big(uint##w##_t lhs, const void *rhs, \ + uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \ + uint##w##_t res; \ + const uint8_t *rhs_bytes = rhs; \ + if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \ + !zig_shlo_u##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \ + return lhs == INT##w##_C(0) ? zig_minInt_u(w, lhs_bits) : zig_maxInt_u(w, lhs_bits); \ + } \ +\ + static inline int##w##_t zig_shls_i##w##_big(int##w##_t lhs, const void *rhs, \ + uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \ + int##w##_t res; \ + const uint8_t *rhs_bytes = rhs; \ + if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \ + !zig_shlo_i##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \ + return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ + lhs < INT##w##_C(0) ? zig_minInt_i(w, lhs_bits) : zig_maxInt_i(w, lhs_bits); \ + } \ +\ + static inline void zig_shls_big_u##w(void *res, const void *lhs, uint##w##_t rhs, bool is_signed, uint16_t bits) { \ + const uint8_t *lhs_bytes = lhs; \ + if (rhs < bits && !zig_shlo_big(res, lhs, zig_u16_intCast_u##w(rhs), is_signed, bits)) return; \ + switch (zig_cmp_big_u8(lhs, UINT8_C(0), is_signed, bits)) { \ + case -INT32_C(1): return zig_minInt_big(res, is_signed, bits); \ + case INT32_C(0): return zig_minInt_big(res, false, bits); \ + case INT32_C(1): return zig_maxInt_big(res, is_signed, bits); \ + default: zig_unreachable(); \ + } \ } +zig_big_shls_builtin(8) +zig_big_shls_builtin(16) +zig_big_shls_builtin(32) +zig_big_shls_builtin(64) + +static inline void zig_byteSwap_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_byte_offset = UINT16_C(0); + uint16_t arg_byte_offset = bits / CHAR_BIT; + uint16_t end_byte_offset = UINT16_C(1); + uint16_t size = zig_int_bytes(bits); - while (remaining_bytes >= 64 / CHAR_BIT) { #if zig_big_endian - byte_offset -= 64 / CHAR_BIT; + res_byte_offset = size - res_byte_offset; + arg_byte_offset = size - arg_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - { - uint64_t val_limb; - - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u64(val_limb, 64); - } + while (arg_byte_offset != end_byte_offset) { +#if zig_little_endian + arg_byte_offset -= UINT16_C(1); +#else + res_byte_offset -= UINT16_C(1); +#endif - total_tz += limb_tz; - if (limb_tz < 64) return total_tz; - remaining_bytes -= 64 / CHAR_BIT; + res_bytes[res_byte_offset] = arg_bytes[arg_byte_offset]; #if zig_little_endian - byte_offset += 64 / CHAR_BIT; + res_byte_offset += UINT16_C(1); +#else + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 32 / CHAR_BIT) { -#if zig_big_endian - byte_offset -= 32 / CHAR_BIT; + { +#if zig_little_endian + arg_byte_offset -= UINT16_C(1); +#else + res_byte_offset -= UINT16_C(1); #endif { - uint32_t val_limb; + uint8_t byte = arg_bytes[arg_byte_offset]; + uint8_t fill = is_signed + ? zig_u8_bitCast_i8(zig_shr_i8(zig_i8_bitCast_u8(byte, UINT8_C(8)), UINT8_C(7)), UINT8_C(8)) + : UINT8_C(0); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u32(val_limb, 32); + res_bytes[res_byte_offset] = byte; + +#if zig_little_endian + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); +#else + memset(&res_bytes[0], fill, res_byte_offset); +#endif } + } +} - total_tz += limb_tz; - if (limb_tz < 32) return total_tz; - remaining_bytes -= 32 / CHAR_BIT; +static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = UINT16_C(0); + uint16_t arg_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t end_byte_offset = UINT16_C(0); + uint8_t arg_prev_byte; + uint8_t byte_shift = zig_u8_intCast_u16(zig_subw_u16(UINT16_C(0), bits, UINT8_C(3))); + +#if zig_big_endian + res_byte_offset = size - res_byte_offset; + arg_byte_offset = size - arg_byte_offset; + end_byte_offset = size - end_byte_offset; +#endif + { #if zig_little_endian - byte_offset += 32 / CHAR_BIT; + arg_byte_offset -= UINT16_C(1); +#endif + + arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); + +#if zig_big_endian + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 16 / CHAR_BIT) { + while (arg_byte_offset != end_byte_offset) { #if zig_big_endian - byte_offset -= 16 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); +#else + arg_byte_offset -= UINT16_C(1); #endif { - uint16_t val_limb; + uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u16(val_limb, 16); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(arg_byte), UINT8_C(8)), + zig_u16_intCast_u8(arg_prev_byte) + ), byte_shift)); + arg_prev_byte = arg_byte; } - total_tz += limb_tz; - if (limb_tz < 16) return total_tz; - remaining_bytes -= 16 / CHAR_BIT; - #if zig_little_endian - byte_offset += 16 / CHAR_BIT; + res_byte_offset += UINT16_C(1); +#else + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 8 / CHAR_BIT) { + { + uint8_t arg_sign_fill = UINT8_C(0); + #if zig_big_endian - byte_offset -= 8 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); #endif - { - uint8_t val_limb; + if (is_signed) { + int8_t signed_byte = zig_i8_bitCast_u8(arg_prev_byte, UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u8(val_limb, 8); + res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift); + arg_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8)); + } else { + res_bytes[res_byte_offset] = zig_shr_u8(arg_prev_byte, byte_shift); } - total_tz += limb_tz; - if (limb_tz < 8) return total_tz; - remaining_bytes -= 8 / CHAR_BIT; - #if zig_little_endian - byte_offset += 8 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], arg_sign_fill, size - res_byte_offset); +#else + memset(&res_bytes[0], arg_sign_fill, res_byte_offset); #endif } - - return total_tz; } -static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; +static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); + uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); uint16_t total_pc = 0; (void)is_signed; #if zig_big_endian - byte_offset = remaining_bytes; + byte_offset = zig_int_bytes(bits); #endif while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 128 / CHAR_BIT; #endif { - zig_u128 val_limb; + zig_u128 arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u128(val_limb, 128); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 128 / CHAR_BIT; @@ -3575,15 +5302,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 64 / CHAR_BIT; #endif { - uint64_t val_limb; + uint64_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u64(val_limb, 64); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 64 / CHAR_BIT; @@ -3594,15 +5323,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 32 / CHAR_BIT; #endif { - uint32_t val_limb; + uint32_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u32(val_limb, 32); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 32 / CHAR_BIT; @@ -3613,15 +5344,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 16 / CHAR_BIT; #endif { - uint16_t val_limb; + uint16_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc = zig_popcount_u16(val_limb, 16); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 16 / CHAR_BIT; @@ -3632,15 +5365,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 8 / CHAR_BIT; #endif { - uint8_t val_limb; + uint8_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc = zig_popcount_u8(val_limb, 8); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 8 / CHAR_BIT; @@ -3653,6 +5388,274 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ return total_pc; } +static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = UINT16_C(0); + uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + uint16_t total_tz = UINT16_C(0); + uint16_t limb_tz; + (void)is_signed; + +#if zig_big_endian + byte_offset = zig_int_bytes(bits); +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_tz; +} + +static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t remaining_bytes = byte_offset; + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + bool sign_limb = true; + uint16_t total_lz = UINT16_C(0); + uint16_t limb_lz; + (void)is_signed; + +#if zig_big_endian + byte_offset = zig_int_bytes(bits) - remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_lz; +} + /* ========================= Floating Point Support ========================= */ #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ @@ -3687,29 +5690,29 @@ long double __cdecl nanl(char const* input); #define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg) #define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg) #else -#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr) -#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr) -#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr) -#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr) -#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr) +#define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr) +#define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr) +#define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr) +#define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr) +#define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr) #endif #define zig_has_f16 1 #define zig_libc_name_f16(name) __##name##h #define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr) -#if FLT_MANT_DIG == 11 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11 typedef float zig_f16; #define zig_make_f16(fp, repr) fp##f -#elif DBL_MANT_DIG == 11 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11 typedef double zig_f16; #define zig_make_f16(fp, repr) fp -#elif LDBL_MANT_DIG == 11 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11 typedef long double zig_f16; #define zig_make_f16(fp, repr) fp##l -#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc)) +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc)) typedef _Float16 zig_f16; #define zig_make_f16(fp, repr) fp##f16 -#elif defined(__SIZEOF_FP16__) +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && defined(__SIZEOF_FP16__) typedef __fp16 zig_f16; #define zig_make_f16(fp, repr) fp##f16 #else @@ -3723,11 +5726,6 @@ typedef uint16_t zig_f16; #undef zig_init_special_f16 #define zig_init_special_f16(sign, name, arg, repr) repr #endif -#if defined(zig_darwin) && defined(zig_x86) -typedef uint16_t zig_compiler_rt_f16; -#else -typedef zig_f16 zig_compiler_rt_f16; -#endif #define zig_has_f32 1 #define zig_libc_name_f32(name) name##f @@ -3736,16 +5734,16 @@ typedef zig_f16 zig_compiler_rt_f16; #else #define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr) #endif -#if FLT_MANT_DIG == 24 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24 typedef float zig_f32; #define zig_make_f32(fp, repr) fp##f -#elif DBL_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24 typedef double zig_f32; #define zig_make_f32(fp, repr) fp -#elif LDBL_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24 typedef long double zig_f32; #define zig_make_f32(fp, repr) fp##l -#elif FLT32_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24 typedef _Float32 zig_f32; #define zig_make_f32(fp, repr) fp##f32 #else @@ -3768,19 +5766,19 @@ typedef uint32_t zig_f32; #else #define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr) #endif -#if FLT_MANT_DIG == 53 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53 typedef float zig_f64; #define zig_make_f64(fp, repr) fp##f -#elif DBL_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53 typedef double zig_f64; #define zig_make_f64(fp, repr) fp -#elif LDBL_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53 typedef long double zig_f64; #define zig_make_f64(fp, repr) fp##l -#elif FLT64_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53 typedef _Float64 zig_f64; #define zig_make_f64(fp, repr) fp##f64 -#elif FLT32X_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53 typedef _Float32x zig_f64; #define zig_make_f64(fp, repr) fp##f32x #else @@ -3798,7 +5796,14 @@ typedef uint64_t zig_f64; #define zig_has_f80 1 #define zig_libc_name_f80(name) __##name##x #define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr) -#if FLT_MANT_DIG == 64 +#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F80_ABI +#undef zig_has_f80 +typedef struct { uint64_t mantissa; uint16_t exponent; } zig_f80; +#define zig_init_repr_f80(mantissa, exponent) { .mant##issa = mantissa, .expo##nent = exponent } +#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent) +#define zig_mantissa_repr_f80(arg) (arg).mantissa +#define zig_exponent_repr_f80(arg) (arg).exponent +#elif FLT_MANT_DIG == 64 typedef float zig_f80; #define zig_make_f80(fp, repr) fp##f #elif DBL_MANT_DIG == 64 @@ -3818,10 +5823,18 @@ typedef __float80 zig_f80; #define zig_make_f80(fp, repr) fp##l #else #undef zig_has_f80 -#define zig_has_f80 0 -#define zig_repr_f80 u128 typedef zig_u128 zig_f80; +#define zig_init_repr_f80(mantissa, exponent) zig_init_u128(exponent, mantissa) +#define zig_make_repr_f80(mantissa, exponent) zig_make_u128(exponent, mantissa) +#define zig_mantissa_repr_f80(arg) zig_lo_u128(arg) +#define zig_exponent_repr_f80(arg) (uint16_t)zig_hi_u128(arg) +#endif +#ifndef zig_has_f80 +#define zig_has_f80 0 #define zig_make_f80(fp, repr) repr +#ifndef zig_make_repr_f80 +#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent) +#endif #undef zig_make_special_f80 #define zig_make_special_f80(sign, name, arg, repr) repr #undef zig_init_special_f80 @@ -3833,11 +5846,20 @@ typedef zig_u128 zig_f80; #else #define zig_f128_has_miscompilations 0 #endif - #define zig_has_f128 1 #define zig_libc_name_f128(name) name##f128 #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) -#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 +#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F128_ABI +#undef zig_has_f128 +#if zig_little_endian +typedef struct { uint64_t lo, hi; } zig_f128; +#else +typedef struct { uint64_t hi, lo; } zig_f128; +#endif +#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_lo_repr_f128(arg) (arg).lo +#define zig_hi_repr_f128(arg) (arg).hi +#elif !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 typedef float zig_f128; #define zig_make_f128(fp, repr) fp##f #elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 @@ -3859,27 +5881,38 @@ typedef __float128 zig_f128; #define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg) #else #undef zig_has_f128 -#define zig_has_f128 0 -#undef zig_make_special_f128 -#undef zig_init_special_f128 -#if defined(zig_darwin) || defined(zig_aarch64) -typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64; -zig_basic_operator(zig_v2u64, xor_v2u64, ^) -#define zig_repr_f128 v2u64 -typedef zig_v2u64 zig_f128; -#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi } -#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128 -#define zig_make_f128(fp, repr) zig_make_f128_##repr -#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr -#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr +#if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC) +#if defined(zig_msvc) && !defined(__clang__) +#include +typedef __m128i zig_f128; +#define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } } +#define zig_lo_repr_f128(arg) (arg).m128i_u64[0] +#define zig_hi_repr_f128(arg) (arg).m128i_u64[1] +#else +typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128; +#define zig_init_repr_f128(hi, lo) { lo, hi } +#define zig_lo_repr_f128(arg) (arg)[0] +#define zig_hi_repr_f128(arg) (arg)[1] +#endif #else -#define zig_repr_f128 u128 typedef zig_u128 zig_f128; +#define zig_init_repr_f128(hi, lo) zig_init_u128(hi, lo) +#define zig_make_repr_f128(hi, lo) zig_make_u128(hi, lo) +#define zig_lo_repr_f128(arg) zig_lo_u128(arg) +#define zig_hi_repr_f128(arg) zig_hi_u128(arg) +#endif +#endif +#ifndef zig_has_f128 +#define zig_has_f128 0 #define zig_make_f128(fp, repr) repr +#ifndef zig_make_repr_f128 +#define zig_make_repr_f128(hi, lo) (zig_f128)zig_init_repr_f128(hi, lo) +#endif +#undef zig_make_special_f128 #define zig_make_special_f128(sign, name, arg, repr) repr +#undef zig_init_special_f128 #define zig_init_special_f128(sign, name, arg, repr) repr #endif -#endif #if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC) /* Emulate msvc abi on a gnu compiler */ @@ -3892,84 +5925,141 @@ typedef zig_f128 zig_c_longdouble; typedef long double zig_c_longdouble; #endif -#define zig_bitCast_float(Type, ReprType) \ - static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \ - zig_##Type result; \ - memcpy(&result, &repr, sizeof(result)); \ - return result; \ +#if __AVR__ +typedef signed char zig_FloatCompareResult; +#elif defined(zig_aarch64) +typedef signed int zig_FloatCompareResult; +#elif __SIZEOF_LONG__ >= __SIZEOF_POINTER__ +typedef signed long zig_FloatCompareResult; +#else +typedef signed long long zig_FloatCompareResult; +#endif + +#define zig_bitCast_float(w, iw, UnsignedReprType, SignedReprType) \ + static inline zig_f##w zig_f##w##_bitCast_u##iw(UnsignedReprType arg) { \ + zig_f##w res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return res; \ + } \ + static inline zig_f##w zig_f##w##_bitCast_i##iw(SignedReprType arg) { \ + zig_f##w res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return res; \ + } \ + static inline UnsignedReprType zig_u##iw##_bitCast_f##w(zig_f##w arg) { \ + UnsignedReprType res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return zig_u##iw##_truncate_u##iw(res, w); \ + } \ + static inline SignedReprType zig_i##iw##_bitCast_f##w(zig_f##w arg) { \ + SignedReprType res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return zig_i##iw##_truncate_i##iw(res, w); \ + } +zig_bitCast_float(16, 16, uint16_t, int16_t) +zig_bitCast_float(32, 32, uint32_t, int32_t) +zig_bitCast_float(64, 64, uint64_t, int64_t) +#if zig_has_f80 +zig_bitCast_float(80, 128, zig_u128, zig_i128) +#else +static inline zig_f80 zig_f80_bitCast_u128(zig_u128 arg) { + return zig_make_repr_f80(zig_lo_u128(arg), (uint16_t)zig_hi_u128(arg)); +} +static inline zig_f80 zig_f80_bitCast_i128(zig_i128 arg) { + return zig_make_repr_f80(zig_lo_i128(arg), (uint16_t)zig_hi_i128(arg)); +} +static inline zig_u128 zig_u128_bitCast_f80(zig_f80 arg) { + return zig_make_u128(zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg)); +} +static inline zig_i128 zig_i128_bitCast_f80(zig_f80 arg) { + return zig_make_i128((int16_t)zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg)); +} +#endif +static inline zig_f80 zig_f80_bitCast_big(const void *arg) { + return zig_f80_bitCast_u128(zig_u128_truncate_big(arg, UINT8_C(80), false, UINT16_C(80))); +} +static inline void zig_big_bitCast_f80(void *res, zig_f80 arg, bool res_is_signed, uint16_t res_bits) { + if (res_is_signed) { + zig_big_truncate_i128(res, zig_i128_bitCast_f80(arg), res_is_signed, res_bits); + } else { + zig_big_truncate_u128(res, zig_u128_bitCast_f80(arg), res_is_signed, res_bits); } -zig_bitCast_float(f16, uint16_t) -zig_bitCast_float(f32, uint32_t) -zig_bitCast_float(f64, uint64_t) -zig_bitCast_float(f80, zig_u128) -zig_bitCast_float(f128, zig_u128) +} +#if zig_has_f128 +zig_bitCast_float(128, 128, zig_u128, zig_i128) +#else +static inline zig_f128 zig_f128_bitCast_u128(zig_u128 arg) { + return zig_make_repr_f128(zig_hi_u128(arg), zig_lo_u128(arg)); +} +static inline zig_f128 zig_f128_bitCast_i128(zig_i128 arg) { + return zig_make_repr_f128((uint64_t)zig_hi_i128(arg), zig_lo_i128(arg)); +} +static inline zig_u128 zig_u128_bitCast_f128(zig_f128 arg) { + return zig_make_u128(zig_hi_repr_f128(arg), zig_lo_repr_f128(arg)); +} +static inline zig_i128 zig_i128_bitCast_f128(zig_f128 arg) { + return zig_make_i128((int64_t)zig_hi_repr_f128(arg), zig_lo_repr_f128(arg)); +} +#endif -#define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \ - zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ - zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \ +#define zig_convert_float_00(ResType, operation, ArgType, version) \ + zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType arg); \ + return zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(arg) +#define zig_convert_float_01(ResType, operation, ArgType, version) \ + zig_convert_float_00(ResType, operation, ArgType, version) +#define zig_convert_float_10(ResType, operation, ArgType, version) \ + zig_convert_float_00(ResType, operation, ArgType, version) +#define zig_convert_float_11(ResType, operation, ArgType, version) \ + return (ResType)arg +#define zig_convert_float(res_when, ResType, operation, arg_when, ArgType, version) \ static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \ zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \ - ResType res; \ - ExternResType extern_res; \ - ExternArgType extern_arg; \ - memcpy(&extern_arg, &arg, sizeof(extern_arg)); \ - extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ - zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \ - memcpy(&res, &extern_res, sizeof(res)); \ - return extern_res; \ + zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \ + zig_has_##arg_when)(ResType, operation, ArgType, version); \ } -zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2) -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2) -zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2) -#ifdef __ARM_EABI__ +#define zig_convert_floats(SmallType, BigType) \ + zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \ + zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2) +zig_convert_floats(f16, f32) +zig_convert_floats(f16, f64) +zig_convert_floats(f16, f80) +zig_convert_floats(f16, f128) +zig_convert_floats(f32, f64) +zig_convert_floats(f32, f80) +zig_convert_floats(f32, f128) +zig_convert_floats(f64, f80) +zig_convert_floats(f64, f128) +zig_convert_floats(f80, f128) -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64); -static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32); -static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); } - -#else /* __ARM_EABI__ */ - -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2) - -#endif /* __ARM_EABI__ */ - -#define zig_float_negate_builtin_0(w, c, sb) \ - zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb)) -#define zig_float_negate_builtin_1(w, c, sb) -arg -#define zig_float_negate_builtin(w, c, sb) \ +#define zig_float_negate_builtin_0(w, sb) \ + zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb)) +#define zig_float_negate_builtin_1(w, sb) -arg +#define zig_float_negate_builtin(w, sb) \ static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \ - return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, c, sb); \ + return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, sb); \ } -zig_float_negate_builtin(16, , UINT16_C(1) << 15 ) -zig_float_negate_builtin(32, , UINT32_C(1) << 31 ) -zig_float_negate_builtin(64, , UINT64_C(1) << 63 ) -zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0))) -zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) +zig_float_negate_builtin(16, UINT16_C(1) << 15) +zig_float_negate_builtin(32, UINT32_C(1) << 31) +zig_float_negate_builtin(64, UINT64_C(1) << 63) + +#undef zig_float_negate_builtin_0 +#define zig_float_negate_builtin_0(w, sb) \ + zig_make_repr_f##w(zig_mantissa_repr_f##w(arg), zig_xor_u16(zig_exponent_repr_f##w(arg), sb)) +zig_float_negate_builtin(80, UINT16_C(1) << 15) + +#undef zig_float_negate_builtin_0 +#define zig_float_negate_builtin_0(w, sb) \ + zig_make_repr_f##w(zig_xor_u64(zig_hi_repr_f##w(arg), sb), zig_lo_repr_f##w(arg)) +zig_float_negate_builtin(128, UINT64_C(1) << 63) #define zig_float_less_builtin_0(Type, operation) \ - zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \ + zig_extern zig_FloatCompareResult zig_expand_concat(zig_expand_concat(__##operation, \ zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \ static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ - return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \ + return (int32_t)zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \ } #define zig_float_less_builtin_1(Type, operation) \ static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ @@ -3994,13 +6084,52 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) return lhs operator rhs; \ } +#define zig_float_builtins(w) \ + zig_common_float_builtins(w) \ + zig_convert_float(f##w, zig_f##w, float, int128, zig_i128, ) \ + zig_convert_float(f##w, zig_f##w, floatun, int128, zig_u128, ) #define zig_common_float_builtins(w) \ - zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \ + zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \ + zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \ + zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \ + zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(int128, zig_u128, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(f##w, zig_f##w, float, always, int32_t, ) \ + zig_convert_float(f##w, zig_f##w, float, always, int64_t, ) \ + zig_convert_float(f##w, zig_f##w, floatun, always, uint32_t, ) \ + zig_convert_float(f##w, zig_f##w, floatun, always, uint64_t, ) \ +\ + static inline void zig_expand_concat(zig_expand_concat(zig_fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ + zig_extern void zig_expand_concat(zig_expand_concat(__fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ + zig_expand_concat(zig_expand_concat(__fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ + } \ +\ + static inline void zig_expand_concat(zig_expand_concat(zig_fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ + zig_extern void zig_expand_concat(zig_expand_concat(__fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ + zig_expand_concat(zig_expand_concat(__fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ + } \ +\ + static inline zig_f##w zig_expand_concat(zig_floatei, \ + zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ + zig_extern zig_f##w zig_expand_concat(__floatei, \ + zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ + return zig_expand_concat(__floatei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ + } \ +\ + static inline zig_f##w zig_expand_concat(zig_floatunei, \ + zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ + zig_extern zig_f##w zig_expand_concat(__floatunei, \ + zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ + return zig_expand_concat(__floatunei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ + } \ +\ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, eq) \ @@ -4031,82 +6160,48 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmax)))(zig_f##w, zig_max_f##w, zig_libc_name_f##w(fmax), (zig_f##w x, zig_f##w y), (x, y)) \ zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fma)))(zig_f##w, zig_fma_f##w, zig_libc_name_f##w(fma), (zig_f##w x, zig_f##w y, zig_f##w z), (x, y, z)) \ \ - static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divTrunc_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ - static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divFloor_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ - static inline zig_f##w zig_div_ceil_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divCeil_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \ - return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \ + return zig_sub_f##w(lhs, zig_mul_f##w(zig_divFloor_f##w(lhs, rhs), rhs)); \ } -zig_common_float_builtins(16) -zig_common_float_builtins(32) -zig_common_float_builtins(64) -zig_common_float_builtins(80) -zig_common_float_builtins(128) - -#define zig_float_builtins(w) \ - zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, ) zig_float_builtins(16) -zig_float_builtins(80) -zig_float_builtins(128) - -#ifdef __ARM_EABI__ - -zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32); -static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32); -static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32); -static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t); -static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t); -static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t); -static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64); -static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64); -static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64); -static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t); -static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t); -static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t); -static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); } - -#else /* __ARM_EABI__ */ - zig_float_builtins(32) zig_float_builtins(64) - -#endif /* __ARM_EABI__ */ +zig_float_builtins(80) +#if defined(zig_x86_32) +zig_common_float_builtins(128) +static inline zig_f128 zig_floattitf(zig_i128 arg) { + extern zig_f128 __floattitf(zig_f128 arg); + return __floattitf(zig_f128_bitCast_i128(arg)); +} +static inline zig_f128 zig_floatuntitf(zig_u128 arg) { + extern zig_f128 __floatuntitf(zig_f128 arg); + return __floatuntitf(zig_f128_bitCast_u128(arg)); +} +#elif defined(zig_x86_64) && defined(zig_windows) +zig_common_float_builtins(128) +static inline zig_f128 zig_floattitf(zig_i128 arg) { + extern zig_f128 __floattitf(zig_i128 arg); + return __floattitf(arg); +} +static inline zig_f128 zig_floatuntitf(zig_u128 arg) { + extern zig_f128 __floatuntitf(uint64_t arg_lo, uint64_t arg_hi); + return __floatuntitf(zig_lo_u128(arg), zig_hi_u128(arg)); +} +#else +zig_float_builtins(128) +#endif /* ============================ Atomics Support ============================= */ @@ -4410,19 +6505,19 @@ typedef int zig_memory_order; } \ static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \ (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \ - } \ + } \ static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \ return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ } \ static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \ - Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ + Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - return val; \ + return value; \ } \ static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \ - Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ + Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - return val; \ + return value; \ } zig_msvc_atomics( u8, uint8_t, char, 8, 8) @@ -4465,14 +6560,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64) zig_##Type result; \ SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - memcpy(&result, &initial, sizeof(result)); \ + memcpy(&result, &initial, sizeof(result)); \ return result; \ } \ static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \ zig_##Type result; \ SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - memcpy(&result, &initial, sizeof(result)); \ + memcpy(&result, &initial, sizeof(result)); \ return result; \ } @@ -4502,9 +6597,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat } static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) { - void* val = (void*)__iso_volatile_load32(obj); + void* value = (void*)__iso_volatile_load32(obj); _ReadWriteBarrier(); - return val; + return value; } static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) { @@ -4532,9 +6627,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volat } static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) { - void* val = (void*)__iso_volatile_load64(obj); + void* value = (void*)__iso_volatile_load64(obj); _ReadWriteBarrier(); - return val; + return value; } static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 9ecd3a4e0b1f4483c878e056cf3786bccafed62b..d1605b457e2f3673807c16fd10836612aae804d5 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -164,7 +164,8 @@ const BlockData = struct { const LocalType = struct { type: Type, - alignment: Alignment, + alignment: Alignment = .none, + array_len: u2 = 1, }; const LocalIndex = u16; @@ -184,13 +185,11 @@ const ValueRenderLocation = enum { } }; -const BuiltinInfo = enum { none, bits }; +const BuiltinInfo = enum { none, bits, bits_none, big_temp_bits }; const reserved_idents = std.StaticStringMap(void).initComptime(.{ // C language - .{ "alignas", { - @setEvalBranchQuota(4000); - } }, + .{ "alignas", {} }, .{ "alignof", {} }, .{ "asm", {} }, .{ "atomic_bool", {} }, @@ -302,7 +301,100 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{ // stddef.h .{ "offsetof", {} }, + // math.h (only symbols exported by compiler-rt) + .{ "ceil", {} }, + .{ "ceilf", {} }, + .{ "ceilf128", {} }, + .{ "ceill", {} }, + .{ "cos", {} }, + .{ "cosf", {} }, + .{ "cosf128", {} }, + .{ "cosl", {} }, + .{ "exp", {} }, + .{ "exp2", {} }, + .{ "exp2f", {} }, + .{ "exp2f128", {} }, + .{ "exp2l", {} }, + .{ "expf", {} }, + .{ "expf128", {} }, + .{ "expl", {} }, + .{ "fabs", {} }, + .{ "fabsf", {} }, + .{ "fabsf128", {} }, + .{ "fabsl", {} }, + .{ "floor", {} }, + .{ "floorf", {} }, + .{ "floorf128", {} }, + .{ "floorl", {} }, + .{ "fma", {} }, + .{ "fmaf", {} }, + .{ "fmaf128", {} }, + .{ "fmal", {} }, + .{ "fmax", {} }, + .{ "fmaxf", {} }, + .{ "fmaxf128", {} }, + .{ "fmaxl", {} }, + .{ "fmin", {} }, + .{ "fminf", {} }, + .{ "fminf128", {} }, + .{ "fminl", {} }, + .{ "fmod", {} }, + .{ "fmodf", {} }, + .{ "fmodf128", {} }, + .{ "fmodl", {} }, + .{ "log", {} }, + .{ "log10", {} }, + .{ "log10f", {} }, + .{ "log10f128", {} }, + .{ "log10l", {} }, + .{ "log2", {} }, + .{ "log2f", {} }, + .{ "log2f128", {} }, + .{ "log2l", {} }, + .{ "logf", {} }, + .{ "logf128", {} }, + .{ "logl", {} }, + .{ "round", {} }, + .{ "roundf", {} }, + .{ "roundf128", {} }, + .{ "roundl", {} }, + .{ "sin", {} }, + .{ "sincos", {} }, + .{ "sincosf", {} }, + .{ "sincosf128", {} }, + .{ "sincosl", {} }, + .{ "sinf", {} }, + .{ "sinf128", {} }, + .{ "sinl", {} }, + .{ "sqrt", {} }, + .{ "sqrtf", {} }, + .{ "sqrtf128", {} }, + .{ "sqrtl", {} }, + .{ "tan", {} }, + .{ "tanf", {} }, + .{ "tanf128", {} }, + .{ "tanl", {} }, + .{ "trunc", {} }, + .{ "truncf", {} }, + .{ "truncf128", {} }, + .{ "truncl", {} }, + // windows.h + .{"DUMMYSTRUCTNAME"}, + .{"DUMMYSTRUCTNAME2"}, + .{"DUMMYSTRUCTNAME3"}, + .{"DUMMYSTRUCTNAME4"}, + .{"DUMMYSTRUCTNAME5"}, + .{"DUMMYSTRUCTNAME6"}, + .{"DUMMYUNIONNAME"}, + .{"DUMMYUNIONNAME2"}, + .{"DUMMYUNIONNAME3"}, + .{"DUMMYUNIONNAME4"}, + .{"DUMMYUNIONNAME5"}, + .{"DUMMYUNIONNAME6"}, + .{"DUMMYUNIONNAME7"}, + .{"DUMMYUNIONNAME8"}, + .{"DUMMYUNIONNAME9"}, .{ "max", {} }, .{ "min", {} }, }); @@ -316,13 +408,6 @@ fn isReservedIdent(ident: []const u8) bool { } } - // windows.h - if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or - mem.startsWith(u8, ident, "DUMMYUNIONNAME")) - { - return true; - } - // CType if (mem.startsWith(u8, ident, "enum__") or mem.startsWith(u8, ident, "bitpack__") or @@ -469,10 +554,7 @@ pub const Function = struct { } fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue { - return f.allocAlignedLocal(inst, .{ - .type = ty, - .alignment = .none, - }); + return f.allocAlignedLocal(inst, .{ .type = ty }); } /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should @@ -564,10 +646,6 @@ pub const Function = struct { return f.dg.renderType(w, ty); } - fn renderIntCast(f: *Function, w: *Writer, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void { - return f.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location); - } - fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) { return f.dg.fmtIntLiteralDec(val, .other); } @@ -672,7 +750,9 @@ pub const DeclGen = struct { // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. const ptr_ty: Type = .fromInterned(uav.orig_ty); if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { - return dg.renderUndefValue(w, ptr_ty, location); + try w.writeByte('('); + try dg.renderOpvPointer(w, ptr_ty, location); + return w.writeByte(')'); } switch (ip.indexToKey(uav.val)) { @@ -737,8 +817,10 @@ pub const DeclGen = struct { // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).resolved.?.type); const ptr_ty = try pt.navPtrType(owner_nav); - if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { - return dg.renderUndefValue(w, ptr_ty, location); + if (nav_ty.zigTypeTag(zcu) != .@"opaque" and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { + try w.writeByte('('); + try dg.renderOpvPointer(w, ptr_ty, location); + return w.writeByte(')'); } // We shouldn't cast C function pointers as this is UB (when you call @@ -758,6 +840,26 @@ pub const DeclGen = struct { if (need_cast) try w.writeByte(')'); } + fn renderOpvPointer( + dg: *DeclGen, + w: *Writer, + ptr_ty: Type, + location: ValueRenderLocation, + ) Error!void { + const zcu = dg.pt.zcu; + const target = zcu.getTarget(); + try w.writeByte('('); + try dg.renderType(w, ptr_ty); + return w.print("){f}", .{fmtUnsignedIntLiteralSmall( + target, + .uintptr_t, + ptr_ty.ptrAlignment(zcu).forward(undefPattern(u64) >> @intCast(64 - target.ptrBitWidth())), + location == .static_initializer, + 16, + .lower, + )}); + } + fn renderPointer( dg: *DeclGen, w: *Writer, @@ -959,9 +1061,6 @@ pub const DeclGen = struct { const bits = ty.floatBits(target); const f128_val = val.toFloat(f128, zcu); - // All unsigned ints matching float types are pre-allocated. - const repr_ty = pt.intType(.unsigned, bits) catch unreachable; - assert(bits <= 128); var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; var repr_val_big = BigInt.Mutable{ @@ -971,29 +1070,27 @@ pub const DeclGen = struct { }; switch (bits) { + else => unreachable, 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))), 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))), 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))), 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))), 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))), - else => unreachable, } - var empty = true; if (std.math.isFinite(f128_val)) { try w.writeAll("zig_make_"); try dg.renderTypeForBuiltinFnName(w, ty); try w.writeByte('('); switch (bits) { + else => unreachable, 16 => try w.print("{x}", .{val.toFloat(f16, zcu)}), 32 => try w.print("{x}", .{val.toFloat(f32, zcu)}), 64 => try w.print("{x}", .{val.toFloat(f64, zcu)}), 80 => try w.print("{x}", .{val.toFloat(f80, zcu)}), 128 => try w.print("{x}", .{f128_val}), - else => unreachable, } try w.writeAll(", "); - empty = false; } else { // isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan const operation = if (std.math.isNan(f128_val)) @@ -1028,6 +1125,7 @@ pub const DeclGen = struct { try w.writeAll(operation); try w.writeAll(", "); if (std.math.isNan(f128_val)) switch (bits) { + else => unreachable, // We only actually need to pass the significand, but it will get // properly masked anyway, so just pass the whole value. 16 => try w.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}), @@ -1035,16 +1133,23 @@ pub const DeclGen = struct { 64 => try w.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}), 80 => try w.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}), 128 => try w.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}), - else => unreachable, }; try w.writeAll(", "); - empty = false; } - try w.print("{f}", .{try dg.fmtIntLiteralHex( - try pt.intValue_big(repr_ty, repr_val_big.toConst()), - location, - )}); - if (!empty) try w.writeByte(')'); + switch (bits) { + else => unreachable, + 16, 32, 64 => { + // All unsigned ints matching float types are pre-allocated. + const repr_ty = pt.intType(.unsigned, bits) catch unreachable; + try w.print("{f}", .{try dg.fmtIntLiteralHex( + try pt.intValue_big(repr_ty, repr_val_big.toConst()), + location, + )}); + }, + 80 => try F80Repr.write(@bitCast(val.toFloat(f80, zcu)), w, target, location == .static_initializer), + 128 => try F128Repr.write(@bitCast(f128_val), w, target, location == .static_initializer), + } + try w.writeByte(')'); }, .slice => |slice| { if (!location.isInitializer()) { @@ -1319,22 +1424,29 @@ pub const DeclGen = struct { .f128_type, => { const bits = ty.floatBits(target); - // All unsigned ints matching float types are pre-allocated. - const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable; try w.writeAll("zig_make_"); try dg.renderTypeForBuiltinFnName(w, ty); try w.writeByte('('); switch (bits) { - 16 => try w.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}), - 32 => try w.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}), - 64 => try w.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}), - 80 => try w.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}), - 128 => try w.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}), else => unreachable, + 16 => try w.print("{x}", .{undefPattern(f16)}), + 32 => try w.print("{x}", .{undefPattern(f32)}), + 64 => try w.print("{x}", .{undefPattern(f64)}), + 80 => try w.print("{x}", .{undefPattern(f80)}), + 128 => try w.print("{x}", .{undefPattern(f128)}), } try w.writeAll(", "); - try dg.renderUndefValue(w, repr_ty, .other); + switch (bits) { + else => unreachable, + 16, 32, 64 => { + // All unsigned ints matching float types are pre-allocated. + const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable; + try dg.renderUndefValue(w, repr_ty, .other); + }, + 80 => try undefPattern(F80Repr).write(w, target, location == .static_initializer), + 128 => try undefPattern(F128Repr).write(w, target, location == .static_initializer), + } return w.writeByte(')'); }, .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"), @@ -1726,136 +1838,6 @@ pub const DeclGen = struct { try w.print("{f}", .{cty.fmtTypeName(zcu)}); } - const IntCastContext = union(enum) { - c_value: struct { - f: *Function, - value: CValue, - v: Vectorize, - }, - value: struct { - value: Value, - }, - - pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: *Writer, location: ValueRenderLocation) !void { - switch (self.*) { - .c_value => |v| { - try v.f.writeCValue(w, v.value, location); - try v.v.elem(v.f, w); - }, - .value => |v| try dg.renderValue(w, v.value, location), - } - } - }; - fn intCastIsNoop(dg: *DeclGen, dest_ty: Type, src_ty: Type) bool { - const pt = dg.pt; - const zcu = pt.zcu; - const dest_bits = dest_ty.bitSize(zcu); - const dest_int_info = dest_ty.intInfo(pt.zcu); - - const src_is_ptr = src_ty.isPtrAtRuntime(pt.zcu); - const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { - .unsigned => .usize, - .signed => .isize, - } else src_ty; - - const src_bits = src_eff_ty.bitSize(zcu); - const src_int_info = if (src_eff_ty.isAbiInt(pt.zcu)) src_eff_ty.intInfo(pt.zcu) else null; - if (dest_bits <= 64 and src_bits <= 64) { - const needs_cast = src_int_info == null or - (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or - dest_int_info.signedness != src_int_info.?.signedness); - return !needs_cast and !src_is_ptr; - } else return false; - } - /// Renders a cast to an int type, from either an int or a pointer. - /// - /// Some platforms don't have 128 bit integers, so we need to use - /// the zig_make_ and zig_lo_ macros in those cases. - /// - /// | Dest type bits | Src type | Result - /// |------------------|------------------|---------------------------| - /// | < 64 bit integer | pointer | (zig_)(zig_size)src - /// | < 64 bit integer | < 64 bit integer | (zig_)src - /// | < 64 bit integer | > 64 bit integer | zig_lo(src) - /// | > 64 bit integer | pointer | zig_make_(0, (zig_size)src) - /// | > 64 bit integer | < 64 bit integer | zig_make_(0, src) - /// | > 64 bit integer | > 64 bit integer | zig_make_(zig_hi_(src), zig_lo_(src)) - fn renderIntCast( - dg: *DeclGen, - w: *Writer, - dest_ty: Type, - context: IntCastContext, - src_ty: Type, - location: ValueRenderLocation, - ) !void { - const pt = dg.pt; - const zcu = pt.zcu; - const dest_bits = dest_ty.bitSize(zcu); - const dest_int_info = dest_ty.intInfo(zcu); - - const src_is_ptr = src_ty.isPtrAtRuntime(zcu); - const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { - .unsigned => .usize, - .signed => .isize, - } else src_ty; - - const src_bits = src_eff_ty.bitSize(zcu); - const src_int_info = if (src_eff_ty.isAbiInt(zcu)) src_eff_ty.intInfo(zcu) else null; - if (dest_bits <= 64 and src_bits <= 64) { - const needs_cast = src_int_info == null or - (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or - dest_int_info.signedness != src_int_info.?.signedness); - - if (needs_cast) { - try w.writeByte('('); - try dg.renderType(w, dest_ty); - try w.writeByte(')'); - } - if (src_is_ptr) { - try w.writeByte('('); - try dg.renderType(w, src_eff_ty); - try w.writeByte(')'); - } - try context.writeValue(dg, w, location); - } else if (dest_bits <= 64 and src_bits > 64) { - assert(!src_is_ptr); - if (dest_bits < 64) { - try w.writeByte('('); - try dg.renderType(w, dest_ty); - try w.writeByte(')'); - } - try w.writeAll("zig_lo_"); - try dg.renderTypeForBuiltinFnName(w, src_eff_ty); - try w.writeByte('('); - try context.writeValue(dg, w, .other); - try w.writeByte(')'); - } else if (dest_bits > 64 and src_bits <= 64) { - try w.writeAll("zig_make_"); - try dg.renderTypeForBuiltinFnName(w, dest_ty); - try w.writeAll("(0, "); - if (src_is_ptr) { - try w.writeByte('('); - try dg.renderType(w, src_eff_ty); - try w.writeByte(')'); - } - try context.writeValue(dg, w, .other); - try w.writeByte(')'); - } else { - assert(!src_is_ptr); - try w.writeAll("zig_make_"); - try dg.renderTypeForBuiltinFnName(w, dest_ty); - try w.writeAll("(zig_hi_"); - try dg.renderTypeForBuiltinFnName(w, src_eff_ty); - try w.writeByte('('); - try context.writeValue(dg, w, .other); - try w.writeAll("), zig_lo_"); - try dg.renderTypeForBuiltinFnName(w, src_eff_ty); - try w.writeByte('('); - try context.writeValue(dg, w, .other); - try w.writeAll("))"); - } - } - /// Renders to `w` a C declarator whose type is the C lowering of the given Zig type. fn renderTypeAndName( dg: *DeclGen, @@ -2000,6 +1982,7 @@ pub const DeclGen = struct { switch (info) { .none => if (!is_big) return, .bits => {}, + .bits_none, .big_temp_bits => unreachable, } const int_info: std.lang.Type.Int = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{ @@ -2056,6 +2039,72 @@ const CQualifiers = packed struct { restrict: bool = false, }; +pub fn genHeader(zcu: *Zcu, w: *Writer) !void { + const gpa = zcu.comp.gpa; + + var arena: std.heap.ArenaAllocator = .init(gpa); + defer arena.deinit(); + var ctype_deps: CType.Dependencies = .empty; + defer ctype_deps.deinit(gpa); + + const target = zcu.getTarget(); + switch (target.abi) { + .msvc, .itanium => try w.writeAll("#define ZIG_TARGET_ABI_MSVC\n"), + else => {}, + } + for ([_]u16{ 16, 32, 64, 80, 128 }) |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => {}, + .soft => try w.print("#define ZIG_TARGET_SOFT_COMPILER_RT_F{d}_ABI\n", .{bits}), + }; + try w.print( + \\#define ZIG_TARGET_MAX_INT_ALIGNMENT {d} + \\#include "zig.h" + \\ + \\ + , + .{target.cMaxIntAlignment()}, + ); + + var basic_ty: Type = .fromInterned(.first_type); + while (true) : ({ + basic_ty = .fromInterned(@fromBackingInt(@intCast(@backingInt(basic_ty.toIntern()) + 1))); + if (basic_ty.toIntern() == InternPool.Index.last_type) break; + }) { + switch (basic_ty.toIntern()) { + else => {}, + .anyframe_type, + .adhoc_inferred_error_set_type, + .generic_poison_type, + => continue, // skip unsupported types + } + const basic_cty: CType = try .lower(basic_ty, &ctype_deps, arena.allocator(), zcu); + switch (basic_cty) { + .void => {}, // no layout to check + .bool, + .int, + .float, + => try CType.render_defs.writeStaticAssertTypeLayout(basic_ty, basic_cty, w, zcu), + .@"fn", + .@"enum", + .bitpack, + .@"struct", + .union_auto, + .union_extern, + .slice, + .opt, + .arr, + .vec, + .errunion, + .aligned, + .bigint, + .pointer, + .array, + .function, + => {}, + } + } +} + pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void { for (zcu.global_assembly.values()) |asm_source| { try w.print("__asm({f});\n", .{fmtStringLiteral(asm_source, null)}); @@ -2070,16 +2119,16 @@ pub fn genErrDecls( const ip = &zcu.intern_pool; const names = ip.global_error_set.getNamesFromMainThread(); - // Don't generate an invalid empty enum if the global error set is empty! - if (names.len > 0) { - try w.writeAll("enum {\n"); - for (names, 1..) |name_nts, value| { - try w.writeByte(' '); - try renderErrorName(w, name_nts.toSlice(ip)); - try w.print(" = {d}u,\n", .{value}); - } - try w.writeAll("};\n"); + // Don't generate an invalid empty enum/array if the global error set is empty! + if (names.len == 0) return; + + try w.writeAll("enum {\n"); + for (names, 1..) |name_nts, value| { + try w.writeByte(' '); + try renderErrorName(w, name_nts.toSlice(ip)); + try w.print(" = {d}u,\n", .{value}); } + try w.writeAll("};\n"); for (names) |name_nts| { const name = name_nts.toSlice(ip); @@ -2093,7 +2142,7 @@ pub fn genErrDecls( "static {s} const zig_errorName[{d}] = {{", .{ slice_const_u8_sentinel_0_type_name, names.len }, ); - if (names.len > 0) try w.writeByte('\n'); + try w.writeByte('\n'); for (names) |name_nts| { const name = name_nts.toSlice(ip); try w.print( @@ -2114,10 +2163,18 @@ pub fn genTagNameFn( const ip = &zcu.intern_pool; const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); assert(loaded_enum.field_names.len > 0); - if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) { - @panic("TODO CBE: tagName for enum over 64 bits"); + switch (CType.classifyInt(enum_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => {}, + .zig_u128, .zig_i128 => @panic("TODO CBE: tagName for 128-bit enums"), + }, + .big => @panic("TODO CBE: tagName for bigint enums"), } + if (!zcu.comp.config.root_strip) try w.print("/* @tagName({f}) */\n", .{ + loaded_enum.name.fmt(ip), + }); try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{ slice_const_u8_sentinel_0_type_name, fmtIdentUnsolo(loaded_enum.name.toSlice(ip)), @@ -2291,6 +2348,7 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E .{ .nav = nav_index }, ); try header_writer.writeAll(" {\n "); + if (!f.dg.mod.strip) try header_writer.print("/* {f} */\n ", .{nav.fqn.fmt(ip)}); f.free_locals_map.clearRetainingCapacity(); @@ -2346,6 +2404,7 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E for (list.keys()) |local_index| { const local = f.locals.items[local_index]; try f.dg.renderTypeAndName(header_writer, local.type, .{ .local = local_index }, .{}, local.alignment); + if (local.array_len != 1) try header_writer.print("[{d}]", .{local.array_len}); try header_writer.writeAll(";\n "); } } @@ -2461,7 +2520,12 @@ pub fn genDeclValue(dg: *DeclGen, w: *Writer, options: struct { try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none); try w.writeAll(" = "); try dg.renderValue(w, options.init_val, .static_initializer); - try w.writeAll(";\n"); + try w.writeByte(';'); + if (dg.owner_nav.unwrap()) |nav_index| { + const ip = &zcu.intern_pool; + if (!dg.mod.strip) try w.print(" /* {f} */", .{ip.getNav(nav_index).fqn.fmt(ip)}); + } + try w.writeByte('\n'); } pub fn genDeclValueFwd(dg: *DeclGen, w: *Writer, options: struct { name: CValue, @@ -2662,22 +2726,22 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .mul => try airBinOp(f, inst, "*", "mul", .none), .neg => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "neg", .none), - .div_float => try airBinBuiltinCall(f, inst, "div", .none), + .div_float => try airBinBuiltinCall(f, inst, "div", .big_temp_bits), - .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none), + .div_trunc, .div_exact => try airBinOp(f, inst, "/", "divTrunc", .big_temp_bits), .rem => blk: { const bin_op = air_datas[@intFromEnum(inst)].bin_op; const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu); // For binary operations @TypeOf(lhs)==@TypeOf(rhs), // so we only check one. break :blk if (lhs_scalar_ty.isInt(zcu)) - try airBinOp(f, inst, "%", "rem", .none) + try airBinOp(f, inst, "%", "rem", .big_temp_bits) else try airBinBuiltinCall(f, inst, "fmod", .none); }, - .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none), - .div_ceil => try airBinBuiltinCall(f, inst, "div_ceil", .none), - .mod => try airBinBuiltinCall(f, inst, "mod", .none), + .div_floor => try airBinBuiltinCall(f, inst, "divFloor", .big_temp_bits), + .div_ceil => try airBinBuiltinCall(f, inst, "divCeil", .big_temp_bits), + .mod => try airBinBuiltinCall(f, inst, "mod", .big_temp_bits), .abs => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "abs", .none), .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits), @@ -2687,7 +2751,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .add_sat => try airBinBuiltinCall(f, inst, "adds", .bits), .sub_sat => try airBinBuiltinCall(f, inst, "subs", .bits), .mul_sat => try airBinBuiltinCall(f, inst, "muls", .bits), - .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits), + .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits_none), .sqrt => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sqrt", .none), .sin => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sin", .none), @@ -2764,8 +2828,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .int_from_error => try airNopCast(f, inst), .union_from_enum => try airUnionFromEnum(f, inst), .bit_cast => try airBitCast(f, inst), - .int_cast => try airIntCast(f, inst), - .trunc => try airTrunc(f, inst), + .int_cast => try airIntCast(f, inst, "intCast", .none), + .trunc => try airIntCast(f, inst, "truncate", .bits), .load => try airLoad(f, inst), .store => try airStore(f, inst, false), .store_safe => try airStore(f, inst, true), @@ -2783,9 +2847,9 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .get_union_tag => try airGetUnionTag(f, inst), .clz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "clz", .bits), .ctz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "ctz", .bits), - .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popcount", .bits), - .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byte_swap", .bits), - .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bit_reverse", .bits), + .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popCount", .bits), + .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byteSwap", .bits), + .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bitReverse", .bits), .tag_name => try airTagName(f, inst), .error_name => try airErrorName(f, inst), .splat => try airSplat(f, inst), @@ -3124,7 +3188,16 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { const zcu = pt.zcu; const inst_ty = f.typeOfIndex(inst); const elem_ty = inst_ty.childType(zcu); - if (!elem_ty.hasRuntimeBits(zcu)) return .{ .undef = inst_ty }; + if (!elem_ty.hasRuntimeBits(zcu)) { + const w = &f.code.writer; + const local = try f.allocLocal(inst, inst_ty); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); + try f.dg.renderOpvPointer(w, inst_ty, .other); + try w.writeByte(';'); + try f.newline(); + return local; + } const local = try f.allocLocalValue(.{ .type = elem_ty, @@ -3298,120 +3371,57 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void { } } -fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { +fn airIntCast(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue { const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op; - const operand = try f.resolveInst(ty_op.operand); - try reap(f, inst, &.{ty_op.operand}); - - const inst_ty = f.typeOfIndex(inst); + const inst_ty = ty_op.ty.toType(); const inst_scalar_ty = inst_ty.scalarType(zcu); const operand_ty = f.typeOf(ty_op.operand); - const scalar_ty = operand_ty.scalarType(zcu); - - // `intCastIsNoop` doesn't apply to vectors because every vector lowers to a different C struct. - if (inst_ty.zigTypeTag(zcu) != .vector and f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) { - return f.moveCValue(inst, inst_ty, operand); - } - - const w = &f.code.writer; - const local = try f.allocLocal(inst, inst_ty); - const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, local, .other); - try v.elem(f, w); - try w.writeAll(" = "); - try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .other); - try w.writeByte(';'); - try f.newline(); - try v.end(f, inst, w); - return local; -} - -fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.dg.pt; - const zcu = pt.zcu; - const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op; + const operand_scalar_ty = operand_ty.scalarType(zcu); + const is_big = lowersToBigInt(operand_ty, zcu); const operand = try f.resolveInst(ty_op.operand); - try reap(f, inst, &.{ty_op.operand}); - - const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(zcu); - const dest_int_info = inst_scalar_ty.intInfo(zcu); - const dest_bits = dest_int_info.bits; - const dest_c_bits = toCIntBits(dest_bits) orelse - return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); - const operand_ty = f.typeOf(ty_op.operand); - const scalar_ty = operand_ty.scalarType(zcu); - const scalar_int_info = scalar_ty.intInfo(zcu); + if (!is_big) try reap(f, inst, &.{ty_op.operand}); - const need_cast = dest_c_bits < 64; - const need_lo = scalar_int_info.bits > 64 and dest_bits <= 64; - const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits); - if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand); + const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); + const ref_arg = lowersToBigInt(operand_scalar_ty, zcu); const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); + if (is_big) try reap(f, inst, &.{ty_op.operand}); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, local, .other); - try v.elem(f, w); - try w.writeAll(" = "); - if (need_cast) { - try w.writeByte('('); - try f.renderType(w, inst_scalar_ty); - try w.writeByte(')'); - } - if (need_lo) { - try w.writeAll("zig_lo_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); - try w.writeByte('('); + if (!ref_ret) { + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(" = "); } - if (!need_mask) { - try f.writeCValue(w, operand, .other); + try w.writeAll("zig_"); + try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); + try w.print("_{s}_", .{operation}); + try f.dg.renderTypeForBuiltinFnName(w, operand_scalar_ty); + try w.writeByte('('); + if (ref_ret) { + try w.writeByte('&'); + try f.writeCValue(w, local, .other); try v.elem(f, w); - } else switch (dest_int_info.signedness) { - .unsigned => { - try w.writeAll("zig_and_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); - try w.writeByte('('); - try f.writeCValue(w, operand, .other); - try v.elem(f, w); - try w.print(", {f})", .{ - try f.fmtIntLiteralHex(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)), - }); - }, - .signed => { - const c_bits = toCIntBits(scalar_int_info.bits) orelse - return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); - const shift_val = try pt.intValue(.u8, c_bits - dest_bits); - - try w.writeAll("zig_shr_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); - if (c_bits == 128) { - try w.print("(zig_bitCast_i{d}(", .{c_bits}); - } else { - try w.print("((int{d}_t)", .{c_bits}); - } - try w.print("zig_shl_u{d}(", .{c_bits}); - if (c_bits == 128) { - try w.print("zig_bitCast_u{d}(", .{c_bits}); - } else { - try w.print("(uint{d}_t)", .{c_bits}); - } - try f.writeCValue(w, operand, .other); - try v.elem(f, w); - if (c_bits == 128) try w.writeByte(')'); - try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); - if (c_bits == 128) try w.writeByte(')'); - try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); - }, + try w.writeAll(", "); } - if (need_lo) try w.writeByte(')'); - try w.writeByte(';'); + if (ref_arg) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, inst_scalar_ty, info); + try f.dg.renderBuiltinInfo(w, operand_scalar_ty, .none); + try w.writeAll(");"); try f.newline(); try v.end(f, inst, w); + return local; } @@ -3525,39 +3535,46 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: const ty_pl = f.air.instructions.items(.data)[@backingInt(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; + const lhs_ty = f.typeOf(bin_op.lhs); + const rhs_ty = f.typeOf(bin_op.rhs); + const is_big = lowersToBigInt(lhs_ty, zcu); + const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); - try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); + if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const inst_ty = f.typeOfIndex(inst); - const operand_ty = f.typeOf(bin_op.lhs); - const scalar_ty = operand_ty.scalarType(zcu); + const lhs_scalar_ty = lhs_ty.scalarType(zcu); + const rhs_scalar_ty = rhs_ty.scalarType(zcu); - const ref_arg = lowersToBigInt(scalar_ty, zcu); + const ref_lhs = lowersToBigInt(lhs_scalar_ty, zcu); + const ref_rhs = lowersToBigInt(rhs_scalar_ty, zcu); const w = &f.code.writer; - const local = try f.allocLocal(inst, inst_ty); - const v = try Vectorize.start(f, inst, w, operand_ty); + const local = try f.allocLocal(inst, f.typeOfIndex(inst)); + if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); + const v = try Vectorize.start(f, inst, w, lhs_ty); try f.writeCValueMember(w, local, .{ .field = 1 }); try v.elem(f, w); - try w.writeAll(" = zig_"); + try w.writeAll(" = "); + try w.writeAll("zig_"); try w.writeAll(operation); try w.writeAll("o_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty); try w.writeByte('('); // '&dest', possibly preceded by a cast - switch (zcu.intern_pool.indexToKey(scalar_ty.toIntern())) { + switch (zcu.intern_pool.indexToKey(lhs_scalar_ty.toIntern())) { .int_type => {}, // we already have a '[u]intX_t *' .simple_type => { // '&dest' will be something like a 'uintptr_t *', which might be a different C type to // the equivalent sized integer (e.g. 'uint64_t *'), so we need a cast. We don't need a // cast on the *operands* because they are passed by value (except for big integers, // where this issue doesn't exist because no "simple" int type needs bigint repr). - try w.print("({s}int{d}_t *)", .{ - if (scalar_ty.isUnsignedInt(zcu)) "u" else "", - scalar_ty.abiSize(zcu) * 8, - }); + const inst_int_info = lhs_scalar_ty.intInfo(zcu); + try w.print("({s}int{d}_t *)", .{ switch (inst_int_info.signedness) { + .signed => "", + .unsigned => "u", + }, inst_int_info.bits }); }, else => unreachable, } @@ -3566,14 +3583,24 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, lhs, .other); + if (ref_lhs) { + try w.writeByte('&'); + switch (lhs) { + .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), + else => try f.writeCValue(w, lhs, .other), + } + } else try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, rhs, .other); - if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); - try f.dg.renderBuiltinInfo(w, scalar_ty, info); + if (ref_rhs) { + try w.writeByte('&'); + switch (rhs) { + .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), + else => try f.writeCValue(w, rhs, .other), + } + } else try f.writeCValue(w, rhs, .other); + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info); try w.writeAll(");"); try f.newline(); try v.end(f, inst, w); @@ -3622,8 +3649,18 @@ fn airBinOp( const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; const operand_ty = f.typeOf(bin_op.lhs); const scalar_ty = operand_ty.scalarType(zcu); - if ((scalar_ty.isInt(zcu) and scalar_ty.bitSize(zcu) > 64) or scalar_ty.isRuntimeFloat()) - return try airBinBuiltinCall(f, inst, operation, info); + + builtin: { + if (scalar_ty.isInt(zcu)) switch (CType.classifyInt(scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } else if (!scalar_ty.isRuntimeFloat()) break :builtin; + return airBinBuiltinCall(f, inst, operation, info); + } const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -3662,19 +3699,21 @@ fn airCmpOp( const lhs_ty = f.typeOf(data.lhs); const scalar_ty = lhs_ty.scalarType(zcu); - if (scalar_ty.isInt(zcu)) { - const scalar_bits = scalar_ty.bitSize(zcu); - if (scalar_bits > 64) return airCmpBuiltinCall( - f, - inst, - data, - operator, - .cmp, - if (scalar_bits > 128) .bits else .none, - ); + builtin: { + if (scalar_ty.isInt(zcu)) { + switch (CType.classifyInt(scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } + return airCmpBuiltinCall(f, inst, data, operator, .cmp, .none); + } + if (scalar_ty.isRuntimeFloat()) + return airCmpBuiltinCall(f, inst, data, operator, .operator, .none); } - if (scalar_ty.isRuntimeFloat()) - return airCmpBuiltinCall(f, inst, data, operator, .operator, .none); const inst_ty = f.typeOfIndex(inst); const lhs = try f.resolveInst(data.lhs); @@ -3716,21 +3755,23 @@ fn airEquality( const pt = f.dg.pt; const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; - const operand_ty = f.typeOf(bin_op.lhs); - if (operand_ty.isAbiInt(zcu)) { - const operand_bits = operand_ty.bitSize(zcu); - if (operand_bits > 64) return airCmpBuiltinCall( - f, - inst, - bin_op, - operator, - .cmp, - if (operand_bits > 128) .bits else .none, - ); + + builtin: { + if (operand_ty.isAbiInt(zcu)) { + switch (CType.classifyInt(operand_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } + return airCmpBuiltinCall(f, inst, bin_op, operator, .cmp, .none); + } + if (operand_ty.isRuntimeFloat()) + return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); } - if (operand_ty.isRuntimeFloat()) - return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -3809,7 +3850,7 @@ fn airCmpLteErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(w, local, .other); try w.writeAll(" = "); try f.writeCValue(w, operand, .other); - try w.writeAll(" < sizeof(zig_errorName) / sizeof(*zig_errorName);"); + try w.writeAll(" <= sizeof(zig_errorName) / sizeof(*zig_errorName);"); try f.newline(); return local; } @@ -3862,8 +3903,17 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); - if ((inst_scalar_ty.isInt(zcu) and inst_scalar_ty.bitSize(zcu) > 64) or inst_scalar_ty.isRuntimeFloat()) - return try airBinBuiltinCall(f, inst, operation, .none); + builtin: { + if (inst_scalar_ty.isInt(zcu)) switch (CType.classifyInt(inst_scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } else if (!inst_scalar_ty.isRuntimeFloat()) break :builtin; + return airBinBuiltinCall(f, inst, operation, .none); + } const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -3979,10 +4029,7 @@ fn airCall( try w.writeAll("(void)"); break :result .none; } else { - const local = try f.allocAlignedLocal(inst, .{ - .type = ret_ty, - .alignment = .none, - }); + const local = try f.allocAlignedLocal(inst, .{ .type = ret_ty }); try f.writeCValue(w, local, .other); try w.writeAll(" = "); break :result local; @@ -4058,16 +4105,7 @@ fn airCall( fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { const dbg_stmt = f.air.instructions.items(.data)[@backingInt(inst)].dbg_stmt; const w = &f.code.writer; - // TODO re-evaluate whether to emit these or not. If we naively emit - // these directives, the output file will report bogus line numbers because - // every newline after the #line directive adds one to the line. - // We also don't print the filename yet, so the output is strictly unhelpful. - // If we wanted to go this route, we would need to go all the way and not output - // newlines until the next dbg_stmt occurs. - // Perhaps an additional compilation option is in order? - //try w.print("#line {d}", .{dbg_stmt.line + 1}); - //try f.newline(); - try w.print("/* file:{d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); + try w.print("/* {d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); try f.newline(); return .none; } @@ -4433,12 +4471,12 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue { const operand_scalar_ty = operand_ty.scalarType(zcu); const dest_scalar_ty = dest_ty.scalarType(zcu); - // Some cases are handled with a simple cast: - // * float -> float - // * bool -> int if ((operand_scalar_ty.isRuntimeFloat() and dest_scalar_ty.isRuntimeFloat()) or (operand_scalar_ty.toIntern() == .bool_type and dest_scalar_ty.isAbiInt(zcu))) { + // Some cases are handled with a simple cast: + // * float -> float + // * bool -> int try f.writeCValue(w, dest_local, .other); try v.elem(f, w); try w.writeAll(" = ("); @@ -4458,85 +4496,44 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue { try v.elem(f, w); try w.writeAll(" != 0;"); try f.newline(); - } else if (dest_scalar_ty.isRuntimeFloat()) { - // For int->float, just do a memcpy. - assert(operand_scalar_ty.isAbiInt(zcu)); - try w.writeAll("memcpy(&"); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.writeAll(", &"); - switch (operand) { - .constant => |val| try f.dg.renderValueAsLvalue(w, val), - else => try f.writeCValue(w, operand, .other), - } - try v.elem(f, w); - try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))}); - try f.newline(); } else { - // The only remaining possibility is that the result is an integer. We will need to use - // `zig_wrap_*` to correct the "padding" bits after we populate the value bits. - assert(dest_scalar_ty.isAbiInt(zcu)); assert(operand_scalar_ty.isRuntimeFloat() or operand_scalar_ty.isAbiInt(zcu)); + assert(dest_scalar_ty.isRuntimeFloat() or dest_scalar_ty.isAbiInt(zcu)); - // memcpy the value... - try w.writeAll("memcpy(&"); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.writeAll(", &"); - switch (operand) { - .constant => |val| try f.dg.renderValueAsLvalue(w, val), - else => try f.writeCValue(w, operand, .other), + const ref_ret = lowersToBigInt(dest_scalar_ty, zcu); + const ref_arg = lowersToBigInt(operand_scalar_ty, zcu); + + if (!ref_ret) { + try f.writeCValue(w, dest_local, .other); + try v.elem(f, w); + try w.writeAll(" = "); + } + try w.writeAll("zig_"); + try f.dg.renderTypeForBuiltinFnName(w, dest_scalar_ty); + try w.writeAll("_bitCast_"); + try f.dg.renderTypeForBuiltinFnName(w, operand_scalar_ty); + try w.writeByte('('); + if (ref_ret) { + try w.writeByte('&'); + try f.writeCValue(w, dest_local, .other); + try v.elem(f, w); + try w.writeAll(", "); } + if (ref_arg) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); try v.elem(f, w); - try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))}); + try f.dg.renderBuiltinInfo( + w, + dest_scalar_ty, + if (operand_scalar_ty.isRuntimeFloat() or dest_scalar_ty.isRuntimeFloat()) .none else .bits, + ); + try w.writeAll(");"); try f.newline(); - - // ...and ensure padding bits have the correct value. - switch (CType.classifyInt(dest_scalar_ty, zcu)) { - .void => unreachable, // opv - .small => { - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.writeAll(" = zig_wrap_"); - try f.dg.renderTypeForBuiltinFnName(w, dest_scalar_ty); - try w.writeByte('('); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try f.dg.renderBuiltinInfo(w, dest_scalar_ty, .bits); - try w.writeAll(");"); - try f.newline(); - }, - .big => |big| { - const dest_info = dest_scalar_ty.intInfo(zcu); - const padding_index: u16 = switch (f.dg.mod.resolved_target.result.cpu.arch.endian()) { - .little => big.limbs_len - 1, - .big => 0, - }; - const wrap_bits = ((dest_info.bits - 1) % big.limb_size.bits()) + 1; - if (big.limb_size != .@"128" or dest_info.signedness == .unsigned) { - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}] = zig_wrap_{c}{d}(", .{ - padding_index, - signAbbrev(dest_info.signedness), - big.limb_size.bits(), - }); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}], {d});", .{ padding_index, wrap_bits }); - } else { - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}] = zig_bitCast_u128(zig_wrap_i128(zig_bitCast_i128(", .{ - padding_index, - }); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}]), {d}));", .{ padding_index, wrap_bits }); - try f.newline(); - } - }, - } } try v.end(f, inst, w); @@ -4906,11 +4903,9 @@ fn lowerSwitchCmp( fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { const dg = f.dg; - const target = &dg.mod.resolved_target.result; return switch (constraint[0]) { '{' => true, - 'i', 'r' => false, - 'I' => !target.cpu.arch.isArm(), + 'r', 'i', 'n', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' => false, else => switch (value) { .constant => |val| switch (dg.pt.zcu.intern_pool.indexToKey(val.toIntern())) { .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { @@ -4937,10 +4932,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const w = &f.code.writer; const inst_ty = f.typeOfIndex(inst); const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: { - const inst_local = try f.allocLocalValue(.{ - .type = inst_ty, - .alignment = .none, - }); + const inst_local = try f.allocLocalValue(.{ .type = inst_ty }); if (f.wantSafety()) { try f.writeCValue(w, inst_local, .other); try w.writeAll(" = "); @@ -4967,10 +4959,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { if (is_reg) { const output_ty = if (output.operand == .none) inst_ty else f.typeOf(output.operand).childType(zcu); try w.writeAll("register "); - const output_local = try f.allocLocalValue(.{ - .type = output_ty, - .alignment = .none, - }); + const output_local = try f.allocLocalValue(.{ .type = output_ty }); try f.allocs.put(gpa, output_local.new_local, false); try f.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none); try w.writeAll(" __asm(\""); @@ -5000,10 +4989,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { if (asmInputNeedsLocal(f, constraint, input_val)) { const input_ty = f.typeOf(input.operand); if (is_reg) try w.writeAll("register "); - const input_local = try f.allocLocalValue(.{ - .type = input_ty, - .alignment = .none, - }); + const input_local = try f.allocLocalValue(.{ .type = input_ty }); try f.allocs.put(gpa, input_local.new_local, false); // Do not render the declaration as `const` qualified if we're generating an // explicit `register` local, as GCC will ignore the constraint completely. @@ -5853,28 +5839,124 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { else unreachable; + const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); + const ref_operand = lowersToBigInt(scalar_ty, zcu); + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, local, .other); - try v.elem(f, w); - try w.writeAll(" = "); + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) { + try w.writeAll("zig_"); + try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); + try w.print("_intCast_{c}{d}", .{ + @as(u8, switch (inst_int_info.signedness) { + .signed => 'i', + .unsigned => 'u', + }), + std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)), + }); + try w.writeAll("(&"); + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(", "); + } + } else { + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(" = "); + } if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { - try w.writeAll("zig_wrap_"); - try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); - try w.writeByte('('); + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) try w.print("zig_{c}{d}_truncate_{[0]c}{[1]d}(", .{ + @as(u8, switch (inst_int_info.signedness) { + .signed => 'i', + .unsigned => 'u', + }), + std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)), + }); } try w.writeAll("zig_"); try w.writeAll(operation); try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target)); try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target)); try w.writeByte('('); - try f.writeCValue(w, operand, .other); - try v.elem(f, w); + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits > 128) { + try w.writeByte('&'); + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(", "); + } + } + if (ref_operand) { + const operand_int_info = scalar_ty.intInfo(zcu); + if (operand_int_info.bits <= 128) { + try w.print("zig_{c}{d}_intCast_", .{ + @as(u8, switch (operand_int_info.signedness) { + .signed => 'i', + .unsigned => 'u', + }), + std.math.ceilPowerOfTwoAssert(u16, @max(operand_int_info.bits, 32)), + }); + try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try w.writeAll("(&"); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, scalar_ty, .none); + try w.writeByte(')'); + } else { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + try v.elem(f, w); + try w.print(", {f}", .{fmtUnsignedIntLiteralSmall( + target, + .uint16_t, + operand_int_info.bits, + false, + 10, + .lower, + )}); + } + } else { + try f.writeCValue(w, operand, .other); + try v.elem(f, w); + } + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits > 128) try w.print(", {f}", .{fmtUnsignedIntLiteralSmall( + target, + .uint16_t, + inst_int_info.bits, + false, + 10, + .lower, + )}); + } try w.writeByte(')'); if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { - try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits); - try w.writeByte(')'); + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) { + try w.print(", {f}", .{ + try f.dg.fmtIntLiteralDec(try pt.intValue(.u8, inst_int_info.bits), .other), + }); + try w.writeByte(')'); + } + } + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) { + try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .none); + try w.writeByte(')'); + } } try w.writeByte(';'); try f.newline(); @@ -5893,18 +5975,21 @@ fn airUnBuiltinCall( const pt = f.dg.pt; const zcu = pt.zcu; - const operand = try f.resolveInst(operand_ref); - try reap(f, inst, &.{operand_ref}); const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); const operand_ty = f.typeOf(operand_ref); const scalar_ty = operand_ty.scalarType(zcu); + const is_big = lowersToBigInt(operand_ty, zcu); + + const operand = try f.resolveInst(operand_ref); + if (!is_big) try reap(f, inst, &.{operand_ref}); const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); const ref_arg = lowersToBigInt(scalar_ty, zcu); const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); + if (is_big) try reap(f, inst, &.{operand_ref}); const v = try Vectorize.start(f, inst, w, operand_ty); if (!ref_ret) { try f.writeCValue(w, local, .other); @@ -5920,8 +6005,13 @@ fn airUnBuiltinCall( try v.elem(f, w); try w.writeAll(", "); } - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, operand, .other); + if (ref_arg) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); try v.elem(f, w); try f.dg.renderBuiltinInfo(w, scalar_ty, info); try w.writeAll(");"); @@ -5941,8 +6031,9 @@ fn airBinBuiltinCall( const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; - const operand_ty = f.typeOf(bin_op.lhs); - const is_big = lowersToBigInt(operand_ty, zcu); + const lhs_ty = f.typeOf(bin_op.lhs); + const rhs_ty = f.typeOf(bin_op.rhs); + const is_big = lowersToBigInt(lhs_ty, zcu); const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -5950,22 +6041,31 @@ fn airBinBuiltinCall( const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); - const scalar_ty = operand_ty.scalarType(zcu); + const lhs_scalar_ty = lhs_ty.scalarType(zcu); + const rhs_scalar_ty = rhs_ty.scalarType(zcu); const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); - const ref_arg = lowersToBigInt(scalar_ty, zcu); + const ref_lhs = lowersToBigInt(lhs_scalar_ty, zcu); + const ref_rhs = lowersToBigInt(rhs_scalar_ty, zcu); const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const v = try Vectorize.start(f, inst, w, operand_ty); + const v = try Vectorize.start(f, inst, w, lhs_ty); if (!ref_ret) { try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(" = "); } try w.print("zig_{s}_", .{operation}); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty); + switch (info) { + .bits, .none, .big_temp_bits => {}, + .bits_none => { + try w.writeByte('_'); + try f.dg.renderTypeForBuiltinFnName(w, rhs_scalar_ty); + }, + } try w.writeByte('('); if (ref_ret) { try w.writeByte('&'); @@ -5973,15 +6073,45 @@ fn airBinBuiltinCall( try v.elem(f, w); try w.writeAll(", "); } - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, lhs, .other); + if (ref_lhs) { + try w.writeByte('&'); + switch (lhs) { + .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), + else => try f.writeCValue(w, lhs, .other), + } + } else try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, rhs, .other); - if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); - try f.dg.renderBuiltinInfo(w, scalar_ty, info); - try w.writeAll(");\n"); + if (ref_rhs) { + try w.writeByte('&'); + switch (rhs) { + .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), + else => try f.writeCValue(w, rhs, .other), + } + } else try f.writeCValue(w, rhs, .other); + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info: switch (info) { + .none => .none, + .bits, .bits_none => .bits, + .big_temp_bits => { + if (lowersToBigInt(lhs_scalar_ty, zcu)) { + const temp_local = try f.allocAlignedLocal(inst, .{ + .type = lhs_scalar_ty, + .array_len = 2, + }); + try w.writeAll(", &"); + try f.writeCValue(w, temp_local, .other); + try freeLocal(f, inst, temp_local.new_local, null); + } + break :info .none; + }, + }); + switch (info) { + .none, .bits, .big_temp_bits => {}, + .bits_none => try f.dg.renderBuiltinInfo(w, rhs_scalar_ty, .none), + } + try w.writeAll(");"); + try f.newline(); try v.end(f, inst, w); return local; @@ -6029,12 +6159,22 @@ fn airCmpBuiltinCall( try v.elem(f, w); try w.writeAll(", "); } - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, lhs, .other); + if (ref_arg) { + try w.writeByte('&'); + switch (lhs) { + .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), + else => try f.writeCValue(w, lhs, .other), + } + } else try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, rhs, .other); + if (ref_arg) { + try w.writeByte('&'); + switch (rhs) { + .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), + else => try f.writeCValue(w, rhs, .other), + } + } else try f.writeCValue(w, rhs, .other); try v.elem(f, w); try f.dg.renderBuiltinInfo(w, scalar_ty, info); try w.writeByte(')'); @@ -6595,7 +6735,8 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { }, .value => |val| try f.dg.renderValue(w, .fromInterned(val), .other), } - try w.writeAll(";\n"); + try w.writeByte(';'); + try f.newline(); } return local; @@ -6653,7 +6794,14 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { const operand_ty = f.typeOf(reduce.operand); const w = &f.code.writer; - const use_operator = scalar_ty.bitSize(zcu) <= 64; + const use_operator, const is_big = if (scalar_ty.isInt(zcu)) switch (CType.classifyInt(scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => .{ true, false }, + .zig_u128, .zig_i128 => .{ false, false }, + }, + .big => .{ false, true }, + } else .{ false, false }; const op: union(enum) { const Func = struct { operation: []const u8, info: BuiltinInfo = .none }; builtin: Func, @@ -6742,25 +6890,57 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { try f.newline(); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, accum, .other); switch (op) { .builtin => |func| { - try w.print(" = zig_{s}_", .{func.operation}); + const prev_accum = if (is_big) prev_accum: { + const prev_accum = try f.allocLocal(inst, scalar_ty); + try f.writeCValue(w, prev_accum, .other); + try w.writeAll(" = "); + try f.writeCValue(w, accum, .other); + try w.writeByte(';'); + try f.newline(); + break :prev_accum prev_accum; + } else prev_accum: { + try f.writeCValue(w, accum, .other); + try w.writeAll(" = "); + break :prev_accum accum; + }; + try w.print("zig_{s}_", .{func.operation}); try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); try w.writeByte('('); - try f.writeCValue(w, accum, .other); + if (is_big) { + try w.writeByte('&'); + switch (accum) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, accum, .other), + } + try w.writeAll(", &"); + switch (prev_accum) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, prev_accum, .other), + } + } else try f.writeCValue(w, prev_accum, .other); try w.writeAll(", "); - try f.writeCValue(w, operand, .other); + if (is_big) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); try v.elem(f, w); try f.dg.renderBuiltinInfo(w, scalar_ty, func.info); try w.writeByte(')'); + if (is_big) try freeLocal(f, inst, prev_accum.new_local, null); }, .infix => |ass| { + try f.writeCValue(w, accum, .other); try w.writeAll(ass); try f.writeCValue(w, operand, .other); try v.elem(f, w); }, .ternary => |cmp| { + try f.writeCValue(w, accum, .other); try w.writeAll(" = "); try f.writeCValue(w, accum, .other); try w.writeAll(cmp); @@ -7224,17 +7404,18 @@ fn signAbbrev(signedness: std.lang.Signedness) u8 { fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: *const std.Target) []const u8 { return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) { + 0 => unreachable, 1...32 => "si", 33...64 => "di", 65...128 => "ti", - else => unreachable, + else => "ei", } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) { + else => unreachable, 16 => "hf", 32 => "sf", 64 => "df", 80 => "xf", - 128 => "tf", - else => unreachable, + 128 => if (target.cpu.arch.isPowerPC()) "kf" else "tf", } else unreachable; } @@ -7390,10 +7571,8 @@ fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Alt(FormatStringCont return .{ .data = .{ .str = str, .sentinel = sentinel } }; } -fn undefPattern(comptime IntType: type) IntType { - const int_info = @typeInfo(IntType).int; - const UnsignedType = @Int(.unsigned, int_info.bits); - return @bitCast(@as(UnsignedType, (1 << (int_info.bits | 1)) / 3)); +fn undefPattern(comptime Result: type) Result { + return @bitCast(@as(@Int(.unsigned, @bitSizeOf(Result)), (1 << (@bitSizeOf(Result) | 1)) / 3)); } const FormatIntLiteralContext = struct { @@ -7580,11 +7759,9 @@ const FormatSignedIntLiteralSmall = struct { case: std.fmt.Case, pub fn format(data: FormatSignedIntLiteralSmall, w: *Writer) Writer.Error!void { const bits = data.int_cty.bits(data.target); - const max_int: i64 = @bitCast((@as(u64, 1) << @intCast(bits - 1)) - 1); - const min_int: i64 = @bitCast(@as(u64, 1) << @intCast(bits - 1)); - if (data.val == max_int) { + if (data.val == @as(i64, std.math.maxInt(i64)) >> @intCast(64 - bits)) { return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)}); - } else if (data.val == min_int) { + } else if (data.val == @as(i64, std.math.minInt(i64)) >> @intCast(64 - bits)) { return w.print("{s}_MIN", .{minMaxMacroPrefix(data.int_cty)}); } if (data.val < 0) try w.writeByte('-'); @@ -7596,7 +7773,7 @@ const FormatSignedIntLiteralSmall = struct { 16 => try w.writeAll("0x"), else => unreachable, } - // This `@abs` is safe thanks to the `min_int` case above. + // This `@abs` is safe thanks to the min int check above. try w.printInt(@abs(data.val), data.base, data.case, .{}); try w.writeAll(intLiteralSuffix(data.int_cty)); } @@ -7610,8 +7787,7 @@ const FormatUnsignedIntLiteralSmall = struct { case: std.fmt.Case, pub fn format(data: FormatUnsignedIntLiteralSmall, w: *Writer) Writer.Error!void { const bits = data.int_cty.bits(data.target); - const max_int: u64 = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits); - if (data.val == max_int) { + if (data.val == @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits)) { return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)}); } try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global)); @@ -7735,6 +7911,31 @@ fn intLiteralSuffix(cty: CType.Int) []const u8 { }; } +const F80Repr = packed struct { + mantissa: u64, + exponent: u16, + + fn write(repr: F80Repr, w: *Writer, target: *const std.Target, is_global: bool) Writer.Error!void { + try w.print("zig_{s}_repr_f80({f}, {f})", .{ + if (is_global) "init" else "make", + fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.mantissa, is_global, 16, .lower), + fmtUnsignedIntLiteralSmall(target, .uint16_t, repr.exponent, is_global, 16, .lower), + }); + } +}; +const F128Repr = packed struct { + lo: u64, + hi: u64, + + fn write(repr: F128Repr, w: *Writer, target: *const std.Target, is_global: bool) Writer.Error!void { + try w.print("zig_{s}_repr_f128({f}, {f})", .{ + if (is_global) "init" else "make", + fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.hi, is_global, 16, .lower), + fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.lo, is_global, 16, .lower), + }); + } +}; + const Materialize = struct { local: CValue, diff --git a/src/codegen/c/type/render_defs.zig b/src/codegen/c/type/render_defs.zig index 866ea38cc44be5a44e0dba9aa6c75cf989cb664b..bfa368d3ceee36ac575898019e1b48d19a20d066 100644 --- a/src/codegen/c/type/render_defs.zig +++ b/src/codegen/c/type/render_defs.zig @@ -21,16 +21,21 @@ pub fn defineAligned( if (complete and alignment.compareStrict(.lt, ty.abiAlignment(zcu))) { try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}); } - try w.print("{f}{f}{f}; /* align({d}) {f} */\n", .{ + try w.print("{f}{f}{f};", .{ cty.fmtDeclaratorPrefix(zcu), name_cty.fmtTypeName(zcu), cty.fmtDeclaratorSuffix(zcu), + }); + if (!zcu.comp.config.root_strip) try w.print(" /* align({d}) {f} */", .{ alignment.toByteUnits().?, ty.fmt(pt), }); + try w.writeByte('\n'); } /// Renders the definition of a big-int `struct`. pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error!void { + const target = zcu.getTarget(); + const bits = big.limb_size.bits() *| big.limbs_len; const name_cty: CType = .{ .bigint = .{ .limb_size = big.limb_size, .limbs_len = big.limbs_len, @@ -41,12 +46,20 @@ pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error .elem_ty = &limb_cty, .nonstring = limb_cty.isStringElem(), } }; - try w.print("{f} {{ {f}limbs{f}; }}; /* {d} bits */\n", .{ + try w.print("{f} {{ {f}limbs{f}; }};", .{ name_cty.fmtTypeName(zcu), array_cty.fmtDeclaratorPrefix(zcu), array_cty.fmtDeclaratorSuffix(zcu), - big.limb_size.bits() * @as(u17, big.limbs_len), }); + if (!zcu.comp.config.root_strip) try w.print(" /* u{d}, i{d} */", .{ bits, bits }); + try w.writeByte('\n'); + try writeStaticAssertCTypeLayout( + name_cty, + std.zig.target.intByteSize(target, bits), + .fromByteUnits(std.zig.target.intAlignment(target, bits)), + w, + zcu, + ); } /// Renders a forward declaration of the `struct` which represents an error union whose payload type @@ -81,27 +94,28 @@ pub fn errunionDefineComplete( if (payload_ty.hasRuntimeBits(zcu)) { const payload_cty: CType = try .lower(payload_ty, deps, arena, zcu); try w.print( - \\{f} {{ /* anyerror!{f} */ + \\{f} {{ \\ {f}payload{f}; \\ {f}error{f}; \\}}; - \\ , .{ name_cty.fmtTypeName(zcu), - payload_ty.fmt(pt), payload_cty.fmtDeclaratorPrefix(zcu), payload_cty.fmtDeclaratorSuffix(zcu), error_cty.fmtDeclaratorPrefix(zcu), error_cty.fmtDeclaratorSuffix(zcu), }); } else { - try w.print("{f} {{ {f}error{f}; }}; /* anyerror!{f} */\n", .{ + try w.print("{f} {{ {f}error{f}; }};", .{ name_cty.fmtTypeName(zcu), error_cty.fmtDeclaratorPrefix(zcu), error_cty.fmtDeclaratorSuffix(zcu), - payload_ty.fmt(pt), }); } + if (!zcu.comp.config.root_strip) try w.print(" /* anyerror!{f} */", .{ + payload_ty.fmt(pt), + }); + try w.writeByte('\n'); } /// If the Zig type `ty` lowers to a `struct` or `union` type, renders a forward declaration of that @@ -141,10 +155,13 @@ pub fn defineIncomplete(ty: Type, w: *Writer, pt: Zcu.PerThread) Writer.Error!vo }, else => return, }; - try w.print("typedef void {f}; /* {f} */\n", .{ + try w.print("typedef void {f};", .{ name_cty.fmtTypeName(zcu), + }); + if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{ ty.fmt(pt), }); + try w.writeByte('\n'); } /// If the Zig type `ty` lowers to a `struct` or `union` type, or to a `typedef`, renders the @@ -163,13 +180,13 @@ pub fn defineComplete( ty.assertHasLayout(zcu); - switch (ty.zigTypeTag(zcu)) { + const check_cty = check_cty: switch (ty.zigTypeTag(zcu)) { .@"fn" => if (!ty.fnHasRuntimeBits(zcu)) { const name_cty: CType = .{ .@"fn" = ty }; - try w.print("typedef void {f}; /* {f} */\n", .{ + try w.print("typedef void {f};", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); + break :check_cty null; } else { const ip = &zcu.intern_pool; const func_type = ip.indexToKey(ty.toIntern()).func_type; @@ -205,82 +222,82 @@ pub fn defineComplete( } else if (!any_params) { try w.writeAll("void"); } - try w.print("){f}; /* {f} */\n", .{ + try w.print("){f};", .{ ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu), - ty.fmt(pt), }); + break :check_cty null; }, .@"enum" => { const name_cty: CType = .{ .@"enum" = ty }; const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu); - try w.print("typedef {f}{f}{f}; /* {f} */\n", .{ + try w.print("typedef {f}{f}{f};", .{ cty.fmtDeclaratorPrefix(zcu), name_cty.fmtTypeName(zcu), cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); + break :check_cty null; }, - .@"struct" => if (ty.isTuple(zcu)) { - try defineTuple(ty, deps, arena, w, pt); - } else switch (ty.containerLayout(zcu)) { - .auto, .@"extern" => try defineStruct(ty, deps, arena, w, pt), + .@"struct" => if (ty.isTuple(zcu)) + if (ty.hasRuntimeBits(zcu)) try defineTuple(ty, deps, arena, w, pt) else return + else switch (ty.containerLayout(zcu)) { + .auto, .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineStruct(ty, deps, arena, w, pt) else return, .@"packed" => try defineBitpack(ty, deps, arena, w, pt), }, .@"union" => switch (ty.containerLayout(zcu)) { - .auto => try defineUnionAuto(ty, deps, arena, w, pt), - .@"extern" => try defineUnionExtern(ty, deps, arena, w, pt), + .auto => if (ty.hasRuntimeBits(zcu)) try defineUnionAuto(ty, deps, arena, w, pt) else return, + .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineUnionExtern(ty, deps, arena, w, pt) else return, .@"packed" => try defineBitpack(ty, deps, arena, w, pt), }, .pointer => if (ty.isSlice(zcu)) { const name_cty: CType = .{ .slice = ty }; const ptr_cty: CType = try .lower(ty.slicePtrFieldType(zcu), deps, arena, zcu); try w.print( - \\{f} {{ /* {f} */ + \\{f} {{ \\ {f}ptr{f}; \\ size_t len; \\}}; - \\ , .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), ptr_cty.fmtDeclaratorPrefix(zcu), ptr_cty.fmtDeclaratorSuffix(zcu), }); - // Don't bother with `writeStaticAssertLayout`---there's not really any way we could mess - // slices up, and they're all obviously the same layout. - }, + break :check_cty switch (ty.toIntern()) { + .slice_const_u8_sentinel_0_type => name_cty, + else => null, + }; + } else return, .optional => switch (CType.classifyOptional(ty, zcu)) { .error_set, .ptr_like, .slice_like, .npv_payload, - => {}, + => return, .opv_payload => { const name_cty: CType = .{ .opt = ty }; - try w.print("{f} {{ bool is_null; }}; /* {f} */\n", .{ + try w.print("{f} {{ bool is_null; }};", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); + break :check_cty switch (ty.toIntern()) { + .optional_noreturn_type => name_cty, + else => null, + }; }, .@"struct" => { const name_cty: CType = .{ .opt = ty }; const payload_cty: CType = try .lower(ty.optionalChild(zcu), deps, arena, zcu); try w.print( - \\{f} {{ /* {f} */ + \\{f} {{ \\ {f}payload{f}; \\ bool is_null; \\}}; - \\ , .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), payload_cty.fmtDeclaratorPrefix(zcu), payload_cty.fmtDeclaratorSuffix(zcu), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); + break :check_cty name_cty; }, }, .array => if (ty.hasRuntimeBits(zcu)) { @@ -295,14 +312,13 @@ pub fn defineComplete( break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu); }, } }; - try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ + try w.print("{f} {{ {f}array{f}; }};", .{ name_cty.fmtTypeName(zcu), array_cty.fmtDeclaratorPrefix(zcu), array_cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); - }, + break :check_cty name_cty; + } else return, .vector => if (ty.hasRuntimeBits(zcu)) { const name_cty: CType = .{ .vec = ty }; const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu); @@ -311,16 +327,20 @@ pub fn defineComplete( .elem_ty = &elem_cty, .nonstring = elem_cty.isStringElem(), } }; - try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ + try w.print("{f} {{ {f}array{f}; }};", .{ name_cty.fmtTypeName(zcu), array_cty.fmtDeclaratorPrefix(zcu), array_cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); - }, - else => {}, - } + break :check_cty name_cty; + } else return, + else => return, + }; + if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{ + ty.fmt(pt), + }); + try w.writeByte('\n'); + if (check_cty) |cty| try writeStaticAssertTypeLayout(ty, cty, w, zcu); } fn defineBitpack( ty: Type, @@ -328,16 +348,16 @@ fn defineBitpack( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!?CType { const zcu = pt.zcu; const name_cty: CType = .{ .bitpack = ty }; const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu); - try w.print("typedef {f}{f}{f}; /* {f} */\n", .{ + try w.print("typedef {f}{f}{f};", .{ cty.fmtDeclaratorPrefix(zcu), name_cty.fmtTypeName(zcu), cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); + return null; } fn defineTuple( ty: Type, @@ -345,9 +365,8 @@ fn defineTuple( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const tuple = ip.indexToKey(ty.toIntern()).tuple_type; @@ -367,9 +386,8 @@ fn defineTuple( } else true; const name_cty: CType = .{ .@"struct" = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); var zig_offset: u64 = 0; var c_offset: u64 = 0; @@ -403,9 +421,8 @@ fn defineTuple( zig_offset += field_size; c_offset += field_size; } - try w.writeAll("};\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeAll("};"); + return name_cty; } fn defineStruct( ty: Type, @@ -413,9 +430,8 @@ fn defineStruct( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const struct_type = ip.loadStructType(ty.toIntern()); @@ -457,9 +473,8 @@ fn defineStruct( if (pack) try w.writeAll("zig_packed("); const name_cty: CType = .{ .@"struct" = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); var it = struct_type.iterateRuntimeOrder(ip); var offset: u64 = 0; @@ -497,9 +512,8 @@ fn defineStruct( assert(struct_type.alignment.forward(offset) == struct_type.size); try w.writeByte('}'); if (pack) try w.writeByte(')'); - try w.writeAll(";\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeByte(';'); + return name_cty; } fn defineUnionAuto( ty: Type, @@ -507,9 +521,8 @@ fn defineUnionAuto( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const union_type = ip.loadUnionType(ty.toIntern()); @@ -553,9 +566,8 @@ fn defineUnionAuto( const payload_has_bits = !union_type.has_runtime_tag or union_type.size > enum_tag_ty.abiSize(zcu); const name_cty: CType = .{ .union_auto = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); if (payload_has_bits) { try w.writeByte(' '); @@ -587,9 +599,8 @@ fn defineUnionAuto( tag_cty.fmtDeclaratorSuffix(zcu), }); } - try w.writeAll("};\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeAll("};"); + return name_cty; } fn defineUnionExtern( ty: Type, @@ -597,9 +608,8 @@ fn defineUnionExtern( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const union_type = ip.loadUnionType(ty.toIntern()); @@ -636,9 +646,8 @@ fn defineUnionExtern( if (pack) try w.writeAll("zig_packed("); const name_cty: CType = .{ .union_extern = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| { @@ -659,9 +668,8 @@ fn defineUnionExtern( } try w.writeByte('}'); if (pack) try w.writeByte(')'); - try w.writeAll(";\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeByte(';'); + return name_cty; } /// Writes an annotation which, placed before a struct/union field declaration with field type `ty`, @@ -680,19 +688,29 @@ fn writeFieldAlign( } /// Emits static assertions that the size and alignment of `cty` match those of the Zig type `ty`. -fn writeStaticAssertLayout( +pub fn writeStaticAssertTypeLayout( ty: Type, cty: CType, w: *Writer, zcu: *const Zcu, +) Writer.Error!void { + try writeStaticAssertCTypeLayout(cty, ty.abiSize(zcu), ty.abiAlignment(zcu), w, zcu); +} + +/// Emits static assertions that the size and alignment of `cty` match the provided values. +pub fn writeStaticAssertCTypeLayout( + cty: CType, + expected_size: u64, + expected_alignment: Alignment, + w: *Writer, + zcu: *const Zcu, ) Writer.Error!void { try w.print( - \\zig_static_assert(sizeof ({f}) == {d}, "incorrect size"); - \\zig_static_assert(_Alignof ({f}) == {d}, "incorrect alignment"); + \\zig_static_assert(sizeof({f}) == {d} && zig_alignOf({f}) == {d}, "abi mismatch"); \\ , .{ - cty.fmtTypeName(zcu), ty.abiSize(zcu), - cty.fmtTypeName(zcu), ty.abiAlignment(zcu).toByteUnits().?, + cty.fmtTypeName(zcu), expected_size, + cty.fmtTypeName(zcu), expected_alignment.toByteUnits().?, }); } diff --git a/src/link.zig b/src/link.zig index 7ce8363a3d77d9191b813cc86f2896e0285bec4e..15d9fcb513a8b329d6ebfbc6cf66d92b02352bc8 100644 --- a/src/link.zig +++ b/src/link.zig @@ -1238,7 +1238,7 @@ pub const File = struct { } switch (base.tag) { - inline .elf2, .coff2, .wasm => |tag| { + inline .elf2, .coff2, .wasm, .c => |tag| { dev.check(tag.devFeature()); try @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node); }, diff --git a/src/link/C.zig b/src/link/C.zig index a6830126fb2f048af065093adf6e99e2778e0c88..cf82ed146fa853cc449074721eb294834cde6d1b 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -43,6 +43,8 @@ type_dependencies: std.ArrayList(link.ConstPool.Index), /// one array. align_dependency_masks: std.ArrayList(u64), +/// Emitted at the top of the file. This can be cached since it only depends on the target. +header: String, /// All NAVs, regardless of whether they are functions or simple constants, are put in this map. navs: std.array_hash_map.Auto(InternPool.Nav.Index, RenderedDecl), /// All UAVs which may be referenced are in this map. The UAV alignment is not included in the @@ -404,9 +406,8 @@ pub fn createEmpty( emit: Path, options: link.File.OpenOptions, ) !*C { + assert(comp.root_mod.resolved_target.result.ofmt == .c); const io = comp.io; - const target = &comp.root_mod.resolved_target.result; - assert(target.ofmt == .c); const optimize_mode = comp.root_mod.optimize_mode; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; @@ -422,9 +423,8 @@ pub fn createEmpty( }); errdefer file.close(io); - const c_file = try arena.create(C); - - c_file.* = .{ + const c = try arena.create(C); + c.* = .{ .base = .{ .tag = .c, .comp = comp, @@ -439,6 +439,7 @@ pub fn createEmpty( .string_bytes = .empty, .type_dependencies = .empty, .align_dependency_masks = .empty, + .header = .empty, .navs = .empty, .uavs = .empty, .type_pool = .empty, @@ -447,8 +448,7 @@ pub fn createEmpty( .exported_navs = .empty, .exported_uavs = .empty, }; - - return c_file; + return c; } pub fn deinit(c: *C) void { @@ -469,6 +469,21 @@ pub fn deinit(c: *C) void { c.exported_uavs.deinit(gpa); } +pub fn prelink(c: *C, prog_node: std.Progress.Node) !void { + const comp = c.base.comp; + + const sub_prog_node = prog_node.start("Generate Header", 0); + defer sub_prog_node.end(); + + var header_aw: std.Io.Writer.Allocating = .init(comp.gpa); + defer header_aw.deinit(); + codegen.genHeader(comp.zcu.?, &header_aw.writer) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + else => |e| return e, + }; + c.header = try c.addString(&.{header_aw.written()}); +} + pub fn updateContainerType( c: *C, pt: Zcu.PerThread, @@ -727,7 +742,6 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog const io = comp.io; const zcu = c.base.comp.zcu.?; const ip = &zcu.intern_pool; - const target = zcu.getTarget(); const active = zcu.activate(tid); defer active.deactivate(); const pt = active.pt; @@ -943,7 +957,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog // We have discovered the full set of NAVs, UAVs, and types we need to emit, and will now begin // to build the output buffer. Our strategy is to emit the C source in this order: // - // * ABI defines and `#include "zig.h"` + // * Header // * Big-int type definitions // * Other CType definitions (traversing the dependency graph to sort topologically) // * Global assembly @@ -968,7 +982,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog // We know exactly what we'll be emitting, so can reserve capacity for all of our buffers! - try f.all_buffers.ensureUnusedCapacity(gpa, 3 + // ABI defines and `#include "zig.h"` + try f.all_buffers.ensureUnusedCapacity(gpa, 1 + // Header 1 + // Big-int type definitions need_types.count() + // `RenderedType.fwd_decl` (worst-case) need_types.count() + // `RenderedType.definition` @@ -984,20 +998,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog need_uavs.count() * 3 + // UAV definitions ("static ", "zig_align(4)", "") need_navs.count() * 2); // NAV definitions ("static ", "") - // ABI defines and `#include "zig.h"` - switch (target.abi) { - .msvc, .itanium => f.appendBufAssumeCapacity("#define ZIG_TARGET_ABI_MSVC\n"), - else => {}, - } - f.appendBufAssumeCapacity(try std.fmt.allocPrint( - arena, - "#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", - .{target.cMaxIntAlignment()}, - )); - f.appendBufAssumeCapacity( - \\#include "zig.h" - \\ - ); + f.appendBufAssumeCapacity(c.header.get(c)); // Big-int type definitions var bigint_aw: std.Io.Writer.Allocating = .init(gpa); diff --git a/test/behavior/abs.zig b/test/behavior/abs.zig index 895f9bbf8d956e61bdf5455084cd4d58ebd2b1e9..9c140d35499fe43c6dfb1b5309e4dbd8bd7263c0 100644 --- a/test/behavior/abs.zig +++ b/test/behavior/abs.zig @@ -144,7 +144,6 @@ test "@abs big int <= 128 bits" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO try comptime testAbsSignedBigInt(); try testAbsSignedBigInt(); @@ -256,7 +255,6 @@ fn testAbsFloats(comptime T: type) !void { test "@abs int vectors" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 9ffb238dfdb9994bf587b7e4e4b5743842dbcc4c..957ac6b1796c3ce962c139fc3669c4760c8ede87 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -547,7 +547,6 @@ test "sub-aligned pointer field access" { } test "alignment of zero-bit types is respected" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO @@ -582,7 +581,6 @@ test "zero-bit fields in extern struct pad fields appropriately" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const S = extern struct { x: u8, diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 16fdfc8c15cbd9f5e9ad3cc11d72461092cf839c..964de5d20ff8754e81d3c0deae59fd44a672b6f8 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -800,7 +800,6 @@ test "extern variable with non-pointer opaque type" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO @export(&var_to_export, .{ .name = "opaque_extern_var" }); diff --git a/test/behavior/bit_shifting.zig b/test/behavior/bit_shifting.zig index 9eed252ac8ddc055038a0bf227616f3df49369bd..a9d81b6b53e6d1761e99234200fdcc155e2efa1f 100644 --- a/test/behavior/bit_shifting.zig +++ b/test/behavior/bit_shifting.zig @@ -147,7 +147,6 @@ test "Saturating Shift Left where lhs is of a computed type" { test "Saturating Shift Left" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index b3b64af19b9d99ed922ec087209d02ecab14354a..785daa0d3194b00d43c00760a11199075d9377dd 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -210,7 +210,6 @@ test "triple level result location with bitcast sandwich passed as tuple element test "@bitCast packed struct of floats" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -247,7 +246,6 @@ test "@bitCast packed struct of floats" { test "comptime @bitCast packed struct to int and back" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -283,7 +281,6 @@ test "comptime @bitCast packed struct to int and back" { test "bitcast vector to integer and back" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -329,10 +326,10 @@ fn bitCastWrapper128(x: f128) u128 { } test "bitcast nan float does not modify signaling bit" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const snan_u16: u16 = 0x7D00; const snan_u32: u32 = 0x7FA00000; @@ -383,7 +380,6 @@ test "bitcast nan float does not modify signaling bit" { test "@bitCast of packed struct of bools all true" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO @@ -404,7 +400,6 @@ test "@bitCast of packed struct of bools all true" { test "@bitCast of packed struct of bools all false" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO const P = packed struct { diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 0117c647880eb21fb9226abfc816a22ad2bcd2a7..4cbe2f1aed593d513d58691ec7baf5613494f9e7 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -134,7 +134,6 @@ test "@intFromFloat > 128 bits" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testIntFromFloat(f16, 1024, u140, 1024); try testIntFromFloat(f16, -1024, i140, -1024); @@ -160,7 +159,6 @@ test "@floatFromInt > 128 bits" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testFloatFromInt(u140, 1024, f16, 1024); try testFloatFromInt(i140, -1024, f16, -1024); @@ -182,7 +180,6 @@ test "@floatFromInt(f80)" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { @@ -281,6 +278,7 @@ test "type coercion from int to float" { test "@intFromFloat" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + try testIntFromFloats(); try comptime testIntFromFloats(); } @@ -1473,11 +1471,6 @@ fn foobar(func: PFN_void) !void { test "cast function with an opaque parameter" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) { - // https://github.com/ziglang/zig/issues/16845 - return error.SkipZigTest; - } - const Container = struct { const Ctx = opaque {}; ctx: *Ctx, @@ -1724,7 +1717,6 @@ test "cast f16 to wider types" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; @@ -1831,7 +1823,6 @@ test "pointer to empty struct literal to mutable slice" { test "coerce between pointers of compatible differently-named floats" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows and !builtin.link_libc) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/cast_int.zig b/test/behavior/cast_int.zig index 34adedf7267030379ee573cb519ce6dbe29c95e3..50a1b74d8ab76bdccf8b04795a04ca77bdee078b 100644 --- a/test/behavior/cast_int.zig +++ b/test/behavior/cast_int.zig @@ -168,7 +168,6 @@ test "@intCast <= 64 bits" { test "@intCast > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testIntCast(u8, 123, u140, 123); diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 60a06886d45ac988b55d0a51f5bc40101f098e7e..f86ab963d2a4ea5dd0cec5493f583ac672a174e7 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -513,7 +513,6 @@ test "runtime 128 bit integer division" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var a: u128 = 152313999999999991610955792383; diff --git a/test/behavior/extern.zig b/test/behavior/extern.zig index 4de68589468790419a9e993fd68caf2f20e6eae9..ed95406aa889d361abbf87a79764eb23d62021ca 100644 --- a/test/behavior/extern.zig +++ b/test/behavior/extern.zig @@ -3,7 +3,6 @@ const std = @import("std"); const expect = std.testing.expect; test "anyopaque extern symbol" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/field_parent_ptr.zig b/test/behavior/field_parent_ptr.zig index 85250c54ad7d083be1a2f132b7fdc0a2785e10b2..c3d0c0087cc7eb9694310d5f8ff3755e35ca8077 100644 --- a/test/behavior/field_parent_ptr.zig +++ b/test/behavior/field_parent_ptr.zig @@ -586,7 +586,6 @@ test "@fieldParentPtr extern struct last zero-bit field" { } test "@fieldParentPtr unaligned packed struct" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -725,7 +724,6 @@ test "@fieldParentPtr unaligned packed struct" { } test "@fieldParentPtr aligned packed struct" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index f8fbab0aaefd3d3d4b39d472eb84e41b9382dc8f..7e9f58e46b0cfa6632234c2136344da6240f468f 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -142,7 +142,6 @@ test "cmp f64" { test "cmp f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -152,7 +151,6 @@ test "cmp f128" { test "cmp f80/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -253,7 +251,6 @@ test "vector cmp f64" { test "vector cmp f128" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .powerpc64le) return error.SkipZigTest; @@ -1055,7 +1052,6 @@ test "@abs f32/f64" { test "@abs f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1173,7 +1169,6 @@ test "@floor f32/f64" { test "@floor f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1262,7 +1257,6 @@ test "@ceil f32/f64" { test "@ceil f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1282,7 +1276,6 @@ test "@ceil f80/f128/c_longdouble" { test "@ceil f80 maxInt(u64)" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1369,7 +1362,6 @@ test "@trunc f32/f64" { test "@trunc f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index 14cb20f5442a452695ccad2134bd4d0c306ab4b2..47e6be86bb715f90bae1eb08a9237af2f07c1515 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -147,7 +147,6 @@ fn fnWithUnreachable() noreturn { test "extern struct with stdcallcc fn pointer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .x86) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = extern struct { diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 22b91be640579e1e8fe460f4652f998c5c1b9b6d..8750c7723149a9c772ec2dae6aaeda0b4ba03f8b 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -873,7 +873,6 @@ test "umax wrapped squaring" { test "128-bit multiplication" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; { @@ -968,7 +967,6 @@ test "@addWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; try testAddWithOverflow(u129, 4, 105, 109, 0); try testAddWithOverflow(u129, 1000, 100, 1100, 0); @@ -1136,7 +1134,6 @@ test "Multiply unwrap error * immediate" { test "@mulWithOverflow bitsize 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -1163,7 +1160,6 @@ test "@mulWithOverflow bitsize 128 bits" { test "@mulWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMulWithOverflow(u140, 0, maxInt(u140), 0, 0); @@ -1193,7 +1189,6 @@ test "@mulWithOverflow > 128 bits" { test "@mulWithOverflow bitsize 256 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1298,7 +1293,6 @@ test "@subWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; try testSubWithOverflow(u129, 4, 105, maxInt(u129) - 100, 1); try testSubWithOverflow(u129, 1000, 100, 900, 0); @@ -1389,7 +1383,6 @@ test "@shlWithOverflow > 64 bits" { test "@shlWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testShlWithOverflow(u140, 1 << 100, 20, 1 << 120, 0); @@ -1419,7 +1412,6 @@ fn testAnd(comptime T: type, a: T, b: T, expected: T) !void { test "and > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testAnd(u140, (1 << 139) | (1 << 70) | 0xaa, (1 << 139) | (1 << 69) | 0xcc, (1 << 139) | 0x88); try testAnd(u140, maxInt(u140), 1 << 100, 1 << 100); @@ -1448,7 +1440,6 @@ fn testOr(comptime T: type, a: T, b: T, expected: T) !void { test "or > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testOr(u140, 0, 1 << 139, 1 << 139); try testOr(u140, (1 << 70) | 0xa, (1 << 69) | 0x5, (1 << 70) | (1 << 69) | 0xf); @@ -1477,7 +1468,6 @@ fn testXor(comptime T: type, a: T, b: T, expected: T) !void { test "xor > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testXor(u140, 0, maxInt(u140), maxInt(u140)); try testXor(u140, 1 << 139, 1 << 139, 0); @@ -1506,7 +1496,6 @@ fn testNot(comptime T: type, a: T, expected: T) !void { test "not > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testNot(u140, 0, maxInt(u140)); try testNot(u140, maxInt(u140), 0); @@ -1535,7 +1524,6 @@ fn testShl(comptime T: type, a: T, b: std.math.Log2Int(T), expected: T) !void { test "shl > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testShl(u140, 1 << 5, 10, 1 << 15); try testShl(u140, 3, 138, (1 << 139) | (1 << 138)); @@ -1564,7 +1552,6 @@ fn testShr(comptime T: type, a: T, b: std.math.Log2Int(T), expected: T) !void { test "shr > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testShr(u140, 1 << 139, 39, 1 << 100); try testShr(u140, (1 << 70) | 8, 3, (1 << 67) | 1); @@ -1593,7 +1580,6 @@ fn testClz(comptime T: type, a: T, expected: u16) !void { test "@clz > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testClz(u140, 0, 140); @@ -1623,7 +1609,6 @@ fn testCtz(comptime T: type, a: T, expected: u16) !void { test "@ctz > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testCtz(u140, 0, 140); @@ -1653,7 +1638,6 @@ fn testPopCount(comptime T: type, a: T, expected: u16) !void { test "@popCount > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testPopCount(u140, 0, 0); @@ -1683,7 +1667,6 @@ fn testBitReverse(comptime T: type, a: T, expected: T) !void { test "@bitReverse > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testBitReverse(u140, 1 << 139, 1); @@ -1713,7 +1696,6 @@ fn testByteSwap(comptime T: type, a: T, expected: T) !void { test "@byteSwap > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testByteSwap(u144, 1 << 136, 1); @@ -1743,7 +1725,6 @@ fn testMax(comptime T: type, a: T, b: T, expected: T) !void { test "@max > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMax(u140, 0, maxInt(u140), maxInt(u140)); @@ -1773,7 +1754,6 @@ fn testMin(comptime T: type, a: T, b: T, expected: T) !void { test "@min > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMin(u140, 0, maxInt(u140), 0); @@ -1803,7 +1783,6 @@ fn testAbs(comptime T: type, a: T, expected: anytype) !void { test "@abs > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testAbs(u140, 0, 0); try testAbs(u140, 1 << 139, 1 << 139); @@ -1827,7 +1806,6 @@ fn testRem(comptime T: type, numerator: T, denominator: T, expected: T) !void { test "@rem > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testRem(u140, 0, maxInt(u140), 0); @@ -1855,7 +1833,6 @@ fn testMod(comptime T: type, numerator: T, denominator: T, expected: T) !void { test "@mod > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMod(u140, 0, maxInt(u140), 0); @@ -1883,7 +1860,6 @@ fn testDivFloor(comptime T: type, numerator: T, denominator: T, expected: T) !vo test "@divFloor > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testDivFloor(u140, 0, maxInt(u140), 0); @@ -1912,7 +1888,6 @@ fn testDivCeil(comptime T: type, numerator: T, denominator: T, expected: T) !voi test "@divCeil > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testDivCeil(u140, 0, maxInt(u140), 0); @@ -1941,7 +1916,6 @@ fn testDivTrunc(comptime T: type, numerator: T, denominator: T, expected: T) !vo test "@divTrunc > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testDivTrunc(u140, 0, maxInt(u140), 0); @@ -2166,7 +2140,6 @@ test "remainder division" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { @@ -2315,7 +2288,6 @@ test "@round f80" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try testRound(f80, 12.0); @@ -2326,7 +2298,6 @@ test "@round f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try testRound(f128, 12.0); diff --git a/test/behavior/maximum_minimum.zig b/test/behavior/maximum_minimum.zig index 22db5a75502f8456ac0637ef134a137434d3da75..533f44869573a924e50a08b3806a03c4243fc7ee 100644 --- a/test/behavior/maximum_minimum.zig +++ b/test/behavior/maximum_minimum.zig @@ -115,7 +115,6 @@ test "@min/max for floats" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { diff --git a/test/behavior/muladd.zig b/test/behavior/muladd.zig index 086a325bd6246dd660641aec924c20339494f8a2..bde6459e849c14384d69fc57811f59b747a0f2de 100644 --- a/test/behavior/muladd.zig +++ b/test/behavior/muladd.zig @@ -49,7 +49,6 @@ test "@mulAdd f80" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime testMulAdd80(); @@ -68,7 +67,6 @@ test "@mulAdd f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime testMulAdd128(); @@ -169,7 +167,6 @@ test "vector f80" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime vector80(); @@ -194,7 +191,6 @@ test "vector f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime vector128(); diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 96585d056cdf4c13b1aff3610ad08088fc0bf61c..045c19767454b64d970fe6c7a46dafcb9b2a1ac4 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -404,7 +404,6 @@ test "nested packed struct field pointers" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO const S2 = packed struct { base: u8, @@ -579,7 +578,6 @@ test "packed struct fields modification" { } test "nested packed struct field access test" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -733,7 +731,6 @@ test "nested packed struct at non-zero offset 2" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { @@ -1171,7 +1168,6 @@ test "packed struct equality" { test "packed struct equality ignores padding bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = packed struct { b: bool }; diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig index 9ac875fad4990e03554fc217fb38f42d0dfa6e62..807f4f5450d3fb372e18e2fc78f71fea9ce4d5bb 100644 --- a/test/behavior/pointers.zig +++ b/test/behavior/pointers.zig @@ -275,7 +275,7 @@ test "compare equality of optional and non-optional pointer" { } test "allowzero pointer and slice" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/saturating_arithmetic.zig b/test/behavior/saturating_arithmetic.zig index c434f014f36e40f2cfea9fc0c2508320d09c74a4..c5fa221c124d4113a73db22ab33778e521a9c52a 100644 --- a/test/behavior/saturating_arithmetic.zig +++ b/test/behavior/saturating_arithmetic.zig @@ -144,7 +144,6 @@ test "saturating multiplication <= 32 bits" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try testSatMul(u8, 0, maxInt(u8), 0); @@ -238,7 +237,6 @@ test "saturating multiplication" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { @@ -313,7 +311,6 @@ test "saturating shift-left" { test "saturating shift-left large rhs" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; @@ -361,7 +358,6 @@ test "saturating shl uses the LHS type" { test "sat add > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatAdd(u140, 0, 0, 0); @@ -377,7 +373,6 @@ test "sat add > 128 bits" { test "sat sub > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatSub(u140, 0, 1, 0); @@ -393,7 +388,6 @@ test "sat sub > 128 bits" { test "sat mul > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatMul(u140, 0, maxInt(u140), 0); @@ -409,7 +403,6 @@ test "sat mul > 128 bits" { test "sat shl > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatShl(u140, 0, u8, 17, 0); diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 379e5ec18343c226b0e2d67b1dca8b8d53f13340..2aa7920ab4b17ae56df165a880d3242e3a3fedb0 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -535,7 +535,6 @@ test "zero-bit field in packed struct" { test "packed struct with non-ABI-aligned field" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -792,7 +791,6 @@ test "non-packed struct with u128 entry in union" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const U = union(enum) { @@ -1539,7 +1537,6 @@ test "instantiate struct with comptime field" { } test "struct field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -1569,7 +1566,6 @@ test "struct field pointer has correct alignment" { } test "extern struct field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -2007,7 +2003,6 @@ test "initiate global variable with runtime value" { } test "struct containing optional pointer to array of @This()" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { @@ -2266,7 +2261,8 @@ test "struct contains aligned pointer to itself through type decl" { test "struct contains underaligned field with overaligned pointer to itself" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const S = struct { ptr: *align(8) @This() align(1), }; diff --git a/test/behavior/switch_loop.zig b/test/behavior/switch_loop.zig index 9f4859789c9c3f23488ae0814c67b132112a3335..caaea13e7f8aa3571a0f3f34c7b05b0ee37eea3b 100644 --- a/test/behavior/switch_loop.zig +++ b/test/behavior/switch_loop.zig @@ -223,7 +223,6 @@ test "unanalyzed continue with operand" { test "switch loop on larger than pointer integer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var entry: @Int(.unsigned, @bitSizeOf(usize) + 1) = undefined; @@ -268,7 +267,7 @@ test "switch loop on non-exhaustive enum" { test "switch loop with discarded tag capture" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const S = struct { const U = union(enum) { a: u32, diff --git a/test/behavior/truncate.zig b/test/behavior/truncate.zig index 07d19f29c0da73a045ae58d35836502cbebe5cdc..506a0d2bea99b768c6761cc3da31558b88eddf11 100644 --- a/test/behavior/truncate.zig +++ b/test/behavior/truncate.zig @@ -49,7 +49,6 @@ fn testTruncate(comptime S: type, a: S, comptime D: type, expected: D) !void { test "@truncate > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testTruncate(u140, 0, u128, 0); diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 340f7006e72b7f48ecaf7280cd9cd982f8600060..8ed483d02278160bc13f52b60a6b5cf5344eb40e 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1437,7 +1437,6 @@ test "coerce enum literal to union in result loc" { } test "defined-layout union field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -1472,7 +1471,6 @@ test "defined-layout union field pointer has correct alignment" { } test "undefined-layout union field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -1758,8 +1756,6 @@ test "reinterpret packed union" { }; try comptime S.doTheTest(); - - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO try S.doTheTest(); } @@ -1800,8 +1796,6 @@ test "reinterpret packed union inside packed struct" { }; try comptime S.doTheTest(); - - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO try S.doTheTest(); } diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 7d63b136fda14fca1358123c1546820a42f0dcf9..9f8d277774f278dd2e7ee138e5d54e52fbfaa491 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -128,7 +128,6 @@ test "vector float operators" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) { // Triggers an assertion with LLVM 18: @@ -736,7 +735,6 @@ test "vector reduce operation" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/195562 @@ -1437,7 +1435,6 @@ test "store packed vector element" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var v = @Vector(4, u1){ 1, 1, 1, 1 }; @@ -1469,7 +1466,6 @@ test "store vector with memset" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var a: [5]@Vector(2, i1) = undefined; @@ -1610,7 +1606,6 @@ test "bitcast vector to array of smaller vectors" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const u8x32 = @Vector(32, u8); const u8x64 = @Vector(64, u8); diff --git a/test/standalone/build.zig b/test/standalone/build.zig index dc8d85d399477256b65c60dc1b4850144c641738..f14d17562d4715ca75340d67b6b2ce5b7344b73d 100644 --- a/test/standalone/build.zig +++ b/test/standalone/build.zig @@ -39,7 +39,6 @@ pub fn build(b: *std.Build) void { "../../tools/gen_parser_oracle.zig", "../../tools/gen_spirv_spec.zig", "../../tools/gen_stubs.zig", - "../../tools/generate_c_size_and_align_checks.zig", "../../tools/generate_JSONTestSuite.zig", "../../tools/generate_linux_syscalls.zig", "../../tools/process_headers.zig", diff --git a/test/tests.zig b/test/tests.zig index 9a11d7c496a5179e02c74969f4481034764baa55..849267617f0cfe5e8c8f227a3758a397ba047083 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -274,6 +274,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .arm, + .os_tag = .linux, + .abi = .musleabi, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ .cpu_arch = .arm, @@ -292,6 +301,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .arm, + .os_tag = .linux, + .abi = .musleabihf, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ .cpu_arch = .arm, @@ -341,6 +359,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .armeb, + .os_tag = .linux, + .abi = .musleabi, + .ofmt = .c, + }, + .link_libc = true, + }, // Crashes in weird ways when applying relocations. // .{ // .target = .{ @@ -360,6 +387,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .armeb, + .os_tag = .linux, + .abi = .musleabihf, + .ofmt = .c, + }, + .link_libc = true, + }, // Crashes in weird ways when applying relocations. // .{ // .target = .{ @@ -1107,6 +1143,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .x86, + .os_tag = .linux, + .abi = .musl, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ .cpu_arch = .x86, @@ -1645,6 +1690,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .x86, + .os_tag = .windows, + .abi = .gnu, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ @@ -2782,16 +2836,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { const target = &resolved_target.result; - if (target.cpu.arch == .s390x and target.ofmt == .c) { - // https://codeberg.org/ziglang/zig/issues/35523 - continue; - } - - if (target.cpu.arch == .riscv64 and target.ofmt == .c) { - // https://codeberg.org/ziglang/zig/issues/30930 - continue; - } - if (std.mem.eql(u8, options.name, "libc")) { // The libc API tests obviously need to link libc. So for test // target entries where we wouldn't link libc by default, skip the diff --git a/tools/generate_c_size_and_align_checks.zig b/tools/generate_c_size_and_align_checks.zig deleted file mode 100644 index 09400615f2c526bdde3ce99c62b0f5a0bf386932..0000000000000000000000000000000000000000 --- a/tools/generate_c_size_and_align_checks.zig +++ /dev/null @@ -1,62 +0,0 @@ -//! Usage: zig run tools/generate_c_size_and_align_checks.zig -- [target_triple] -//! e.g. zig run tools/generate_c_size_and_align_checks.zig -- x86_64-linux-gnu -//! -//! Prints _Static_asserts for the size and alignment of all the basic built-in C -//! types. The output can be run through a compiler for the specified target to -//! verify that Zig's values are the same as those used by a C compiler for the -//! target. - -const std = @import("std"); -const Io = std.Io; - -fn cName(ty: std.Target.CType) []const u8 { - return switch (ty) { - .char => "char", - .short => "short", - .ushort => "unsigned short", - .int => "int", - .uint => "unsigned int", - .long => "long", - .ulong => "unsigned long", - .longlong => "long long", - .ulonglong => "unsigned long long", - .float => "float", - .double => "double", - .longdouble => "long double", - }; -} - -var general_purpose_allocator: std.heap.DebugAllocator(.{}) = .init; - -pub fn main(init: std.process.Init) !void { - const args = try init.minimal.args.toSlice(init.arena.allocator()); - const io = init.io; - - if (args.len != 2) { - std.debug.print("Usage: {s} [target_triple]\n", .{args[0]}); - std.process.exit(1); - } - - const query = try std.Target.Query.parse(.{ .arch_os_abi = args[1] }); - const target = try std.zig.system.resolveTargetQuery(io, query); - - var buffer: [2000]u8 = undefined; - var stdout_writer = Io.File.stdout().writerStreaming(io, &buffer); - const w = &stdout_writer.interface; - inline for (@typeInfo(std.Target.CType).@"enum".field_values) |field_value| { - const c_type: std.Target.CType = @fromBackingInt(@intCast(field_value)); - try w.print("_Static_assert(sizeof({0s}) == {1d}, \"sizeof({0s}) == {1d}\");\n", .{ - cName(c_type), - target.cTypeByteSize(c_type), - }); - try w.print("_Static_assert(_Alignof({0s}) == {1d}, \"_Alignof({0s}) == {1d}\");\n", .{ - cName(c_type), - target.cTypeAlignment(c_type), - }); - try w.print("_Static_assert(__alignof({0s}) == {1d}, \"__alignof({0s}) == {1d}\");\n\n", .{ - cName(c_type), - target.cTypePreferredAlignment(c_type), - }); - } - try w.flush(); -} -- 2.54.0 From b425e6869452ebeaf9b15ceb5739ce4b4bb5b87d Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 24 Jun 2026 19:34:13 -0400 Subject: [PATCH 12/22] llvm: update for compiler_rt abi changes Closes #12602 Closes #21234 Closes #35899 Closes #36127 --- lib/compiler/aro/aro/Target.zig | 6 +- lib/compiler/reduce.zig | 2 +- lib/compiler/test_runner.zig | 21 +- lib/compiler_rt/comparef.zig | 2 +- lib/std/Io/Writer.zig | 12 +- lib/std/Target.zig | 34 +- lib/std/math/gamma.zig | 2 - lib/std/zig/llvm/Builder.zig | 4 +- lib/std/zig/target.zig | 36 +- src/Sema.zig | 8 +- src/Sema/type_resolution.zig | 2 +- src/Type.zig | 184 +-- src/Value.zig | 7 +- src/codegen/aarch64/Select.zig | 2 +- src/codegen/aarch64/abi.zig | 7 +- src/codegen/arm/abi.zig | 16 +- src/codegen/c/type.zig | 36 +- src/codegen/c/type/render_defs.zig | 26 +- src/codegen/llvm.zig | 936 +++++++++----- src/codegen/llvm/FuncGen.zig | 1919 ++++++++++++++++------------ src/codegen/mips/abi.zig | 9 +- src/codegen/riscv64/CodeGen.zig | 4 +- src/codegen/riscv64/abi.zig | 12 +- src/codegen/s390x/abi.zig | 8 +- src/codegen/wasm/CodeGen.zig | 24 +- src/codegen/wasm/abi.zig | 6 +- src/codegen/x86_64/CodeGen.zig | 18 +- src/codegen/x86_64/abi.zig | 12 +- src/libs/mingw/Preprocessor.zig | 4 +- src/target.zig | 4 +- test/behavior/align.zig | 40 +- test/behavior/cast.zig | 3 +- test/behavior/floatop.zig | 22 - test/behavior/math.zig | 6 - test/behavior/vector.zig | 24 +- test/c_abi/cfuncs.c | 10 +- test/c_abi/main.zig | 141 +- test/tests.zig | 6 - 38 files changed, 2141 insertions(+), 1474 deletions(-) diff --git a/lib/compiler/aro/aro/Target.zig b/lib/compiler/aro/aro/Target.zig index 3a871504700f666b6e74ca464d37c0770568c43d..a0c9f3be3943810313dfcd94b94f6bea0794ff2d 100644 --- a/lib/compiler/aro/aro/Target.zig +++ b/lib/compiler/aro/aro/Target.zig @@ -1559,15 +1559,15 @@ pub fn ptrBitWidth(target: *const Target) u16 { } pub fn cCharSignedness(target: *const Target) std.builtin.Signedness { - return target.toZigTarget().cCharSignedness(); + return target.toZigTarget().cCharSignedness().?; } pub fn cTypeBitSize(target: *const Target, c_type: std.Target.CType) u16 { - return target.toZigTarget().cTypeBitSize(c_type); + return target.toZigTarget().cTypeBitSize(c_type).?; } pub fn cTypeAlignment(target: *const Target, c_type: std.Target.CType) u16 { - return target.toZigTarget().cTypeAlignment(c_type); + return target.toZigTarget().cTypeAlignment(c_type).?; } pub fn standardDynamicLinkerPath(target: *const Target) std.Target.DynamicLinker { diff --git a/lib/compiler/reduce.zig b/lib/compiler/reduce.zig index 04f0c03650031d0083cd84f89fa87bfa7b8aff09..398a44a9b4e1d9ec0670db4cd0d2878c37ff6c83 100644 --- a/lib/compiler/reduce.zig +++ b/lib/compiler/reduce.zig @@ -400,7 +400,7 @@ fn parse(gpa: Allocator, io: Io, file_path: []const u8) !Ast { file_path, gpa, .limited(std.math.maxInt(u32)), - .fromByteUnits(1), + .@"1", 0, ) catch |err| { fatal("unable to open '{s}': {s}", .{ file_path, @errorName(err) }); diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index 4e9502656c56f1e8cc43a03529d5d2599abbace5..2827d32c496e12c3a2bf7c481b54afa50eb477fe 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -91,24 +91,23 @@ fn mainServer(init: std.process.Init.Minimal) !void { return std.process.exit(0); }, .query_test_metadata => { - testing.allocator_instance = .init(std.heap.page_allocator, .{}); - defer if (testing.allocator_instance.deinit() != 0) { - @panic("internal test runner memory leak"); - }; + var sa: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); + defer if (sa.deinit() != 0) @panic("internal test runner memory leak"); + const gpa = sa.allocator(); var string_bytes: std.ArrayList(u8) = .empty; - defer string_bytes.deinit(testing.allocator); - try string_bytes.append(testing.allocator, 0); // Reserve 0 for null. + defer string_bytes.deinit(gpa); + try string_bytes.append(gpa, 0); // Reserve 0 for null. const test_fns = builtin.test_functions; - const names = try testing.allocator.alloc(u32, test_fns.len); - defer testing.allocator.free(names); - const expected_panic_msgs = try testing.allocator.alloc(u32, test_fns.len); - defer testing.allocator.free(expected_panic_msgs); + const names = try gpa.alloc(u32, test_fns.len); + defer gpa.free(names); + const expected_panic_msgs = try gpa.alloc(u32, test_fns.len); + defer gpa.free(expected_panic_msgs); for (test_fns, names, expected_panic_msgs) |test_fn, *name, *expected_panic_msg| { name.* = @intCast(string_bytes.items.len); - try string_bytes.ensureUnusedCapacity(testing.allocator, test_fn.name.len + 1); + try string_bytes.ensureUnusedCapacity(gpa, test_fn.name.len + 1); string_bytes.appendSliceAssumeCapacity(test_fn.name); string_bytes.appendAssumeCapacity(0); expected_panic_msg.* = 0; diff --git a/lib/compiler_rt/comparef.zig b/lib/compiler_rt/comparef.zig index 7b397ba02f9aca5a534f015726bcb143a456eb63..d230e9a6b42f8ef88114e4d72b838f3f47c01cec 100644 --- a/lib/compiler_rt/comparef.zig +++ b/lib/compiler_rt/comparef.zig @@ -8,7 +8,7 @@ const Unordered = if (builtin.cpu.arch == .avr) i8 else if (builtin.cpu.arch.isAARCH64()) i32 -else if (builtin.target.cTypeBitSize(.long) >= builtin.target.ptrBitWidth()) +else if (builtin.target.cTypeBitSize(.long).? >= builtin.target.ptrBitWidth()) c_long else c_longlong; diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index c243c8551f4917ef210159743f0d55ba749d1e6a..ebfe6cd502f399501eeafdbdf44205ca6636e8d2 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -2817,12 +2817,12 @@ pub const Allocating = struct { } test Allocating { - try testAllocating(.fromByteUnits(1)); - try testAllocating(.fromByteUnits(4)); - try testAllocating(.fromByteUnits(8)); - try testAllocating(.fromByteUnits(16)); - try testAllocating(.fromByteUnits(32)); - try testAllocating(.fromByteUnits(64)); + try testAllocating(.@"1"); + try testAllocating(.@"4"); + try testAllocating(.@"8"); + try testAllocating(.@"16"); + try testAllocating(.@"32"); + try testAllocating(.@"64"); } }; diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 5dc5075bada694841849a65904acdaa60471a23b..3a6cfabb42be0d191520ef33ae7cbbc190e7c644 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3066,9 +3066,13 @@ pub fn stackGrowth(target: *const Target) StackGrowth { /// Default signedness of `char` for the native C compiler for this target /// Note that char signedness is implementation-defined and many compilers provide /// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char -pub fn cCharSignedness(target: *const Target) std.builtin.Signedness { +/// Returns `null` if no C ABI is defined for this target. +pub fn cCharSignedness(target: *const Target) ?std.builtin.Signedness { + switch (target.os.tag) { + .opengl => return null, + else => {}, + } if (target.os.tag.isDarwin() or target.os.tag == .windows or target.os.tag == .uefi) return .signed; - return switch (target.cpu.arch) { .aarch64, .aarch64_be, @@ -3114,7 +3118,8 @@ pub const CType = enum { longdouble, }; -pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 { +/// Returns `null` if no C ABI is defined for this target. +pub fn cTypeByteSize(t: *const Target, c_type: CType) ?u16 { return switch (c_type) { .char, .short, @@ -3127,18 +3132,19 @@ pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 { .ulonglong, .float, .double, - => @divExact(cTypeBitSize(t, c_type), 8), + => @divExact(cTypeBitSize(t, c_type) orelse return null, 8), - .longdouble => switch (cTypeBitSize(t, c_type)) { + .longdouble => switch (cTypeBitSize(t, c_type) orelse return null) { 64 => 8, - 80 => @intCast(std.mem.alignForward(usize, 10, cTypeAlignment(t, .longdouble))), + 80 => @intCast(std.mem.alignForward(usize, 10, cTypeAlignment(t, c_type).?)), 128 => 16, else => unreachable, }, }; } -pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 { +/// Returns `null` if no C ABI is defined for this target. +pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 { switch (target.os.tag) { .freestanding, .other, @@ -3459,15 +3465,17 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 { .longlong, .ulonglong, .longdouble => return 64, }, + .opengl => return null, + .ps3, .contiki, .managarm, - .opengl, => @panic("specify the C integer and float type sizes for this OS"), } } -pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { +/// Returns `null` if no C ABI is defined for this target. +pub fn cTypeAlignment(target: *const Target, c_type: CType) ?u16 { // Overrides for unusual alignments switch (target.cpu.arch) { .avr, @@ -3500,7 +3508,7 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { // Next-power-of-two-aligned, up to a maximum. return @min( - std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8), + std.math.ceilPowerOfTwoAssert(u16, ((cTypeBitSize(target, c_type) orelse return null) + 7) / 8), @as(u16, switch (target.cpu.arch) { .msp430, .x86_16, @@ -3598,6 +3606,11 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { .xcore, => 4, + .x86 => switch (target.os.tag) { + else => 4, + .uefi, .windows => 8, + }, + .arm, .armeb, .hexagon, @@ -3616,7 +3629,6 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { .sparc, .thumb, .thumbeb, - .x86, .xtensa, .xtensaeb, => 8, diff --git a/lib/std/math/gamma.zig b/lib/std/math/gamma.zig index ce9a2b07f91b2cc5e5909069813d28bd4b7e9ce6..fed7e87ceef250eb92b67d43973289635c54d06c 100644 --- a/lib/std/math/gamma.zig +++ b/lib/std/math/gamma.zig @@ -263,8 +263,6 @@ test gamma { } test "gamma.special" { - if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 - inline for (&.{ f32, f64 }) |T| { try expect(std.math.isNan(gamma(T, -std.math.nan(T)))); try expect(std.math.isNan(gamma(T, std.math.nan(T)))); diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 48ae8216b9026099894b01f95ca9505215bef869..a19a54651db7736b3a31ca926c534690ee27bf79 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -5999,7 +5999,7 @@ pub const WipFunction = struct { alignment: Alignment, name: []const u8, ) Allocator.Error!Value { - return self.loadAtomic(access_kind, ty, ptr, .system, .none, alignment, name); + return self.loadAtomic(access_kind, ty, ptr, undefined, .none, alignment, name); } pub fn loadAtomic( @@ -6043,7 +6043,7 @@ pub const WipFunction = struct { ptr: Value, alignment: Alignment, ) Allocator.Error!Instruction.Index { - return self.storeAtomic(kind, val, ptr, .system, .none, alignment); + return self.storeAtomic(kind, val, ptr, undefined, .none, alignment); } pub fn storeAtomic( diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index 2315405a9e89549e26a875b00b51390fc3bc1b3d..e30cae2a6728a7df71e9bef14f194f6264809604 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -499,31 +499,12 @@ pub fn intByteSize(target: *const std.Target, bits: u16) u16 { } pub fn intAlignment(target: *const std.Target, bits: u16) u16 { - return switch (target.cpu.arch) { - .x86 => switch (bits) { - 0...8 => 1, - 9...16 => 2, - 17...32 => 4, - 33...64 => switch (target.os.tag) { - .uefi, .windows => 8, - else => 4, - }, - else => 16, - }, - .x86_64 => switch (bits) { - 0...8 => 1, - 9...16 => 2, - 17...32 => 4, - 33...64 => 8, - else => 16, - }, - else => switch (bits) { - 0 => 1, - else => @min( - std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)), - target.cMaxIntAlignment(), - ), - }, + return switch (bits) { + 0 => 1, + else => @min( + std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)), + target.cMaxIntAlignment(), + ), }; } @@ -536,7 +517,10 @@ pub fn compilerRtFloatAbi(target: *const std.Target, bits: u16) std.Target.Abi.F 16 => if (target.cpu.arch.isMIPS() or target.cpu.arch.isPowerPC()) return no_c_type_available, 32, 64 => {}, 80 => if (target.cTypeBitSize(.longdouble) != 80) return no_c_type_available, - 128 => if (target.cTypeBitSize(.longdouble) <= 64) return no_c_type_available, + 128 => { + if (target.cpu.arch.isX86()) return .hard; // if (target.abi == .msvc) __m128i else __float128 + if (target.cTypeBitSize(.longdouble) != 128) return no_c_type_available; + }, } return .hard; } diff --git a/src/Sema.zig b/src/Sema.zig index bb2cd4eff32547c659ec0e7f14fddf3cc4b07d18..cb8f87836a5e2c8623670cb870f7bf2b4b05a43d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -29657,7 +29657,7 @@ fn coerceVarArgParam( .array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}), .float => float: { const target = zcu.getTarget(); - const double_bits = target.cTypeBitSize(.double); + const double_bits = target.cTypeBitSize(.double) orelse break :float inst; const inst_bits = uncasted_ty.floatBits(target); if (inst_bits >= double_bits) break :float inst; switch (double_bits) { @@ -29673,21 +29673,21 @@ fn coerceVarArgParam( if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { .signed => .int, .unsigned => .uint, - })) break :int try sema.coerce(block, switch (uncasted_info.signedness) { + }) orelse break :int inst) break :int try sema.coerce(block, switch (uncasted_info.signedness) { .signed => .c_int, .unsigned => .c_uint, }, inst, inst_src); if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { .signed => .long, .unsigned => .ulong, - })) break :int try sema.coerce(block, switch (uncasted_info.signedness) { + }).?) break :int try sema.coerce(block, switch (uncasted_info.signedness) { .signed => .c_long, .unsigned => .c_ulong, }, inst, inst_src); if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { .signed => .longlong, .unsigned => .ulonglong, - })) break :int try sema.coerce(block, switch (uncasted_info.signedness) { + }).?) break :int try sema.coerce(block, switch (uncasted_info.signedness) { .signed => .c_longlong, .unsigned => .c_ulonglong, }, inst, inst_src); diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index ef8e24c86744023e52bef9d9c2d0f1f029936852..b3de4f8433a768a6a5c4c174fb300f1a899edf64 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -364,7 +364,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { const a = struct_obj.field_aligns.get(ip)[field_idx]; if (a != .none) break :a a; } - break :a field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu); + break :a field_ty.abiAlignment(zcu); }; align_out.* = field_align; if (struct_obj.field_is_comptime_bits.get(ip, field_idx)) { diff --git a/src/Type.zig b/src/Type.zig index 56b2388710b2b919a2a429fd3afa0dfa515bcf66..466a707b998294905c7d068acc1f2c98193232dc 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -957,10 +957,25 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { if (vector_type.len == 0) return .@"1"; switch (zcu.comp.getZigBackend()) { else => { - const elem_bits: u32 = @intCast(Type.fromInterned(vector_type.child).bitSize(zcu)); + const elem_ty: Type = .fromInterned(vector_type.child); + switch (if (elem_ty.isRuntimeFloat()) + std.zig.target.compilerRtFloatAbi(target, elem_ty.floatBits(target)) + else + .hard) { + .hard => {}, + .soft => return elem_ty.abiAlignment(zcu), + } + const elem_bits: u32 = @intCast(elem_ty.bitSize(zcu)); if (elem_bits == 0) return .@"1"; const bytes = ((elem_bits * vector_type.len) + 7) / 8; - return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes)); + const arch = target.cpu.arch; + return .fromByteUnits(std.math.ceilPowerOfTwoAssert( + u32, + if (arch.isArm() or arch.isAARCH64() or arch == .s390x) + @min(bytes, target.stackAlignment()) + else + bytes, + )); }, .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).abiAlignment(zcu), .stage2_x86_64 => { @@ -1018,19 +1033,33 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { .c_ulonglong => cTypeAlign(target, .ulonglong), .c_longdouble => cTypeAlign(target, .longdouble), - .f16 => .@"2", - .f32 => if (target.os.tag == .opengl) .@"4" else cTypeAlign(target, .float), - .f64 => if (target.os.tag == .opengl) .@"8" else switch (target.cTypeBitSize(.double)) { - 64 => cTypeAlign(target, .double), - else => .@"8", - }, - .f80 => switch (target.cTypeBitSize(.longdouble)) { - 80 => cTypeAlign(target, .longdouble), - else => Type.u80.abiAlignment(zcu), - }, - .f128 => switch (target.cTypeBitSize(.longdouble)) { - 128 => cTypeAlign(target, .longdouble), - else => .@"16", + .f16 => .fromByteUnits(std.zig.target.intAlignment(target, 16)), // repr: u16 + .f32 => if (target.cTypeBitSize(.float) == 32) + cTypeAlign(target, .float) // abi: c_float, + else + .fromByteUnits(std.zig.target.intAlignment(target, 32)), // repr: u32, + .f64 => if (target.cTypeBitSize(.double) == 64) + cTypeAlign(target, .double) // abi: c_double, + else + .fromByteUnits(std.zig.target.intAlignment(target, 64)), // repr: u64, + .f80 => if (target.cTypeBitSize(.longdouble) == 80) + cTypeAlign(target, .longdouble) // abi: c_longdouble, + else + .fromByteUnits(switch (std.zig.target.compilerRtFloatAbi(target, 80)) { + .hard => std.zig.target.intAlignment(target, 80), // repr: u80, + .soft => @max( + std.zig.target.intAlignment(target, 64), // mantissa: u64, + std.zig.target.intAlignment(target, 16), // exponent: u16, + ), + }), + .f128 => if (target.cTypeBitSize(.longdouble) == 128) + cTypeAlign(target, .longdouble) // abi: c_longdouble, + else switch (std.zig.target.compilerRtFloatAbi(target, 128)) { + .hard => if (target.cpu.arch.isX86()) + .@"16" // abi: c___float128, + else + .fromByteUnits(std.zig.target.intAlignment(target, 128)), // repr: u128, + .soft => .fromByteUnits(std.zig.target.intAlignment(target, 64)), // lo: u64, hi: u64, }, .generic_poison => unreachable, @@ -1111,7 +1140,13 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { .vector_type => |vec| { const elem_ty: Type = .fromInterned(vec.child); const bytes = switch (zcu.comp.getZigBackend()) { - else => @divCeil(vec.len * elem_ty.bitSize(zcu), 8), + else => switch (if (elem_ty.isRuntimeFloat()) + std.zig.target.compilerRtFloatAbi(target, elem_ty.floatBits(target)) + else + .hard) { + .hard => @divCeil(vec.len * elem_ty.bitSize(zcu), 8), + .soft => vec.len * elem_ty.abiSize(zcu), + }, .stage2_c, .stage2_wasm => vec.len * elem_ty.abiSize(zcu), .stage2_x86_64 => switch (elem_ty.toIntern()) { .bool_type => @divCeil(vec.len, 8), @@ -1167,25 +1202,44 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { .anyerror, .adhoc_inferred_error_set => errorAbiSize(zcu), .usize, .isize => ptrAbiSize(target), - .c_char => target.cTypeByteSize(.char), - .c_short => target.cTypeByteSize(.short), - .c_ushort => target.cTypeByteSize(.ushort), - .c_int => target.cTypeByteSize(.int), - .c_uint => target.cTypeByteSize(.uint), - .c_long => target.cTypeByteSize(.long), - .c_ulong => target.cTypeByteSize(.ulong), - .c_longlong => target.cTypeByteSize(.longlong), - .c_ulonglong => target.cTypeByteSize(.ulonglong), - .c_longdouble => target.cTypeByteSize(.longdouble), + .c_char => target.cTypeByteSize(.char).?, + .c_short => target.cTypeByteSize(.short).?, + .c_ushort => target.cTypeByteSize(.ushort).?, + .c_int => target.cTypeByteSize(.int).?, + .c_uint => target.cTypeByteSize(.uint).?, + .c_long => target.cTypeByteSize(.long).?, + .c_ulong => target.cTypeByteSize(.ulong).?, + .c_longlong => target.cTypeByteSize(.longlong).?, + .c_ulonglong => target.cTypeByteSize(.ulonglong).?, + .c_longdouble => target.cTypeByteSize(.longdouble).?, - .f16 => 2, - .f32 => 4, - .f64 => 8, - .f80 => switch (target.cTypeBitSize(.longdouble)) { - 80 => target.cTypeByteSize(.longdouble), - else => Type.u80.abiSize(zcu), + .f16 => std.zig.target.intByteSize(target, 16), // repr: u16 + .f32 => if (target.cTypeBitSize(.float) == 32) + target.cTypeByteSize(.float).? // abi: c_float, + else + std.zig.target.intByteSize(target, 32), // repr: u32, + .f64 => if (target.cTypeBitSize(.double) == 64) + target.cTypeByteSize(.double).? // abi: c_double, + else + std.zig.target.intByteSize(target, 64), // repr: u64, + .f80 => if (target.cTypeBitSize(.longdouble) == 80) + target.cTypeByteSize(.longdouble).? // abi: c_longdouble, + else switch (std.zig.target.compilerRtFloatAbi(target, 80)) { + .hard => std.zig.target.intByteSize(target, 80), // repr: u80, + .soft => ty.abiAlignment(zcu).forward( + std.zig.target.intByteSize(target, 64) + // mantissa: u64, + std.zig.target.intByteSize(target, 16), // exponent: u16 + ), + }, + .f128 => if (target.cTypeBitSize(.longdouble) == 128) + target.cTypeByteSize(.longdouble).? // abi: c_longdouble, + else switch (std.zig.target.compilerRtFloatAbi(target, 128)) { + .hard => if (target.cpu.arch.isX86()) + 16 // abi: c___float128, + else + std.zig.target.intByteSize(target, 128), // repr: u128, + .soft => std.zig.target.intByteSize(target, 64) * 2, // lo: u64, hi: u64, }, - .f128 => 16, .anyopaque => unreachable, .generic_poison => unreachable, @@ -1733,7 +1787,7 @@ pub fn isInt(self: Type, zcu: *const Zcu) bool { /// Returns true if and only if the type is a fixed-width, signed integer. pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool { return switch (ty.toIntern()) { - .c_char_type => zcu.getTarget().cCharSignedness() == .signed, + .c_char_type => zcu.getTarget().cCharSignedness().? == .signed, .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true, else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) { .int_type => |int_type| int_type.signedness == .signed, @@ -1745,7 +1799,7 @@ pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool { /// Returns true if and only if the type is a fixed-width, unsigned integer. pub fn isUnsignedInt(ty: Type, zcu: *const Zcu) bool { return switch (ty.toIntern()) { - .c_char_type => zcu.getTarget().cCharSignedness() == .unsigned, + .c_char_type => zcu.getTarget().cCharSignedness().? == .unsigned, .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true, else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) { .int_type => |int_type| int_type.signedness == .unsigned, @@ -1776,15 +1830,15 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { }, .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() }, .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() }, - .c_char_type => return .{ .signedness = zcu.getTarget().cCharSignedness(), .bits = target.cTypeBitSize(.char) }, - .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short) }, - .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort) }, - .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int) }, - .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint) }, - .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long) }, - .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong) }, - .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong) }, - .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong) }, + .c_char_type => return .{ .signedness = target.cCharSignedness().?, .bits = target.cTypeBitSize(.char).? }, + .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short).? }, + .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort).? }, + .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int).? }, + .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint).? }, + .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long).? }, + .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong).? }, + .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong).? }, + .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong).? }, else => switch (ip.indexToKey(ty.toIntern())) { .int_type => |int_type| return int_type, .struct_type => { @@ -1882,7 +1936,7 @@ pub fn floatBits(ty: Type, target: *const Target) u16 { .f64_type => 64, .f80_type => 80, .f128_type, .comptime_float_type => 128, - .c_longdouble_type => target.cTypeBitSize(.longdouble), + .c_longdouble_type => target.cTypeBitSize(.longdouble).?, else => unreachable, }; @@ -2147,13 +2201,6 @@ pub fn isVector(ty: Type, zcu: *const Zcu) bool { return ty.zigTypeTag(zcu) == .vector; } -/// Returns 0 if not a vector, otherwise returns @bitSizeOf(Element) * vector_len. -pub fn totalVectorBits(ty: Type, zcu: *Zcu) u64 { - if (!ty.isVector(zcu)) return 0; - const v = zcu.intern_pool.indexToKey(ty.toIntern()).vector_type; - return v.len * Type.fromInterned(v.child).bitSize(zcu); -} - pub fn isArrayOrVector(ty: Type, zcu: *const Zcu) bool { return switch (ty.zigTypeTag(zcu)) { .array, .vector => true, @@ -2416,34 +2463,6 @@ pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment }; } -/// Returns the alignment a struct field of type `field_ty` will be given if no alignment is -/// explicitly specified. However, in an `extern struct`, a higher alignment may be available due -/// to the struct's full layout (i.e. a field might coincidentally be more aligned). -/// -/// Asserts that the layout of `field_ty` is resolved. Asserts that `layout` is not `.@"packed"`. -pub fn defaultStructFieldAlignment( - field_ty: Type, - layout: std.lang.Type.ContainerLayout, - zcu: *const Zcu, -) Alignment { - const overalign_big_int = switch (layout) { - .@"packed" => unreachable, - .auto => zcu.getTarget().ofmt == .c, - .@"extern" => true, - }; - const abi_align = field_ty.abiAlignment(zcu); - assert(abi_align != .none); - // We check for anything over 64 here, because the C backend will lower e.g. u64 to a 128-bit - // integer, which has 16-byte alignment. - if (overalign_big_int and - ((field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits > 64) or - (field_ty.toIntern() == .f80_type and zcu.getTarget().cTypeBitSize(.longdouble) != 80))) - { - return abi_align.maxStrict(if (zcu.getTarget().cpu.arch == .s390x) .@"8" else .@"16"); - } - return abi_align; -} - pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) ?Value { const ip = &zcu.intern_pool; switch (ip.indexToKey(ty.toIntern())) { @@ -2961,8 +2980,7 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator } const actual_field_align = switch (field_align) { .none => switch (ip.indexToKey(aggregate_ty.toIntern())) { - .tuple_type, .union_type => field_ty.abiAlignment(zcu), - .struct_type => field_ty.defaultStructFieldAlignment(.auto, zcu), + .struct_type, .tuple_type, .union_type => field_ty.abiAlignment(zcu), .ptr_type => Type.usize.abiAlignment(zcu), else => unreachable, }, @@ -3603,5 +3621,5 @@ pub fn smallestUnsignedBits(max: u64) u16 { pub const packed_struct_layout_version = 2; fn cTypeAlign(target: *const Target, c_type: Target.CType) Alignment { - return Alignment.fromByteUnits(target.cTypeAlignment(c_type)); + return .fromByteUnits(target.cTypeAlignment(c_type).?); } diff --git a/src/Value.zig b/src/Value.zig index dfc124659c3f6d9fb3be15430a5734ff2a3fe194..f6905eb4b55d11df4c1610c9c8e41475cd4fe522 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -611,12 +611,7 @@ pub fn toFloat(val: Value, comptime T: type, zcu: *const Zcu) T { return switch (zcu.intern_pool.indexToKey(val.toIntern())) { .int => |int| switch (int.storage) { .big_int => |big_int| big_int.toFloat(T, .nearest_even)[0], - inline .u64, .i64 => |x| { - if (T == f80) { - @panic("TODO we can't lower this properly on non-x86 llvm backend yet"); - } - return @floatFromInt(x); - }, + inline .u64, .i64 => |x| @floatFromInt(x), }, .float => |float| switch (float.storage) { inline else => |x| @floatCast(x), diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 73cd6ea1e357e38497633fbcbb5af744f1815e1a..1050b8fb0eb1425205f04b7440640ec55d6cf69a 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -12388,7 +12388,7 @@ pub const CallAbiIterator = struct { .f32 => .single, .f64 => .double, .f128 => .quad, - .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble)) { + .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble).?) { else => unreachable, 64 => .double, 80 => null, diff --git a/src/codegen/aarch64/abi.zig b/src/codegen/aarch64/abi.zig index 942e4d0660d79fd8bb0e204714586dd7878b3ebe..863a45e2d4bded294e263edff46787942cbcb31b 100644 --- a/src/codegen/aarch64/abi.zig +++ b/src/codegen/aarch64/abi.zig @@ -35,7 +35,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { if (bit_size > 64) return .double_integer; return .integer; }, - .int, .@"enum", .error_set, .float, .bool => return .byval, + .int, .@"enum", .error_set, .bool => return .byval, + .float => return switch (ty.floatBits(zcu.getTarget())) { + else => unreachable, + 16, 32, 64, 128 => .byval, + 80 => .double_integer, + }, .vector => { const bit_size = ty.bitSize(zcu); // TODO is this controlled by a cpu feature? diff --git a/src/codegen/arm/abi.zig b/src/codegen/arm/abi.zig index 14acccbb7963991a3c9c201bcebaeb9218af7ff8..bd767560f1c0ac8fb3d5b8b6eed5956ea8e8253d 100644 --- a/src/codegen/arm/abi.zig +++ b/src/codegen/arm/abi.zig @@ -39,7 +39,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { const float_count = countFloats(ty, zcu, &maybe_float_bits); if (float_count <= byval_float_count) return .byval; - if (ty.abiAlignment(zcu).compare(.gt, .@"32")) { + if (ty.abiAlignment(zcu).compare(.gt, .@"4")) { return Class.arrSize(bit_size, 64); } @@ -62,7 +62,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { const float_count = countFloats(ty, zcu, &maybe_float_bits); if (float_count <= byval_float_count) return .byval; - if (union_obj.alignment.compareStrict(.gt, .@"32")) { + if (union_obj.alignment.compareStrict(.gt, .@"4")) { return Class.arrSize(bit_size, 64); } @@ -73,14 +73,16 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { } return Class.arrSize(bit_size, 32); }, - .bool, .float => return .byval, + .bool => return .byval, .int => { - // TODO this is incorrect for _BitInt(128) but implementing - // this correctly makes implementing compiler-rt impossible. - // const bit_size = ty.bitSize(zcu); - // if (bit_size > 64) return .memory; + if (ctx == .ret and ty.intInfo(zcu).bits > 64) return .memory; return .byval; }, + .float => return switch (ty.floatBits(zcu.getTarget())) { + else => unreachable, + 16, 32, 64 => .byval, + 80, 128 => .{ .i64_array = 2 }, + }, .@"enum", .error_set => { const bit_size = ty.bitSize(zcu); if (bit_size > 64) return .memory; diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 8e86c0da93dabcda0bdfec08c406bbe0dab4f04d..41ce79a2f5ef333ad5d319f0fbbdd544d9347409 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -130,28 +130,28 @@ pub const CType = union(enum) { pub fn bits(int: Int, target: *const std.Target) u16 { return switch (int) { // zig fmt: off - .char => target.cTypeBitSize(.char), + .char => target.cTypeBitSize(.char).?, - .@"unsigned short" => target.cTypeBitSize(.ushort), - .@"unsigned int" => target.cTypeBitSize(.uint), - .@"unsigned long" => target.cTypeBitSize(.ulong), - .@"unsigned long long" => target.cTypeBitSize(.ulonglong), + .@"unsigned short" => target.cTypeBitSize(.ushort).?, + .@"unsigned int" => target.cTypeBitSize(.uint).?, + .@"unsigned long" => target.cTypeBitSize(.ulong).?, + .@"unsigned long long" => target.cTypeBitSize(.ulonglong).?, - .@"signed short" => target.cTypeBitSize(.short), - .@"signed int" => target.cTypeBitSize(.int), - .@"signed long" => target.cTypeBitSize(.long), - .@"signed long long" => target.cTypeBitSize(.longlong), + .@"signed short" => target.cTypeBitSize(.short).?, + .@"signed int" => target.cTypeBitSize(.int).?, + .@"signed long" => target.cTypeBitSize(.long).?, + .@"signed long long" => target.cTypeBitSize(.longlong).?, - .uintptr_t, .intptr_t => target.ptrBitWidth(), + .uintptr_t, .intptr_t => target.ptrBitWidth(), - .uint8_t, .int8_t => 8, - .uint16_t, .int16_t => 16, - .uint24_t, .int24_t => 24, - .uint32_t, .int32_t => 32, - .uint48_t, .int48_t => 48, - .uint64_t, .int64_t => 64, - .zig_u128, .zig_i128 => 128, - // zig fmt: on + .uint8_t, .int8_t => 8, + .uint16_t, .int16_t => 16, + .uint24_t, .int24_t => 24, + .uint32_t, .int32_t => 32, + .uint48_t, .int48_t => 48, + .uint64_t, .int64_t => 64, + .zig_u128, .zig_i128 => 128, + // zig fmt: on }; } }; diff --git a/src/codegen/c/type/render_defs.zig b/src/codegen/c/type/render_defs.zig index bfa368d3ceee36ac575898019e1b48d19a20d066..d591c09bf16d71b77c4d7b2dc3c4659665dd94a1 100644 --- a/src/codegen/c/type/render_defs.zig +++ b/src/codegen/c/type/render_defs.zig @@ -381,7 +381,7 @@ fn defineTuple( const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| { const field_ty: Type = .fromInterned(field_ty_ip); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gte, tuple_align)) break false; } else true; @@ -402,15 +402,17 @@ fn defineTuple( if (zig_offset == 0 and overalign) { // This is the first field; specify its alignment to align the tuple. try writeFieldAlign(field_ty, tuple_align, w, zcu); - } else if (zig_offset > c_offset) { - // This field needs to be overaligned compared to what its offset would otherwise be. - const need_align: Alignment = .minStrict( - tuple_align, // don't make the struct more aligned than it should be - .fromLog2Units(@ctz(zig_offset)), - ); - try writeFieldAlign(field_ty, need_align, w, zcu); - c_offset = need_align.forward(c_offset); + } else switch (zig_offset - c_offset) { + 0 => {}, + else => |need_bytes| { + // This field needs to be overaligned compared to what its offset would otherwise be. + const need_align: Alignment = .fromLog2Units(std.math.log2_int(u64, need_bytes) + 1); + assert(need_align.compareStrict(.lte, tuple_align)); + try writeFieldAlign(field_ty, need_align, w, zcu); + c_offset = need_align.forward(c_offset); + }, } + assert(c_offset == zig_offset); const field_cty: CType = try .lower(field_ty, deps, arena, zcu); try w.print("{f}f{d}{f};\n", .{ field_cty.fmtDeclaratorPrefix(zcu), @@ -443,7 +445,7 @@ fn defineStruct( while (it.next()) |field_index| { const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); + const natural_align = field_ty.abiAlignment(zcu); const natural_offset = natural_align.forward(offset); const actual_offset = struct_type.field_offsets.get(ip)[field_index]; if (actual_offset < natural_offset) break :pack true; @@ -464,7 +466,7 @@ fn defineStruct( while (it.next()) |field_index| { const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gte, struct_type.alignment)) break :overalign false; } break :overalign true; @@ -481,7 +483,7 @@ fn defineStruct( while (it.next()) |field_index| { const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); + const natural_align = field_ty.abiAlignment(zcu); const natural_offset = switch (pack) { true => offset, false => natural_align.forward(offset), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 6d200cacafc52cc7067eefe18f07c1d1a9580768..221c9423e3a035367c010f0d6225940ab70a8ffb 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -573,6 +573,8 @@ pub const Object = struct { val: InternPool.Index, @"addrspace": std.lang.AddressSpace, }, Builder.Variable.Index), + /// Same as `uav_map` but for llvm values not originating from the frontend. + const_map: std.AutoHashMapUnmanaged(Builder.Constant, Builder.Variable.Index), /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction. enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index), /// Serves the same purpose as `enum_tag_name_map` but for the `is_named_enum_value` instruction. @@ -693,6 +695,7 @@ pub const Object = struct { .zcu = zcu, .nav_map = .empty, .uav_map = .empty, + .const_map = .empty, .enum_tag_name_map = .empty, .named_enum_map = .empty, .type_map = .empty, @@ -703,21 +706,22 @@ pub const Object = struct { return obj; } - pub fn deinit(self: *Object) void { - const gpa = self.gpa; - self.type_pool.deinit(gpa); - self.lazy_abi_aligns.deinit(gpa); - self.debug_enums.deinit(gpa); - self.debug_globals.deinit(gpa); - self.debug_file_map.deinit(gpa); - self.debug_types.deinit(gpa); - self.nav_map.deinit(gpa); - self.uav_map.deinit(gpa); - self.enum_tag_name_map.deinit(gpa); - self.named_enum_map.deinit(gpa); - self.type_map.deinit(gpa); - self.builder.deinit(); - self.* = undefined; + pub fn deinit(o: *Object) void { + const gpa = o.gpa; + o.type_pool.deinit(gpa); + o.lazy_abi_aligns.deinit(gpa); + o.debug_enums.deinit(gpa); + o.debug_globals.deinit(gpa); + o.debug_file_map.deinit(gpa); + o.debug_types.deinit(gpa); + o.nav_map.deinit(gpa); + o.uav_map.deinit(gpa); + o.const_map.deinit(gpa); + o.enum_tag_name_map.deinit(gpa); + o.named_enum_map.deinit(gpa); + o.type_map.deinit(gpa); + o.builder.deinit(); + o.* = undefined; } fn genErrorNameTable(o: *Object) Allocator.Error!void { @@ -741,16 +745,16 @@ pub const Object = struct { for (llvm_errors[1..], error_name_list) |*llvm_error, name| { const name_string = try o.builder.stringNull(name.toSlice(ip)); const name_init = try o.builder.stringConst(name_string); - const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); - try name_variable_index.setInitializer(name_init, &o.builder); - name_variable_index.setMutability(.constant, &o.builder); - name_variable_index.setAlignment(comptime .fromByteUnits(1), &o.builder); - const global_index = name_variable_index.ptrConst(&o.builder).global; - global_index.setLinkage(.private, &o.builder); - global_index.setUnnamedAddr(.unnamed_addr, &o.builder); + const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); + try name_llvm_variable.setInitializer(name_init, &o.builder); + name_llvm_variable.setMutability(.constant, &o.builder); + name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder); + const llvm_global = name_llvm_variable.ptrConst(&o.builder).global; + llvm_global.setLinkage(.private, &o.builder); + llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{ - name_variable_index.toConst(&o.builder), + name_llvm_variable.toConst(&o.builder), try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len - 1), }); } @@ -1199,19 +1203,33 @@ pub const Object = struct { global.dll_storage_class = .default; global.unnamed_addr = .unnamed_addr; } - llvm_function.setAlignment(switch (nav.resolved.?.@"align") { - .none => fn_ty.abiAlignment(zcu).toLlvm(), - else => |a| a.toLlvm(), - }, &o.builder); + llvm_function.setAlignment(nav.resolved.?.@"align".toLlvm(), &o.builder); llvm_function.setSection(s: { const section = nav.resolved.?.@"linksection".toSlice(ip) orelse break :s .none; break :s try o.builder.string(section); }, &o.builder); - try o.addLlvmFunctionAttributes(pt, func.owner_nav, llvm_function); - var attributes = try llvm_function.ptrConst(&o.builder).attributes.toWip(&o.builder); + var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); + // Function attributes that are independent of analysis results of the function body. + try o.addCommonFnAttributes( + &attributes, + owner_mod, + // Some backends don't respect the `naked` attribute in `TargetFrameLowering::hasFP()`, + // so for these backends, LLVM will happily emit code that accesses the stack through + // the frame pointer. This is nonsensical since what the `naked` attribute does is + // suppress generation of the prologue and epilogue, and the prologue is where the + // frame pointer normally gets set up. At time of writing, this is the case for at + // least x86 and RISC-V. + owner_mod.omit_frame_pointer or fn_info.cc == .naked, + ); + + try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, if (nav.getExtern(ip)) |@"extern"| .{ + .name = nav.name.toSlice(ip), + .lib_name = @"extern".lib_name.toSlice(ip), + } else null, .fromIntern(fn_info, ip)); + const func_analysis = func.analysisUnordered(ip); if (func_analysis.is_noinline) { try attributes.addFnAttr(.@"noinline", &o.builder); @@ -1324,7 +1342,7 @@ pub const Object = struct { const counters_variable = try o.builder.addVariable(anon_name, .void, .default); try o.used.append(gpa, counters_variable.toConst(&o.builder)); counters_variable.ptrConst(&o.builder).global.setLinkage(.private, &o.builder); - counters_variable.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); + counters_variable.setAlignment(comptime .fromByteUnits(1), &o.builder); if (target.ofmt == .macho) { counters_variable.setSection(try o.builder.string("__DATA,__sancov_cntrs"), &o.builder); @@ -1507,10 +1525,6 @@ pub const Object = struct { llvm_global.ptr(&o.builder).unnamed_addr = .unnamed_addr; } - const llvm_align = switch (resolved.@"align") { - .none => nav_ty.abiAlignment(zcu).toLlvm(), - else => |a| a.toLlvm(), - }; const llvm_section: Builder.String = if (resolved.@"linksection".toSlice(ip)) |section| s: { break :s try o.builder.string(section); } else .none; @@ -1519,13 +1533,20 @@ pub const Object = struct { // can see are extern functions or other comptime function body values (e.g. undefined). Of // these, only extern functions need to be lowered to LLVM functions. if (opt_extern != null and nav_ty.zigTypeTag(zcu) == .@"fn" and nav_ty.fnHasRuntimeBits(zcu)) { + const fn_info = zcu.typeToFunc(nav_ty).?; const llvm_function: Builder.Function.Index = switch (llvm_global.ptrConst(&o.builder).kind) { .function => |function| function, // re-use existing `Builder.Function` .replaced, .alias, .variable => try llvm_global.toNewFunction(&o.builder), }; - llvm_function.setAlignment(llvm_align, &o.builder); + llvm_function.setAlignment(resolved.@"align".toLlvm(), &o.builder); llvm_function.setSection(llvm_section, &o.builder); - try o.addLlvmFunctionAttributes(pt, nav_id, llvm_function); + var attributes: Builder.FunctionAttributes.Wip = .{}; + defer attributes.deinit(&o.builder); + try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, .{ + .name = nav.name.toSlice(ip), + .lib_name = opt_extern.?.lib_name.toSlice(ip), + }, .fromIntern(fn_info, ip)); + llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder); } else { const file_scope = nav.srcInst(ip).resolveFile(ip); const mod = zcu.fileByIndex(file_scope).mod.?; @@ -1534,7 +1555,10 @@ pub const Object = struct { .variable => |variable| variable, // re-use existing `Builder.Variable` .replaced, .alias, .function => try llvm_global.toNewVariable(&o.builder), }; - llvm_variable.setAlignment(llvm_align, &o.builder); + llvm_variable.setAlignment(switch (resolved.@"align") { + .none => nav_ty.abiAlignment(zcu).toLlvm(), + else => |a| a.toLlvm(), + }, &o.builder); llvm_variable.setSection(llvm_section, &o.builder); llvm_variable.setMutability(if (resolved.@"const") .constant else .global, &o.builder); try llvm_variable.setInitializer(if (opt_extern != null) .no_init else try o.lowerValue(resolved.value, .in_memory), &o.builder); @@ -1585,7 +1609,7 @@ pub const Object = struct { const uav_ty = Value.fromInterned(uav).typeOf(zcu); const uav_ref = try o.lowerUavRef( uav, - uav_ty.abiAlignment(zcu), + uav_ty.abiAlignment(zcu).toLlvm(), target_util.defaultAddressSpace(zcu.getTarget(), .global_constant), ); break :exp .{ uav_ty, uav_ref }; @@ -1599,7 +1623,7 @@ pub const Object = struct { fn updateExportedGlobal( o: *Object, - global_index: Builder.Global.Index, + llvm_global: Builder.Global.Index, ty: Type, export_indices: []const Zcu.Export.Index, ) link.Error!void { @@ -1634,11 +1658,11 @@ pub const Object = struct { // make much sense: the linksection should be associated with the declaration itself rather // than some particular symbol it is exported as! if (export_indices[0].ptr(zcu).opts.section.toSlice(ip)) |section_slice| { - const variable = &global_index.ptrConst(&o.builder).kind.variable; + const variable = &llvm_global.ptrConst(&o.builder).kind.variable; variable.setSection(try o.builder.string(section_slice), &o.builder); } - const llvm_global_ty = global_index.typeOf(&o.builder); + const llvm_global_ty = llvm_global.typeOf(&o.builder); // All exports are represented as aliases to the original global. @@ -1661,8 +1685,8 @@ pub const Object = struct { const alias = try o.builder.addAlias( exp_name, llvm_global_ty, - global_index.ptrConst(&o.builder).addr_space, - global_index.toConst(), + llvm_global.ptrConst(&o.builder).addr_space, + llvm_global.toConst(), ); break :global alias.ptrConst(&o.builder).global; }; @@ -1671,12 +1695,9 @@ pub const Object = struct { switch (existing_global.ptrConst(&o.builder).kind) { .alias => |alias| { // We can just repurpose the existing alias. - alias.setAliasee(global_index.toConst(), &o.builder); - alias.ptrConst(&o.builder).global.ptr(&o.builder).type = global_index.typeOf(&o.builder); - // If the type the alias is pointing to can change, then - // it makes sense that we should update the address - // space too. - alias.ptrConst(&o.builder).global.ptr(&o.builder).addr_space = global_index.ptrConst(&o.builder).addr_space; + alias.setAliasee(llvm_global.toConst(), &o.builder); + alias.ptrConst(&o.builder).global.ptr(&o.builder).type = llvm_global.typeOf(&o.builder); + alias.ptrConst(&o.builder).global.ptr(&o.builder).addr_space = llvm_global.ptrConst(&o.builder).addr_space; break :global existing_global; }, .variable, .function => { @@ -1686,13 +1707,13 @@ pub const Object = struct { // We need to make a new global which is an alias. Replace this existing one // with the target global, making the name available and fixing references // to this global to point to the target. - try existing_global.replace(global_index, &o.builder); + try existing_global.replace(llvm_global, &o.builder); // The name is now free, so create an alias. const alias = try o.builder.addAlias( exp_name, llvm_global_ty, - global_index.ptrConst(&o.builder).addr_space, - global_index.toConst(), + llvm_global.ptrConst(&o.builder).addr_space, + llvm_global.toConst(), ); break :global alias.ptrConst(&o.builder).global; }, @@ -1725,11 +1746,11 @@ pub const Object = struct { pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void { _ = o.type_map.remove(ty); try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success); - if (o.named_enum_map.get(ty)) |function_index| { - try o.updateIsNamedEnumValueFunction(.fromInterned(ty), function_index); + if (o.named_enum_map.get(ty)) |llvm_function| { + try o.updateIsNamedEnumValueFunction(.fromInterned(ty), llvm_function); } - if (o.enum_tag_name_map.get(ty)) |function_index| { - try o.updateEnumTagNameFunction(.fromInterned(ty), function_index); + if (o.enum_tag_name_map.get(ty)) |llvm_function| { + try o.updateEnumTagNameFunction(.fromInterned(ty), llvm_function); } } @@ -2102,7 +2123,7 @@ pub const Object = struct { payload_offset * 8, ); - return try o.builder.debugStructType( + return o.builder.debugStructType( name, null, // File o.debug_compile_unit.unwrap().?, // Scope @@ -2140,7 +2161,7 @@ pub const Object = struct { defer debug_param_types.deinit(gpa); // Return type goes first. - if (try fnReturnStrat(o, fn_info) == .sret) { + if (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)) == .sret) { // Actual return type is void, then first arg is the sret pointer. const ptr_ty = try pt.singleMutPtrType(.fromInterned(fn_info.return_type)); debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, .void)); @@ -2575,50 +2596,114 @@ pub const Object = struct { fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata { const zcu = o.zcu; const namespace = zcu.namespacePtr(namespace_index); - if (namespace.parent == .none) return try o.getDebugFile(namespace.file_scope); + if (namespace.parent == .none) return o.getDebugFile(namespace.file_scope); return o.getDebugType(pt, .fromInterned(namespace.owner_type)); } - /// Sets the attributes and callconv of the given `Builder.Function`, which corresponds to the - /// given `Nav` (which is a function). - fn addLlvmFunctionAttributes( + fn addCommonFnAttributes( + o: *Object, + attributes: *Builder.FunctionAttributes.Wip, + owner_mod: *Module, + omit_frame_pointer: bool, + ) Allocator.Error!void { + if (!owner_mod.red_zone) { + try attributes.addFnAttr(.noredzone, &o.builder); + } + if (omit_frame_pointer) { + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("frame-pointer"), + .value = try o.builder.string("none"), + } }, &o.builder); + } else { + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("frame-pointer"), + .value = try o.builder.string("all"), + } }, &o.builder); + } + try attributes.addFnAttr(.nounwind, &o.builder); + if (owner_mod.unwind_tables != .none) { + try attributes.addFnAttr( + .{ .uwtable = if (owner_mod.unwind_tables == .async) .async else .sync }, + &o.builder, + ); + } + if (owner_mod.optimize_mode == .small) { + try attributes.addFnAttr(.minsize, &o.builder); + try attributes.addFnAttr(.optsize, &o.builder); + } + const target = &owner_mod.resolved_target.result; + if (target.cpu.model.llvm_name) |s| { + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("target-cpu"), + .value = try o.builder.string(s), + } }, &o.builder); + } + if (owner_mod.resolved_target.llvm_cpu_features) |s| { + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("target-features"), + .value = try o.builder.string(std.mem.span(s)), + } }, &o.builder); + } + if (target.abi.float() == .soft) { + // `use-soft-float` means "use software routines for floating point computations". In + // other words, it configures how LLVM lowers basic float instructions like `fcmp`, + // `fadd`, etc. The float calling convention is configured on `TargetMachine` and is + // mostly an orthogonal concept, although obviously we do need hardware float operations + // to actually be able to pass float values in float registers. + // + // Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC + // and Clang support for Arm32 and CSKY. We don't currently expose such an option in + // Zig, and using CPU features as the source of truth for this makes for a miserable + // user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float + // unless the compiler has explicitly been told otherwise. (And note that our baseline + // CPU models almost all include FPU features!) + // + // Revisit this at some point. + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("use-soft-float"), + .value = try o.builder.string("true"), + } }, &o.builder); + + // This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the + // above, this should be revisited if `softfp` support is added. + try attributes.addFnAttr(.noimplicitfloat, &o.builder); + } + } + + pub fn addCallingConventionFnAttributes( o: *Object, pt: Zcu.PerThread, - nav_id: InternPool.Nav.Index, - function_index: Builder.Function.Index, + llvm_function: Builder.Function.Index, + attributes: *Builder.FunctionAttributes.Wip, + opt_extern: ?struct { + name: []const u8, + lib_name: ?[]const u8 = null, + }, + fn_info: FuncInfo, ) Allocator.Error!void { const zcu = o.zcu; - const ip = &zcu.intern_pool; - const nav = ip.getNav(nav_id); - const owner_mod = zcu.navFileScope(nav_id).mod.?; - const ty: Type = .fromInterned(nav.resolved.?.type); - - const fn_info = zcu.typeToFunc(ty).?; - const target = &owner_mod.resolved_target.result; - - var attributes: Builder.FunctionAttributes.Wip = .{}; - defer attributes.deinit(&o.builder); - - if (target.cpu.arch.isWasm()) if (nav.getExtern(ip)) |@"extern"| { - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("wasm-import-name"), - .value = try o.builder.string(nav.name.toSlice(ip)), - } }, &o.builder); - if (@"extern".lib_name.toSlice(ip)) |lib_name_slice| { - if (!std.mem.eql(u8, lib_name_slice, "c")) try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("wasm-import-module"), - .value = try o.builder.string(lib_name_slice), - } }, &o.builder); - } - }; + const target = zcu.getTarget(); if (fn_info.cc == .async) { @panic("TODO: LLVM backend lower async function"); } + if (target.cpu.arch.isWasm()) if (opt_extern) |@"extern"| { + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("wasm-import-name"), + .value = try o.builder.string(@"extern".name), + } }, &o.builder); + if (@"extern".lib_name) |lib_name| { + if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("wasm-import-module"), + .value = try o.builder.string(lib_name), + } }, &o.builder); + } + }; + const cc_info = toLlvmCallConv(fn_info.cc, target).?; - function_index.setCallConv(cc_info.llvm_cc, &o.builder); + llvm_function.setCallConv(cc_info.llvm_cc, &o.builder); if (cc_info.align_stack) { try attributes.addFnAttr(.{ .alignstack = .wrap(.fromByteUnits(target.stackAlignment())) }, &o.builder); @@ -2672,29 +2757,16 @@ pub const Object = struct { else => {}, } - // Function attributes that are independent of analysis results of the function body. - try o.addCommonFnAttributes( - &attributes, - owner_mod, - // Some backends don't respect the `naked` attribute in `TargetFrameLowering::hasFP()`, - // so for these backends, LLVM will happily emit code that accesses the stack through - // the frame pointer. This is nonsensical since what the `naked` attribute does is - // suppress generation of the prologue and epilogue, and the prologue is where the - // frame pointer normally gets set up. At time of writing, this is the case for at - // least x86 and RISC-V. - owner_mod.omit_frame_pointer or fn_info.cc == .naked, - ); - if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder); - var it = iterateParamTypes(o, fn_info); - if (try fnReturnStrat(o, fn_info) == .sret) { - // Sret pointers must not be address 0 - try attributes.addParamAttr(it.llvm_index, .nonnull, &o.builder); - try attributes.addParamAttr(it.llvm_index, .@"noalias", &o.builder); - - const raw_llvm_ret_ty = try o.lowerType(.fromInterned(fn_info.return_type), .in_memory); - try attributes.addParamAttr(it.llvm_index, .{ .sret = raw_llvm_ret_ty }, &o.builder); + var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); + if (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)) == .sret) { + try o.addSRetFnAttributes( + attributes, + try o.lowerType(.fromInterned(fn_info.return_type), .in_memory), + Type.fromInterned(fn_info.return_type).abiAlignment(zcu).toLlvm(), + .declaration, + ); it.llvm_index += 1; } else if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) { .signed => try attributes.addRetAttr(.signext, &o.builder), @@ -2713,9 +2785,9 @@ pub const Object = struct { while (try it.next()) |lowering| switch (lowering) { .byval => { const param_index = it.zig_index - 1; - const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[param_index]); + const param_ty: Type = .fromInterned(fn_info.param_types[param_index]); if (!isByRef(param_ty, zcu)) { - try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1); + try o.addByValParamAttrs(pt, attributes, param_ty, param_index, fn_info, it.llvm_index - 1); } if (remaining_inreg_int > 0 and @@ -2734,12 +2806,12 @@ pub const Object = struct { } }, .byref => { - const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty); + const param_ty: Type = .fromInterned(fn_info.param_types[it.zig_index - 1]); + try o.addByRefParamAttrs(attributes, it.llvm_index - 1, it.byval_attr, param_ty); }, .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), .slice => { - const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty: Type = .fromInterned(fn_info.param_types[it.zig_index - 1]); const ptr_info = param_ty.ptrInfo(zcu); const llvm_ptr_index = it.llvm_index - 2; if (std.math.cast(u5, it.zig_index - 1)) |i| { @@ -2771,78 +2843,24 @@ pub const Object = struct { .i64_array, => continue, }; - - function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); } - fn addCommonFnAttributes( + pub fn addSRetFnAttributes( o: *Object, attributes: *Builder.FunctionAttributes.Wip, - owner_mod: *Module, - omit_frame_pointer: bool, + ret_ty: Builder.Type, + ret_align: Builder.Alignment, + location: enum { declaration, callsite }, ) Allocator.Error!void { - if (!owner_mod.red_zone) { - try attributes.addFnAttr(.noredzone, &o.builder); - } - if (omit_frame_pointer) { - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("frame-pointer"), - .value = try o.builder.string("none"), - } }, &o.builder); - } else { - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("frame-pointer"), - .value = try o.builder.string("all"), - } }, &o.builder); - } - try attributes.addFnAttr(.nounwind, &o.builder); - if (owner_mod.unwind_tables != .none) { - try attributes.addFnAttr( - .{ .uwtable = if (owner_mod.unwind_tables == .async) .async else .sync }, - &o.builder, - ); - } - if (owner_mod.optimize_mode == .small) { - try attributes.addFnAttr(.minsize, &o.builder); - try attributes.addFnAttr(.optsize, &o.builder); - } - const target = &owner_mod.resolved_target.result; - if (target.cpu.model.llvm_name) |s| { - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("target-cpu"), - .value = try o.builder.string(s), - } }, &o.builder); - } - if (owner_mod.resolved_target.llvm_cpu_features) |s| { - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("target-features"), - .value = try o.builder.string(std.mem.span(s)), - } }, &o.builder); - } - if (target.abi.float() == .soft) { - // `use-soft-float` means "use software routines for floating point computations". In - // other words, it configures how LLVM lowers basic float instructions like `fcmp`, - // `fadd`, etc. The float calling convention is configured on `TargetMachine` and is - // mostly an orthogonal concept, although obviously we do need hardware float operations - // to actually be able to pass float values in float registers. - // - // Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC - // and Clang support for Arm32 and CSKY. We don't currently expose such an option in - // Zig, and using CPU features as the source of truth for this makes for a miserable - // user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float - // unless the compiler has explicitly been told otherwise. (And note that our baseline - // CPU models almost all include FPU features!) - // - // Revisit this at some point. - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("use-soft-float"), - .value = try o.builder.string("true"), - } }, &o.builder); - - // This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the - // above, this should be revisited if `softfp` support is added. - try attributes.addFnAttr(.noimplicitfloat, &o.builder); - } + try attributes.addParamAttr(0, .dead_on_unwind, &o.builder); + switch (location) { + .declaration => try attributes.addParamAttr(0, .@"noalias", &o.builder), + .callsite => {}, + } + try attributes.addParamAttr(0, .writeonly, &o.builder); + try attributes.addParamAttr(0, .{ .captures = .none }, &o.builder); + try attributes.addParamAttr(0, .{ .sret = ret_ty }, &o.builder); + try attributes.addParamAttr(0, .{ .@"align" = .wrap(ret_align) }, &o.builder); } pub const TypeRepr = enum { @@ -2861,6 +2879,151 @@ pub const Object = struct { }); } + pub const SoftF80Layout = struct { + alignment: InternPool.Alignment, + /// byte offset of u64 field + mantissa_offset: u64, + /// byte offset of u16 field + exponent_offset: u64, + llvm_fields_len: u32, + + pub const LlvmFieldTag = enum { mantissa, exponent, padding }; + }; + pub fn softF80Layout(o: *Object, opts: struct { + llvm_field_tags_buf: []SoftF80Layout.LlvmFieldTag = &.{}, + llvm_field_types_buf: []Builder.Type = &.{}, + }) Allocator.Error!SoftF80Layout { + const zcu = o.zcu; + const target = zcu.getTarget(); + assert(std.zig.target.compilerRtFloatAbi(target, 80) == .soft); + // Current compiler rt soft abi, which is not yet affected by endianness for simplicity: + // + // typedef struct { uint64_t mantissa; uint16_t exponent; } f80; + // + var layout: SoftF80Layout = .{ + .alignment = Type.f80.abiAlignment(zcu), + .mantissa_offset = undefined, + .exponent_offset = undefined, + .llvm_fields_len = 0, + }; + var offset: u64 = 0; + for ([2]SoftF80Layout.LlvmFieldTag{ .mantissa, .exponent }, [2]Type{ .u64, .u16 }) |field_tag, field_type| { + const field_align = field_type.abiAlignment(zcu); + assert(field_align.compareStrict(.lte, layout.alignment)); + const field_offset = field_align.forward(offset); + switch (field_offset - offset) { + 0 => {}, + else => |padding| { + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); + layout.llvm_fields_len += 1; + }, + } + switch (field_tag) { + .mantissa => layout.mantissa_offset = field_offset, + .exponent => layout.exponent_offset = field_offset, + .padding => unreachable, + } + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = field_tag; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.lowerType(field_type, .in_memory); + layout.llvm_fields_len += 1; + offset = field_offset + field_type.abiSize(zcu); + } + const end = layout.alignment.forward(offset); + assert(end == Type.f80.abiSize(zcu)); + switch (end - offset) { + 0 => {}, + else => |padding| { + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); + layout.llvm_fields_len += 1; + }, + } + return layout; + } + + pub const SoftF128Layout = struct { + alignment: InternPool.Alignment, + /// byte offset of u64 field + lo_offset: u64, + /// byte offset of u64 field + hi_offset: u64, + llvm_fields_len: u32, + + pub const LlvmFieldTag = enum { lo, hi, padding }; + }; + pub fn softF128Layout(o: *Object, opts: struct { + llvm_field_tags_buf: []SoftF128Layout.LlvmFieldTag = &.{}, + llvm_field_types_buf: []Builder.Type = &.{}, + }) Allocator.Error!SoftF128Layout { + const zcu = o.zcu; + const target = zcu.getTarget(); + assert(std.zig.target.compilerRtFloatAbi(target, 128) == .soft); + // Current compiler rt soft abi: + // + // #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + // typedef struct { uint64_t hi, lo; } f128; + // #else + // typedef struct { uint64_t lo, hi; } f128; + // #endif + // + var layout: SoftF128Layout = .{ + .alignment = Type.f128.abiAlignment(zcu), + .lo_offset = undefined, + .hi_offset = undefined, + .llvm_fields_len = 0, + }; + var offset: u64 = 0; + for (@as([2]SoftF128Layout.LlvmFieldTag, switch (target.cpu.arch.endian()) { + .big => .{ .hi, .lo }, + .little => .{ .lo, .hi }, + }), [2]Type{ .u64, .u64 }) |field_tag, field_type| { + const field_align = field_type.abiAlignment(zcu); + assert(field_align.compareStrict(.lte, layout.alignment)); + const field_offset = field_align.forward(offset); + switch (field_offset - offset) { + 0 => {}, + else => |padding| { + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); + layout.llvm_fields_len += 1; + }, + } + switch (field_tag) { + .lo => layout.lo_offset = field_offset, + .hi => layout.hi_offset = field_offset, + .padding => unreachable, + } + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = field_tag; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.lowerType(field_type, .in_memory); + layout.llvm_fields_len += 1; + offset = field_offset + field_type.abiSize(zcu); + } + const end = layout.alignment.forward(offset); + assert(end == Type.f128.abiSize(zcu)); + switch (end - offset) { + 0 => {}, + else => |padding| { + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); + layout.llvm_fields_len += 1; + }, + } + return layout; + } + pub fn lowerType(o: *Object, t: Type, repr: TypeRepr) Allocator.Error!Builder.Type { const zcu = o.zcu; const target = zcu.getTarget(); @@ -2901,7 +3064,7 @@ pub const Object = struct { .c_ulonglong_type, => |tag| try o.builder.intType(target.cTypeBitSize( @field(std.Target.CType, @tagName(tag)["c_".len .. @tagName(tag).len - "_type".len]), - )), + ).?), .c_longdouble_type, .f16_type, .f32_type, @@ -2909,11 +3072,44 @@ pub const Object = struct { .f80_type, .f128_type, => switch (t.floatBits(target)) { - 16 => if (backendSupportsF16(target)) .half else .i16, - 32 => .float, - 64 => .double, - 80 => if (backendSupportsF80(target)) .x86_fp80 else .i80, - 128 => .fp128, + 16 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => .half, + .soft => .i16, + }, + 32 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => .float, + .soft => .i32, + }, + 64 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => .double, + .soft => .i64, + }, + 80 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => .x86_fp80, + .soft => { + var llvm_field_types_buf: [5]Builder.Type = undefined; + const f80_layout = try o.softF80Layout(.{ + .llvm_field_types_buf = &llvm_field_types_buf, + }); + return o.builder.structType( + .normal, + llvm_field_types_buf[0..f80_layout.llvm_fields_len], + ); + }, + }, + 128 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => .fp128, + .soft => { + var llvm_field_types_buf: [5]Builder.Type = undefined; + const f128_layout = try o.softF128Layout(.{ + .llvm_field_types_buf = &llvm_field_types_buf, + }); + return o.builder.structType( + .normal, + llvm_field_types_buf[0..f128_layout.llvm_fields_len], + ); + }, + }, else => unreachable, }, .anyopaque_type => { @@ -2992,11 +3188,13 @@ pub const Object = struct { array_type.lenIncludingSentinel(), try o.lowerType(.fromInterned(array_type.child), repr), ), - .vector_type => |vector_type| o.builder.vectorType( - .normal, - vector_type.len, - try o.lowerType(.fromInterned(vector_type.child), .as_value), - ), + .vector_type => |vector_type| if (isByRef(t, zcu)) { + const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), .in_memory); + return o.builder.arrayType(vector_type.len, child_llvm_ty); + } else { + const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), .as_value); + return o.builder.vectorType(.normal, vector_type.len, child_llvm_ty); + }, .opt_type => |child_ty| { // Must stay in sync with `opt_payload` logic in `lowerPtr`. switch (Type.fromInterned(child_ty).classify(zcu)) { @@ -3257,7 +3455,10 @@ pub const Object = struct { }, .opaque_type, .spirv_type => unreachable, // no runtime bits .enum_type => try o.lowerType(t.backingIntType(zcu), repr), - .func_type => |func_type| try o.lowerFnType(t, func_type), + .func_type => |func_type| { + assert(t.fnHasRuntimeBits(zcu)); + return o.lowerFnType(.fromIntern(func_type, ip)); + }, .error_set_type, .inferred_error_set_type => try o.errorIntType(repr), // values, not types .undef, @@ -3283,14 +3484,28 @@ pub const Object = struct { }; } - fn lowerFnType(o: *Object, fn_ty: Type, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { + pub const FuncInfo = struct { + cc: std.lang.CallingConvention, + noalias_bits: u32 = 0, + param_types: []const InternPool.Index, + return_type: InternPool.Index = .void_type, + is_var_args: bool = false, + + pub fn fromIntern(fn_info: InternPool.Key.FuncType, ip: *InternPool) FuncInfo { + return .{ + .cc = fn_info.cc, + .noalias_bits = fn_info.noalias_bits, + .param_types = fn_info.param_types.get(ip), + .return_type = fn_info.return_type, + .is_var_args = fn_info.is_var_args, + }; + } + }; + pub fn lowerFnType(o: *Object, fn_info: FuncInfo) Allocator.Error!Builder.Type { const zcu = o.zcu; - const ip = &zcu.intern_pool; const target = zcu.getTarget(); - assert(fn_ty.fnHasRuntimeBits(zcu)); - - const ret_strat = try fnReturnStrat(o, fn_info); + const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)); var llvm_params: std.ArrayList(Builder.Type) = .empty; defer llvm_params.deinit(o.gpa); @@ -3305,24 +3520,24 @@ pub const Object = struct { try llvm_params.append(o.gpa, llvm_ptr_ty); } - var it = iterateParamTypes(o, fn_info); + var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); while (try it.next()) |lowering| switch (lowering) { .no_bits => continue, .byval => { - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .as_value)); }, .byref, .byref_mut => { try llvm_params.append(o.gpa, .ptr); }, .abi_sized_int => { - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); try llvm_params.append(o.gpa, try o.builder.intType( @intCast(param_ty.abiSize(zcu) * 8), )); }, .slice => { - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); try llvm_params.appendSlice(o.gpa, &.{ try o.builder.ptrType(toLlvmAddressSpace(param_ty.ptrAddressSpace(zcu), target)), try o.lowerType(.usize, .as_value), @@ -3332,7 +3547,7 @@ pub const Object = struct { try llvm_params.appendSlice(o.gpa, it.types_buffer[0..it.types_len]); }, .float_array => |count| { - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .in_memory); try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty)); }, @@ -3460,18 +3675,12 @@ pub const Object = struct { }, .enum_tag => |enum_tag| o.lowerValue(enum_tag.int, repr), .float => switch (ty.floatBits(target)) { - 16 => if (backendSupportsF16(target)) - try o.builder.halfConst(val.toFloat(f16, zcu)) - else - try o.builder.intConst(.i16, @as(i16, @bitCast(val.toFloat(f16, zcu)))), - 32 => try o.builder.floatConst(val.toFloat(f32, zcu)), - 64 => try o.builder.doubleConst(val.toFloat(f64, zcu)), - 80 => if (backendSupportsF80(target)) - try o.builder.x86_fp80Const(val.toFloat(f80, zcu)) - else - try o.builder.intConst(.i80, @as(i80, @bitCast(val.toFloat(f80, zcu)))), - 128 => try o.builder.fp128Const(val.toFloat(f128, zcu)), else => unreachable, + 16 => try o.f16Const(val.toFloat(f16, zcu)), + 32 => try o.f32Const(val.toFloat(f32, zcu)), + 64 => try o.f64Const(val.toFloat(f64, zcu)), + 80 => try o.f80Const(val.toFloat(f80, zcu)), + 128 => try o.f128Const(val.toFloat(f128, zcu)), }, .ptr => try o.lowerPtr(arg_val, 0), .slice => |slice| return o.builder.structConst(try o.lowerType(ty, repr), &.{ @@ -3590,12 +3799,13 @@ pub const Object = struct { }, .vector_type => |vector_type| { const vector_ty = try o.lowerType(ty, repr); + const ExpectedContents = [Builder.expected_fields_len]Builder.Constant; + var bfa_buf: ExpectedContents = undefined; + var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), o.gpa); + const allocator = bfa.allocator(); + const is_by_ref = isByRef(ty, zcu); switch (aggregate.storage) { .bytes, .elems => { - const ExpectedContents = [Builder.expected_fields_len]Builder.Constant; - var bfa_buf: ExpectedContents = undefined; - var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), o.gpa); - const allocator = bfa.allocator(); const vals = try allocator.alloc(Builder.Constant, vector_type.len); defer allocator.free(vals); @@ -3604,16 +3814,21 @@ pub const Object = struct { result_val.* = try o.builder.intConst(.i8, byte); }, .elems => |elems| for (vals, elems) |*result_val, elem| { - result_val.* = try o.lowerValue(elem, .as_value); + result_val.* = try o.lowerValue(elem, if (is_by_ref) .in_memory else .as_value); }, .repeated_elem => unreachable, } - return o.builder.vectorConst(vector_ty, vals); + return if (is_by_ref) + o.builder.arrayConst(vector_ty, vals) + else + o.builder.vectorConst(vector_ty, vals); }, - .repeated_elem => |elem| return o.builder.splatConst( - vector_ty, - try o.lowerValue(elem, .as_value), - ), + .repeated_elem => |elem| if (is_by_ref) { + const vals = try allocator.alloc(Builder.Constant, vector_type.len); + defer allocator.free(vals); + @memset(vals, try o.lowerValue(elem, .in_memory)); + return o.builder.arrayConst(vector_ty, vals); + } else return o.builder.splatConst(vector_ty, try o.lowerValue(elem, .as_value)), } }, .tuple_type => |tuple| { @@ -3841,6 +4056,117 @@ pub const Object = struct { }; } + pub fn f16Const(o: *Object, val: f16) Allocator.Error!Builder.Constant { + return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 16)) { + .hard => o.builder.halfConst(val), + .soft => o.builder.intConst(.i16, @as(u16, @bitCast(val))), + }; + } + + pub fn f32Const(o: *Object, val: f32) Allocator.Error!Builder.Constant { + return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 32)) { + .hard => o.builder.floatConst(val), + .soft => o.builder.intConst(.i32, @as(u32, @bitCast(val))), + }; + } + + pub fn f64Const(o: *Object, val: f64) Allocator.Error!Builder.Constant { + return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 64)) { + .hard => o.builder.doubleConst(val), + .soft => o.builder.intConst(.i64, @as(u64, @bitCast(val))), + }; + } + + pub fn f80Const(o: *Object, val: f80) Allocator.Error!Builder.Constant { + switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 80)) { + .hard => return o.builder.x86_fp80Const(val), + .soft => {}, + } + var llvm_field_tags_buf: [5]SoftF80Layout.LlvmFieldTag = undefined; + var llvm_field_types_buf: [5]Builder.Type = undefined; + const f80_layout = try o.softF80Layout(.{ + .llvm_field_tags_buf = &llvm_field_tags_buf, + .llvm_field_types_buf = &llvm_field_types_buf, + }); + const llvm_field_types = llvm_field_types_buf[0..f80_layout.llvm_fields_len]; + const f80_llvm_ty = try o.builder.structType(.normal, llvm_field_types); + const f80_repr: packed struct { mantissa: u64, exponent: u16 } = @bitCast(val); + var llvm_field_vals_buf: [5]Builder.Constant = undefined; + const llvm_field_vals = llvm_field_vals_buf[0..f80_layout.llvm_fields_len]; + for ( + llvm_field_vals, + llvm_field_tags_buf[0..f80_layout.llvm_fields_len], + llvm_field_types, + ) |*llvm_field_val, llvm_field_tag, llvm_field_type| + llvm_field_val.* = switch (llvm_field_tag) { + .mantissa => try o.builder.intConst(llvm_field_type, f80_repr.mantissa), + .exponent => try o.builder.intConst(llvm_field_type, f80_repr.exponent), + .padding => try o.builder.undefConst(llvm_field_type), + }; + return o.builder.structConst(f80_llvm_ty, llvm_field_vals); + } + + pub fn f128Const(o: *Object, val: f128) Allocator.Error!Builder.Constant { + switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 128)) { + .hard => return o.builder.fp128Const(val), + .soft => {}, + } + var llvm_field_tags_buf: [5]SoftF128Layout.LlvmFieldTag = undefined; + var llvm_field_types_buf: [5]Builder.Type = undefined; + const f128_layout = try o.softF128Layout(.{ + .llvm_field_tags_buf = &llvm_field_tags_buf, + .llvm_field_types_buf = &llvm_field_types_buf, + }); + const llvm_field_types = llvm_field_types_buf[0..f128_layout.llvm_fields_len]; + const f128_llvm_ty = try o.builder.structType(.normal, llvm_field_types); + const f128_repr: packed struct { lo: u64, hi: u64 } = @bitCast(val); + var llvm_field_vals_buf: [5]Builder.Constant = undefined; + const llvm_field_vals = llvm_field_vals_buf[0..f128_layout.llvm_fields_len]; + for ( + llvm_field_vals, + llvm_field_tags_buf[0..f128_layout.llvm_fields_len], + llvm_field_types, + ) |*llvm_field_val, llvm_field_tag, llvm_field_type| + llvm_field_val.* = switch (llvm_field_tag) { + .lo => try o.builder.intConst(llvm_field_type, f128_repr.lo), + .hi => try o.builder.intConst(llvm_field_type, f128_repr.hi), + .padding => try o.builder.undefConst(llvm_field_type), + }; + return o.builder.structConst(f128_llvm_ty, llvm_field_vals); + } + + pub fn lowerConstRef( + o: *Object, + constant: Builder.Constant, + @"align": Builder.Alignment, + ) Allocator.Error!Builder.Constant { + assert(@"align" != .default); + const zcu = o.zcu; + const gpa = zcu.comp.gpa; + const gop = try o.const_map.getOrPut(gpa, constant); + if (gop.found_existing) { + // Keep the greater of the two alignments. + const llvm_variable = gop.value_ptr.*; + const llvm_old_align = llvm_variable.getAlignment(&o.builder); + const llvm_new_align = llvm_old_align.max(@"align"); + llvm_variable.setAlignment(llvm_new_align, &o.builder); + return llvm_variable.ptrConst(&o.builder).global.toConst(); + } + errdefer assert(o.const_map.remove(constant)); + + const llvm_ty = constant.typeOf(&o.builder); + const llvm_addrspace = toLlvmAddressSpace(.generic, zcu.getTarget()); + const llvm_variable = try o.builder.addVariable(.empty, llvm_ty, llvm_addrspace); + gop.value_ptr.* = llvm_variable; + try llvm_variable.setInitializer(constant, &o.builder); + llvm_variable.setMutability(.constant, &o.builder); + llvm_variable.setAlignment(@"align", &o.builder); + const llvm_global = llvm_variable.ptrConst(&o.builder).global; + llvm_global.setLinkage(.private, &o.builder); + llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); + return llvm_global.toConst(); + } + fn lowerPtr( o: *Object, ptr_val: InternPool.Index, @@ -3860,7 +4186,7 @@ pub const Object = struct { const orig_ptr_ty: Type = .fromInterned(uav.orig_ty); const base_ptr = try o.lowerUavRef( uav.val, - orig_ptr_ty.ptrAlignment(zcu), + orig_ptr_ty.ptrAlignment(zcu).toLlvm(), orig_ptr_ty.ptrAddressSpace(zcu), ); return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{ @@ -3912,8 +4238,8 @@ pub const Object = struct { pub fn lowerPtrToVoid( o: *Object, - /// Must not be `.none`. - @"align": InternPool.Alignment, + /// Must not be `.default`. + @"align": Builder.Alignment, @"addrspace": std.lang.AddressSpace, ) Allocator.Error!Builder.Constant { const addr: u64 = @"align".toByteUnits().?; @@ -3926,11 +4252,11 @@ pub const Object = struct { pub fn lowerUavRef( o: *Object, uav_val: InternPool.Index, - /// Must not be `.none`. - @"align": InternPool.Alignment, + /// Must not be `.default`. + @"align": Builder.Alignment, @"addrspace": std.lang.AddressSpace, ) Allocator.Error!Builder.Constant { - assert(@"align" != .none); + assert(@"align" != .default); const zcu = o.zcu; const ip = &zcu.intern_pool; @@ -3955,7 +4281,7 @@ pub const Object = struct { // Keep the greater of the two alignments. const llvm_variable = gop.value_ptr.*; const llvm_old_align = llvm_variable.getAlignment(&o.builder); - const llvm_new_align = llvm_old_align.max(@"align".toLlvm()); + const llvm_new_align = llvm_old_align.max(@"align"); llvm_variable.setAlignment(llvm_new_align, &o.builder); return llvm_variable.ptrConst(&o.builder).global.toConst(); } @@ -3967,7 +4293,7 @@ pub const Object = struct { gop.value_ptr.* = llvm_variable; try llvm_variable.setInitializer(try o.lowerValue(uav_val, .in_memory), &o.builder); llvm_variable.setMutability(.constant, &o.builder); - llvm_variable.setAlignment(@"align".toLlvm(), &o.builder); + llvm_variable.setAlignment(@"align", &o.builder); const llvm_global = llvm_variable.ptrConst(&o.builder).global; llvm_global.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); @@ -3986,7 +4312,7 @@ pub const Object = struct { .none => nav_ty.abiAlignment(zcu), else => |a| a, }; - return o.lowerPtrToVoid(nav_align, nav.resolved.?.@"addrspace"); + return o.lowerPtrToVoid(nav_align.toLlvm(), nav.resolved.?.@"addrspace"); } const gop = try o.nav_map.getOrPut(gpa, nav_id); @@ -4015,7 +4341,7 @@ pub const Object = struct { attributes: *Builder.FunctionAttributes.Wip, param_ty: Type, param_index: u32, - fn_info: InternPool.Key.FuncType, + fn_info: FuncInfo, llvm_arg_i: u32, ) Allocator.Error!void { const zcu = o.zcu; @@ -4075,18 +4401,18 @@ pub const Object = struct { const name = try o.builder.strtabString("__zig_error_name_table"); // TODO: Address space - const variable_index = try o.builder.addVariable(name, .ptr, .default); - variable_index.setMutability(.constant, &o.builder); - variable_index.setAlignment( + const llvm_variable = try o.builder.addVariable(name, .ptr, .default); + llvm_variable.setMutability(.constant, &o.builder); + llvm_variable.setAlignment( Type.slice_const_u8_sentinel_0.abiAlignment(o.zcu).toLlvm(), &o.builder, ); - const global_index = variable_index.ptrConst(&o.builder).global; - global_index.setLinkage(.private, &o.builder); - global_index.setUnnamedAddr(.unnamed_addr, &o.builder); + const llvm_global = llvm_variable.ptrConst(&o.builder).global; + llvm_global.setLinkage(.private, &o.builder); + llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); - o.error_name_table = variable_index; - return variable_index; + o.error_name_table = llvm_variable; + return llvm_variable; } pub fn getErrorsLen(o: *Object) Allocator.Error!Builder.Variable.Index { @@ -4094,13 +4420,13 @@ pub const Object = struct { if (o.errors_len_variable == .none) { const llvm_err_int_ty = try o.errorIntType(.in_memory); const name = try builder.strtabString("__zig_errors_len"); - const variable_index = try builder.addVariable(name, llvm_err_int_ty, .default); - variable_index.setMutability(.constant, builder); - variable_index.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder); - const global_index = variable_index.ptrConst(&o.builder).global; - global_index.setLinkage(.private, builder); - global_index.setUnnamedAddr(.unnamed_addr, builder); - o.errors_len_variable = variable_index; + const llvm_variable = try builder.addVariable(name, llvm_err_int_ty, .default); + llvm_variable.setMutability(.constant, builder); + llvm_variable.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder); + const llvm_global = llvm_variable.ptrConst(&o.builder).global; + llvm_global.setLinkage(.private, builder); + llvm_global.setUnnamedAddr(.unnamed_addr, builder); + o.errors_len_variable = llvm_variable; } return o.errors_len_variable; } @@ -4112,21 +4438,21 @@ pub const Object = struct { const gop = try o.enum_tag_name_map.getOrPut(o.gpa, enum_ty.toIntern()); if (gop.found_existing) return gop.value_ptr.*; errdefer assert(o.enum_tag_name_map.remove(enum_ty.toIntern())); - const function_index = try o.builder.addFunction( + const llvm_function = try o.builder.addFunction( // Dummy function type; `updateEnumTagNameFunction` will replace it with the correct type. // TODO: change the builder API so we don't need to do this. try o.builder.fnType(.void, &.{}, .normal), try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), toLlvmAddressSpace(.generic, zcu.getTarget()), ); - gop.value_ptr.* = function_index; - try o.updateEnumTagNameFunction(enum_ty, function_index); - return function_index; + gop.value_ptr.* = llvm_function; + try o.updateEnumTagNameFunction(enum_ty, llvm_function); + return llvm_function; } fn updateEnumTagNameFunction( o: *Object, enum_ty: Type, - function_index: Builder.Function.Index, + llvm_function: Builder.Function.Index, ) Allocator.Error!void { const zcu = o.zcu; const ip = &zcu.intern_pool; @@ -4136,19 +4462,19 @@ pub const Object = struct { const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .as_value); const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value); - function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = + llvm_function.ptrConst(&o.builder).global.ptr(&o.builder).type = try o.builder.fnType(llvm_ret_ty, &.{llvm_int_ty}, .normal); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer); - function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); - function_index.setCallConv(.fastcc, &o.builder); - function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); + llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); + llvm_function.setCallConv(.fastcc, &o.builder); + llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder); var wip = try Builder.WipFunction.init(&o.builder, .{ - .function = function_index, + .function = llvm_function, .strip = true, }); defer wip.deinit(); @@ -4167,16 +4493,16 @@ pub const Object = struct { for (0..loaded_enum.field_names.len) |field_index| { const name = try o.builder.stringNull(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); const name_init = try o.builder.stringConst(name); - const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); - try name_variable_index.setInitializer(name_init, &o.builder); - name_variable_index.setMutability(.constant, &o.builder); - name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); - const name_global_index = name_variable_index.ptrConst(&o.builder).global; - name_global_index.setLinkage(.private, &o.builder); - name_global_index.setUnnamedAddr(.unnamed_addr, &o.builder); + const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); + try name_llvm_variable.setInitializer(name_init, &o.builder); + name_llvm_variable.setMutability(.constant, &o.builder); + name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder); + const name_llvm_global = name_llvm_variable.ptrConst(&o.builder).global; + name_llvm_global.setLinkage(.private, &o.builder); + name_llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); const name_val = try o.builder.structValue(llvm_ret_ty, &.{ - name_global_index.toConst(), + name_llvm_global.toConst(), try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len - 1), }); @@ -4209,40 +4535,40 @@ pub const Object = struct { const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern()); if (gop.found_existing) return gop.value_ptr.*; errdefer assert(o.named_enum_map.remove(enum_ty.toIntern())); - const function_index = try o.builder.addFunction( + const llvm_function = try o.builder.addFunction( // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type. // TODO: change the builder API so we don't need to do this. try o.builder.fnType(.void, &.{}, .normal), try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), toLlvmAddressSpace(.generic, zcu.getTarget()), ); - gop.value_ptr.* = function_index; - try o.updateIsNamedEnumValueFunction(enum_ty, function_index); - return function_index; + gop.value_ptr.* = llvm_function; + try o.updateIsNamedEnumValueFunction(enum_ty, llvm_function); + return llvm_function; } fn updateIsNamedEnumValueFunction( o: *Object, enum_ty: Type, - function_index: Builder.Function.Index, + llvm_function: Builder.Function.Index, ) Allocator.Error!void { const zcu = o.zcu; const ip = &zcu.intern_pool; const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value); - function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = + llvm_function.ptrConst(&o.builder).global.ptr(&o.builder).type = try o.builder.fnType(.i1, &.{llvm_int_ty}, .normal); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer); - function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); - function_index.setCallConv(.fastcc, &o.builder); - function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); + llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); + llvm_function.setCallConv(.fastcc, &o.builder); + llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder); var wip: Builder.WipFunction = try .init(&o.builder, .{ - .function = function_index, + .function = llvm_function, .strip = true, }); defer wip.deinit(); @@ -4278,20 +4604,27 @@ pub const Object = struct { pub fn getLibcFunction( o: *Object, + pt: Zcu.PerThread, fn_name: Builder.StrtabString, - param_types: []const Builder.Type, - return_type: Builder.Type, + fn_info: FuncInfo, ) Allocator.Error!Builder.Function.Index { if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) { .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function, .function => |function| function, .variable, .replaced => unreachable, }; - return o.builder.addFunction( - try o.builder.fnType(return_type, param_types, .normal), + const llvm_function = try o.builder.addFunction( + try o.lowerFnType(fn_info), fn_name, toLlvmAddressSpace(.generic, o.zcu.getTarget()), ); + var attributes: Builder.FunctionAttributes.Wip = .{}; + defer attributes.deinit(&o.builder); + try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, .{ + .name = fn_name.slice(&o.builder).?, + }, fn_info); + llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder); + return llvm_function; } }; @@ -4585,47 +4918,6 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.lang.AddressSpace, target: }; } -/// This function returns true if we expect LLVM to lower f16 correctly -/// and false if we expect LLVM to crash if it encounters an f16 type, -/// or if it produces miscompilations. -pub fn backendSupportsF16(target: *const std.Target) bool { - return switch (target.cpu.arch) { - .arm, - .armeb, - .thumb, - .thumbeb, - => target.abi.float() == .soft or target.cpu.has(.arm, .fullfp16), - else => true, - }; -} - -/// This function returns true if we expect LLVM to lower x86_fp80 correctly -/// and false if we expect LLVM to crash if it encounters an x86_fp80 type, -/// or if it produces miscompilations. -pub fn backendSupportsF80(target: *const std.Target) bool { - return switch (target.cpu.arch) { - .x86, .x86_64 => !target.cpu.has(.x86, .soft_float), - else => false, - }; -} - -/// This function returns true if we expect LLVM to lower f128 correctly, -/// and false if we expect LLVM to crash if it encounters an f128 type, -/// or if it produces miscompilations. -pub fn backendSupportsF128(target: *const std.Target) bool { - return switch (target.cpu.arch) { - // https://github.com/llvm/llvm-project/issues/121122 - .amdgcn, - => false, - .arm, - .armeb, - .thumb, - .thumbeb, - => target.abi.float() == .soft or target.cpu.has(.arm, .fp_armv8), - else => true, - }; -} - /// We need to insert extra padding if LLVM's isn't enough. /// However we don't want to ever call LLVMABIAlignmentOfType or /// LLVMABISizeOfType because these functions will trip assertions diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 156aa875926d6d3d55341b2eac6d1e8f93e18972..5bdf5029d1b4a639c41652f0792d56aba08e927a 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -169,7 +169,7 @@ fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant { // We need a pointer to a global constant, i.e. a UAV. return o.lowerUavRef( val.toIntern(), - ty.abiAlignment(zcu), + ty.abiAlignment(zcu).toLlvm(), target_util.defaultAddressSpace(zcu.getTarget(), .global_constant), ); } @@ -190,10 +190,10 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { const fn_info = zcu.typeToFunc(fn_ty).?; const param_types = fn_info.param_types.get(ip); - var it = iterateParamTypes(o, fn_info); + var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types.get(ip)); // Populate `fg.ret_ptr`... - fg.ret_ptr = switch (try fnReturnStrat(o, fn_info)) { + fg.ret_ptr = switch (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type))) { .sret => rp: { defer it.llvm_index += 1; break :rp fg.wip.arg(it.llvm_index); @@ -721,29 +721,19 @@ fn genBodyDebugScope( try self.genBody(body, coverage_point); } -const CallAttr = enum { - Auto, - NeverTail, - NeverInline, - AlwaysTail, - AlwaysInline, -}; - -fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) Allocator.Error!Builder.Value { - const air_call = self.air.unwrapCall(inst); +fn airCall(fg: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) Allocator.Error!Builder.Value { + const o = fg.object; + const zcu = o.zcu; + const air_call = fg.air.unwrapCall(inst); const args = air_call.args; - const o = self.object; - const pt = self.pt; - const zcu = o.zcu; const ip = &zcu.intern_pool; - const callee_ty = self.typeOf(air_call.callee); + const callee_ty = fg.typeOf(air_call.callee); const zig_fn_ty = switch (callee_ty.zigTypeTag(zcu)) { .@"fn" => callee_ty, .pointer => callee_ty.childType(zcu), else => unreachable, }; const fn_info = zcu.typeToFunc(zig_fn_ty).?; - const return_type: Type = .fromInterned(fn_info.return_type); const llvm_fn = llvm_fn: { // If the callee is a function *body*, we need to use a pointer to the global. if (air_call.callee.toInterned()) |ip_index| switch (ip.indexToKey(ip_index)) { @@ -752,22 +742,54 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier else => {}, }; // Otherwise, the operand is already a function pointer (possibly runtime-known). - break :llvm_fn try self.resolveInst(air_call.callee); + break :llvm_fn try fg.resolveInst(air_call.callee); }; + + const arg_types = try fg.gpa.alloc(InternPool.Index, args.len); + defer fg.gpa.free(arg_types); + const arg_values = try fg.gpa.alloc(Builder.Value, args.len); + defer fg.gpa.free(arg_values); + for (arg_types, arg_values, args) |*arg_type, *arg_value, arg| { + const arg_ty = fg.typeOf(arg); + arg_type.* = arg_ty.toIntern(); + arg_value.* = if (arg_ty.hasRuntimeBits(zcu)) try fg.resolveInst(arg) else .none; + } + return fg.buildCall(.{ + .is_unused = fg.liveness.isUnused(inst), + .modifier = modifier, + }, try o.lowerType(zig_fn_ty, .as_value), llvm_fn, .fromIntern(fn_info, ip), arg_types, arg_values); +} + +fn buildCall( + fg: *FuncGen, + opts: struct { + is_unused: bool = false, + modifier: std.lang.CallModifier = .auto, + }, + llvm_fn_ty: Builder.Type, + llvm_fn: Builder.Value, + fn_info: Object.FuncInfo, + arg_types: []const InternPool.Index, + arg_values: []const Builder.Value, +) Allocator.Error!Builder.Value { + const o = fg.object; + const pt = fg.pt; + const zcu = o.zcu; + const return_type: Type = .fromInterned(fn_info.return_type); const target = zcu.getTarget(); - const ret_strat = try fnReturnStrat(o, fn_info); + const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)); - var llvm_args = std.array_list.Managed(Builder.Value).init(self.gpa); - defer llvm_args.deinit(); + var llvm_args: std.ArrayList(Builder.Value) = .empty; + defer llvm_args.deinit(fg.gpa); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); - if (self.disable_intrinsics) { + if (fg.disable_intrinsics) { try attributes.addFnAttr(.nobuiltin, &o.builder); } - switch (modifier) { + switch (opts.modifier) { .auto, .always_tail => {}, .never_tail, .never_inline => try attributes.addFnAttr(.@"noinline", &o.builder), .no_suspend, .always_inline, .compile_time => unreachable, @@ -775,10 +797,11 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier const sret_alloc: ?Builder.Value = switch (ret_strat) { .sret => sret_alloc: { - try attributes.addParamAttr(0, .{ .sret = try o.lowerType(return_type, .in_memory) }, &o.builder); + const alignment = return_type.abiAlignment(zcu).toLlvm(); + try o.addSRetFnAttributes(&attributes, try o.lowerType(return_type, .in_memory), alignment, .callsite); - const ptr = try self.buildZigAlloca(return_type, .none); - try llvm_args.append(ptr); + const ptr = try fg.buildZigAlloca(return_type, .none); + try llvm_args.append(fg.gpa, ptr); break :sret_alloc ptr; }, else => sret_alloc: { @@ -792,132 +815,111 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing; if (err_return_tracing) { - assert(self.err_ret_trace != .none); - try llvm_args.append(self.err_ret_trace); + assert(fg.err_ret_trace != .none); + try llvm_args.append(fg.gpa, fg.err_ret_trace); } - var it = iterateParamTypes(o, fn_info); - while (try it.nextCall(self, args)) |lowering| switch (lowering) { - .no_bits => continue, - .byval => { - const arg = args[it.zig_index - 1]; - const param_ty = self.typeOf(arg); - const llvm_arg = try self.resolveInst(arg); - if (isByRef(param_ty, zcu)) { - const alignment = param_ty.abiAlignment(zcu).toLlvm(); - // We don't need to handle non-ABI-sized integer types in memory here since they are - // never by-ref. - const llvm_param_ty = try o.lowerType(param_ty, .in_memory); - const loaded = try self.wip.load(.normal, llvm_param_ty, llvm_arg, alignment, ""); - try llvm_args.append(loaded); - } else { - try llvm_args.append(llvm_arg); - } - }, - .byref => { - const arg = args[it.zig_index - 1]; - const param_ty = self.typeOf(arg); - const llvm_arg = try self.resolveInst(arg); - if (isByRef(param_ty, zcu)) { - try llvm_args.append(llvm_arg); - } else { - const arg_ptr = try self.buildZigAlloca(param_ty, .none); - try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal); - try llvm_args.append(arg_ptr); - } - }, - .byref_mut => { - const arg = args[it.zig_index - 1]; - const param_ty = self.typeOf(arg); - const llvm_arg = try self.resolveInst(arg); + var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); + while (try it.nextCall(arg_types)) |lowering| { + const arg_ty: Type = .fromInterned(arg_types[it.zig_index - 1]); + const arg_val = arg_values[it.zig_index - 1]; + switch (lowering) { + .no_bits => continue, + .byval => { + if (isByRef(arg_ty, zcu)) { + const alignment = arg_ty.abiAlignment(zcu).toLlvm(); + // We don't need to handle non-ABI-sized integer types in memory here since they are + // never by-ref. + const llvm_arg_ty = try o.lowerType(arg_ty, .in_memory); + const loaded = try fg.wip.load(.normal, llvm_arg_ty, arg_val, alignment, ""); + try llvm_args.append(fg.gpa, loaded); + } else { + try llvm_args.append(fg.gpa, arg_val); + } + }, + .byref => { + if (isByRef(arg_ty, zcu)) { + try llvm_args.append(fg.gpa, arg_val); + } else { + const arg_ptr = try fg.buildZigAlloca(arg_ty, .none); + try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal); + try llvm_args.append(fg.gpa, arg_ptr); + } + }, + .byref_mut => { + const arg_ptr = try fg.buildZigAlloca(arg_ty, .none); + try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal); + try llvm_args.append(fg.gpa, arg_ptr); + }, + .abi_sized_int => { + const int_llvm_ty = try o.builder.intType(@intCast(arg_ty.abiSize(zcu) * 8)); - const arg_ptr = try self.buildZigAlloca(param_ty, .none); - try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal); - try llvm_args.append(arg_ptr); - }, - .abi_sized_int => { - const arg = args[it.zig_index - 1]; - const param_ty = self.typeOf(arg); - const llvm_arg = try self.resolveInst(arg); - const int_llvm_ty = try o.builder.intType(@intCast(param_ty.abiSize(zcu) * 8)); + if (isByRef(arg_ty, zcu)) { + const alignment = arg_ty.abiAlignment(zcu).toLlvm(); + const loaded = try fg.wip.load(.normal, int_llvm_ty, arg_val, alignment, ""); + try llvm_args.append(fg.gpa, loaded); + } else { + // LLVM does not allow bitcasting structs so we must allocate + // a local, store as one type, and then load as another type. + const alignment = arg_ty.abiAlignment(zcu).toLlvm(); + const ptr = try fg.buildAlloca(int_llvm_ty, alignment); + try fg.store(ptr, .none, arg_val, arg_ty, .normal); + const loaded = try fg.wip.load(.normal, int_llvm_ty, ptr, alignment, ""); + try llvm_args.append(fg.gpa, loaded); + } + }, + .slice => { + const ptr = try fg.wip.extractValue(arg_val, &.{0}, ""); + const len = try fg.wip.extractValue(arg_val, &.{1}, ""); + try llvm_args.appendSlice(fg.gpa, &.{ ptr, len }); + }, + .multiple_llvm_types => { + const arg_alignment = arg_ty.abiAlignment(zcu); + const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8); + const arg_ptr = try fg.buildAlloca(llvm_ty, arg_alignment.toLlvm()); + try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal); - if (isByRef(param_ty, zcu)) { - const alignment = param_ty.abiAlignment(zcu).toLlvm(); - const loaded = try self.wip.load(.normal, int_llvm_ty, llvm_arg, alignment, ""); - try llvm_args.append(loaded); - } else { - // LLVM does not allow bitcasting structs so we must allocate - // a local, store as one type, and then load as another type. - const alignment = param_ty.abiAlignment(zcu).toLlvm(); - const ptr = try self.buildAlloca(int_llvm_ty, alignment); - try self.store(ptr, .none, llvm_arg, param_ty, .normal); - const loaded = try self.wip.load(.normal, int_llvm_ty, ptr, alignment, ""); - try llvm_args.append(loaded); - } - }, - .slice => { - const arg = args[it.zig_index - 1]; - const llvm_arg = try self.resolveInst(arg); - const ptr = try self.wip.extractValue(llvm_arg, &.{0}, ""); - const len = try self.wip.extractValue(llvm_arg, &.{1}, ""); - try llvm_args.appendSlice(&.{ ptr, len }); - }, - .multiple_llvm_types => { - const arg = args[it.zig_index - 1]; - const param_ty = self.typeOf(arg); - const llvm_arg = try self.resolveInst(arg); - const param_alignment = param_ty.abiAlignment(zcu); - const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8); - const arg_ptr = try self.buildAlloca(llvm_ty, param_alignment.toLlvm()); - try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal); + try llvm_args.ensureUnusedCapacity(fg.gpa, it.types_len); + for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| { + const field_ptr = try fg.ptraddConst(arg_ptr, offset); + const loaded = try fg.wip.load(.normal, field_ty, field_ptr, arg_alignment.offset(offset).toLlvm(), ""); + llvm_args.appendAssumeCapacity(loaded); + } + }, + .float_array => |count| { + const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { + const ptr = try fg.buildZigAlloca(arg_ty, .none); + try fg.store(ptr, .none, arg_val, arg_ty, .normal); + break :ptr ptr; + } else arg_val; - try llvm_args.ensureUnusedCapacity(it.types_len); - for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| { - const field_ptr = try self.ptraddConst(arg_ptr, offset); - const loaded = try self.wip.load(.normal, field_ty, field_ptr, param_alignment.offset(offset).toLlvm(), ""); - llvm_args.appendAssumeCapacity(loaded); - } - }, - .float_array => |count| { - const arg = args[it.zig_index - 1]; - const arg_ty = self.typeOf(arg); - const arg_val = try self.resolveInst(arg); + const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .in_memory); + const array_ty = try o.builder.arrayType(count, float_ty); - const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { - const ptr = try self.buildZigAlloca(arg_ty, .none); - try self.store(ptr, .none, arg_val, arg_ty, .normal); - break :ptr ptr; - } else arg_val; + const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); + try llvm_args.append(fg.gpa, loaded); + }, + .i32_array, .i64_array => |arr_len| { + const elem_size: u8 = if (lowering == .i32_array) 32 else 64; - const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .in_memory); - const array_ty = try o.builder.arrayType(count, float_ty); + const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { + const ptr = try fg.buildZigAlloca(arg_ty, .none); + try fg.store(ptr, .none, arg_val, arg_ty, .normal); + break :ptr ptr; + } else arg_val; - const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); - try llvm_args.append(loaded); - }, - .i32_array, .i64_array => |arr_len| { - const elem_size: u8 = if (lowering == .i32_array) 32 else 64; - const arg = args[it.zig_index - 1]; - const arg_ty = self.typeOf(arg); - const arg_val = try self.resolveInst(arg); - - const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { - const ptr = try self.buildZigAlloca(arg_ty, .none); - try self.store(ptr, .none, arg_val, arg_ty, .normal); - break :ptr ptr; - } else arg_val; - - const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size))); - const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); - try llvm_args.append(loaded); - }, - }; + const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size))); + const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); + try llvm_args.append(fg.gpa, loaded); + }, + } + } const cc_info = llvm.toLlvmCallConv(fn_info.cc, target).?; { // Add argument attributes. - it = iterateParamTypes(o, fn_info); + it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); it.llvm_index += @intFromBool(ret_strat == .sret); it.llvm_index += @intFromBool(err_return_tracing); var remaining_inreg_int = cc_info.inreg_int_params; @@ -925,7 +927,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier while (try it.next()) |lowering| switch (lowering) { .byval => { const param_index = it.zig_index - 1; - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); + const param_ty = Type.fromInterned(fn_info.param_types[param_index]); if (!isByRef(param_ty, zcu)) { try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1); } @@ -947,7 +949,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier }, .byref => { const param_index = it.zig_index - 1; - const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[param_index]); + const param_ty: Type = .fromInterned(fn_info.param_types[param_index]); try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty); }, .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), @@ -962,7 +964,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier .slice => { assert(!it.byval_attr); - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); const ptr_info = param_ty.ptrInfo(zcu); const llvm_arg_i = it.llvm_index - 2; @@ -989,8 +991,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier }; } - const call = try self.wip.call( - switch (modifier) { + const call = try fg.wip.call( + switch (opts.modifier) { .auto, .never_inline => .normal, .never_tail => .notail, .always_tail => .musttail, @@ -998,19 +1000,14 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier }, cc_info.llvm_cc, try attributes.finish(&o.builder), - try o.lowerType(zig_fn_ty, .as_value), + llvm_fn_ty, llvm_fn, llvm_args.items, "", ); - if (fn_info.return_type == .noreturn_type and modifier != .always_tail) { - return .none; - } - - if (self.liveness.isUnused(inst)) { - return .none; - } + if (opts.is_unused) return .none; + if (fn_info.return_type == .noreturn_type and opts.modifier != .always_tail) return .none; // We exit this `switch` if we have a pointer to the return value. const ret_val_ptr: Builder.Value = switch (ret_strat) { @@ -1020,15 +1017,15 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier .sret => sret_alloc.?, .mem_cast => |llvm_ret_ty| ret_val_ptr: { const alignment = return_type.abiAlignment(zcu).toLlvm(); - const ptr = try self.buildAlloca(llvm_ret_ty, alignment); - _ = try self.wip.store(.normal, call, ptr, alignment); + const ptr = try fg.buildAlloca(llvm_ret_ty, alignment); + _ = try fg.wip.store(.normal, call, ptr, alignment); break :ret_val_ptr ptr; }, }; if (isByRef(return_type, zcu)) { return ret_val_ptr; } else { - return self.load(ret_val_ptr, .none, return_type, .normal); + return fg.load(ret_val_ptr, .none, return_type, .normal); } } @@ -1067,7 +1064,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?; - const ret_strat = try fnReturnStrat(o, fn_info); + const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)); const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false; const ret_ty_align = ret_ty.abiAlignment(zcu); @@ -1141,7 +1138,7 @@ fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { const ret_ty = ptr_ty.childType(zcu); const fn_info = zcu.typeToFunc(.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?; const ptr = try self.resolveInst(un_op); - switch (try fnReturnStrat(o, fn_info)) { + switch (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type))) { .void => _ = try self.wip.retVoid(), .sret => { assert(self.ret_ptr != .none); @@ -2028,135 +2025,95 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, ""); } -fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { - const o = self.object; +fn airFloatFromInt(fg: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { + const o = fg.object; const zcu = o.zcu; - const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; + const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op; - const operand = try self.resolveInst(ty_op.operand); - const operand_ty = self.typeOf(ty_op.operand); + const operand = try fg.resolveInst(ty_op.operand); + const operand_ty = fg.typeOf(ty_op.operand); const operand_scalar_ty = operand_ty.scalarType(zcu); - const is_signed_int = operand_scalar_ty.isSignedInt(zcu); + const operand_scalar_info = operand_scalar_ty.intInfo(zcu); - const dest_ty = self.typeOfIndex(inst); + const dest_ty = fg.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); - const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_scalar_ty, target)) return self.wip.conv( - if (is_signed_int) .signed else .unsigned, - operand, - dest_llvm_ty, - "", - ); + if (intrinsicsAllowed(dest_scalar_ty, target)) + return fg.wip.conv(.fromStdLang(operand_scalar_info.signedness), operand, try o.lowerType(dest_ty, .as_value), ""); - const rt_int_bits = compilerRtIntBits(@intCast(operand_scalar_ty.bitSize(zcu))) orelse { - return self.todo("float_from_int on {d} bit integer", .{operand_scalar_ty.bitSize(zcu)}); + const rt_int_ty = compilerRtPromoteInt(operand_scalar_info) orelse { + return fg.todo("float_from_int on {d} bit integer", .{operand_scalar_info.bits}); }; - const rt_int_ty = try o.builder.intType(rt_int_bits); - var extended = try self.wip.conv( - if (is_signed_int) .signed else .unsigned, + const vector_len = if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null; + const rt_llvm_int_ty = try o.lowerType(rt_int_ty, .as_value); + const extended = try fg.wip.conv( + .fromStdLang(operand_scalar_info.signedness), operand, - rt_int_ty, + if (vector_len) |len| + try o.builder.vectorType(.normal, len, rt_llvm_int_ty) + else + rt_llvm_int_ty, "", ); - const dest_bits = dest_scalar_ty.floatBits(target); - const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits); - const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits); - const sign_prefix = if (is_signed_int) "" else "un"; const fn_name = try o.builder.strtabStringFmt("__float{s}{s}i{s}f", .{ - sign_prefix, - compiler_rt_operand_abbrev, - compiler_rt_dest_abbrev, + switch (operand_scalar_info.signedness) { + .signed => "", + .unsigned => "un", + }, + compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits), + compilerRtFloatAbbrev(target, dest_scalar_ty.floatBits(target)), }); - - var param_type = rt_int_ty; - if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) { - // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard - // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have. - param_type = try o.builder.vectorType(.normal, 2, .i64); - extended = try self.wip.cast(.bitcast, extended, param_type, ""); - } - - const libc_fn = try o.getLibcFunction(fn_name, &.{param_type}, dest_llvm_ty); - return self.wip.call( - .normal, - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - &.{extended}, - "", - ); + return fg.buildElementwiseCall(fn_name, .{ + .cc = target.cCallingConvention().?, + .param_types = &.{rt_int_ty.toIntern()}, + .return_type = dest_scalar_ty.toIntern(), + }, &.{extended}, vector_len); } fn airIntFromFloat( - self: *FuncGen, + fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind, ) TodoError!Builder.Value { _ = fast; - const o = self.object; + const o = fg.object; const zcu = o.zcu; const target = zcu.getTarget(); - const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; + const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op; - const operand = try self.resolveInst(ty_op.operand); - const operand_ty = self.typeOf(ty_op.operand); + const operand = try fg.resolveInst(ty_op.operand); + const operand_ty = fg.typeOf(ty_op.operand); const operand_scalar_ty = operand_ty.scalarType(zcu); - const dest_ty = self.typeOfIndex(inst); + const dest_ty = fg.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); + const dest_scalar_info = dest_scalar_ty.intInfo(zcu); if (intrinsicsAllowed(operand_scalar_ty, target)) { // TODO set fast math flag - return self.wip.conv( - if (dest_scalar_ty.isSignedInt(zcu)) .signed else .unsigned, - operand, - dest_llvm_ty, - "", - ); + return fg.wip.conv(.fromStdLang(dest_scalar_info.signedness), operand, dest_llvm_ty, ""); } - const rt_int_bits = compilerRtIntBits(@intCast(dest_scalar_ty.bitSize(zcu))) orelse { - return self.todo("int_from_float to {d} bit integer", .{dest_scalar_ty.bitSize(zcu)}); + const rt_int_ty = compilerRtPromoteInt(dest_scalar_info) orelse { + return fg.todo("int_from_float to {d} bit integer", .{dest_scalar_info.bits}); }; - const ret_ty = try o.builder.intType(rt_int_bits); - const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: { - // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard - // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have. - break :b try o.builder.vectorType(.normal, 2, .i64); - } else ret_ty; - - const operand_bits = operand_scalar_ty.floatBits(target); - const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits); - - const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits); - const sign_prefix = if (dest_scalar_ty.isSignedInt(zcu)) "" else "uns"; - const fn_name = try o.builder.strtabStringFmt("__fix{s}{s}f{s}i", .{ - sign_prefix, - compiler_rt_operand_abbrev, - compiler_rt_dest_abbrev, + switch (dest_scalar_info.signedness) { + .signed => "", + .unsigned => "uns", + }, + compilerRtFloatAbbrev(target, operand_scalar_ty.floatBits(target)), + compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits), }); - - const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); - const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); - var result = try self.wip.call( - .normal, - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - &.{operand}, - "", - ); - - if (libc_ret_ty != ret_ty) result = try self.wip.cast(.bitcast, result, ret_ty, ""); - if (ret_ty != dest_llvm_ty) result = try self.wip.cast(.trunc, result, dest_llvm_ty, ""); - return result; + const result = try fg.buildElementwiseCall(fn_name, .{ + .cc = target.cCallingConvention().?, + .param_types = &.{operand_scalar_ty.toIntern()}, + .return_type = rt_int_ty.toIntern(), + }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null); + return fg.wip.cast(.trunc, result, try o.lowerType(dest_ty, .as_value), ""); } fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value { @@ -3692,15 +3649,17 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); const inst_ty = self.typeOfIndex(inst); - const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const scalar_ty = inst_ty.scalarType(zcu); if (scalar_ty.isRuntimeFloat()) { const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs }); const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs }); const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs }); - const zero = try o.builder.zeroInitValue(inst_llvm_ty); - const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero }); + const zero = if (isByRef(inst_ty, zcu)) zero: { + const zero = try o.builder.zeroInitConst(try o.lowerType(inst_ty, .in_memory)); + break :zero try o.lowerConstRef(zero, inst_ty.abiAlignment(zcu).toLlvm()); + } else try o.builder.zeroInitConst(try o.lowerType(inst_ty, .as_value)); + const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero.toValue() }); return self.wip.select(fast, ltz, c, a, ""); } if (scalar_ty.isSignedInt(zcu)) { @@ -3709,6 +3668,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), self.gpa); const allocator = bfa.allocator(); + const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const scalar_bits = scalar_ty.intInfo(zcu).bits; var smin_big_int: std.math.big.int.Mutable = .{ .limbs = try allocator.alloc( @@ -3818,34 +3778,97 @@ fn airOverflow( } fn buildElementwiseCall( - self: *FuncGen, - llvm_fn: Builder.Function.Index, - args_vectors: []const Builder.Value, - result_vector: Builder.Value, - vector_len: usize, + fg: *FuncGen, + fn_name: Builder.StrtabString, + fn_info: Object.FuncInfo, + arg_values: []const Builder.Value, + vector_len: ?u32, ) Allocator.Error!Builder.Value { - const o = self.object; - assert(args_vectors.len <= 3); + const o = fg.object; + const zcu = o.zcu; + const llvm_fn = try fg.object.getLibcFunction(fg.pt, fn_name, fn_info); - var i: usize = 0; - var result = result_vector; - while (i < vector_len) : (i += 1) { - const index_i32 = try o.builder.intValue(.i32, i); + const iterations = vector_len orelse 1; + const ret_ty: Type = .fromInterned(fn_info.return_type); + const ret_is_by_ref = isByRef(ret_ty, zcu); + if (iterations > 1 and (fn_info.return_type == .void_type or ret_is_by_ref) and + for (fn_info.param_types) |param_type| { + if (!isByRef(.fromInterned(param_type), zcu)) break false; + } else true) + { + const entry_block = fg.wip.cursor.block; + const loop_block = try fg.wip.block(2, "elementwise.loop"); + const done_block = try fg.wip.block(1, "elementwise.done"); - var args: [3]Builder.Value = undefined; - for (args[0..args_vectors.len], args_vectors) |*arg_elem, arg_vector| { - arg_elem.* = try self.wip.extractElement(arg_vector, index_i32, ""); + const result_ptr = if (fn_info.return_type == .void_type) .none else result_ptr: { + const ret_llvm_ty = try o.lowerType(ret_ty, .in_memory); + break :result_ptr try fg.buildAlloca( + if (vector_len) |len| try o.builder.arrayType(len, ret_llvm_ty) else ret_llvm_ty, + ret_ty.abiAlignment(zcu).toLlvm(), + ); + }; + _ = try fg.wip.br(loop_block); + + fg.wip.cursor = .{ .block = loop_block }; + const index = try fg.wip.phi(.i32, "elementwise.index"); + + var arg_elems_buf: [3]Builder.Value = undefined; + const arg_elems = arg_elems_buf[0..arg_values.len]; + for (arg_elems, fn_info.param_types, arg_values) |*arg_elem, param_type, arg_value| { + const arg_elem_ptr = try fg.ptraddScaled(arg_value, index.toValue(), Type.fromInterned(param_type).abiSize(zcu)); + arg_elem.* = try fg.load(arg_elem_ptr, .none, .fromInterned(param_type), .normal); + } + const result_elem = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, arg_elems); + if (fn_info.return_type == .void_type) { + assert(result_elem == .none); + } else if (result_elem != .none) { + const result_elem_ptr = try fg.ptraddScaled(result_ptr, index.toValue(), ret_ty.abiSize(zcu)); + try fg.store(result_elem_ptr, .none, result_elem, ret_ty, .normal); } - const result_elem = try self.wip.call( - .normal, - .ccc, - .none, - llvm_fn.typeOf(&o.builder), - llvm_fn.toValue(&o.builder), - args[0..args_vectors.len], - "", + + const next_index = try fg.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(.i32, 1), "elementwise.next_index"); + index.finish(&.{ try o.builder.intValue(.i32, 0), next_index }, &.{ entry_block, loop_block }, &fg.wip); + const is_done = try fg.wip.icmp(.eq, next_index, try o.builder.intValue(.i32, iterations), "elementwise.is_done"); + _ = try fg.wip.brCond(is_done, done_block, loop_block, .none); + + fg.wip.cursor = .{ .block = done_block }; + return result_ptr; + } + + var result = if (fn_info.return_type == .void_type) .none else if (ret_is_by_ref) result: { + const ret_llvm_ty = try o.lowerType(ret_ty, .in_memory); + break :result try fg.buildAlloca( + if (vector_len) |len| try o.builder.arrayType(len, ret_llvm_ty) else ret_llvm_ty, + ret_ty.abiAlignment(zcu).toLlvm(), ); - result = try self.wip.insertElement(result, result_elem, index_i32, ""); + } else if (vector_len) |len| try o.builder.poisonValue( + try o.builder.vectorType(.normal, len, try o.lowerType(ret_ty, .as_value)), + ) else .none; + for (0..iterations) |index| { + const index_value = try o.builder.intValue(.i32, index); + var arg_elems_buf: [3]Builder.Value = undefined; + const arg_elems = arg_elems_buf[0..arg_values.len]; + for (arg_elems, fn_info.param_types, arg_values) |*arg_elem_value, param_type, arg_value| { + const arg_ty: Type = .fromInterned(param_type); + if (isByRef(arg_ty, zcu)) { + const arg_elem_ptr = try fg.ptraddConst(arg_value, index * arg_ty.abiSize(zcu)); + arg_elem_value.* = try fg.load(arg_elem_ptr, .none, .fromInterned(param_type), .normal); + } else if (vector_len) |_| { + arg_elem_value.* = try fg.wip.extractElement(arg_value, index_value, "elementwise.arg_elem"); + } else arg_elem_value.* = arg_value; + } + const result_elem = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, arg_elems); + if (fn_info.return_type == .void_type) { + assert(result_elem == .none); + } else if (ret_is_by_ref) { + const result_elem_ptr = try fg.ptraddConst(result, index * ret_ty.abiSize(zcu)); + try fg.store(result_elem_ptr, .none, result_elem, ret_ty, .normal); + } else if (vector_len) |_| { + result = try fg.wip.insertElement(result, result_elem, index_value, "elementwise.result"); + } else { + assert(result == .none); + result = result_elem; + } } return result; } @@ -3853,17 +3876,16 @@ fn buildElementwiseCall( /// Creates a floating point comparison by lowering to the appropriate /// hardware instruction or softfloat routine for the target fn buildFloatCmp( - self: *FuncGen, + fg: *FuncGen, fast: Builder.FastMathKind, pred: math.CompareOperator, ty: Type, params: [2]Builder.Value, ) Allocator.Error!Builder.Value { - const o = self.object; + const o = fg.object; const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); if (intrinsicsAllowed(scalar_ty, target)) { const cond: Builder.FloatCondition = switch (pred) { @@ -3874,53 +3896,33 @@ fn buildFloatCmp( .gt => .ogt, .gte => .oge, }; - return self.wip.fcmp(fast, cond, params[0], params[1], ""); + return fg.wip.fcmp(fast, cond, params[0], params[1], ""); } - const float_bits = scalar_ty.floatBits(target); - const compiler_rt_float_abbrev = compilerRtFloatAbbrev(float_bits); - const fn_base_name = switch (pred) { - .neq => "ne", - .eq => "eq", - .lt => "lt", - .lte => "le", - .gt => "gt", - .gte => "ge", - }; - const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev }); - - const libc_fn = try o.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32); - - const int_cond: Builder.IntegerCondition = switch (pred) { + const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ + switch (pred) { + .neq => "ne", + .eq => "eq", + .lt => "lt", + .lte => "le", + .gt => "gt", + .gte => "ge", + }, + compilerRtFloatAbbrev(target, scalar_ty.floatBits(target)), + }); + const result = try fg.buildElementwiseCall(fn_name, .{ + .cc = target.cCallingConvention().?, + .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() }, + .return_type = .i32_type, + }, ¶ms, if (ty.isVector(zcu)) ty.vectorLen(zcu) else null); + return fg.wip.icmp(switch (pred) { .eq => .eq, .neq => .ne, .lt => .slt, .lte => .sle, .gt => .sgt, .gte => .sge, - }; - - if (ty.zigTypeTag(zcu) == .vector) { - const vec_len = ty.vectorLen(zcu); - const vector_result_ty = try o.builder.vectorType(.normal, vec_len, .i32); - - const init = try o.builder.poisonValue(vector_result_ty); - const result = try self.buildElementwiseCall(libc_fn, ¶ms, init, vec_len); - - const zero_vector = try o.builder.splatValue(vector_result_ty, .@"0"); - return self.wip.icmp(int_cond, result, zero_vector, ""); - } - - const result = try self.wip.call( - .normal, - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - ¶ms, - "", - ); - return self.wip.icmp(int_cond, result, .@"0", ""); + }, result, try o.builder.splatValue(result.typeOfWip(&fg.wip), .@"0"), ""); } const FloatOp = enum { @@ -3949,32 +3951,26 @@ const FloatOp = enum { trunc, }; -const FloatOpStrat = union(enum) { - intrinsic: []const u8, - libc: Builder.String, -}; - /// Creates a floating point operation (add, sub, fma, sqrt, exp, etc.) /// by lowering to the appropriate hardware instruction or softfloat /// routine for the target fn buildFloatOp( - self: *FuncGen, + fg: *FuncGen, comptime op: FloatOp, fast: Builder.FastMathKind, ty: Type, comptime params_len: usize, params: [params_len]Builder.Value, ) Allocator.Error!Builder.Value { - const o = self.object; + const o = fg.object; const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const llvm_ty = try o.lowerType(ty, .as_value); if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) { // Some operations are dedicated LLVM instructions, not available as intrinsics - .neg => return self.wip.un(.fneg, params[0], ""), - .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (fast) { + .neg => return fg.wip.un(.fneg, params[0], ""), + .add, .sub, .mul, .div, .fmod => return fg.wip.bin(switch (fast) { .normal => switch (op) { .add => .fadd, .sub => .fsub, @@ -4008,7 +4004,7 @@ fn buildFloatOp( .sqrt, .trunc, .fma, - => return self.wip.callIntrinsic(fast, .none, switch (op) { + => return fg.wip.callIntrinsic(fast, .none, switch (op) { .fmax => .maxnum, .fmin => .minnum, .ceil => .ceil, @@ -4026,36 +4022,152 @@ fn buildFloatOp( .trunc => .trunc, .fma => .fma, else => unreachable, - }, &.{llvm_ty}, ¶ms, ""), + }, &.{try o.lowerType(ty, .as_value)}, ¶ms, ""), .tan => unreachable, }; const float_bits = scalar_ty.floatBits(target); const fn_name = switch (op) { - .neg => { - // In this case we can generate a softfloat negation by XORing the - // bits with a constant. + // In these cases we can generate a softfloat operation by modifying the sign bit using a bitwise operation. + .neg, .fabs => if (isByRef(scalar_ty, zcu)) { + const is_vector = ty.toIntern() != scalar_ty.toIntern(); + const result_ptr = try fg.buildZigAlloca(ty, .none); + const entry_block = fg.wip.cursor.block; + const loop_block, const done_block, const llvm_usize_ty, const offset, const elem, const result_elem = if (is_vector) loop: { + const loop_block = try fg.wip.block(2, "neg_fabs.loop"); + const done_block = try fg.wip.block(1, "neg_fabs.done"); + _ = try fg.wip.br(loop_block); + + fg.wip.cursor = .{ .block = loop_block }; + const llvm_usize_ty = try o.lowerType(.usize, .as_value); + const offset = try fg.wip.phi(llvm_usize_ty, "neg_fabs.offset"); + break :loop .{ + loop_block, + done_block, + llvm_usize_ty, + offset, + try fg.ptraddScaled(params[0], offset.toValue(), 1), + try fg.ptraddScaled(result_ptr, offset.toValue(), 1), + }; + } else .{ undefined, undefined, undefined, undefined, params[0], result_ptr }; + switch (scalar_ty.floatBits(target)) { + else => unreachable, + 80 => { + const f80_layout = o.softF80Layout(.{}) catch unreachable; + const mantissa = try fg.load( + try fg.ptraddConst(elem, f80_layout.mantissa_offset), + f80_layout.alignment.offset(f80_layout.mantissa_offset), + .u64, + .normal, + ); + const exponent = try fg.load( + try fg.ptraddConst(elem, f80_layout.exponent_offset), + f80_layout.alignment.offset(f80_layout.exponent_offset), + .u16, + .normal, + ); + const exponent_sign_bit: u16 = 1 << (16 - 1); + const updated_exponent = try fg.wip.bin(switch (op) { + else => unreachable, + .neg => .xor, + .fabs => .@"and", + }, exponent, try o.builder.intValue(.i16, switch (op) { + else => unreachable, + .neg => exponent_sign_bit, + .fabs => exponent_sign_bit - 1, + }), "neg_fabs.updated_exponent"); + try fg.store( + try fg.ptraddConst(result_elem, f80_layout.mantissa_offset), + f80_layout.alignment.offset(f80_layout.mantissa_offset), + mantissa, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_elem, f80_layout.exponent_offset), + f80_layout.alignment.offset(f80_layout.exponent_offset), + updated_exponent, + .u16, + .normal, + ); + }, + 128 => { + const f128_layout = o.softF128Layout(.{}) catch unreachable; + const lo = try fg.load( + try fg.ptraddConst(elem, f128_layout.lo_offset), + f128_layout.alignment.offset(f128_layout.lo_offset), + .u64, + .normal, + ); + const hi = try fg.load( + try fg.ptraddConst(elem, f128_layout.hi_offset), + f128_layout.alignment.offset(f128_layout.hi_offset), + .u64, + .normal, + ); + const hi_sign_bit: u64 = 1 << (64 - 1); + const updated_hi = try fg.wip.bin(switch (op) { + else => unreachable, + .neg => .xor, + .fabs => .@"and", + }, hi, try o.builder.intValue(.i64, switch (op) { + else => unreachable, + .neg => hi_sign_bit, + .fabs => hi_sign_bit - 1, + }), "neg_fabs.updated_hi"); + try fg.store( + try fg.ptraddConst(result_elem, f128_layout.lo_offset), + f128_layout.alignment.offset(f128_layout.lo_offset), + lo, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_elem, f128_layout.hi_offset), + f128_layout.alignment.offset(f128_layout.hi_offset), + updated_hi, + .u64, + .normal, + ); + }, + } + if (is_vector) { + const next_offset = try fg.wip.bin(.@"add nuw", offset.toValue(), try o.builder.intValue(llvm_usize_ty, scalar_ty.abiSize(zcu)), "neg_fabs.next_offset"); + offset.finish(&.{ try o.builder.intValue(llvm_usize_ty, 0), next_offset }, &.{ entry_block, loop_block }, &fg.wip); + const is_done = try fg.wip.icmp(.eq, next_offset, try o.builder.intValue(llvm_usize_ty, ty.abiSize(zcu)), "neg_fabs.is_done"); + _ = try fg.wip.brCond(is_done, done_block, loop_block, .none); + + fg.wip.cursor = .{ .block = done_block }; + } + return result_ptr; + } else { const int_ty = try o.builder.intType(@intCast(float_bits)); const cast_ty = switch (ty.zigTypeTag(zcu)) { .vector => try o.builder.vectorType(.normal, ty.vectorLen(zcu), int_ty), else => int_ty, }; - const sign_mask = try o.builder.splatValue( - cast_ty, - try o.builder.intConst(int_ty, @as(u128, 1) << @intCast(float_bits - 1)), - ); - const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, ""); - const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, ""); - return self.wip.cast(.bitcast, result, llvm_ty, ""); + const sign_bit = @as(u128, 1) << @intCast(float_bits - 1); + const bitwise_rhs = try o.builder.splatValue(cast_ty, try o.builder.intConst(int_ty, switch (op) { + else => unreachable, + .neg => sign_bit, + .fabs => sign_bit - 1, + })); + const bitcasted_operand = try fg.wip.cast(.bitcast, params[0], cast_ty, ""); + const result = try fg.wip.bin(switch (op) { + else => unreachable, + .neg => .xor, + .fabs => .@"and", + }, bitcasted_operand, bitwise_rhs, ""); + const llvm_ty = try o.lowerType(ty, .as_value); + return fg.wip.cast(.bitcast, result, llvm_ty, ""); }, .add, .sub, .div, .mul => try o.builder.strtabStringFmt("__{s}{s}f3", .{ - @tagName(op), compilerRtFloatAbbrev(float_bits), + @tagName(op), compilerRtFloatAbbrev(target, float_bits), }), .ceil, .cos, .exp, .exp2, - .fabs, .floor, .fma, .fmax, @@ -4073,27 +4185,27 @@ fn buildFloatOp( libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits), }), }; + return fg.buildElementwiseCall(fn_name, .{ + .cc = target.cCallingConvention().?, + .param_types = &@as([params_len]InternPool.Index, @splat(scalar_ty.toIntern())), + .return_type = scalar_ty.toIntern(), + }, ¶ms, if (ty.isVector(zcu)) ty.vectorLen(zcu) else null); +} - const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); - const libc_fn = try o.getLibcFunction( - fn_name, - @as([3]Builder.Type, @splat(scalar_llvm_ty))[0..params.len], - scalar_llvm_ty, - ); - if (ty.zigTypeTag(zcu) == .vector) { - const result = try o.builder.poisonValue(llvm_ty); - return self.buildElementwiseCall(libc_fn, ¶ms, result, ty.vectorLen(zcu)); - } - - return self.wip.call( - fast.toCallKind(), - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - ¶ms, - "", - ); +/// Creates a floating point cast operation by lowering to the specified softfloat routine. +fn buildFloatCastCall( + fg: *FuncGen, + dest_ty: Type, + fn_name: Builder.StrtabString, + operand_ty: Type, + operand: Builder.Value, +) Allocator.Error!Builder.Value { + const zcu = fg.object.zcu; + return fg.buildElementwiseCall(fn_name, .{ + .cc = zcu.getTarget().cCallingConvention().?, + .param_types = &.{operand_ty.scalarType(zcu).toIntern()}, + .return_type = dest_ty.scalarType(zcu).toIntern(), + }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null); } fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -4471,32 +4583,19 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); + const operand_scalar_ty = operand_ty.scalarType(zcu); const dest_ty = self.typeOfIndex(inst); + const dest_scalar_ty = dest_ty.scalarType(zcu); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { + if (intrinsicsAllowed(dest_scalar_ty, target) and intrinsicsAllowed(operand_scalar_ty, target)) return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .as_value), ""); - } else { - const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); - const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); - - const dest_bits = dest_ty.floatBits(target); - const src_bits = operand_ty.floatBits(target); - const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{ - compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), - }); - - const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); - return self.wip.call( - .normal, - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - &.{operand}, - "", - ); - } + const dest_bits = dest_scalar_ty.floatBits(target); + const src_bits = operand_scalar_ty.floatBits(target); + const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{ + compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits), + }); + return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand); } fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -4505,38 +4604,19 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); + const operand_scalar_ty = operand_ty.scalarType(zcu); const dest_ty = self.typeOfIndex(inst); + const dest_scalar_ty = dest_ty.scalarType(zcu); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { + if (intrinsicsAllowed(dest_scalar_ty, target) and intrinsicsAllowed(operand_scalar_ty, target)) return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .as_value), ""); - } else { - const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); - const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); - - const dest_bits = dest_ty.scalarType(zcu).floatBits(target); - const src_bits = operand_ty.scalarType(zcu).floatBits(target); - const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{ - compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), - }); - - const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); - if (dest_ty.isVector(zcu)) return self.buildElementwiseCall( - libc_fn, - &.{operand}, - try o.builder.poisonValue(dest_llvm_ty), - dest_ty.vectorLen(zcu), - ); - return self.wip.call( - .normal, - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - &.{operand}, - "", - ); - } + const dest_bits = dest_scalar_ty.floatBits(target); + const src_bits = operand_scalar_ty.floatBits(target); + const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{ + compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits), + }); + return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand); } fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value { @@ -4558,10 +4638,143 @@ fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! // * bool/int/float <-> bool/int/float // * `@Vector(n, A)` <-> `@Vector(n, B)` // - // All of these cases can be handled by LLVM's `bitcast` instruction. + // Most of these cases can be handled by LLVM's `bitcast` instruction, except when + // a non-native type like `f80` is used. - assert(!isByRef(operand_ty, zcu)); - assert(!isByRef(dest_ty, zcu)); + if (isByRef(operand_ty, zcu)) { + const operand_scalar_ty = operand_ty.scalarType(zcu); + const target = zcu.getTarget(); + const bits = operand_scalar_ty.floatBits(target); + const dest_scalar_ty = dest_ty.scalarType(zcu); + if (isByRef(dest_ty, zcu)) { + assert(dest_scalar_ty.floatBits(target) == bits); + return operand; + } + assert(dest_scalar_ty.intInfo(zcu).bits == bits); + + const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern()) + operand_ty.vectorLen(zcu) + else + null; + const operand_scalar_size = operand_scalar_ty.abiSize(zcu); + var result = if (len) |_| + try o.builder.poisonValue(try o.lowerType(dest_ty, .as_value)) + else + undefined; + for (0..len orelse 1) |index| { + const result_elem = result_elem: switch (bits) { + else => unreachable, + 80 => { + const f80_layout = o.softF80Layout(.{}) catch unreachable; + const mantissa = try fg.load( + try fg.ptraddConst(operand, operand_scalar_size * index + f80_layout.mantissa_offset), + f80_layout.alignment.offset(f80_layout.mantissa_offset), + .u64, + .normal, + ); + const exponent = try fg.load( + try fg.ptraddConst(operand, operand_scalar_size * index + f80_layout.exponent_offset), + f80_layout.alignment.offset(f80_layout.exponent_offset), + .u16, + .normal, + ); + const casted_mantissa = try fg.wip.cast(.zext, mantissa, .i80, "bitCast.casted_mantissa"); + const casted_exponent = try fg.wip.cast(.zext, exponent, .i80, "bitCast.casted_exponent"); + const shifted_exponent = try fg.wip.bin(.@"shl nuw", casted_exponent, try o.builder.intValue(.i80, 64), "bitCast.shifted_exponent"); + break :result_elem try fg.wip.bin(.@"or", casted_mantissa, shifted_exponent, "bitCast.result_elem"); + }, + 128 => { + const f128_layout = o.softF128Layout(.{}) catch unreachable; + const lo = try fg.load( + try fg.ptraddConst(operand, operand_scalar_size * index + f128_layout.lo_offset), + f128_layout.alignment.offset(f128_layout.lo_offset), + .u64, + .normal, + ); + const hi = try fg.load( + try fg.ptraddConst(operand, operand_scalar_size * index + f128_layout.hi_offset), + f128_layout.alignment.offset(f128_layout.hi_offset), + .u64, + .normal, + ); + const casted_lo = try fg.wip.cast(.zext, lo, .i128, "bitCast.casted_lo"); + const casted_hi = try fg.wip.cast(.zext, hi, .i128, "bitCast.casted_hi"); + const shifted_hi = try fg.wip.bin(.@"shl nuw", casted_hi, try o.builder.intValue(.i128, 64), "bitCast.shifted_hi"); + break :result_elem try fg.wip.bin(.@"or", casted_lo, shifted_hi, "bitCast.result_elem"); + }, + }; + result = if (len) |_| + try fg.wip.insertElement(result, result_elem, try o.builder.intValue(.i32, index), "elementwise.result") + else + result_elem; + } + return result; + } + + if (isByRef(dest_ty, zcu)) { + const dest_scalar_ty = dest_ty.scalarType(zcu); + const bits = dest_scalar_ty.floatBits(zcu.getTarget()); + assert(dest_scalar_ty.isRuntimeFloat()); + const operand_scalar_ty = operand_ty.scalarType(zcu); + assert(operand_scalar_ty.intInfo(zcu).bits == bits); + + const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern()) + operand_ty.vectorLen(zcu) + else + null; + const operand_scalar_size = operand_scalar_ty.abiSize(zcu); + const result_ptr = try fg.buildZigAlloca(dest_ty, .none); + for (0..len orelse 1) |index| { + const operand_elem = if (len) |_| + try fg.wip.extractElement(operand, try o.builder.intValue(.i32, index), "elementwise.operand_elem") + else + operand; + switch (bits) { + else => unreachable, + 80 => { + const f80_layout = o.softF80Layout(.{}) catch unreachable; + const mantissa = try fg.wip.cast(.trunc, operand_elem, .i64, "bitCast.mantissa"); + const shifted_exponent = try fg.wip.bin(.lshr, operand_elem, try o.builder.intValue(.i80, 64), "bitCast.shifted_exponent"); + const exponent = try fg.wip.cast(.@"trunc nuw", shifted_exponent, .i16, "bitCast.exponent"); + try fg.store( + try fg.ptraddConst(result_ptr, operand_scalar_size * index + f80_layout.mantissa_offset), + f80_layout.alignment.offset(f80_layout.mantissa_offset), + mantissa, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_ptr, operand_scalar_size * index + f80_layout.exponent_offset), + f80_layout.alignment.offset(f80_layout.exponent_offset), + exponent, + .u16, + .normal, + ); + }, + 128 => { + const f128_layout = o.softF128Layout(.{}) catch unreachable; + const lo = try fg.wip.cast(.trunc, operand_elem, .i64, "bitCast.lo"); + const shifted_hi = try fg.wip.bin(.lshr, operand_elem, try o.builder.intValue(.i128, 64), "bitCast.shifted_hi"); + const hi = try fg.wip.cast(.@"trunc nuw", shifted_hi, .i64, "bitCast.hi"); + try fg.store( + try fg.ptraddConst(result_ptr, operand_scalar_size * index + f128_layout.lo_offset), + f128_layout.alignment.offset(f128_layout.lo_offset), + lo, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_ptr, operand_scalar_size * index + f128_layout.hi_offset), + f128_layout.alignment.offset(f128_layout.hi_offset), + hi, + .u64, + .normal, + ); + }, + } + } + return result_ptr; + } const llvm_dest_ty = try o.lowerType(dest_ty, .as_value); const result = try fg.wip.cast(.bitcast, operand, llvm_dest_ty, ""); @@ -4730,7 +4943,7 @@ fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ptr_align = ptr_ty.ptrAlignment(zcu); const elem_ty = ptr_ty.childType(zcu); if (!elem_ty.hasRuntimeBits(zcu)) { - return (try o.lowerPtrToVoid(ptr_align, ptr_ty.ptrAddressSpace(zcu))).toValue(); + return (try o.lowerPtrToVoid(ptr_align.toLlvm(), ptr_ty.ptrAddressSpace(zcu))).toValue(); } return self.buildZigAlloca(elem_ty, ptr_align); } @@ -4743,7 +4956,7 @@ fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ptr_align = ptr_ty.ptrAlignment(zcu); const elem_ty = ptr_ty.childType(zcu); if (!elem_ty.hasRuntimeBits(zcu)) { - return (try o.lowerPtrToVoid(ptr_align, ptr_ty.ptrAddressSpace(zcu))).toValue(); + return (try o.lowerPtrToVoid(ptr_align.toLlvm(), ptr_ty.ptrAddressSpace(zcu))).toValue(); } return self.buildZigAlloca(elem_ty, ptr_align); } @@ -4850,17 +5063,24 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu const elem = try fg.resolveInst(bin_op.rhs); if (ptr_info.flags.vector_index != .none) { - // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. - const vec_ty = try fg.pt.vectorType(.{ - .len = ptr_info.packed_offset.host_size, - .child = elem_ty.toIntern(), - }); + if (isByRef(elem_ty, zcu)) { + const offset = @backingInt(ptr_info.flags.vector_index) * elem_ty.abiSize(zcu); + const elem_ptr = try fg.ptraddConst(ptr, offset); + try fg.store(elem_ptr, ptr_alignment.offset(offset), elem, elem_ty, access_kind); + } else { + // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. + const vec_ty = try fg.pt.vectorType(.{ + .len = ptr_info.packed_offset.host_size, + .child = elem_ty.toIntern(), + }); - const loaded_vector = try fg.load(ptr, ptr_alignment, vec_ty, access_kind); - const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); - const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, ""); + const loaded_vector = try fg.load(ptr, ptr_alignment, vec_ty, access_kind); + const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); + const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, ""); + + try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind); + } - try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind); return .none; } @@ -4927,22 +5147,27 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { if (ptr_info.flags.is_volatile) .@"volatile" else .normal; if (ptr_info.flags.vector_index != .none) { - // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. - const vec_ty = try fg.pt.vectorType(.{ - .len = ptr_info.packed_offset.host_size, - .child = elem_ty.toIntern(), - }); - const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind); - const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); - return fg.wip.extractElement(vector_val, index_val, ""); + if (isByRef(elem_ty, zcu)) { + const elem_size = elem_ty.abiSize(zcu); + const offset = @backingInt(ptr_info.flags.vector_index) * elem_size; + const elem_ptr = try fg.ptraddConst(ptr, offset); + return fg.load(elem_ptr, ptr_align.offset(offset), elem_ty, access_kind); + } else { + // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. + const vec_ty = try fg.pt.vectorType(.{ + .len = ptr_info.packed_offset.host_size, + .child = elem_ty.toIntern(), + }); + const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind); + const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); + return fg.wip.extractElement(vector_val, index_val, ""); + } } if (ptr_info.packed_offset.host_size == 0) { return fg.load(ptr, ptr_align, elem_ty, access_kind); } - assert(!isByRef(elem_ty, zcu)); // all packable types are by-val - // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8)); const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .as_value); @@ -4952,6 +5177,67 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const elem_bits = ptr_ty.childType(zcu).bitSize(zcu); const shift_amt = try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset); const shifted_value = try fg.wip.bin(.lshr, backing_int_val, shift_amt, ""); + + if (isByRef(elem_ty, zcu)) { + const result_ptr = try fg.buildZigAlloca(elem_ty, .none); + switch (elem_ty.floatBits(zcu.getTarget())) { + else => unreachable, + 80 => { + const f80_layout = o.softF80Layout(.{}) catch unreachable; + const mantissa = try fg.wip.cast(.trunc, shifted_value, .i64, "load.mantissa"); + const shifted_exponent = try fg.wip.bin( + .lshr, + backing_int_val, + try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset + 64), + "load.shifted_exponent", + ); + const exponent = try fg.wip.cast(.trunc, shifted_exponent, .i16, "load.exponent"); + + try fg.store( + try fg.ptraddConst(result_ptr, f80_layout.mantissa_offset), + f80_layout.alignment.offset(f80_layout.mantissa_offset), + mantissa, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_ptr, f80_layout.exponent_offset), + f80_layout.alignment.offset(f80_layout.exponent_offset), + exponent, + .u16, + .normal, + ); + }, + 128 => { + const f128_layout = o.softF128Layout(.{}) catch unreachable; + const lo = try fg.wip.cast(.trunc, shifted_value, .i64, "load.lo"); + const shifted_hi = try fg.wip.bin( + .lshr, + backing_int_val, + try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset + 64), + "load.shifted_hi", + ); + const hi = try fg.wip.cast(.trunc, shifted_hi, .i64, "load.hi"); + + try fg.store( + try fg.ptraddConst(result_ptr, f128_layout.lo_offset), + f128_layout.alignment.offset(f128_layout.lo_offset), + lo, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_ptr, f128_layout.hi_offset), + f128_layout.alignment.offset(f128_layout.hi_offset), + hi, + .u64, + .normal, + ); + }, + } + return result_ptr; + } + const elem_llvm_ty = try o.lowerType(elem_ty, .as_value); if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) { @@ -5848,95 +6134,25 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val ); } -/// Reduce a vector by repeatedly applying `llvm_fn` to produce an accumulated result. -/// -/// Equivalent to: -/// ``` -/// var accum: T = init; -/// for (0..i) |i| { -/// accum = llvm_fn(accum, vec[i]); -/// } -/// // result is 'accum' -/// ``` -fn buildReducedCall( - self: *FuncGen, - llvm_fn: Builder.Function.Index, - operand_vector: Builder.Value, - vector_len: usize, - accum_init: Builder.Value, -) Allocator.Error!Builder.Value { - const o = self.object; - const llvm_usize_ty = try o.lowerType(.usize, .as_value); - const llvm_vector_len = try o.builder.intValue(llvm_usize_ty, vector_len); - const llvm_result_ty = accum_init.typeOfWip(&self.wip); - - const entry_block = self.wip.cursor.block; - - const cond_block = try self.wip.block(2, "ReduceLoopCond"); - const body_block = try self.wip.block(1, "ReduceLoopBody"); - const exit_block = try self.wip.block(1, "ReduceLoopExit"); - - _ = try self.wip.br(cond_block); - - // ReduceLoopCond: - // %index = phi iN [0, %Entry], [%new_index, %ReduceLoopBody] - // %accum = phi T [%accum_init, %Entry], [%new_accum, %ReduceLoopBody] - // %cond = icmp ult iN %index, %vector_len - // br i1 %cond, label %ReduceLoopBody, label %ReduceLoopExit - self.wip.cursor = .{ .block = cond_block }; - const index = try self.wip.phi(llvm_usize_ty, ""); - const accum = try self.wip.phi(llvm_result_ty, ""); - const cond = try self.wip.icmp(.ult, index.toValue(), llvm_vector_len, ""); - _ = try self.wip.brCond(cond, body_block, exit_block, .none); - - // ReduceLoopBody: - // %elem = extractelement %operand_vec, iN %index - // %new_accum = call T @llvm_fn(T %accum, T %elem) - // %new_index = add nuw iN %index, 1 - // br label %ReduceLoopCond - self.wip.cursor = .{ .block = body_block }; - const elem = try self.wip.extractElement(operand_vector, index.toValue(), ""); - const new_accum = try self.wip.call( - .normal, - .ccc, - .none, - llvm_fn.typeOf(&o.builder), - llvm_fn.toValue(&o.builder), - &.{ accum.toValue(), elem }, - "", - ); - const new_index = try self.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(llvm_usize_ty, 1), ""); - _ = try self.wip.br(cond_block); - - const index_init = try o.builder.intValue(llvm_usize_ty, 0); - index.finish(&.{ index_init, new_index }, &.{ entry_block, body_block }, &self.wip); - accum.finish(&.{ accum_init, new_accum }, &.{ entry_block, body_block }, &self.wip); - - self.wip.cursor = .{ .block = exit_block }; - return accum.toValue(); -} - -fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { - const o = self.object; +fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { + const o = fg.object; const zcu = o.zcu; const target = zcu.getTarget(); - const reduce = self.air.instructions.items(.data)[@backingInt(inst)].reduce; - const operand = try self.resolveInst(reduce.operand); - const operand_ty = self.typeOf(reduce.operand); - const llvm_operand_ty = try o.lowerType(operand_ty, .as_value); - const scalar_ty = self.typeOfIndex(inst); - const llvm_scalar_ty = try o.lowerType(scalar_ty, .as_value); + const reduce = fg.air.instructions.items(.data)[@backingInt(inst)].reduce; + const operand = try fg.resolveInst(reduce.operand); + const operand_ty = fg.typeOf(reduce.operand); + const scalar_ty = fg.typeOfIndex(inst); switch (reduce.operation) { - .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { + .And, .Or, .Xor => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { .And => .@"vector.reduce.and", .Or => .@"vector.reduce.or", .Xor => .@"vector.reduce.xor", else => unreachable, - }, &.{llvm_operand_ty}, &.{operand}, ""), + }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), .Min, .Max => switch (scalar_ty.zigTypeTag(zcu)) { - .int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { + .int => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { .Min => if (scalar_ty.isSignedInt(zcu)) .@"vector.reduce.smin" else @@ -5946,29 +6162,29 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A else .@"vector.reduce.umax", else => unreachable, - }, &.{llvm_operand_ty}, &.{operand}, ""), + }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), .float => if (intrinsicsAllowed(scalar_ty, target)) - return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) { + return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) { .Min => .@"vector.reduce.fmin", .Max => .@"vector.reduce.fmax", else => unreachable, - }, &.{llvm_operand_ty}, &.{operand}, ""), + }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), else => unreachable, }, .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) { - .int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { + .int => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { .Add => .@"vector.reduce.add", .Mul => .@"vector.reduce.mul", else => unreachable, - }, &.{llvm_operand_ty}, &.{operand}, ""), + }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), .float => if (intrinsicsAllowed(scalar_ty, target)) - return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) { + return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) { .Add => .@"vector.reduce.fadd", .Mul => .@"vector.reduce.fmul", else => unreachable, - }, &.{llvm_operand_ty}, &.{ switch (reduce.operation) { - .Add => try o.builder.fpValue(llvm_scalar_ty, -0.0), - .Mul => try o.builder.fpValue(llvm_scalar_ty, 1.0), + }, &.{try o.lowerType(operand_ty, .as_value)}, &.{ switch (reduce.operation) { + .Add => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), -0.0), + .Mul => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), 1.0), else => unreachable, }, operand }, ""), else => unreachable, @@ -5986,62 +6202,119 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A libcFloatPrefix(float_bits), libcFloatSuffix(float_bits), }), .Add => try o.builder.strtabStringFmt("__add{s}f3", .{ - compilerRtFloatAbbrev(float_bits), + compilerRtFloatAbbrev(target, float_bits), }), .Mul => try o.builder.strtabStringFmt("__mul{s}f3", .{ - compilerRtFloatAbbrev(float_bits), + compilerRtFloatAbbrev(target, float_bits), }), else => unreachable, }; - - const libc_fn = try o.getLibcFunction(fn_name, &.{ llvm_scalar_ty, llvm_scalar_ty }, llvm_scalar_ty); - const init_val = switch (llvm_scalar_ty) { - .i16 => try o.builder.intValue(.i16, @as(i16, @bitCast( - @as(f16, switch (reduce.operation) { - .Min, .Max => std.math.nan(f16), - .Add => -0.0, - .Mul => 1.0, - else => unreachable, - }), - ))), - .i80 => try o.builder.intValue(.i80, @as(i80, @bitCast( - @as(f80, switch (reduce.operation) { - .Min, .Max => std.math.nan(f80), - .Add => -0.0, - .Mul => 1.0, - else => unreachable, - }), - ))), - .i128 => try o.builder.intValue(.i128, @as(i128, @bitCast( - @as(f128, switch (reduce.operation) { - .Min, .Max => std.math.nan(f128), - .Add => -0.0, - .Mul => 1.0, - else => unreachable, - }), - ))), + const fn_info: Object.FuncInfo = .{ + .cc = target.cCallingConvention().?, + .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() }, + .return_type = scalar_ty.toIntern(), + }; + const llvm_fn = try fg.object.getLibcFunction(fg.pt, fn_name, fn_info); + const init = switch (float_bits) { else => unreachable, + 16 => try o.f16Const(switch (reduce.operation) { + else => unreachable, + .Min, .Max => std.math.nan(f16), + .Add => -0.0, + .Mul => 1.0, + }), + 32 => try o.f32Const(switch (reduce.operation) { + else => unreachable, + .Min, .Max => std.math.nan(f32), + .Add => -0.0, + .Mul => 1.0, + }), + 64 => try o.f64Const(switch (reduce.operation) { + else => unreachable, + .Min, .Max => std.math.nan(f64), + .Add => -0.0, + .Mul => 1.0, + }), + 80 => try o.f80Const(switch (reduce.operation) { + else => unreachable, + .Min, .Max => std.math.nan(f80), + .Add => -0.0, + .Mul => 1.0, + }), + 128 => try o.f128Const(switch (reduce.operation) { + else => unreachable, + .Min, .Max => std.math.nan(f128), + .Add => -0.0, + .Mul => 1.0, + }), }; - return self.buildReducedCall(libc_fn, operand, operand_ty.vectorLen(zcu), init_val); + const iterations = operand_ty.vectorLen(zcu); + const is_by_ref = isByRef(operand_ty, zcu); + if (iterations > 1 and is_by_ref) { + const init_ref = try o.lowerConstRef(init, scalar_ty.abiAlignment(zcu).toLlvm()); + + const entry_block = fg.wip.cursor.block; + const loop_block = try fg.wip.block(2, "reduce.loop"); + const done_block = try fg.wip.block(1, "reduce.loop"); + + _ = try fg.wip.br(loop_block); + + fg.wip.cursor = .{ .block = loop_block }; + const index = try fg.wip.phi(.i32, "reduce.index"); + const result = try fg.wip.phi(.ptr, "reduce.result"); + + const rhs_elem_ptr = try fg.ptraddScaled(operand, index.toValue(), scalar_ty.abiSize(zcu)); + const rhs_elem = try fg.load(rhs_elem_ptr, .none, scalar_ty, .normal); + const next_result = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, &.{ result.toValue(), rhs_elem }); + + const next_index = try fg.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(.i32, 1), "reduce.next_index"); + index.finish(&.{ try o.builder.intValue(.i32, 0), next_index }, &.{ entry_block, loop_block }, &fg.wip); + result.finish(&.{ init_ref.toValue(), next_result }, &.{ entry_block, loop_block }, &fg.wip); + const is_done = try fg.wip.icmp(.eq, next_index, try o.builder.intValue(.i32, iterations), "reduce.is_done"); + _ = try fg.wip.brCond(is_done, done_block, loop_block, .none); + + fg.wip.cursor = .{ .block = done_block }; + return next_result; + } + var result = init.toValue(); + for (0..iterations) |index| { + const index_value = try o.builder.intValue(.i32, index); + const rhs_elem = if (is_by_ref) rhs_elem: { + const rhs_elem_ptr = try fg.ptraddConst(operand, index * scalar_ty.abiSize(zcu)); + break :rhs_elem try fg.load(rhs_elem_ptr, .none, scalar_ty, .normal); + } else try fg.wip.extractElement(operand, index_value, "reduce.rhs_elem"); + result = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, &.{ result, rhs_elem }); + } + return result; } -fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const o = self.object; +fn airAggregateInit(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { + const o = fg.object; const zcu = o.zcu; const ip = &zcu.intern_pool; - const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl; - const result_ty = self.typeOfIndex(inst); + const ty_pl = fg.air.instructions.items(.data)[@backingInt(inst)].ty_pl; + const result_ty = fg.typeOfIndex(inst); const len: usize = @intCast(result_ty.arrayLen(zcu)); - const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[ty_pl.payload..][0..len]); + const elements: []const Air.Inst.Ref = @ptrCast(fg.air.extra.items[ty_pl.payload..][0..len]); switch (result_ty.zigTypeTag(zcu)) { - .vector => { + .vector => if (isByRef(result_ty, zcu)) { + const elem_ty = result_ty.childType(zcu); + const elem_size = elem_ty.abiSize(zcu); + const result_ptr = try fg.buildZigAlloca(result_ty, .none); + for (elements, 0..) |elem, elem_index| { + const elem_ptr = try fg.ptraddConst(result_ptr, elem_index * elem_size); + const llvm_elem = try fg.resolveInst(elem); + try fg.store(elem_ptr, .none, llvm_elem, elem_ty, .normal); + } + return result_ptr; + } else { const llvm_result_ty = try o.lowerType(result_ty, .as_value); var vector = try o.builder.poisonValue(llvm_result_ty); - for (elements, 0..) |elem, i| { - const index_u32 = try o.builder.intValue(.i32, i); - const llvm_elem = try self.resolveInst(elem); - vector = try self.wip.insertElement(vector, llvm_elem, index_u32, ""); + for (elements, 0..) |elem, elem_index| { + const elem_index_val = try o.builder.intValue(.i32, elem_index); + const llvm_elem = try fg.resolveInst(elem); + vector = try fg.wip.insertElement(vector, llvm_elem, elem_index_val, ""); } return vector; }, @@ -6057,18 +6330,18 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde for (elements, struct_type.field_types.get(ip)) |elem, field_ty| { if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; - const non_int_val = try self.resolveInst(elem); + const non_int_val = try fg.resolveInst(elem); const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu)); const small_int_ty = try o.builder.intType(ty_bit_size); const small_int_val = if (Type.fromInterned(field_ty).isPtrAtRuntime(zcu)) - try self.wip.cast(.ptrtoint, non_int_val, small_int_ty, "") + try fg.wip.cast(.ptrtoint, non_int_val, small_int_ty, "") else - try self.wip.cast(.bitcast, non_int_val, small_int_ty, ""); + try fg.wip.cast(.bitcast, non_int_val, small_int_ty, ""); const shift_rhs = try o.builder.intValue(int_ty, running_bits); const extended_int_val = - try self.wip.conv(.unsigned, small_int_val, int_ty, ""); - const shifted = try self.wip.bin(.shl, extended_int_val, shift_rhs, ""); - running_int = try self.wip.bin(.@"or", running_int, shifted, ""); + try fg.wip.conv(.unsigned, small_int_val, int_ty, ""); + const shifted = try fg.wip.bin(.shl, extended_int_val, shift_rhs, ""); + running_int = try fg.wip.bin(.@"or", running_int, shifted, ""); running_bits += ty_bit_size; } return running_int; @@ -6078,19 +6351,19 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde // TODO in debug builds init to undef so that the padding will be 0xaa // even if we fully populate the fields. const struct_align = result_ty.abiAlignment(zcu); - const alloca_inst = try self.buildZigAlloca(result_ty, .none); + const alloca_inst = try fg.buildZigAlloca(result_ty, .none); for (elements, 0..) |elem, field_index| { if (result_ty.structFieldIsComptime(field_index, zcu)) continue; const field_ty = result_ty.fieldType(field_index, zcu); if (!field_ty.hasRuntimeBits(zcu)) continue; const offset = result_ty.structFieldOffset(field_index, zcu); - const field_ptr = try self.ptraddConst(alloca_inst, offset); + const field_ptr = try fg.ptraddConst(alloca_inst, offset); const field_ptr_align = struct_align.offset(offset); - const llvm_field_val = try self.resolveInst(elem); + const llvm_field_val = try fg.resolveInst(elem); - try self.store(field_ptr, field_ptr_align, llvm_field_val, field_ty, .normal); + try fg.store(field_ptr, field_ptr_align, llvm_field_val, field_ty, .normal); } return alloca_inst; @@ -6099,21 +6372,21 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde .array => { assert(isByRef(result_ty, zcu)); - const alloca_inst = try self.buildZigAlloca(result_ty, .none); + const alloca_inst = try fg.buildZigAlloca(result_ty, .none); const array_info = result_ty.arrayInfo(zcu); const elem_size = array_info.elem_type.abiSize(zcu); for (elements, 0..) |elem, i| { - const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * i); - const llvm_elem = try self.resolveInst(elem); - try self.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal); + const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * i); + const llvm_elem = try fg.resolveInst(elem); + try fg.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal); } if (array_info.sentinel) |sent_val| { - const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * array_info.len); - const llvm_elem = try self.resolveValue(sent_val); - try self.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal); + const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * array_info.len); + const llvm_elem = try fg.resolveValue(sent_val); + try fg.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal); } return alloca_inst; @@ -6469,26 +6742,12 @@ fn store( .unsigned => .zext, .signed => .sext, }, elem, llvm_memory_ty, ""); - _ = try fg.wip.storeAtomic( - access_kind, - extended, - ptr, - fg.sync_scope, - .none, - llvm_ptr_align, - ); + _ = try fg.wip.store(access_kind, extended, ptr, llvm_ptr_align); return; } // `elem_ty` is a simple by-val type which requires no special handling. - _ = try fg.wip.storeAtomic( - access_kind, - elem, - ptr, - fg.sync_scope, - .none, - llvm_ptr_align, - ); + _ = try fg.wip.store(access_kind, elem, ptr, llvm_ptr_align); } fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void { @@ -6650,7 +6909,8 @@ fn typeOfIndex(fg: *FuncGen, inst: Air.Inst.Index) Type { const ParamTypeIterator = struct { object: *Object, - fn_info: InternPool.Key.FuncType, + cc: std.lang.CallingConvention, + param_types: []const InternPool.Index, zig_index: u32, llvm_index: u32, types_len: u32, @@ -6672,63 +6932,66 @@ const ParamTypeIterator = struct { }; pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering { - if (it.zig_index >= it.fn_info.param_types.len) return null; - const ip = &it.object.zcu.intern_pool; - const ty = it.fn_info.param_types.get(ip)[it.zig_index]; + if (it.zig_index >= it.param_types.len) return null; + const ty = it.param_types[it.zig_index]; it.byval_attr = false; return nextInner(it, Type.fromInterned(ty)); } /// `airCall` uses this instead of `next` so that it can take into account variadic functions. - fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering { - const ip = &it.object.zcu.intern_pool; - if (it.zig_index >= it.fn_info.param_types.len) { - if (it.zig_index >= args.len) { + fn nextCall(it: *ParamTypeIterator, arg_types: []const InternPool.Index) Allocator.Error!?Lowering { + if (it.zig_index >= it.param_types.len) { + if (it.zig_index >= arg_types.len) { return null; } else { - return nextInner(it, fg.typeOf(args[it.zig_index])); + return nextInner(it, .fromInterned(arg_types[it.zig_index])); } } else { - return nextInner(it, Type.fromInterned(it.fn_info.param_types.get(ip)[it.zig_index])); + return nextInner(it, .fromInterned(it.param_types[it.zig_index])); } } fn nextInner(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering { const zcu = it.object.zcu; - const target = zcu.getTarget(); - + ty.assertHasLayout(zcu); if (!ty.hasRuntimeBits(zcu)) { it.zig_index += 1; return .no_bits; } - switch (it.fn_info.cc) { + switch (it.cc) { .@"inline" => unreachable, .auto => { it.zig_index += 1; it.llvm_index += 1; + + // Match the c calling convention in some cases to avoid llvm bugs. + const target = zcu.getTarget(); + if (target.cpu.arch == .x86_64 and ty.isVector(zcu) and ty.childType(zcu).toIntern() == .bool_type) return switch (ty.vectorLen(zcu)) { + 0 => .no_bits, + 1...32 => .abi_sized_int, + 33...64 => { + it.types_buffer[0..1].* = .{.double}; + it.offsets_buffer[0..2].* = .{ 0, 8 }; + it.types_len = 1; + return .multiple_llvm_types; + }, + else => .byval, + }; + if (ty.isSlice(zcu) or (ty.zigTypeTag(zcu) == .optional and ty.optionalChild(zcu).isSlice(zcu) and !ty.ptrAllowsZero(zcu))) { it.llvm_index += 1; return .slice; - } else if (isByRef(ty, zcu)) { - return .byref; - } else if (target.cpu.arch.isX86() and - !target.cpu.has(.x86, .avx512f) and - ty.totalVectorBits(zcu) >= 512) - { - // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns - // "512-bit vector arguments require 'avx512f' for AVX512" - return .byref; - } else { - return .byval; } + if (isByRef(ty, zcu)) return .byref; + return .byval; }, .async => { @panic("TODO implement async function lowering in the LLVM backend"); }, - .x86_64_sysv, .x86_64_x32 => return it.nextSystemV(ty), - .x86_64_win => return it.nextWin64(ty), + .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty), + .x86_64_win => return it.next_x86_64_win(ty), .x86_stdcall => { it.zig_index += 1; it.llvm_index += 1; @@ -6748,9 +7011,9 @@ const ParamTypeIterator = struct { .float_array => |len| return Lowering{ .float_array = len }, .byval => return .byval, .integer => { - it.types_len = 1; it.types_buffer[0..1].* = .{.i64}; it.offsets_buffer[0..2].* = .{ 0, 8 }; + it.types_len = 1; return .multiple_llvm_types; }, .double_integer => return Lowering{ .i64_array = 2 }, @@ -6857,7 +7120,7 @@ const ParamTypeIterator = struct { } } - fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering { + fn next_x86_64_win(it: *ParamTypeIterator, ty: Type) Lowering { const zcu = it.object.zcu; switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget(), .arg)) { .integer => { @@ -6898,113 +7161,108 @@ const ParamTypeIterator = struct { } } - fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering { - const zcu = it.object.zcu; - const ip = &zcu.intern_pool; - ty.assertHasLayout(zcu); - const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg); - if (classes[0] == .memory) { - it.zig_index += 1; - it.llvm_index += 1; - it.byval_attr = true; - return .byref; - } - if (isScalar(zcu, ty)) { - it.zig_index += 1; - it.llvm_index += 1; - return .byval; - } - var types_index: u32 = 0; - var offset: u64 = 0; - for (classes) |class| { - switch (class) { - .integer => { - it.types_buffer[types_index] = .i64; - it.offsets_buffer[types_index] = offset; - types_index += 1; - }, - .sse => { - it.types_buffer[types_index] = .double; - it.offsets_buffer[types_index] = offset; - types_index += 1; - }, - .sseup => { - if (it.types_buffer[types_index - 1] == .double) { - it.types_buffer[types_index - 1] = .fp128; - } else { - it.types_buffer[types_index] = .double; - it.offsets_buffer[types_index] = offset; - types_index += 1; + fn next_x86_64_sysv(it: *ParamTypeIterator, ty: Type) Allocator.Error!Lowering { + const o = it.object; + const zcu = o.zcu; + const target = zcu.getTarget(); + const classes = x86_64_abi.classifySystemV(ty, zcu, target, .arg); + var types_len: u32 = 0; + const classes_len = for (classes, 0..) |class, class_index| switch (class) { + .integer => { + it.types_buffer[types_len] = try o.builder.intType(@min(8 * ty.abiSize(zcu) - 64 * class_index, 64)); + it.offsets_buffer[types_len] = 8 * class_index; + types_len += 1; + }, + .sse => { + it.types_buffer[types_len] = .double; + it.offsets_buffer[types_len] = 8 * class_index; + types_len += 1; + }, + .sseup => { + if (it.types_buffer[types_len - 1] == .double) { + if (ty.isVector(zcu)) { + it.zig_index += 1; + it.llvm_index += 1; + return .byval; } - }, - .float => { - it.types_buffer[types_index] = .float; - it.offsets_buffer[types_index] = offset; - types_index += 1; - }, - .float_combine => { - it.types_buffer[types_index] = try it.object.builder.vectorType(.normal, 2, .float); - it.offsets_buffer[types_index] = offset; - types_index += 1; - }, - .x87 => { - it.zig_index += 1; - it.llvm_index += 1; - it.byval_attr = true; - return .byref; - }, - .x87up => unreachable, - .none => break, - .memory => unreachable, // handled above - .win_i128 => unreachable, // windows only - .bool_vector_mask, - .integer_per_element, - .sse_per_element, - .sse_sse_x87_per_qword, - .sse_per_xword, - .sse_per_yword, - .sse_per_zword, - => unreachable, // vectors already handled by `isScalar` above - } - offset += 8; - } - const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer}); - if (first_non_integer == null or classes[first_non_integer.?] == .none) { - assert(first_non_integer orelse classes.len == types_index); - if (types_index == 1) { + it.types_buffer[types_len - 1] = .fp128; + } else { + it.types_buffer[types_len] = .double; + it.offsets_buffer[types_len] = 8 * class_index; + types_len += 1; + } + }, + .float => { + it.types_buffer[types_len] = .float; + it.offsets_buffer[types_len] = 8 * class_index; + types_len += 1; + }, + .float_combine => { + it.types_buffer[types_len] = try it.object.builder.vectorType(.normal, 2, .float); + it.offsets_buffer[types_len] = 8 * class_index; + types_len += 1; + }, + .x87 => { it.zig_index += 1; it.llvm_index += 1; - return .abi_sized_int; - } - if (it.llvm_index + types_index > 6) { + it.byval_attr = true; + return .byref; + }, + .x87up => unreachable, + .none => break class_index, + .memory => { + it.zig_index += 1; + it.llvm_index += 1; + it.byval_attr = true; + return .byref; + }, + .win_i128 => unreachable, // windows only + .bool_vector_mask, + .integer_per_element, + .sse_per_element, + .sse_sse_x87_per_qword, + .sse_per_xword, + .sse_per_yword, + .sse_per_zword, + => { + it.zig_index += 1; + it.llvm_index += 1; + return .byval; + }, + } else classes.len; + if (types_len > 1) { + if (it.llvm_index + classes_len > 6) { it.zig_index += 1; it.llvm_index += 1; it.byval_attr = true; return .byref; } - switch (ip.indexToKey(ty.toIntern())) { - .struct_type => { - const size = ty.abiSize(zcu); - assert(@divCeil(size, 8) == types_index); - if (size % 8 > 0) { - it.types_buffer[types_index - 1] = - try it.object.builder.intType(@intCast(size % 8 * 8)); - } - }, - else => {}, + } else if (!isByRef(ty, zcu)) { + const llvm_ty = try o.lowerType(ty, .as_value); + if (it.types_buffer[0] == llvm_ty or + (it.types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder))) + { + it.zig_index += 1; + it.llvm_index += 1; + return .byval; } } - it.offsets_buffer[types_index] = offset; - it.types_len = types_index; - it.llvm_index += types_index; + it.offsets_buffer[types_len] = 8 * classes_len; + it.types_len = types_len; + it.llvm_index += types_len; it.zig_index += 1; return .multiple_llvm_types; } }; -pub fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTypeIterator { +pub fn iterateParamTypes( + object: *Object, + cc: std.lang.CallingConvention, + param_types: []const InternPool.Index, +) ParamTypeIterator { return .{ .object = object, - .fn_info = fn_info, + .cc = cc, + .param_types = param_types, .zig_index = 0, .llvm_index = 0, .types_len = undefined, @@ -7035,35 +7293,34 @@ pub const FnReturnStrat = union(enum) { /// In order to support the C calling convention, some return types need to be lowered /// completely differently in the function prototype to honor the C ABI, and then /// be effectively bitcasted to the actual return type. -pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat { +pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) Allocator.Error!FnReturnStrat { const zcu = o.zcu; - const ret_ty: Type = .fromInterned(fn_info.return_type); ret_ty.assertHasLayout(zcu); if (!ret_ty.hasRuntimeBits(zcu)) return .void; - switch (fn_info.cc) { + switch (cc) { .@"inline" => unreachable, .auto => { + // Match the c calling convention in some cases to avoid llvm bugs. + const target = zcu.getTarget(); + if (target.cpu.arch == .x86_64 and ret_ty.isVector(zcu) and ret_ty.childType(zcu).toIntern() == .bool_type) return switch (ret_ty.vectorLen(zcu)) { + 0 => .void, + 1...8 => .{ .mem_cast = .i8 }, + 9...16 => .{ .mem_cast = .i16 }, + 17...32 => .{ .mem_cast = .i32 }, + 33...64 => .{ .mem_cast = .double }, + else => .by_val, + }; + if (isByRef(ret_ty, zcu)) return .sret; - - const target = zcu.getTarget(); - if (target.cpu.arch.isX86() and - !target.cpu.has(.x86, .avx512f) and - ret_ty.totalVectorBits(zcu) >= 512) - { - // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns - // "512-bit vector arguments require 'avx512f' for AVX512" - return .sret; - } - return .by_val; }, - .x86_64_sysv, .x86_64_x32 => return lowerSystemVFnRetTy(o, fn_info), - .x86_64_win => return lowerWin64FnRetTy(o, fn_info), + .x86_64_sysv, .x86_64_x32 => return fnReturnStrat_x86_64_sysv(o, ret_ty), + .x86_64_win => return fnReturnStrat_x86_64_win(o, ret_ty), .x86_stdcall => if (isScalar(zcu, ret_ty)) { assert(!isByRef(ret_ty, zcu)); return .by_val; } else return .sret, - .x86_fastcall => return lowerX86FastcallFnRetTy(o, zcu, ret_ty), + .x86_fastcall => return fnReturnStrat_x86_fastcall(o, zcu, ret_ty), .x86_sysv, .x86_win => return if (isByRef(ret_ty, zcu)) .sret else .by_val, .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(ret_ty, zcu)) { .memory => return .sret, @@ -7124,7 +7381,7 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err } } -fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat { +fn fnReturnStrat_x86_fastcall(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat { if (isScalar(zcu, ty)) { assert(!isByRef(ty, zcu)); return .by_val; @@ -7139,9 +7396,8 @@ fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnRe return .sret; } -fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat { +fn fnReturnStrat_x86_64_win(o: *Object, ret_ty: Type) Allocator.Error!FnReturnStrat { const zcu = o.zcu; - const ret_ty = Type.fromInterned(fn_info.return_type); switch (x86_64_abi.classifyWindows(ret_ty, zcu, zcu.getTarget(), .ret)) { .integer => if (isScalar(zcu, ret_ty)) { assert(!isByRef(ret_ty, zcu)); @@ -7174,78 +7430,65 @@ fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err } } -fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat { +fn fnReturnStrat_x86_64_sysv(o: *Object, ret_ty: Type) Allocator.Error!FnReturnStrat { const zcu = o.zcu; - const ip = &zcu.intern_pool; - const ret_ty = Type.fromInterned(fn_info.return_type); - if (isScalar(zcu, ret_ty)) { - assert(!isByRef(ret_ty, zcu)); - return .by_val; - } const classes = x86_64_abi.classifySystemV(ret_ty, zcu, zcu.getTarget(), .ret); - var types_index: u32 = 0; var types_buffer: [8]Builder.Type = undefined; - for (classes) |class| { - switch (class) { - .integer => { - types_buffer[types_index] = .i64; - types_index += 1; - }, - .sse => { - types_buffer[types_index] = .double; - types_index += 1; - }, - .sseup => { - if (types_buffer[types_index - 1] == .double) { - types_buffer[types_index - 1] = .fp128; - } else { - types_buffer[types_index] = .double; - types_index += 1; - } - }, - .float => { - types_buffer[types_index] = .float; - types_index += 1; - }, - .float_combine => { - types_buffer[types_index] = try o.builder.vectorType(.normal, 2, .float); - types_index += 1; - }, - .x87 => { - if (types_index != 0 or classes[2] != .none) return .sret; - types_buffer[types_index] = .x86_fp80; - types_index += 1; - }, - .x87up => continue, - .none => break, - .memory => return .sret, - .win_i128 => unreachable, // windows only - .bool_vector_mask, - .integer_per_element, - .sse_per_element, - .sse_sse_x87_per_qword, - .sse_per_xword, - .sse_per_yword, - .sse_per_zword, - => unreachable, // vectors already handled by `isScalar` above - } + var types_len: u32 = 0; + for (classes, 0..) |class, class_index| switch (class) { + .integer => { + types_buffer[types_len] = try o.builder.intType(@min(8 * ret_ty.abiSize(zcu) - 64 * class_index, 64)); + types_len += 1; + }, + .sse => { + types_buffer[types_len] = .double; + types_len += 1; + }, + .sseup => { + if (types_buffer[types_len - 1] == .double) { + if (ret_ty.isVector(zcu)) return .by_val; + types_buffer[types_len - 1] = .fp128; + } else { + types_buffer[types_len] = .double; + types_len += 1; + } + }, + .float => { + types_buffer[types_len] = .float; + types_len += 1; + }, + .float_combine => { + types_buffer[types_len] = try o.builder.vectorType(.normal, 2, .float); + types_len += 1; + }, + .x87 => { + if (types_len > 0 or classes[2] != .none) return .sret; + types_buffer[types_len] = .x86_fp80; + types_len += 1; + }, + .x87up => continue, + .none => break, + .memory => return if (ret_ty.isVector(zcu)) .by_val else .sret, + .win_i128 => unreachable, // windows only + .bool_vector_mask, + .integer_per_element, + .sse_per_element, + .sse_sse_x87_per_qword, + .sse_per_xword, + .sse_per_yword, + .sse_per_zword, + => return .by_val, + }; + if (types_len > 1) return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_len]) }; + if (!isByRef(ret_ty, zcu)) { + const llvm_ty = try o.lowerType(ret_ty, .as_value); + if (types_buffer[0] == llvm_ty) return .by_val; + if (types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder)) return .by_val; + if (types_buffer[0] == .double and llvm_ty.isVector(&o.builder) and + llvm_ty.vectorLen(&o.builder) == 1 and + llvm_ty.scalarType(&o.builder) == .double) return .by_val; } - const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer}); - if (first_non_integer == null or classes[first_non_integer.?] == .none) { - assert(first_non_integer orelse classes.len == types_index); - switch (ip.indexToKey(ret_ty.toIntern())) { - .struct_type => { - const size = ret_ty.abiSize(zcu); - assert(@divCeil(size, 8) == types_index); - if (size % 8 > 0) { - types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8)); - } - }, - else => {}, - } - if (types_index == 1) return .{ .mem_cast = types_buffer[0] }; - } - return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_index]) }; + return .{ .mem_cast = types_buffer[0] }; } /// This function deliberately does not handle `_BitInt` because it typically @@ -7258,15 +7501,22 @@ pub fn ccAbiPromoteInt(cc: std.lang.CallingConvention, zcu: *Zcu, ty: Type) ?std else => {}, } - const ty_tag = ty.zigTypeTag(zcu); - const int_info = switch (ty_tag) { - .bool => Type.u1.intInfo(zcu), - else => if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else return null, - }; - - assert(int_info.bits == 0 or (int_info.bits == 1 and ty_tag == .bool) or std.math.isPowerOfTwo(int_info.bits)); - const target = zcu.getTarget(); + const int_info: std.lang.Type.Int = if (ty.toIntern() == .bool_type) + .{ .signedness = .unsigned, .bits = 1 } + else if (ty.isAbiInt(zcu)) + ty.intInfo(zcu) + else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) { + else => unreachable, + 16, 32, 64 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => return null, + .soft => .{ .signedness = .unsigned, .bits = bits }, + }, + 80, 128 => return null, + } else return null; + + assert(int_info.bits == 0 or (int_info.bits == 1 and ty.toIntern() == .bool_type) or std.math.isPowerOfTwo(int_info.bits)); + return switch (target.cpu.arch) { .aarch64, .aarch64_be, @@ -7362,15 +7612,26 @@ pub fn isByRef(ty: Type, zcu: *const Zcu) bool { .void, .bool, .int, - .float, .pointer, .error_set, .@"fn", .@"enum", - .vector, .@"anyframe", => false, + .float, .vector => { + const target = zcu.getTarget(); + const scalar_ty = ty.scalarType(zcu); + return if (scalar_ty.isRuntimeFloat()) switch (scalar_ty.floatBits(target)) { + else => unreachable, + 16, 32, 64 => false, + 80, 128 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => false, + .soft => true, + }, + } else false; + }, + .array, .frame, => ty.hasRuntimeBits(zcu), @@ -7431,12 +7692,19 @@ fn ptraddScaled(fg: *FuncGen, ptr: Builder.Value, index: Builder.Value, scale: u return fg.wip.gep(.inbounds, llvm_scale_ty, ptr, &.{index}, ""); } -fn compilerRtIntBits(bits: u16) ?u16 { - inline for (.{ 32, 64, 128 }) |b| { - if (bits <= b) { - return b; - } - } +fn compilerRtPromoteInt(int_info: InternPool.Key.IntType) ?Type { + if (int_info.bits <= 32) return switch (int_info.signedness) { + .signed => .i32, + .unsigned => .u32, + }; + if (int_info.bits <= 64) return switch (int_info.signedness) { + .signed => .i64, + .unsigned => .u64, + }; + if (int_info.bits <= 128) return switch (int_info.signedness) { + .signed => .i128, + .unsigned => .u128, + }; return null; } @@ -7495,13 +7763,12 @@ fn appendConstraints( } /// LLVM does not support all relevant intrinsics for all targets, so we -/// may need to manually generate a compiler-rt call. +/// may need to manually generate a compiler-rt call using a soft type. fn intrinsicsAllowed(scalar_ty: Type, target: *const std.Target) bool { - return switch (scalar_ty.toIntern()) { - .f16_type => llvm.backendSupportsF16(target), - .f80_type => (target.cTypeBitSize(.longdouble) == 80) and llvm.backendSupportsF80(target), - .f128_type => (target.cTypeBitSize(.longdouble) == 128) and llvm.backendSupportsF128(target), - else => true, + if (!scalar_ty.isRuntimeFloat()) return true; + return switch (std.zig.target.compilerRtFloatAbi(target, scalar_ty.floatBits(target))) { + .hard => true, + .soft => false, }; } diff --git a/src/codegen/mips/abi.zig b/src/codegen/mips/abi.zig index f512f1e6db98031dd581bc9cb19ef7be42b7ae29..e7c07582030cc16d73f07b0d56d56f09f0607a0f 100644 --- a/src/codegen/mips/abi.zig +++ b/src/codegen/mips/abi.zig @@ -38,7 +38,14 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { return .byval; }, .bool => return .byval, - .float => return .byval, + .float => return switch (ty.floatBits(target)) { + else => unreachable, + 16, 32, 64 => .byval, + 80, 128 => switch (max_direct_size) { + else => unreachable, + 64 => .memory, + }, + }, .int, .@"enum", .error_set => { return .byval; }, diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index 4ee131d079c666a52516e480137782e44f45a553..aed925be2953ddfb56581b9bb5eef521e8b78507 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -5036,7 +5036,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void { .register_pair, => { if (ret_ty.isVector(zcu)) { - const bit_size = ret_ty.totalVectorBits(zcu); + const bit_size = ret_ty.bitSize(zcu); // set the vtype to hold the entire vector's contents in a single element try func.setVl(.zero, 0, .{ @@ -6871,7 +6871,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! // size to the total size of the vector, and vmv.x.s will work then if (src_reg.class() == .vector) { try func.setVl(.zero, 0, .{ - .vsew = switch (ty.totalVectorBits(zcu)) { + .vsew = switch (ty.bitSize(zcu)) { 8 => .@"8", 16 => .@"16", 32 => .@"32", diff --git a/src/codegen/riscv64/abi.zig b/src/codegen/riscv64/abi.zig index 5c89a35f7bd4e718e8e032093856f6068b751c9b..154118c50c98572fea63fcc00986c7cc338b3ca6 100644 --- a/src/codegen/riscv64/abi.zig +++ b/src/codegen/riscv64/abi.zig @@ -56,12 +56,20 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { return .integer; }, .bool => return .integer, - .float => return .byval, .int, .@"enum", .error_set => { const bit_size = ty.bitSize(zcu); if (bit_size > max_byval_size) return .memory; return .byval; }, + .float => return switch (ty.floatBits(target)) { + else => unreachable, + 16, 32, 64, 128 => .byval, + 80 => switch (max_byval_size) { + else => unreachable, + 64 => .memory, + 128 => .double_integer, + }, + }, .vector => { const bit_size = ty.bitSize(zcu); if (bit_size > max_byval_size) return .memory; @@ -190,7 +198,7 @@ pub fn classifySystem(ty: Type, zcu: *Zcu) [8]SystemClass { }, .vector => { // we pass vectors through integer registers if they are small enough to fit. - const vec_bits = ty.totalVectorBits(zcu); + const vec_bits = ty.bitSize(zcu); if (vec_bits <= 64) { result[0] = .integer; return result; diff --git a/src/codegen/s390x/abi.zig b/src/codegen/s390x/abi.zig index 6fb81d3e6b8792566b9c69156ca63a67ed788299..7b35245fdad37be5e062bbcc873c116a78a99152 100644 --- a/src/codegen/s390x/abi.zig +++ b/src/codegen/s390x/abi.zig @@ -38,9 +38,11 @@ pub fn classifyType(ty: Type, context: Context, zcu: *Zcu) Class { 1...64 => .simple, else => .pointer, }, - .float => return switch (ty.floatBits(zcu.getTarget())) { - 16, 32, 64 => .double_or_float, - else => .pointer, + .float => switch (ty.floatBits(zcu.getTarget())) { + else => unreachable, + 16, 32, 64 => return .double_or_float, + 80 => {}, + 128 => return .pointer, }, .pointer, .optional => return .simple, .array => switch (ty.arrayLen(zcu)) { diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index 3dc36619686e53a6112e3cc81ec9ccd3f902e0c6..2848a5f2573c75c73036aa2ff19f583403a9085f 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -24,12 +24,6 @@ const Alignment = InternPool.Alignment; const errUnionPayloadOffset = codegen.errUnionPayloadOffset; const errUnionErrorOffset = codegen.errUnionErrorOffset; -const target_util = @import("../../target.zig"); -const libcFloatPrefix = target_util.libcFloatPrefix; -const libcFloatSuffix = target_util.libcFloatSuffix; -const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev; -const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; - pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { return comptime &.initMany(&.{ .expand_bit_cast_safe, @@ -2515,15 +2509,15 @@ const IntType = struct { .anyerror, .adhoc_inferred_error_set => .{ .is_signed = false, .bits = zcu.errorSetBits() }, .isize => .{ .is_signed = true, .bits = cg.target.ptrBitWidth() }, .usize => .{ .is_signed = false, .bits = cg.target.ptrBitWidth() }, - .c_char => .{ .is_signed = cg.target.cCharSignedness() == .signed, .bits = cg.target.cTypeBitSize(.char) }, - .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short) }, - .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short) }, - .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int) }, - .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int) }, - .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long) }, - .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long) }, - .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong) }, - .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong) }, + .c_char => .{ .is_signed = cg.target.cCharSignedness().? == .signed, .bits = cg.target.cTypeBitSize(.char).? }, + .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short).? }, + .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short).? }, + .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int).? }, + .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int).? }, + .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long).? }, + .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long).? }, + .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong).? }, + .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong).? }, .f16, .f32, .f64, .f80, .f128, .c_longdouble => unreachable, .anyopaque, .void, .type, .comptime_int, .comptime_float, .noreturn, .null, .undefined, .enum_literal, .generic_poison => unreachable, }, diff --git a/src/codegen/wasm/abi.zig b/src/codegen/wasm/abi.zig index 7a643e8dc7a755937f096f9826e5d770c2394b42..244b2c7719476ffa1542ce5863c11ac62c3c36de 100644 --- a/src/codegen/wasm/abi.zig +++ b/src/codegen/wasm/abi.zig @@ -25,7 +25,11 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { assert(ty.hasRuntimeBits(zcu)); switch (ty.zigTypeTag(zcu)) { .int, .@"enum", .error_set => return .{ .direct = ty }, - .float => return .{ .direct = ty }, + .float => return switch (ty.floatBits(zcu.getTarget())) { + else => unreachable, + 16, 32, 64, 128 => .{ .direct = ty }, + 80 => .indirect, + }, .bool => return .{ .direct = ty }, .vector => return .{ .direct = ty }, .array => return .indirect, diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index da82d324608abdc1a1dabc4c691c41b4f9c470d5..662fc600b1e863b89bdfc0f8719545786ac64dac 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -182636,15 +182636,15 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.lang.Type.Int { .anyerror => .{ .signedness = .unsigned, .bits = zcu.errorSetBits() }, .isize => .{ .signedness = .signed, .bits = cg.target.ptrBitWidth() }, .usize => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() }, - .c_char => .{ .signedness = cg.target.cCharSignedness(), .bits = cg.target.cTypeBitSize(.char) }, - .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short) }, - .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short) }, - .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int) }, - .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int) }, - .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long) }, - .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long) }, - .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong) }, - .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong) }, + .c_char => .{ .signedness = cg.target.cCharSignedness().?, .bits = cg.target.cTypeBitSize(.char).? }, + .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short).? }, + .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short).? }, + .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int).? }, + .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int).? }, + .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long).? }, + .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long).? }, + .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong).? }, + .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong).? }, .f16, .f32, .f64, .f80, .f128, .c_longdouble => null, .anyopaque, .void, diff --git a/src/codegen/x86_64/abi.zig b/src/codegen/x86_64/abi.zig index 3e7a9a548d54baee16d64a54de9a42c4650f7ea5..0bff5bd60a2f7e918dda9fd5835d653378686cff 100644 --- a/src/codegen/x86_64/abi.zig +++ b/src/codegen/x86_64/abi.zig @@ -133,7 +133,7 @@ pub fn classifyWindows(init_ty: Type, zcu: *Zcu, target: *const std.Target, ctx: .float => switch (ty.floatBits(target)) { 16, 32, 64 => .sse, 80 => .memory, - 128 => if (ctx == .arg) .memory else .sse, + 128 => .win_i128, else => unreachable, }, .vector => { @@ -238,16 +238,18 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont }; const unaligned_size = elem_ty.abiSize(zcu) * len; if (unaligned_size <= 4) return Class.one_integer; - if (ctx == .arg and unaligned_size == 8 * 1 * 1 and len == 1 and - elem_ty.isRuntimeFloat()) return Class.stack; // what + if (unaligned_size == 8 * 1 * 1 and len == 1) { + if (ctx == .arg and elem_ty.isRuntimeFloat()) return Class.stack; // what? + if (ctx != .other and !elem_ty.isRuntimeFloat() and target.os.tag == .freebsd) return Class.one_integer; // who? + } if (unaligned_size <= 8 * 1) return .{ .sse, .none, .none, .none, .none, .none, .none, .none }; if (unaligned_size <= 8 * 2) return .{ .sse, .sseup, .none, .none, .none, .none, .none, .none }; if (!target.cpu.has(.x86, .avx)) { if (ctx == .ret) switch (unaligned_size) { else => {}, 8 * 3 => if (len == 3) return if (elem_ty.isRuntimeFloat()) .{ - .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how - } else Class.len_integers, // why + .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how? + } else Class.len_integers, // why? 8 * 2 * 2, 8 * 2 * 4 => return .{ .sse_per_xword, .none, .none, .none, .none, .none, .none, .none }, }; return Class.stack; diff --git a/src/libs/mingw/Preprocessor.zig b/src/libs/mingw/Preprocessor.zig index dcf8e01d043dbc6790aeff839718fd65b5e621cd..9098b6013a4179ba15de85707d70d290f09bd116 100644 --- a/src/libs/mingw/Preprocessor.zig +++ b/src/libs/mingw/Preprocessor.zig @@ -91,9 +91,9 @@ fn addTokenAssumeCapacity(pp: *Preprocessor, tok: Token) void { fn defineBuiltins(pp: *Preprocessor) !void { var buf: [5]u8 = undefined; - var val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeBitSize(.longdouble)}) catch unreachable; + var val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeByteSize(.longdouble).?}) catch unreachable; try pp.defineBuiltinValue("__SIZEOF_LONG_DOUBLE__", val, .pp_num); - val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeBitSize(.double)}) catch unreachable; + val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeByteSize(.double).?}) catch unreachable; try pp.defineBuiltinValue("__SIZEOF_DOUBLE__", val, .pp_num); if (pp.target.abi.isGnu()) { diff --git a/src/target.zig b/src/target.zig index e249be39947d8d99f6f9eef6bd15b271887625fe..b4dc16b3185bb4e60ec99d93e2a39595f815eeed 100644 --- a/src/target.zig +++ b/src/target.zig @@ -881,13 +881,13 @@ pub fn libcFloatSuffix(float_bits: u16) []const u8 { }; } -pub fn compilerRtFloatAbbrev(float_bits: u16) []const u8 { +pub fn compilerRtFloatAbbrev(target: *const std.Target, float_bits: u16) []const u8 { return switch (float_bits) { 16 => "h", 32 => "s", 64 => "d", 80 => "x", - 128 => "t", + 128 => if (target.cpu.arch.isPowerPC()) "k" else "t", else => unreachable, }; } diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 957ac6b1796c3ce962c139fc3669c4760c8ede87..d79d2d07ba75c4660478753dc4d9a23d48fdfe2c 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -129,8 +129,7 @@ test "alignment and size of structs with 128-bit fields" { y: u8, }; const expected = switch (builtin.cpu.arch) { - .s390x, - => .{ + .s390x => .{ .a_align = 8, .a_size = 16, @@ -142,7 +141,32 @@ test "alignment and size of structs with 128-bit fields" { .u129_align = 8, .u129_size = 24, }, + .x86 => switch (builtin.os.tag) { + else => .{ + .a_align = 4, + .a_size = 16, + .b_align = 4, + .b_size = 20, + + .u128_align = 4, + .u128_size = 16, + .u129_align = 4, + .u129_size = 20, + }, + .uefi, .windows => .{ + .a_align = 8, + .a_size = 16, + + .b_align = 8, + .b_size = 24, + + .u128_align = 8, + .u128_size = 16, + .u129_align = 8, + .u129_size = 24, + }, + }, .amdgcn, .arm, .armeb, @@ -155,12 +179,13 @@ test "alignment and size of structs with 128-bit fields" { .powerpc, .powerpcle, .riscv32, + .sparc, => .{ .a_align = 8, .a_size = 16, - .b_align = 16, - .b_size = 32, + .b_align = 8, + .b_size = 24, .u128_align = 8, .u128_size = 16, @@ -178,12 +203,10 @@ test "alignment and size of structs with 128-bit fields" { .nvptx64, .powerpc64, .powerpc64le, - .sparc, .sparc64, .riscv64, .wasm32, .wasm64, - .x86, .x86_64, => .{ .a_align = 16, @@ -200,12 +223,11 @@ test "alignment and size of structs with 128-bit fields" { else => return error.SkipZigTest, }; - const min_struct_align = if (builtin.zig_backend == .stage2_c) if (builtin.cpu.arch == .s390x) 8 else 16 else 0; comptime { - assert(@alignOf(A) == @max(expected.a_align, min_struct_align)); + assert(@alignOf(A) == expected.a_align); assert(@sizeOf(A) == expected.a_size); - assert(@alignOf(B) == @max(expected.b_align, min_struct_align)); + assert(@alignOf(B) == expected.b_align); assert(@sizeOf(B) == expected.b_size); assert(@alignOf(u128) == expected.u128_align); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 4cbe2f1aed593d513d58691ec7baf5613494f9e7..697da63db23d14bb9e583745c80c8aca350d8a8d 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -181,6 +181,7 @@ test "@floatFromInt(f80)" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; const S = struct { fn doTheTest(comptime Int: type) !void { @@ -204,7 +205,7 @@ test "@floatFromInt(f80)" { try S.doTheTest(i64); try S.doTheTest(i80); try S.doTheTest(i128); - // try S.doTheTest(i256); // TODO missing compiler_rt symbols + try S.doTheTest(i256); try comptime S.doTheTest(i31); try comptime S.doTheTest(i32); try comptime S.doTheTest(i45); diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 7e9f58e46b0cfa6632234c2136344da6240f468f..ea01c8a88fe3ebf590d71027a7a5516cd57eeedb 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -118,7 +118,6 @@ fn testMul(comptime T: type) !void { test "cmp f16" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 try testCmp(f16); try comptime testCmp(f16); @@ -127,7 +126,6 @@ test "cmp f16" { test "cmp f32" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 try testCmp(f32); try comptime testCmp(f32); @@ -1173,11 +1171,6 @@ test "@floor f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12602 - return error.SkipZigTest; - } - try testFloor(f80); try comptime testFloor(f80); try testFloor(f128); @@ -1261,11 +1254,6 @@ test "@ceil f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12602 - return error.SkipZigTest; - } - try testCeil(f80); try comptime testCeil(f80); try testCeil(f128); @@ -1280,11 +1268,6 @@ test "@ceil f80 maxInt(u64)" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12602 - return error.SkipZigTest; - } - var x: u64 = std.math.maxInt(u64); x = x; const float: f80 = @floatFromInt(x); @@ -1366,11 +1349,6 @@ test "@trunc f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12602 - return error.SkipZigTest; - } - try testTrunc(f80); try comptime testTrunc(f80); try testTrunc(f128); diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 8750c7723149a9c772ec2dae6aaeda0b4ba03f8b..e76ca9850f3ce2bc9ca356910e76407dfae07fb1 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -2142,11 +2142,6 @@ test "remainder division" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12602 - return error.SkipZigTest; - } - if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest; try comptime remdiv(f16); @@ -2337,7 +2332,6 @@ test "NaN comparison" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 try testNanEqNan(f16); try testNanEqNan(f32); diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 9f8d277774f278dd2e7ee138e5d54e52fbfaa491..5838231e75ed214364a9a1af0527e5b9e480eaa9 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -774,6 +774,8 @@ test "vector reduce operation" { try testReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9)); try testReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9)); try testReduce(.Add, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 42.9)); + try testReduce(.Add, [4]f80{ -1.9, 5.1, -60.3, 100.0 }, @as(f80, 42.9)); + try testReduce(.Add, [4]f128{ -1.9, 5.1, -60.3, 100.0 }, @as(f128, 42.9)); try testReduce(.And, [4]bool{ true, false, true, true }, @as(bool, false)); try testReduce(.And, [4]u1{ 1, 0, 1, 1 }, @as(u1, 0)); @@ -792,6 +794,8 @@ test "vector reduce operation" { try testReduce(.Min, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, -100.0)); try testReduce(.Min, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, -100.0)); try testReduce(.Min, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, -100.0)); + try testReduce(.Min, [4]f80{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f80, -100.0)); + try testReduce(.Min, [4]f128{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f128, -100.0)); try testReduce(.Max, [4]i16{ -1, 2, 3, 4 }, @as(i16, 4)); try testReduce(.Max, [4]u16{ 1, 2, 3, 4 }, @as(u16, 4)); @@ -804,6 +808,8 @@ test "vector reduce operation" { try testReduce(.Max, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, 10.0e9)); try testReduce(.Max, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, 10.0e9)); try testReduce(.Max, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, 10.0e9)); + try testReduce(.Max, [4]f80{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f80, 10.0e9)); + try testReduce(.Max, [4]f128{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f128, 10.0e9)); try testReduce(.Mul, [4]i16{ -1, 2, 3, 4 }, @as(i16, -24)); try testReduce(.Mul, [4]u16{ 1, 2, 3, 4 }, @as(u16, 24)); @@ -816,6 +822,8 @@ test "vector reduce operation" { try testReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7)); try testReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7)); try testReduce(.Mul, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 58430.7)); + try testReduce(.Mul, [4]f80{ -1.9, 5.1, -60.3, 100.0 }, @as(f80, 58430.7)); + try testReduce(.Mul, [4]f128{ -1.9, 5.1, -60.3, 100.0 }, @as(f128, 58430.7)); try testReduce(.Or, [4]bool{ false, true, false, false }, @as(bool, true)); try testReduce(.Or, [4]u1{ 0, 1, 0, 0 }, @as(u1, 1)); @@ -823,6 +831,7 @@ test "vector reduce operation" { try testReduce(.Or, [4]u32{ 0xffff0000, 0xff00, 0xf0, 0xf }, ~@as(u32, 0)); try testReduce(.Or, [4]u64{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u64, 0xffffffff)); try testReduce(.Or, [4]u128{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u128, 0xffffffff)); + try testReduce(.Or, [4]u80{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u80, 0xffffffff)); try testReduce(.Xor, [4]bool{ true, true, true, false }, @as(bool, true)); try testReduce(.Xor, [4]u1{ 1, 1, 1, 0 }, @as(u1, 1)); @@ -835,22 +844,32 @@ test "vector reduce operation" { const f16_nan = math.nan(f16); const f32_nan = math.nan(f32); const f64_nan = math.nan(f64); + const f80_nan = math.nan(f80); + const f128_nan = math.nan(f128); try testReduce(.Add, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan); try testReduce(.Add, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan); try testReduce(.Add, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan); + try testReduce(.Add, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, f80_nan); + try testReduce(.Add, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, f128_nan); try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, -1.9)); try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, -1.9)); try testReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, -1.9)); + try testReduce(.Min, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, @as(f80, -1.9)); + try testReduce(.Min, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, @as(f128, -1.9)); try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, 100.0)); try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, 100.0)); try testReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, 100.0)); + try testReduce(.Max, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, @as(f80, 100.0)); + try testReduce(.Max, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, @as(f128, 100.0)); try testReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan); try testReduce(.Mul, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan); try testReduce(.Mul, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan); + try testReduce(.Mul, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, f80_nan); + try testReduce(.Mul, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, f128_nan); } }; @@ -1319,11 +1338,6 @@ test "byte vector initialized in inline function" { if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and comptime builtin.cpu.has(.x86, .avx512f)) { - // TODO https://github.com/ziglang/zig/issues/13279 - return error.SkipZigTest; - } - const S = struct { fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) { return .{ e0, e1, e2, e3 }; diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index acd8c258649e3cccadadbd4390d8f9b0cf0999a6..101e07c97ccf7a4c9c2cd702c545b7898f858082 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -408,7 +408,11 @@ void c_test_longdouble(void) { zig_8_longdouble(0, 1, 2, 3, 4, 5, 6, 7, 10, 9); } -#if defined(ZIG_BACKEND_STAGE2_X86_64) || defined(ZIG_PPC32) || defined(__wasm__) +#ifndef __hexagon__ +#ifndef __loongarch__ +#ifndef __mips__ +#ifndef ZIG_PPC64 +#if !(defined(__i386__) && defined(_WIN32)) typedef bool Vector_2_bool __attribute__((ext_vector_type(2))); @@ -4657,6 +4661,10 @@ void c_test_vector_512_bool(void) { }); } +#endif +#endif +#endif +#endif #endif typedef uint8_t Vector_1_u8 __attribute__((vector_size(1 * sizeof(uint8_t)))); diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 387eeb88c20b4ebfa9646ff10fde7322db299302..1f9b5a9f2ab04f4d3269a1ff6058d1d15ae2a63c 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -451,8 +451,11 @@ test "long double" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_2_bool() @Vector(2, bool) { @@ -474,7 +477,13 @@ extern fn c_vector_2_bool(@Vector(2, bool)) void; extern fn c_test_vector_2_bool() void; test "@Vector(2, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_2_bool(); try expect(vec[0] == true); @@ -488,8 +497,11 @@ test "@Vector(2, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_4_bool() @Vector(4, bool) { @@ -515,7 +527,13 @@ extern fn c_vector_4_bool(@Vector(4, bool)) void; extern fn c_test_vector_4_bool() void; test "@Vector(4, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_4_bool(); try expect(vec[0] == true); @@ -533,8 +551,11 @@ test "@Vector(4, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_8_bool() @Vector(8, bool) { @@ -568,7 +589,13 @@ extern fn c_vector_8_bool(@Vector(8, bool)) void; extern fn c_test_vector_8_bool() void; test "@Vector(8, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_8_bool(); try expect(vec[0] == false); @@ -594,8 +621,11 @@ test "@Vector(8, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_16_bool() @Vector(16, bool) { @@ -645,7 +675,13 @@ extern fn c_vector_16_bool(@Vector(16, bool)) void; extern fn c_test_vector_16_bool() void; test "@Vector(16, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_16_bool(); try expect(vec[0] == true); @@ -687,8 +723,11 @@ test "@Vector(16, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_32_bool() @Vector(32, bool) { @@ -770,7 +809,13 @@ extern fn c_vector_32_bool(@Vector(32, bool)) void; extern fn c_test_vector_32_bool() void; test "@Vector(32, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_32_bool(); try expect(vec[0] == true); @@ -844,8 +889,11 @@ test "@Vector(32, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_64_bool() @Vector(64, bool) { @@ -991,7 +1039,11 @@ extern fn c_vector_64_bool(@Vector(64, bool)) void; extern fn c_test_vector_64_bool() void; test "@Vector(64, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; const vec = c_ret_vector_64_bool(); try expect(vec[0] == false); @@ -1129,8 +1181,11 @@ test "@Vector(64, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_128_bool() @Vector(128, bool) { @@ -1404,7 +1459,11 @@ extern fn c_vector_128_bool(@Vector(128, bool)) void; extern fn c_test_vector_128_bool() void; test "@Vector(128, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_128_bool(); try expect(vec[0] == false); @@ -1670,8 +1729,11 @@ test "@Vector(128, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_256_bool() @Vector(256, bool) { @@ -2201,7 +2263,11 @@ extern fn c_vector_256_bool(@Vector(256, bool)) void; extern fn c_test_vector_256_bool() void; test "@Vector(256, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_256_bool(); try expect(vec[0] == true); @@ -2723,8 +2789,11 @@ test "@Vector(256, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_512_bool() @Vector(512, bool) { @@ -3766,7 +3835,11 @@ extern fn c_vector_512_bool(@Vector(512, bool)) void; extern fn c_test_vector_512_bool() void; test "@Vector(512, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_512_bool(); try expect(vec[0] == false); @@ -4840,7 +4913,7 @@ test "@Vector(2, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest; const v = c_ret_vector_2_u8(); try expect(v[0] == 9); @@ -4869,7 +4942,6 @@ test "@Vector(3, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest; const v = c_ret_vector_3_u8(); try expect(v[0] == 19); @@ -4912,7 +4984,7 @@ test "@Vector(4, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest; const v = c_ret_vector_4_u8(); try expect(v[0] == 41); @@ -4946,7 +5018,6 @@ test "@Vector(6, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest; const v = c_ret_vector_6_u8(); try expect(v[0] == 53); @@ -9063,7 +9134,7 @@ test "@Vector(2, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest; const v = c_ret_vector_2_u16(); try expect(v[0] == 9); @@ -9091,7 +9162,6 @@ test "@Vector(3, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest; const v = c_ret_vector_3_u16(); try expect(v[0] == 19); @@ -12564,8 +12634,6 @@ extern fn c_vector_1_u64(@Vector(1, u64), usize) void; extern fn c_test_vector_1_u64() void; test "@Vector(1, u64)" { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest; - const v = c_ret_vector_1_u64(); try expect(v[0] == 3); c_vector_1_u64(.{4}, 1); @@ -13291,7 +13359,6 @@ test "@Vector(1, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest; const v = c_ret_vector_1_f32(); try expect(v[0] == 3); @@ -14633,7 +14700,6 @@ test "@Vector(4, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899 const v = c_ret_vector_4_f64(); try expect(v[0] == 33); @@ -14701,7 +14767,6 @@ test "@Vector(8, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899 const v = c_ret_vector_8_f64(); try expect(v[0] == 81); diff --git a/test/tests.zig b/test/tests.zig index 849267617f0cfe5e8c8f227a3758a397ba047083..d823d2add16c8a4486decb3671025cd60cbc16e2 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -2015,7 +2015,6 @@ const c_abi_targets = blk: { .abi = .musl, }, .use_llvm = false, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ @@ -2026,7 +2025,6 @@ const c_abi_targets = blk: { }, .use_llvm = false, .strip = true, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ @@ -2037,7 +2035,6 @@ const c_abi_targets = blk: { }, .use_llvm = false, .pic = true, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ @@ -2082,7 +2079,6 @@ const c_abi_targets = blk: { .abi = .gnu, }, .use_llvm = false, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ @@ -2092,7 +2088,6 @@ const c_abi_targets = blk: { .abi = .gnu, }, .use_llvm = false, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ @@ -2102,7 +2097,6 @@ const c_abi_targets = blk: { .abi = .gnu, }, .use_llvm = false, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ -- 2.54.0 From 6aed49f6baad85fc4a509f4c631da8c623e7c28f Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 15 Jul 2026 08:44:30 -0400 Subject: [PATCH 13/22] llvm.Builder: parse llvm alignment information from data layout This is required to correctly lower types in the llvm backend. --- lib/std/zig/llvm/Builder.zig | 563 ++++++++++++++++++++++++++++++++++- src/codegen/llvm.zig | 270 ++++------------- src/codegen/llvm/FuncGen.zig | 21 +- 3 files changed, 618 insertions(+), 236 deletions(-) diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index a19a54651db7736b3a31ca926c534690ee27bf79..8b9e87f8139f951b7abc475c5afb3035176cb209 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -17,7 +17,7 @@ gpa: Allocator, strip: bool, source_filename: String, -data_layout: String, +data_layout: DataLayout, target_triple: String, module_asm: std.ArrayList(u8), @@ -87,6 +87,455 @@ pub const Options = struct { triple: []const u8 = &.{}, }; +pub const DataLayout = struct { + endian: ?std.lang.Endian, + int_specs: PrimitiveSpec.Map, + float_specs: PrimitiveSpec.Map, + vector_specs: PrimitiveSpec.Map, + pointer_specs: PointerSpec.Map, + string_repr: String, + + const PrimitiveSpec = packed struct(u32) { + bit_width: BitWidth, + abi_align: Alignment, + pref_align: Alignment, + + const BitWidth = u20; + + const Map = std.array_hash_map.Custom(PrimitiveSpec, void, Context, false); + + const Context = struct { + pub fn hash(_: Context, spec: PrimitiveSpec) u32 { + return std.hash.int(spec.bit_width); + } + + pub fn eql(_: Context, lhs_spec: PrimitiveSpec, rhs_spec: PrimitiveSpec, _: usize) bool { + return lhs_spec.bit_width == rhs_spec.bit_width; + } + }; + }; + + const PointerSpec = struct { + bit_width: BitWidth, + index_bit_width: BitWidth, + flags: packed struct(u32) { + abi_align: Alignment, + pref_align: Alignment, + has_unstable_repr: bool, + has_external_state: bool, + null_ptr_repr: NullPtrRepr, + unused: u17 = 0, + }, + addr_space_name: String, + + const BitWidth = u32; + + const NullPtrRepr = enum(u1) { all_zeros, all_ones }; + + const Map = std.array_hash_map.Auto(AddrSpace, PointerSpec); + }; + + pub fn stringForTarget(target: *const std.Target) []const u8 { + // These data layouts should match Clang. + return switch (target.cpu.arch) { + .arc => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32", + .xcore => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32", + .hexagon => "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048", + .lanai => "E-m:e-p:32:32-i64:64-a:0:32-n32-S64", + .aarch64 => if (target.ofmt == .macho) + if (target.os.tag == .windows or target.os.tag == .uefi) + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + else if (target.abi == .ilp32) + "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + else + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + else if (target.os.tag == .windows or target.os.tag == .uefi) + "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32" + else + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32", + .aarch64_be => "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32", + .arm => if (target.ofmt == .macho) + "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + else + "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", + .armeb, .thumbeb => if (target.ofmt == .macho) + "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + else + "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", + .thumb => if (target.ofmt == .macho) + "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + else if (target.os.tag == .windows or target.os.tag == .uefi) + "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + else + "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", + .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8", + .bpfeb => "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + .bpfel => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + .msp430 => "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16", + .mips => "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", + .mipsel => "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", + .mips64 => switch (target.abi) { + .gnuabin32, .muslabin32, .abin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + else => "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + }, + .mips64el => switch (target.abi) { + .gnuabin32, .muslabin32, .abin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + else => "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + }, + .m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16", + .powerpc => "E-m:e-p:32:32-Fn32-i64:64-n32", + .powerpcle => "e-m:e-p:32:32-Fn32-i64:64-n32", + .powerpc64 => switch (target.os.tag) { + .linux => "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512", + .ps3 => "E-m:e-p:32:32-Fi64-i64:64-i128:128-n32:64", + else => "E-m:e-Fn32-i64:64-i128:128-n32:64", + }, + .powerpc64le => if (target.os.tag == .linux) + "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512" + else + "e-m:e-Fn32-i64:64-i128:128-n32:64", + .nvptx => "e-p:32:32-p6:32:32-p7:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64", + .nvptx64 => "e-p6:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64", + .amdgcn => "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9", + .riscv32 => if (target.cpu.has(.riscv, .e)) + "e-m:e-p:32:32-i64:64-n32-S32" + else + "e-m:e-p:32:32-i64:64-n32-S128", + .riscv32be => if (target.cpu.has(.riscv, .e)) + "E-m:e-p:32:32-i64:64-n32-S32" + else + "E-m:e-p:32:32-i64:64-n32-S128", + .riscv64 => if (target.cpu.has(.riscv, .e)) + "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64" + else + "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + .riscv64be => if (target.cpu.has(.riscv, .e)) + "E-m:e-p:64:64-i64:64-i128:128-n32:64-S64" + else + "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + .sparc => "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64", + .sparc64 => "E-m:e-i64:64-i128:128-n32:64-S128", + .s390x => "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64", + .x86 => if (target.os.tag == .windows or target.os.tag == .uefi) switch (target.abi) { + .gnu => if (target.ofmt == .coff) + "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" + else + "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32", + else => blk: { + const msvc = switch (target.abi) { + .none, .msvc => true, + else => false, + }; + + break :blk if (target.ofmt == .coff) + if (msvc) + "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" + else + "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" + else if (msvc) + "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" + else + "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"; + }, + } else if (target.ofmt == .macho) + "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128" + else + "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", + .x86_64 => if (target.os.tag.isDarwin() or target.ofmt == .macho) + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" + else switch (target.abi) { + .gnux32, .muslx32, .x32 => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", + else => if ((target.os.tag == .windows or target.os.tag == .uefi) and target.ofmt == .coff) + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" + else + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", + }, + .spirv32 => switch (target.os.tag) { + .vulkan, .opengl => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", + else => "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", + }, + .spirv64 => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", + .wasm32 => if (target.os.tag == .emscripten) + "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20" + else + "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20", + .wasm64 => if (target.os.tag == .emscripten) + "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20" + else + "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20", + .ve => "e-m:e-i64:64-n32:64-S128-v64:64:64-v128:64:64-v256:64:64-v512:64:64-v1024:64:64-v2048:64:64-v4096:64:64-v8192:64:64-v16384:64:64", + .csky => "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32", + .loongarch32 => "e-m:e-p:32:32-i64:64-n32-S128", + .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32", + + .alpha, + .arceb, + .ez80, + .hppa, + .hppa64, + .kalimba, + .kvx, + .m88k, + .microblaze, + .microblazeel, + .or1k, + .propeller, + .sh, + .sheb, + .x86_16, + .xtensaeb, + => unreachable, + }; + } + + const default_int_specs: []const PrimitiveSpec = &.{ + .{ .bit_width = 8, .abi_align = .fromByteUnits(1), .pref_align = .fromByteUnits(1) }, // i8:8:8 + .{ .bit_width = 16, .abi_align = .fromByteUnits(2), .pref_align = .fromByteUnits(2) }, // i16:16:16 + .{ .bit_width = 32, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(4) }, // i32:32:32 + .{ .bit_width = 64, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(8) }, // i64:32:64 + }; + const default_float_specs: []const PrimitiveSpec = &.{ + .{ .bit_width = 16, .abi_align = .fromByteUnits(2), .pref_align = .fromByteUnits(2) }, // f16:16:16 + .{ .bit_width = 32, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(4) }, // f32:32:32 + .{ .bit_width = 64, .abi_align = .fromByteUnits(8), .pref_align = .fromByteUnits(8) }, // f64:64:64 + .{ .bit_width = 128, .abi_align = .fromByteUnits(16), .pref_align = .fromByteUnits(16) }, // f128:128:128 + }; + const default_vector_specs: []const PrimitiveSpec = &.{ + .{ .bit_width = 64, .abi_align = .fromByteUnits(8), .pref_align = .fromByteUnits(8) }, // v64:64:64 + .{ .bit_width = 128, .abi_align = .fromByteUnits(16), .pref_align = .fromByteUnits(16) }, // v128:128:128 + }; + + pub fn parseString(string_repr: String, builder: *Builder) Allocator.Error!DataLayout { + const gpa = builder.gpa; + + var int_specs: PrimitiveSpec.Map = .empty; + defer int_specs.deinit(gpa); + var float_specs: PrimitiveSpec.Map = .empty; + defer float_specs.deinit(gpa); + var vector_specs: PrimitiveSpec.Map = .empty; + defer vector_specs.deinit(gpa); + var pointer_specs: PointerSpec.Map = .empty; + defer pointer_specs.deinit(gpa); + var non_integral_addr_spaces: std.ArrayList(AddrSpace) = .empty; + defer non_integral_addr_spaces.deinit(gpa); + + try int_specs.ensureTotalCapacity(gpa, default_int_specs.len); + for (default_int_specs) |int_spec| int_specs.putAssumeCapacityNoClobber(int_spec, {}); + try float_specs.ensureTotalCapacity(gpa, default_float_specs.len); + for (default_float_specs) |float_spec| float_specs.putAssumeCapacityNoClobber(float_spec, {}); + try vector_specs.ensureTotalCapacity(gpa, default_vector_specs.len); + for (default_vector_specs) |vector_spec| vector_specs.putAssumeCapacityNoClobber(vector_spec, {}); + try pointer_specs.putNoClobber(gpa, .default, comptime .{ + .bit_width = 64, + .index_bit_width = 64, + .flags = .{ + .abi_align = .fromByteUnits(8), + .pref_align = .fromByteUnits(8), + .has_unstable_repr = false, + .has_external_state = false, + .null_ptr_repr = .all_zeros, + }, + .addr_space_name = .none, + }); + + var endian: ?std.lang.Endian = null; + var spec_it = std.mem.splitScalar(u8, string_repr.slice(builder).?, '-'); + while (spec_it.next()) |spec| switch (spec[0]) { + else => {}, + 'E' => { + assert(spec.len == 1); + assert(endian == null); + endian = .big; + }, + 'e' => { + assert(spec.len == 1); + assert(endian == null); + endian = .little; + }, + 'p' => { + var field_it = std.mem.splitScalar(u8, spec[1..], ':'); + + const first = field_it.first(); + var has_unstable_repr = false; + var has_external_state = false; + var null_ptr_repr: ?PointerSpec.NullPtrRepr = null; + var addr_space_name: String = .none; + const addr_space = for (first, 0..) |flag, as_start| switch (flag) { + 'u' => has_unstable_repr = true, + 'e' => has_external_state = true, + 'z' => { + assert(null_ptr_repr == null); + null_ptr_repr = .all_zeros; + }, + 'o' => { + assert(null_ptr_repr == null); + null_ptr_repr = .all_ones; + }, + else => { + if (first[first.len - ")".len] != ')') break first[as_start..]; + const name_start = std.mem.findScalarPos(u8, first, as_start, '(').?; + addr_space_name = try builder.string(first[name_start + "(".len .. first.len - ")".len]); + break first[as_start..name_start]; + }, + } else first[first.len..]; + const bit_width = std.fmt.parseInt(PointerSpec.BitWidth, field_it.next().?, 10) catch unreachable; + const abi_align: Alignment = .fromByteUnits(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable); + const pref_align: Alignment = if (field_it.next()) |pref_align| + .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable) + else + abi_align; + const index_bit_width = if (field_it.next()) |index_bit_width| + std.fmt.parseInt(PointerSpec.BitWidth, index_bit_width, 10) catch unreachable + else + bit_width; + assert(field_it.peek() == null); + + try pointer_specs.put(gpa, switch (addr_space.len) { + 0 => .default, + else => @fromBackingInt(std.fmt.parseInt(u24, addr_space, 10) catch unreachable), + }, .{ + .bit_width = bit_width, + .index_bit_width = index_bit_width, + .flags = .{ + .abi_align = abi_align, + .pref_align = pref_align, + .has_unstable_repr = has_unstable_repr, + .has_external_state = has_external_state, + .null_ptr_repr = null_ptr_repr orelse .all_zeros, + }, + .addr_space_name = addr_space_name, + }); + }, + 'i', 'f', 'v' => |kind| { + if (std.mem.eql(u8, spec, "ve")) { + vector_specs.clearRetainingCapacity(); + continue; + } + var field_it = std.mem.splitScalar(u8, spec[1..], ':'); + const bit_width = std.fmt.parseInt(PrimitiveSpec.BitWidth, field_it.first(), 10) catch unreachable; + const abi_align: Alignment = .fromByteUnits(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable); + const pref_align: Alignment = if (field_it.next()) |pref_align| + .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable) + else + abi_align; + assert(field_it.peek() == null); + const specs = switch (kind) { + else => unreachable, + 'i' => &int_specs, + 'f' => &float_specs, + 'v' => &vector_specs, + }; + try specs.put(gpa, .{ .bit_width = bit_width, .abi_align = abi_align, .pref_align = pref_align }, {}); + }, + 'n' => { + var field_it = std.mem.splitScalar(u8, spec[1..], ':'); + if (std.mem.eql(u8, field_it.first(), "i")) { + while (field_it.next()) |non_integral_addr_space| try non_integral_addr_spaces.append( + gpa, + @fromBackingInt(std.fmt.parseInt(u24, non_integral_addr_space, 10) catch unreachable), + ); + } else { + field_it.reset(); + while (field_it.next()) |native_bit_width| { + _ = std.fmt.parseInt(PrimitiveSpec.BitWidth, native_bit_width, 10) catch unreachable; + } + } + }, + }; + + for (non_integral_addr_spaces.items) |non_integral_addr_space| { + const pointer_spec_gop = try pointer_specs.getOrPut(gpa, non_integral_addr_space); + if (!pointer_spec_gop.found_existing) pointer_spec_gop.value_ptr.* = pointer_specs.get(.default).?; + pointer_spec_gop.value_ptr.flags.has_unstable_repr = true; + pointer_spec_gop.value_ptr.flags.has_external_state = false; + } + + { + const SortContext = struct { + specs: []const PrimitiveSpec, + pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { + return ctx.specs[lhs_index].bit_width < ctx.specs[rhs_index].bit_width; + } + }; + int_specs.sortUnstable(SortContext{ .specs = int_specs.keys() }); + float_specs.sortUnstable(SortContext{ .specs = float_specs.keys() }); + vector_specs.sortUnstable(SortContext{ .specs = vector_specs.keys() }); + } + { + const SortContext = struct { + addr_spaces: []const AddrSpace, + pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { + return @backingInt(ctx.addr_spaces[lhs_index]) < @backingInt(ctx.addr_spaces[rhs_index]); + } + }; + pointer_specs.sortUnstable(SortContext{ .addr_spaces = pointer_specs.keys() }); + assert(pointer_specs.keys()[0] == .default); + } + + return .{ + .endian = endian, + .int_specs = int_specs.move(), + .float_specs = float_specs.move(), + .vector_specs = vector_specs.move(), + .pointer_specs = pointer_specs.move(), + .string_repr = string_repr, + }; + } + + pub fn deinit(data_layout: *DataLayout, gpa: Allocator) void { + data_layout.int_specs.deinit(gpa); + data_layout.float_specs.deinit(gpa); + data_layout.vector_specs.deinit(gpa); + data_layout.pointer_specs.deinit(gpa); + } + + pub fn getIntegerSpec(data_layout: *const DataLayout, bit_width: PrimitiveSpec.BitWidth) PrimitiveSpec { + const specs = data_layout.int_specs.keys(); + return specs[ + @min(std.sort.lowerBound(PrimitiveSpec, specs, bit_width, struct { + fn order(ctx: PrimitiveSpec.BitWidth, spec: PrimitiveSpec) std.math.Order { + return std.math.order(ctx, spec.bit_width); + } + }.order), specs.len - 1) + ]; + } + + pub fn getFloatSpec(data_layout: *const DataLayout, bit_width: PrimitiveSpec.BitWidth) PrimitiveSpec { + if (data_layout.float_specs.getEntry(.{ + .bit_width = bit_width, + .abi_align = .default, + .pref_align = .default, + })) |entry| return entry.key_ptr.*; + const default_align: Alignment = .fromByteUnits( + std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, bit_width / 8), + ); + return .{ .bit_width = bit_width, .abi_align = default_align, .pref_align = default_align }; + } + + pub fn getVectorSpec( + data_layout: *const DataLayout, + bit_width: PrimitiveSpec.BitWidth, + store_size: Type.Size, + ) PrimitiveSpec { + if (data_layout.float_specs.getEntry(.{ + .bit_width = bit_width, + .abi_align = .default, + .pref_align = .default, + })) |entry| return entry.key_ptr.*; + const default_align: Alignment = .fromByteUnits( + std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, switch (store_size) { + .fixed, .scalable => |known_min| known_min, + }), + ); + return .{ .bit_width = bit_width, .abi_align = default_align, .pref_align = default_align }; + } + + pub fn getPointerSpec(data_layout: *const DataLayout, addr_space: AddrSpace) PointerSpec { + return data_layout.pointer_specs.get(addr_space) orelse data_layout.pointer_specs.values()[0]; + } +}; + pub const String = enum(u32) { none = maxInt(u31), empty, @@ -489,7 +938,10 @@ pub const Type = enum(u32) { .double, .i64, .x86_mmx => 64, .x86_fp80, .i80 => 80, .fp128, .ppc_fp128, .i128 => 128, - .ptr, .@"ptr addrspace(4)" => @panic("TODO: query data layout"), + .ptr => @intCast(builder.data_layout.getPointerSpec(.default).bit_width), + .@"ptr addrspace(4)" => @intCast( + builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(4))).bit_width, + ), _ => { const item = builder.type_items.items[@backingInt(self)]; return switch (item.tag) { @@ -498,7 +950,9 @@ pub const Type = enum(u32) { .vararg_function, => unreachable, .integer => @intCast(item.data), - .pointer => @panic("TODO: query data layout"), + .pointer => @intCast( + builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))).bit_width, + ), .target => unreachable, .vector, .scalable_vector, @@ -931,6 +1385,67 @@ pub const Type = enum(u32) { }, }; } + + const Size = union(enum) { fixed: u64, scalable: u64 }; + pub fn bits(ty: Type, builder: *const Builder) Size { + const item = builder.type_items.items[@backingInt(ty)]; + return switch (item.tag) { + else => unreachable, + .simple => switch (@as(Simple, @fromBackingInt(@intCast(item.data)))) { + else => unreachable, + .label => .{ .fixed = builder.data_layout.getPointerSpec(.default).bit_width }, + .half, .bfloat => .{ .fixed = 16 }, + .float => .{ .fixed = 32 }, + .double => .{ .fixed = 64 }, + .ppc_fp128, .fp128 => .{ .fixed = 128 }, + .x86_amx => .{ .fixed = 8192 }, + .x86_fp80 => .{ .fixed = 80 }, + }, + .integer => .{ .fixed = item.data }, + .pointer => .{ + .fixed = builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))).bit_width, + }, + }; + } + + pub fn alignment(ty: Type, kind: enum { abi, pref }, builder: *const Builder) Alignment { + const item = builder.type_items.items[@backingInt(ty)]; + switch (item.tag) { + else => unreachable, + .simple => switch (@as(Simple, @fromBackingInt(@intCast(item.data)))) { + else => unreachable, + .label => { + const spec = builder.data_layout.getPointerSpec(.default); + return switch (kind) { + .abi => spec.flags.abi_align, + .pref => spec.flags.pref_align, + }; + }, + .half, .bfloat, .float, .double, .ppc_fp128, .fp128, .x86_fp80 => { + const spec = builder.data_layout.getFloatSpec(@intCast(ty.bits(builder).fixed)); + return switch (kind) { + .abi => spec.abi_align, + .pref => spec.pref_align, + }; + }, + .x86_amx => return comptime .fromByteUnits(64), + }, + .integer => { + const spec = builder.data_layout.getIntegerSpec(@intCast(item.data)); + return switch (kind) { + .abi => spec.abi_align, + .pref => spec.pref_align, + }; + }, + .pointer => { + const spec = builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))); + return switch (kind) { + .abi => spec.flags.abi_align, + .pref => spec.flags.pref_align, + }; + }, + } + } }; pub const Attribute = union(Kind) { @@ -2182,11 +2697,18 @@ pub const Alignment = enum(u6) { }; } - /// Asserts that neither `a` nor `b` is `.default`. - pub fn max(a: Alignment, b: Alignment) Alignment { - assert(a != .default); - assert(b != .default); - return @fromBackingInt(@intCast(@max(@backingInt(a), @backingInt(b)))); + /// Asserts that neither `lhs` nor `rhs` is `.default`. + pub fn max(lhs: Alignment, rhs: Alignment) Alignment { + assert(lhs != .default); + assert(rhs != .default); + return @fromBackingInt(@max(@backingInt(lhs), @backingInt(rhs))); + } + + /// Asserts that neither `lhs` nor `rhs` is `.default`. + pub fn order(lhs: Alignment, rhs: Alignment) std.math.Order { + assert(lhs != .default); + assert(rhs != .default); + return std.math.order(@backingInt(lhs), @backingInt(rhs)); } pub fn toLlvm(self: Alignment) u6 { @@ -9023,7 +9545,14 @@ pub fn init(options: Options) Allocator.Error!Builder { .strip = options.strip, .source_filename = .none, - .data_layout = .none, + .data_layout = .{ + .endian = null, + .int_specs = .empty, + .float_specs = .empty, + .vector_specs = .empty, + .pointer_specs = .empty, + .string_repr = .none, + }, .target_triple = .none, .module_asm = .empty, @@ -9079,14 +9608,14 @@ pub fn init(options: Options) Allocator.Error!Builder { try self.string_indices.append(self.gpa, 0); assert(try self.string("") == .empty); + self.data_layout = try .parseString(try self.string(DataLayout.stringForTarget(options.target)), &self); + try self.strtab_string_indices.append(self.gpa, 0); assert(try self.strtabString("") == .empty); if (options.name.len > 0) self.source_filename = try self.string(options.name); - if (options.triple.len > 0) { - self.target_triple = try self.string(options.triple); - } + if (options.triple.len > 0) self.target_triple = try self.string(options.triple); { const static_len = @typeInfo(Type).@"enum".field_names.len - 1; @@ -9179,6 +9708,8 @@ pub fn clearAndFree(self: *Builder) void { pub fn deinit(self: *Builder) void { const gpa = self.gpa; + self.data_layout.deinit(gpa); + self.module_asm.deinit(gpa); self.string_map.deinit(gpa); @@ -9998,17 +10529,17 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined }; defer metadata_formatter.map.deinit(self.gpa); - if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) { + if (self.source_filename != .none or self.data_layout.string_repr != .none or self.target_triple != .none) { if (need_newline) try w.writeByte('\n') else need_newline = true; if (self.source_filename != .none) try w.print( \\; ModuleID = '{s}' \\source_filename = {f} \\ , .{ self.source_filename.slice(self).?, self.source_filename.fmtQ(self) }); - if (self.data_layout != .none) try w.print( + if (self.data_layout.string_repr != .none) try w.print( \\target datalayout = {f} \\ - , .{self.data_layout.fmtQ(self)}); + , .{self.data_layout.string_repr.fmtQ(self)}); if (self.target_triple != .none) try w.print( \\target triple = {f} \\ @@ -13706,7 +14237,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco }); } - if (self.data_layout.slice(self)) |data_layout| { + if (self.data_layout.string_repr.slice(self)) |data_layout| { try module_block.writeAbbrev(ModuleBlock.String{ .code = 3, .string = data_layout, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 221c9423e3a035367c010f0d6225940ab70a8ffb..689a0349ce7cf9aa2c49c2101f476303667c50cd 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -345,160 +345,6 @@ pub fn supportsTailCall(target: *const std.Target) bool { }; } -pub fn dataLayout(target: *const std.Target) []const u8 { - // These data layouts should match Clang. - return switch (target.cpu.arch) { - .arc => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32", - .xcore => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32", - .hexagon => "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048", - .lanai => "E-m:e-p:32:32-i64:64-a:0:32-n32-S64", - .aarch64 => if (target.ofmt == .macho) - if (target.os.tag == .windows or target.os.tag == .uefi) - "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" - else if (target.abi == .ilp32) - "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" - else - "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" - else if (target.os.tag == .windows or target.os.tag == .uefi) - "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32" - else - "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32", - .aarch64_be => "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32", - .arm => if (target.ofmt == .macho) - "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" - else - "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", - .armeb, .thumbeb => if (target.ofmt == .macho) - "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" - else - "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", - .thumb => if (target.ofmt == .macho) - "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" - else if (target.os.tag == .windows or target.os.tag == .uefi) - "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" - else - "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", - .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8", - .bpfeb => "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128", - .bpfel => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", - .msp430 => "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16", - .mips => "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", - .mipsel => "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", - .mips64 => switch (target.abi) { - .gnuabin32, .muslabin32, .abin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", - else => "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", - }, - .mips64el => switch (target.abi) { - .gnuabin32, .muslabin32, .abin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", - else => "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", - }, - .m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16", - .powerpc => "E-m:e-p:32:32-Fn32-i64:64-n32", - .powerpcle => "e-m:e-p:32:32-Fn32-i64:64-n32", - .powerpc64 => switch (target.os.tag) { - .linux => "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512", - .ps3 => "E-m:e-p:32:32-Fi64-i64:64-i128:128-n32:64", - else => "E-m:e-Fn32-i64:64-i128:128-n32:64", - }, - .powerpc64le => if (target.os.tag == .linux) - "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512" - else - "e-m:e-Fn32-i64:64-i128:128-n32:64", - .nvptx => "e-p:32:32-p6:32:32-p7:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64", - .nvptx64 => "e-p6:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64", - .amdgcn => "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9", - .riscv32 => if (target.cpu.has(.riscv, .e)) - "e-m:e-p:32:32-i64:64-n32-S32" - else - "e-m:e-p:32:32-i64:64-n32-S128", - .riscv32be => if (target.cpu.has(.riscv, .e)) - "E-m:e-p:32:32-i64:64-n32-S32" - else - "E-m:e-p:32:32-i64:64-n32-S128", - .riscv64 => if (target.cpu.has(.riscv, .e)) - "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64" - else - "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", - .riscv64be => if (target.cpu.has(.riscv, .e)) - "E-m:e-p:64:64-i64:64-i128:128-n32:64-S64" - else - "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128", - .sparc => "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64", - .sparc64 => "E-m:e-i64:64-i128:128-n32:64-S128", - .s390x => "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64", - .x86 => if (target.os.tag == .windows or target.os.tag == .uefi) switch (target.abi) { - .gnu => if (target.ofmt == .coff) - "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" - else - "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32", - else => blk: { - const msvc = switch (target.abi) { - .none, .msvc => true, - else => false, - }; - - break :blk if (target.ofmt == .coff) - if (msvc) - "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" - else - "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" - else if (msvc) - "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" - else - "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"; - }, - } else if (target.ofmt == .macho) - "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128" - else - "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", - .x86_64 => if (target.os.tag.isDarwin() or target.ofmt == .macho) - "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" - else switch (target.abi) { - .gnux32, .muslx32, .x32 => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", - else => if ((target.os.tag == .windows or target.os.tag == .uefi) and target.ofmt == .coff) - "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" - else - "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", - }, - .spirv32 => switch (target.os.tag) { - .vulkan, .opengl => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", - else => "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", - }, - .spirv64 => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", - .wasm32 => if (target.os.tag == .emscripten) - "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20" - else - "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20", - .wasm64 => if (target.os.tag == .emscripten) - "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20" - else - "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20", - .ve => "e-m:e-i64:64-n32:64-S128-v64:64:64-v128:64:64-v256:64:64-v512:64:64-v1024:64:64-v2048:64:64-v4096:64:64-v8192:64:64-v16384:64:64", - .csky => "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32", - .loongarch32 => "e-m:e-p:32:32-i64:64-n32-S128", - .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", - .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32", - - .alpha, - .arceb, - .ez80, - .hppa, - .hppa64, - .kalimba, - .kvx, - .m88k, - .microblaze, - .microblazeel, - .or1k, - .propeller, - .sh, - .sheb, - .x86_16, - .xtensaeb, - => unreachable, // Gated by hasLlvmSupport(). - }; -} - // Avoid depending on `bindings.CodeModel` in the bitcode-only case. const CodeModel = enum { default, @@ -618,8 +464,6 @@ pub const Object = struct { }); errdefer builder.deinit(); - builder.data_layout = try builder.string(dataLayout(target)); - const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref = if (!builder.strip) debug_info: { // We fully resolve all paths at this point to avoid lack of @@ -2865,18 +2709,38 @@ pub const Object = struct { pub const TypeRepr = enum { /// The representation of the type when it is being manipulated as a value in a function. - /// e.g. Zig `u5` -> LLVM `i5` + /// e.g. Zig `u90` -> LLVM `i90` as_value, - /// The representation of the type when it is stored in memory. - /// e.g. Zig `u5` -> LLVM `i8` + /// The representation of the type when it is loaded from or stored to memory. + /// e.g. Zig `u90` -> LLVM `i96` + memory_access, + /// The representation of the type when it is in memory. + /// e.g. Zig `u90` -> LLVM `[12 x i8]` in_memory, }; + pub fn intType(o: *Object, bits: u16, repr: TypeRepr) Allocator.Error!Builder.Type { + switch (repr) { + .as_value => return o.builder.intType(bits), + .memory_access, .in_memory => {}, + } + const target = o.zcu.getTarget(); + const abi_size = std.zig.target.intByteSize(target, bits); + const llvm_bit_width = @as(u20, 8) * abi_size; + switch (repr) { + .as_value => unreachable, + .memory_access => {}, + .in_memory => { + const zig_align = std.zig.target.intAlignment(target, bits); + const llvm_align = o.builder.data_layout.getIntegerSpec(llvm_bit_width).abi_align; + if (zig_align < llvm_align.toByteUnits().?) return o.builder.arrayType(abi_size, .i8); + }, + } + return o.builder.intType(llvm_bit_width); + } + pub fn errorIntType(o: *Object, repr: TypeRepr) Allocator.Error!Builder.Type { - return o.builder.intType(switch (repr) { - .as_value => o.zcu.errorSetBits(), - .in_memory => @intCast(Type.anyerror.abiSize(o.zcu) * 8), - }); + return o.intType(o.zcu.errorSetBits(), repr); } pub const SoftF80Layout = struct { @@ -3029,42 +2893,31 @@ pub const Object = struct { const target = zcu.getTarget(); const ip = &zcu.intern_pool; - if (repr == .as_value) { - assert(!isByRef(t, zcu)); // by-ref types must only be manipulated in memory + switch (repr) { + .as_value => assert(!isByRef(t, zcu)), // by-ref types must only be manipulated in memory + .memory_access, .in_memory => {}, } return switch (t.toIntern()) { .u0_type => unreachable, // no runtime bits - inline .u1_type, - .u8_type, - .i8_type, - .u16_type, - .i16_type, - .u29_type, - .u32_type, - .i32_type, - .u64_type, - .i64_type, - .u80_type, - .u128_type, - .i128_type, - => |tag| switch (repr) { - .as_value => @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]), - .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)), - }, - .usize_type, .isize_type => try o.builder.intType(target.ptrBitWidth()), - inline .c_char_type, - .c_short_type, - .c_ushort_type, - .c_int_type, - .c_uint_type, - .c_long_type, - .c_ulong_type, - .c_longlong_type, - .c_ulonglong_type, - => |tag| try o.builder.intType(target.cTypeBitSize( - @field(std.Target.CType, @tagName(tag)["c_".len .. @tagName(tag).len - "_type".len]), - ).?), + .u1_type => try o.intType(1, repr), + .u8_type, .i8_type => try o.intType(8, repr), + .u16_type, .i16_type => try o.intType(16, repr), + .u29_type => try o.intType(29, repr), + .u32_type, .i32_type => try o.intType(32, repr), + .u64_type, .i64_type => try o.intType(64, repr), + .u80_type => try o.intType(80, repr), + .u128_type, .i128_type => try o.intType(128, repr), + .usize_type, .isize_type => try o.intType(target.ptrBitWidth(), repr), + .c_char_type => try o.intType(target.cTypeBitSize(.char).?, repr), + .c_short_type => try o.intType(target.cTypeBitSize(.short).?, repr), + .c_ushort_type => try o.intType(target.cTypeBitSize(.ushort).?, repr), + .c_int_type => try o.intType(target.cTypeBitSize(.int).?, repr), + .c_uint_type => try o.intType(target.cTypeBitSize(.uint).?, repr), + .c_long_type => try o.intType(target.cTypeBitSize(.long).?, repr), + .c_ulong_type => try o.intType(target.cTypeBitSize(.ulong).?, repr), + .c_longlong_type => try o.intType(target.cTypeBitSize(.longlong).?, repr), + .c_ulonglong_type => try o.intType(target.cTypeBitSize(.ulonglong).?, repr), .c_longdouble_type, .f16_type, .f32_type, @@ -3168,10 +3021,7 @@ pub const Object = struct { .none, => unreachable, else => switch (ip.indexToKey(t.toIntern())) { - .int_type => |int_type| switch (repr) { - .as_value => try o.builder.intType(int_type.bits), - .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)), - }, + .int_type => |int_type| o.intType(int_type.bits, repr), .ptr_type => |ptr_type| type: { const ptr_ty = try o.builder.ptrType( toLlvmAddressSpace(ptr_type.flags.address_space, target), @@ -3189,7 +3039,7 @@ pub const Object = struct { try o.lowerType(.fromInterned(array_type.child), repr), ), .vector_type => |vector_type| if (isByRef(t, zcu)) { - const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), .in_memory); + const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), repr); return o.builder.arrayType(vector_type.len, child_llvm_ty); } else { const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), .as_value); @@ -3454,7 +3304,7 @@ pub const Object = struct { return ty; }, .opaque_type, .spirv_type => unreachable, // no runtime bits - .enum_type => try o.lowerType(t.backingIntType(zcu), repr), + .enum_type => try o.intType(t.backingIntType(zcu).intInfo(zcu).bits, repr), .func_type => |func_type| { assert(t.fnHasRuntimeBits(zcu)); return o.lowerFnType(.fromIntern(func_type, ip)); @@ -3525,7 +3375,7 @@ pub const Object = struct { .no_bits => continue, .byval => { const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); - try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .as_value)); + try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .memory_access else .as_value)); }, .byref, .byref_mut => { try llvm_params.append(o.gpa, .ptr); @@ -3548,7 +3398,7 @@ pub const Object = struct { }, .float_array => |count| { const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); - const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .in_memory); + const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .memory_access); try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty)); }, .i32_array, .i64_array => |arr_len| { @@ -3620,7 +3470,12 @@ pub const Object = struct { var bigint_space: Value.BigIntSpace = undefined; const bigint = val.toBigInt(&bigint_space, zcu); const llvm_int_ty = try o.lowerType(ty, repr); - return o.builder.bigIntConst(llvm_int_ty, bigint); + if (llvm_int_ty.isInteger(&o.builder)) + return o.builder.bigIntConst(llvm_int_ty, bigint); + const buffer = try o.gpa.alloc(u8, llvm_int_ty.aggregateLen(&o.builder)); + defer o.gpa.free(buffer); + bigint.writeTwosComplement(buffer, target.cpu.arch.endian()); + return o.builder.stringConst(try o.builder.string(buffer)); }, .err => |err| { const int = zcu.intern_pool.getErrorValueIfExists(err.name).?; @@ -3814,7 +3669,7 @@ pub const Object = struct { result_val.* = try o.builder.intConst(.i8, byte); }, .elems => |elems| for (vals, elems) |*result_val, elem| { - result_val.* = try o.lowerValue(elem, if (is_by_ref) .in_memory else .as_value); + result_val.* = try o.lowerValue(elem, if (is_by_ref) repr else .as_value); }, .repeated_elem => unreachable, } @@ -3826,7 +3681,7 @@ pub const Object = struct { .repeated_elem => |elem| if (is_by_ref) { const vals = try allocator.alloc(Builder.Constant, vector_type.len); defer allocator.free(vals); - @memset(vals, try o.lowerValue(elem, .in_memory)); + @memset(vals, try o.lowerValue(elem, repr)); return o.builder.arrayConst(vector_ty, vals); } else return o.builder.splatConst(vector_ty, try o.lowerValue(elem, .as_value)), } @@ -4287,9 +4142,8 @@ pub const Object = struct { } errdefer assert(o.uav_map.remove(.{ .val = uav_val, .@"addrspace" = @"addrspace" })); - const llvm_ty = try o.lowerType(uav_ty, .in_memory); const llvm_name = try o.builder.strtabStringFmt("__anon_{d}", .{@backingInt(uav_val)}); - const llvm_variable = try o.builder.addVariable(llvm_name, llvm_ty, llvm_addrspace); + const llvm_variable = try o.builder.addVariable(llvm_name, .void, llvm_addrspace); gop.value_ptr.* = llvm_variable; try llvm_variable.setInitializer(try o.lowerValue(uav_val, .in_memory), &o.builder); llvm_variable.setMutability(.constant, &o.builder); diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 5bdf5029d1b4a639c41652f0792d56aba08e927a..f9ba9ecbac5056091f6ff13721ada61080baf5e4 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -830,7 +830,7 @@ fn buildCall( const alignment = arg_ty.abiAlignment(zcu).toLlvm(); // We don't need to handle non-ABI-sized integer types in memory here since they are // never by-ref. - const llvm_arg_ty = try o.lowerType(arg_ty, .in_memory); + const llvm_arg_ty = try o.lowerType(arg_ty, .memory_access); const loaded = try fg.wip.load(.normal, llvm_arg_ty, arg_val, alignment, ""); try llvm_args.append(fg.gpa, loaded); } else { @@ -893,7 +893,7 @@ fn buildCall( break :ptr ptr; } else arg_val; - const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .in_memory); + const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .memory_access); const array_ty = try o.builder.arrayType(count, float_ty); const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); @@ -4967,10 +4967,7 @@ fn buildZigAlloca(fg: *FuncGen, ty: Type, @"align": InternPool.Alignment) Alloca .none => ty.abiAlignment(o.zcu), else => |a| a, }; - return fg.buildAlloca( - try o.lowerType(ty, .in_memory), - resolved_align.toLlvm(), - ); + return fg.buildAlloca(try o.lowerType(ty, .in_memory), resolved_align.toLlvm()); } /// Unlike `WipFunction.alloca`, this puts the alloca instruction at the top of the function. @@ -6657,10 +6654,10 @@ fn load( return result_ptr; } - const llvm_memory_ty = try o.lowerType(load_ty, .in_memory); + const llvm_access_ty = try o.lowerType(load_ty, .memory_access); const llvm_value_ty = try o.lowerType(load_ty, .as_value); - if (llvm_memory_ty != llvm_value_ty) { + if (llvm_access_ty != llvm_value_ty) { assert(load_ty.isAbiInt(zcu)); // `load_ty` is an integer type with padding bits. In theory, we shouldn't need any special // handling for these, as LLVM's documented semantics are a valid implementation of Zig's @@ -6674,7 +6671,7 @@ fn load( // // Therefore, we handle these memory accesses specially: in this case we will actually load // the next-largest "natural" integer type and then truncate to `load_ty`. - const loaded = try fg.wip.load(access_kind, llvm_memory_ty, ptr, llvm_ptr_align, ""); + const loaded = try fg.wip.load(access_kind, llvm_access_ty, ptr, llvm_ptr_align, ""); // For packed structs, current Zig semantics don't really allow us to make the padding bits // well-defined. This should be solved once https://github.com/ziglang/zig/issues/24061 is // implemented, but until then, do a normal trunc for packed types. @@ -6731,17 +6728,17 @@ fn store( assert(elem.typeOfWip(&fg.wip) == try o.lowerType(elem_ty, .as_value)); - const llvm_memory_ty = try o.lowerType(elem_ty, .in_memory); + const llvm_access_ty = try o.lowerType(elem_ty, .memory_access); const llvm_value_ty = try o.lowerType(elem_ty, .as_value); - if (llvm_memory_ty != llvm_value_ty) { + if (llvm_access_ty != llvm_value_ty) { assert(elem_ty.isAbiInt(zcu)); // `elem_ty` is an integer type with padding bits, so we need to handle it specially---see // the corresponding comment in `FuncGen.load` for more details. const extended = try fg.wip.cast(switch (elem_ty.intInfo(zcu).signedness) { .unsigned => .zext, .signed => .sext, - }, elem, llvm_memory_ty, ""); + }, elem, llvm_access_ty, ""); _ = try fg.wip.store(access_kind, extended, ptr, llvm_ptr_align); return; } -- 2.54.0 From 092f019be98b9cba5ecdc9a2b1a14ba107479a41 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 27 Jun 2026 02:05:27 -0400 Subject: [PATCH 14/22] llvm: implement placeholder powerpc64le c abi logic This was honestly easier than disabling most of the tests. --- src/codegen/llvm/FuncGen.zig | 111 +++++++++++--------- test/behavior/vector.zig | 1 - test/c_abi/cfuncs.c | 14 +-- test/c_abi/main.zig | 198 ++++++++++++++++++----------------- 4 files changed, 172 insertions(+), 152 deletions(-) diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index f9ba9ecbac5056091f6ff13721ada61080baf5e4..30a188749337f24690130a4a36e9fbe7a4cb578b 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -6987,25 +6987,12 @@ const ParamTypeIterator = struct { .async => { @panic("TODO implement async function lowering in the LLVM backend"); }, - .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty), - .x86_64_win => return it.next_x86_64_win(ty), - .x86_stdcall => { - it.zig_index += 1; - it.llvm_index += 1; - - if (isScalar(zcu, ty)) { - return .byval; - } else { - it.byval_attr = true; - return .byref; - } - }, .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => { it.zig_index += 1; it.llvm_index += 1; switch (aarch64_c_abi.classifyType(ty, zcu)) { .memory => return .byref_mut, - .float_array => |len| return Lowering{ .float_array = len }, + .float_array => |len| return .{ .float_array = len }, .byval => return .byval, .integer => { it.types_buffer[0..1].* = .{.i64}; @@ -7013,7 +7000,7 @@ const ParamTypeIterator = struct { it.types_len = 1; return .multiple_llvm_types; }, - .double_integer => return Lowering{ .i64_array = 2 }, + .double_integer => return .{ .i64_array = 2 }, } }, .arm_aapcs, .arm_aapcs_vfp => { @@ -7025,8 +7012,8 @@ const ParamTypeIterator = struct { return .byref; }, .byval => return .byval, - .i32_array => |size| return Lowering{ .i32_array = size }, - .i64_array => |size| return Lowering{ .i64_array = size }, + .i32_array => |size| return .{ .i32_array = size }, + .i64_array => |size| return .{ .i64_array = size }, } }, .mips_o32 => { @@ -7038,9 +7025,19 @@ const ParamTypeIterator = struct { return .byref; }, .byval => return .byval, - .i32_array => |size| return Lowering{ .i32_array = size }, + .i32_array => |size| return .{ .i32_array = size }, } }, + .powerpc64_elf_v2 => { + it.zig_index += 1; + it.llvm_index += 1; + if (isByRef(ty, zcu)) return switch (ty.abiSize(zcu)) { + 1...8 => .abi_sized_int, + 9...64 => |abi_size| .{ .i64_array = @intCast(@divCeil(abi_size, 8)) }, + else => .byref, + }; + return .byval; // TODO + }, .riscv64_lp64, .riscv32_ilp32 => { it.zig_index += 1; it.llvm_index += 1; @@ -7048,7 +7045,7 @@ const ParamTypeIterator = struct { .memory => return .byref_mut, .byval => return .byval, .integer => return .abi_sized_int, - .double_integer => return Lowering{ .i64_array = 2 }, + .double_integer => return .{ .i64_array = 2 }, .fields => { it.types_len = 0; var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| @@ -7108,6 +7105,19 @@ const ParamTypeIterator = struct { return .byref; }, }, + .x86_stdcall => { + it.zig_index += 1; + it.llvm_index += 1; + + if (isScalar(zcu, ty)) { + return .byval; + } else { + it.byval_attr = true; + return .byref; + } + }, + .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty), + .x86_64_win => return it.next_x86_64_win(ty), // TODO investigate other callconvs else => { it.zig_index += 1; @@ -7294,7 +7304,7 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A const zcu = o.zcu; ret_ty.assertHasLayout(zcu); if (!ret_ty.hasRuntimeBits(zcu)) return .void; - switch (cc) { + return switch (cc) { .@"inline" => unreachable, .auto => { // Match the c calling convention in some cases to avoid llvm bugs. @@ -7307,36 +7317,31 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A 33...64 => .{ .mem_cast = .double }, else => .by_val, }; - - if (isByRef(ret_ty, zcu)) return .sret; - return .by_val; + return if (isByRef(ret_ty, zcu)) .sret else .by_val; }, - .x86_64_sysv, .x86_64_x32 => return fnReturnStrat_x86_64_sysv(o, ret_ty), - .x86_64_win => return fnReturnStrat_x86_64_win(o, ret_ty), - .x86_stdcall => if (isScalar(zcu, ret_ty)) { - assert(!isByRef(ret_ty, zcu)); - return .by_val; - } else return .sret, - .x86_fastcall => return fnReturnStrat_x86_fastcall(o, zcu, ret_ty), - .x86_sysv, .x86_win => return if (isByRef(ret_ty, zcu)) .sret else .by_val, .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(ret_ty, zcu)) { - .memory => return .sret, - .float_array, .byval => return .forceByVal(o, ret_ty), - .integer => return .{ .mem_cast = .i64 }, - .double_integer => return .{ .mem_cast = try o.builder.arrayType(2, .i64) }, + .memory => .sret, + .float_array, .byval => .forceByVal(o, ret_ty), + .integer => .{ .mem_cast = .i64 }, + .double_integer => .{ .mem_cast = try o.builder.arrayType(2, .i64) }, }, .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(ret_ty, zcu, .ret)) { - .memory, .i64_array => return .sret, - .i32_array => |len| return if (len == 1) .{ .mem_cast = .i32 } else .sret, - .byval => return .forceByVal(o, ret_ty), + .memory, .i64_array => .sret, + .i32_array => |len| if (len == 1) .{ .mem_cast = .i32 } else .sret, + .byval => .forceByVal(o, ret_ty), }, .mips_o32 => switch (mips_c_abi.classifyType(ret_ty, zcu, .ret)) { - .memory, .i32_array => return .sret, - .byval => return .forceByVal(o, ret_ty), + .memory, .i32_array => .sret, + .byval => .forceByVal(o, ret_ty), }, + .powerpc64_elf_v2 => if (isByRef(ret_ty, zcu)) switch (ret_ty.abiSize(zcu)) { + 1...8 => .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) }, + 9...16 => .{ .mem_cast = try o.builder.structType(.normal, &.{ .i64, .i64 }) }, + else => .sret, + } else .by_val, // TODO .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(ret_ty, zcu)) { - .memory => return .sret, - .integer => return .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) }, + .memory => .sret, + .integer => .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) }, .double_integer => { const integer: Builder.Type = switch (zcu.getTarget().cpu.arch) { .riscv64, .riscv64be => .i64, @@ -7345,7 +7350,7 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A }; return .{ .mem_cast = try o.builder.structType(.normal, &.{ integer, integer }) }; }, - .byval => return .forceByVal(o, ret_ty), + .byval => .forceByVal(o, ret_ty), .fields => { var types_len: usize = 0; var types: [8]Builder.Type = undefined; @@ -7358,7 +7363,7 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A return .{ .mem_cast = try o.builder.structType(.normal, types[0..types_len]) }; }, }, - .s390x_sysv, .s390x_sysv_vx => return switch (s390x_c_abi.classifyType(ret_ty, .ret, zcu)) { + .s390x_sysv, .s390x_sysv_vx => switch (s390x_c_abi.classifyType(ret_ty, .ret, zcu)) { .none => .void, .double_or_float, .vector, .simple => .by_val, .simple_aggregate => unreachable, @@ -7368,14 +7373,20 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) { assert(!isByRef(ret_ty, zcu)); return .by_val; - } else { - return .{ .mem_cast = try o.lowerType(scalar_ty, .as_value) }; - }, - .indirect => return .sret, + } else .{ .mem_cast = try o.lowerType(scalar_ty, .as_value) }, + .indirect => .sret, }, + .x86_stdcall => if (isScalar(zcu, ret_ty)) { + assert(!isByRef(ret_ty, zcu)); + return .by_val; + } else .sret, + .x86_fastcall => fnReturnStrat_x86_fastcall(o, zcu, ret_ty), + .x86_sysv, .x86_win => if (isByRef(ret_ty, zcu)) .sret else .by_val, + .x86_64_sysv, .x86_64_x32 => fnReturnStrat_x86_64_sysv(o, ret_ty), + .x86_64_win => fnReturnStrat_x86_64_win(o, ret_ty), // TODO investigate other callconvs - else => return .forceByVal(o, ret_ty), - } + else => .forceByVal(o, ret_ty), + }; } fn fnReturnStrat_x86_fastcall(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat { diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 5838231e75ed214364a9a1af0527e5b9e480eaa9..861b2e77db418adbb23343bf0a90db3733ad82f6 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -736,7 +736,6 @@ test "vector reduce operation" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/195562 const S = struct { fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void { diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index 101e07c97ccf7a4c9c2cd702c545b7898f858082..91a33b24ad4d3ffbefc648495d1291491827677c 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -77,7 +77,7 @@ static void assert_or_panic(bool ok) { # define ZIG_NO_COMPLEX #endif -#ifdef ZIG_PPC32 +#ifdef __powerpc__ # define ZIG_NO_COMPLEX #endif @@ -15571,7 +15571,7 @@ void run_c_tests(void) { #if !(defined(__i386__) && defined(_WIN32)) #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct Struct_i32_i32 s = {1, 2}; zig_struct_i32_i32(s); @@ -15584,7 +15584,7 @@ void run_c_tests(void) { #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct BigStruct s = {1, 2, 3, 4, 5}; zig_big_struct(s); @@ -15616,7 +15616,7 @@ void run_c_tests(void) { #ifndef __i386__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct SplitStructInts s = {1234, 100, 1337}; zig_split_struct_ints(s); @@ -15630,7 +15630,7 @@ void run_c_tests(void) { #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct MedStructMixed s = {1234, 100.0f, 1337.0f}; zig_med_struct_mixed(s); @@ -15644,7 +15644,7 @@ void run_c_tests(void) { #ifndef __i386__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct SplitStructMixed s = {1234, 100, 1337.0f}; zig_split_struct_mixed(s); @@ -15658,7 +15658,7 @@ void run_c_tests(void) { #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct BigStruct s = {30, 31, 32, 33, 34}; struct BigStruct res = zig_big_struct_both(s); diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 1f9b5a9f2ab04f4d3269a1ff6058d1d15ae2a63c..f1bbd96806d3b507ee0448f4415f811aae2d929a 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -161,7 +161,7 @@ extern fn c_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat; extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble; const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isMIPS() and - !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC32() and !builtin.cpu.arch.isRISCV() and + !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC() and !builtin.cpu.arch.isRISCV() and builtin.cpu.arch != .hexagon and builtin.cpu.arch != .s390x and !(builtin.cpu.arch.isLoongArch() and builtin.abi.float() == .soft); @@ -15384,7 +15384,7 @@ test "struct u8, u8" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8(); @@ -15418,7 +15418,7 @@ test "struct u8, u8, u8" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8_u8(); @@ -15455,7 +15455,7 @@ test "struct u8, u8, u8, u8" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8_u8_u8(); @@ -15516,7 +15516,7 @@ test "struct u16, u16" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u16_u16(); @@ -15550,7 +15550,7 @@ test "struct u16, u16, u16" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; @@ -15588,7 +15588,7 @@ test "struct u16, u16, u16, u16" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; @@ -15649,7 +15649,7 @@ extern fn c_test_struct_u32_u32() void; test "struct u32, u32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; @@ -15684,7 +15684,7 @@ test "struct u32, u32, u32" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = c_ret_struct_u32_u32_u32(); try expect(s.a == 8); @@ -15720,7 +15720,7 @@ test "struct u32, u32, u32, u32" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = c_ret_struct_u32_u32_u32_u32(); try expect(s.a == 10); @@ -15866,7 +15866,7 @@ extern fn c_test_struct_u64_u64_u64() void; test "struct u64, u64, u64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = c_ret_struct_u64_u64_u64(); try expect(s.a == 8); @@ -15901,7 +15901,7 @@ extern fn c_test_struct_u64_u64_u64_u64() void; test "struct u64, u64, u64, u64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = c_ret_struct_u64_u64_u64_u64(); try expect(s.a == 10); @@ -15930,7 +15930,7 @@ extern fn c_test_struct_f32() void; test "struct f32" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_f32(); @@ -16173,7 +16173,7 @@ test "struct {f32, f32}, f32" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f32f32_f32(); try expect(s.a.b == 1.0); @@ -16206,7 +16206,7 @@ test "struct f32, {f32, f32}" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f32_f32f32(); try expect(s.a == 1.0); @@ -16234,7 +16234,7 @@ extern fn c_test_struct_f64() void; test "struct f64" { if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; @@ -16265,7 +16265,7 @@ extern fn c_test_struct_f64_f64() void; test "struct f64, f64" { if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f64_f64(); try expect(s.a == 6); @@ -16297,7 +16297,7 @@ extern fn c_test_struct_f64_f64_f64() void; test "struct f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64(); try expect(s.a == 8); @@ -16332,7 +16332,7 @@ extern fn c_test_struct_f64_f64_f64_f64() void; test "struct f64, f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64_f64(); try expect(s.a == 10); @@ -16370,7 +16370,7 @@ extern fn c_test_struct_f64_f64_f64_f64_f64() void; test "struct f64, f64, f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64_f64_f64(); try expect(s.a == 12); @@ -16409,7 +16409,7 @@ test "struct{u32,union{u32,struct{u32,u32}}}" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = c_ret_struct_u32_union_u32_u32u32(); try expect(s.a == 1); @@ -16427,10 +16427,10 @@ extern fn c_mut_struct_i32_i32(Struct_i32_i32) Struct_i32_i32; extern fn c_struct_i32_i32(Struct_i32_i32) void; test "struct i32 i32" { + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s: Struct_i32_i32 = .{ @@ -16460,10 +16460,10 @@ const BigStruct = extern struct { extern fn c_big_struct(BigStruct) void; test "big struct" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = BigStruct{ .a = 1, @@ -16489,9 +16489,9 @@ const BigUnion = extern union { extern fn c_big_union(BigUnion) void; test "big union" { - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const x = BigUnion{ .a = BigStruct{ @@ -16523,10 +16523,10 @@ extern fn c_med_struct_mixed(MedStructMixed) void; extern fn c_ret_med_struct_mixed() MedStructMixed; test "medium struct of ints and floats" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = MedStructMixed{ .a = 1234, @@ -16602,11 +16602,11 @@ const SplitStructInt = extern struct { extern fn c_split_struct_ints(SplitStructInt) void; test "split struct of ints" { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = SplitStructInt{ .a = 1234, @@ -16631,11 +16631,11 @@ extern fn c_split_struct_mixed(SplitStructMixed) void; extern fn c_ret_split_struct_mixed() SplitStructMixed; test "split struct of ints and floats" { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = SplitStructMixed{ .a = 1234, @@ -16658,10 +16658,10 @@ export fn zig_split_struct_mixed(x: SplitStructMixed) void { extern fn c_big_struct_both(BigStruct) BigStruct; test "sret and byval together" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = BigStruct{ .a = 1, @@ -16771,11 +16771,11 @@ extern fn c_struct_with_array(StructWithArray) void; extern fn c_ret_struct_with_array() StructWithArray; test "Struct with array as padding." { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 }); @@ -16799,10 +16799,10 @@ extern fn c_float_array_struct(FloatArrayStruct) void; extern fn c_ret_float_array_struct() FloatArrayStruct; test "Float array like struct" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; c_float_array_struct(.{ .origin = .{ @@ -16833,33 +16833,37 @@ pub inline fn expectOk(c_err: c_int) !void { /// Tests for Double + Char struct const DC = extern struct { v1: f64, v2: u8 }; test "DC: Zig passes to C" { + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 })); } test "DC: Zig returns to C" { + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + try expectOk(c_assert_ret_DC()); } test "DC: C passes to Zig" { + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + try expectOk(c_send_DC()); } test "DC: C returns to Zig" { + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + try expectEqual(DC{ .v1 = -0.25, .v2 = 15 }, c_ret_DC()); } @@ -16884,32 +16888,35 @@ const CFF = extern struct { v1: u8, v2: f32, v3: f32 }; test "CFF: Zig passes to C" { if (builtin.target.cpu.arch == .x86) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 })); } test "CFF: Zig returns to C" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + try expectOk(c_assert_ret_CFF()); } test "CFF: C passes to Zig" { - if (builtin.target.cpu.arch == .x86) return error.SkipZigTest; - if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest; - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest; + if (builtin.target.cpu.arch == .x86) return error.SkipZigTest; try expectOk(c_send_CFF()); } test "CFF: C returns to Zig" { - if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest; - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest; + try expectEqual(CFF{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }, c_ret_CFF()); } pub extern fn c_assert_CFF(lv: CFF) c_int; @@ -16932,31 +16939,35 @@ pub export fn zig_ret_CFF() CFF { const PD = extern struct { v1: ?*anyopaque, v2: f64 }; test "PD: Zig passes to C" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; + try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 })); } test "PD: Zig returns to C" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + try expectOk(c_assert_ret_PD()); } test "PD: C passes to Zig" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; + try expectOk(c_send_PD()); } test "PD: C returns to Zig" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + try expectEqual(PD{ .v1 = null, .v2 = 0.5 }, c_ret_PD()); } pub extern fn c_assert_PD(lv: PD) c_int; @@ -17010,10 +17021,10 @@ const ByVal = extern struct { extern fn c_func_ptr_byval(*anyopaque, *anyopaque, ByVal, c_ulong, *anyopaque, c_ulong) void; test "C function that takes byval struct called via function pointer" { + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; var fn_ptr = &c_func_ptr_byval; _ = &fn_ptr; @@ -17032,17 +17043,16 @@ test "C function that takes byval struct called via function pointer" { extern fn c_f16(f16) f16; test "f16 bare" { - if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; - if (builtin.cpu.arch == .x86) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - - if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; + if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; const a = c_f16(12); try expect(a == 34); @@ -17053,9 +17063,9 @@ const f16_struct = extern struct { }; extern fn c_f16_struct(f16_struct) f16_struct; test "f16 struct" { + if (builtin.cpu.arch.isArm() and builtin.mode != .debug) return error.SkipZigTest; if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.mode != .debug) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; @@ -17162,10 +17172,10 @@ const Coord2 = extern struct { extern fn stdcall_coord2(Coord2, Coord2, Coord2) callconv(stdcall_callconv) Coord2; test "Stdcall ABI structs" { + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const res = stdcall_coord2( @@ -17179,9 +17189,9 @@ test "Stdcall ABI structs" { extern fn stdcall_big_union(BigUnion) callconv(stdcall_callconv) void; test "Stdcall ABI big union" { - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const x = BigUnion{ .a = BigStruct{ @@ -17253,10 +17263,10 @@ const byval_tail_callsite_attr = struct { }; test "byval tail callsite attribute" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; // Originally reported at https://github.com/ziglang/zig/issues/16290 // the bug was that the extern function had the byval attribute, but -- 2.54.0 From 703baa4cd662e55ba39ea14ae2f30209e7ff023b Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 1 Jul 2026 12:01:07 -0400 Subject: [PATCH 15/22] llvm: implement c abi for loongarch Closes #35798 --- CMakeLists.txt | 1 + src/codegen/llvm/FuncGen.zig | 86 ++++++++++++++++++++++ src/codegen/loongarch/abi.zig | 133 ++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 src/codegen/loongarch/abi.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index ad4d8bea72ee199d041ef28559b536de2f20f7e3..14df4e9b568d8fb6c5b924f6cd4e3c9778dc5e21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -358,6 +358,7 @@ set(ZIG_STAGE2_SOURCES src/codegen/c/type/render_defs.zig src/codegen/llvm.zig src/codegen/llvm/bindings.zig + src/codegen/loongarch/abi.zig src/codegen/s390x/abi.zig src/crash_report.zig src/dev.zig diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 30a188749337f24690130a4a36e9fbe7a4cb578b..84a7af8362e91e54003cdf82378ce1037b2f617f 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -7016,6 +7016,71 @@ const ParamTypeIterator = struct { .i64_array => |size| return .{ .i64_array = size }, } }, + .loongarch32_ilp32, .loongarch64_lp64 => switch (loongarch_c_abi.classifyType(ty, zcu)) { + .ignored => { + it.zig_index += 1; + return .no_bits; + }, + .gar, .far => { + it.zig_index += 1; + it.llvm_index += 1; + return .byval; + }, + .member => |member_ty| { + it.types_buffer[0..1].* = .{ + try it.object.lowerType(member_ty, .as_value), + }; + it.offsets_buffer[0..2].* = .{ 0, member_ty.abiSize(zcu) }; + it.types_len = 1; + it.zig_index += 1; + it.llvm_index += 1; + return .multiple_llvm_types; + }, + .member_pair => |member_tys| { + it.types_buffer[0..2].* = .{ + try it.object.lowerType(member_tys[0], .as_value), + try it.object.lowerType(member_tys[1], .as_value), + }; + const first_size = member_tys[0].abiSize(zcu); + const second_size = member_tys[0].abiSize(zcu); + it.offsets_buffer[0..3].* = .{ 0, first_size, first_size + second_size }; + it.types_len = 2; + it.zig_index += 1; + it.llvm_index += 2; + return .multiple_llvm_types; + }, + .memory_gar => { + switch (it.cc) { + else => unreachable, + .loongarch32_ilp32 => { + it.types_buffer[0..1].* = .{.i32}; + it.offsets_buffer[0..2].* = .{ 0, 4 }; + }, + .loongarch64_lp64 => { + it.types_buffer[0..1].* = .{.i64}; + it.offsets_buffer[0..2].* = .{ 0, 8 }; + }, + } + it.types_len = 1; + it.zig_index += 1; + it.llvm_index += 1; + return .multiple_llvm_types; + }, + .memory_gar_pair => { + it.zig_index += 1; + it.llvm_index += 1; + return switch (it.cc) { + else => unreachable, + .loongarch32_ilp32 => .{ .i32_array = 2 }, + .loongarch64_lp64 => .{ .i64_array = 2 }, + }; + }, + .address => { + it.zig_index += 1; + it.llvm_index += 1; + return .byref; + }, + }, .mips_o32 => { it.zig_index += 1; it.llvm_index += 1; @@ -7330,6 +7395,26 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A .i32_array => |len| if (len == 1) .{ .mem_cast = .i32 } else .sret, .byval => .forceByVal(o, ret_ty), }, + .loongarch32_ilp32, .loongarch64_lp64 => switch (loongarch_c_abi.classifyType(ret_ty, zcu)) { + .ignored => .void, + .gar, .far => .by_val, + .member => |member_ty| .{ .mem_cast = try o.lowerType(member_ty, .as_value) }, + .member_pair => |member_tys| .{ .mem_cast = try o.builder.structType(.normal, &.{ + try o.lowerType(member_tys[0], .as_value), + try o.lowerType(member_tys[1], .as_value), + }) }, + .memory_gar => .{ .mem_cast = switch (cc) { + else => unreachable, + .loongarch32_ilp32 => .i32, + .loongarch64_lp64 => .i64, + } }, + .memory_gar_pair => .{ .mem_cast = try o.builder.arrayType(2, switch (cc) { + else => unreachable, + .loongarch32_ilp32 => .i32, + .loongarch64_lp64 => .i64, + }) }, + .address => .sret, + }, .mips_o32 => switch (mips_c_abi.classifyType(ret_ty, zcu, .ret)) { .memory, .i32_array => .sret, .byval => .forceByVal(o, ret_ty), @@ -8124,6 +8209,7 @@ const math = std.math; const aarch64_c_abi = @import("../aarch64/abi.zig"); const arm_c_abi = @import("../arm/abi.zig"); +const loongarch_c_abi = @import("../loongarch/abi.zig"); const mips_c_abi = @import("../mips/abi.zig"); const riscv_c_abi = @import("../riscv64/abi.zig"); const s390x_c_abi = @import("../s390x/abi.zig"); diff --git a/src/codegen/loongarch/abi.zig b/src/codegen/loongarch/abi.zig new file mode 100644 index 0000000000000000000000000000000000000000..09e42a7cb96731dbf0ee44b37ad74f0548a08c93 --- /dev/null +++ b/src/codegen/loongarch/abi.zig @@ -0,0 +1,133 @@ +const std = @import("std"); +const InternPool = @import("../../InternPool.zig"); +const Type = @import("../../Type.zig"); +const Zcu = @import("../../Zcu.zig"); + +pub const Class = union(enum) { + ignored, + gar, + far, + member: Type, + member_pair: [2]Type, + memory_gar, + memory_gar_pair, + address, + + fn combineMember(container_class: Class, member_class: Class, member_ty: Type) Class { + const second_member_ty = switch (member_class) { + .ignored => return container_class, + .gar, .far => member_ty, + .member => |second_member_ty| second_member_ty, + .member_pair, .memory_gar, .memory_gar_pair, .address => return .address, + }; + return switch (container_class) { + .ignored => .{ .member = second_member_ty }, + .gar, .far, .memory_gar, .memory_gar_pair => unreachable, + .member => |first_member_ty| .{ .member_pair = .{ first_member_ty, second_member_ty } }, + .member_pair, .address => .address, + }; + } +}; + +pub fn classifyType(ty: Type, zcu: *Zcu) Class { + return Classifier.init(zcu).classifyType(ty); +} + +const Classifier = struct { + zcu: *Zcu, + target: *const std.Target, + grlen: u8, + frlen: u8, + + fn init(zcu: *Zcu) Classifier { + const target = zcu.getTarget(); + return .{ + .zcu = zcu, + .target = target, + .grlen = switch (target.cpu.arch) { + else => unreachable, + .loongarch32 => 32, + .loongarch64 => 64, + }, + .frlen = if (target.cpu.has(.loongarch, .d)) + 64 + else if (target.cpu.has(.loongarch, .f)) + 32 + else + 0, + }; + } + + fn classifyType(c: Classifier, ty: Type) Class { + switch (ty.zigTypeTag(c.zcu)) { + .type, + .comptime_float, + .comptime_int, + .undefined, + .null, + .error_union, + .error_set, + .@"fn", + .@"opaque", + .frame, + .@"anyframe", + .enum_literal, + .spirv, + => unreachable, + .void, .noreturn => return .ignored, + .bool => return .gar, + .int, .@"enum" => { + const bits = ty.intInfo(c.zcu).bits; + if (bits == 0) return .ignored; + if (bits <= c.grlen) return .gar; + if (bits <= 2 * c.grlen) return .memory_gar_pair; + return .address; + }, + .float => { + const bits = ty.floatBits(c.target); + if (bits <= c.frlen) return .far; + if (bits <= c.grlen) return .gar; + if (bits <= 2 * c.grlen) return .memory_gar_pair; + return .address; + }, + .pointer, .optional => return .gar, + .array => { + var class: Class = .ignored; + const elem_ty = ty.childType(c.zcu); + const elem_class = c.classifyType(elem_ty); + for (0..std.math.lossyCast(usize, ty.arrayLen(c.zcu))) |_| { + class = class.combineMember(elem_class, elem_ty); + if (class == .address) break; + } + if (class != .address) return class; + }, + .@"struct" => switch (ty.containerLayout(c.zcu)) { + .auto => unreachable, + .@"extern" => { + var class: Class = .ignored; + var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (c.zcu.typeToStruct(ty)) |loaded_struct| + loaded_struct.iterateRuntimeOrder(&c.zcu.intern_pool) + else + .{ .runtime_order = null, .fields_len = ty.structFieldCount(c.zcu), .next_index = 0 }; + while (field_it.next()) |field_index| { + const field_ty = ty.fieldType(field_index, c.zcu); + class = class.combineMember(c.classifyType(field_ty), field_ty); + if (class == .address) break; + } + if (class != .address) return class; + }, + .@"packed" => return c.classifyType(ty.backingIntType(c.zcu)), + }, + .@"union" => switch (ty.containerLayout(c.zcu)) { + .auto => unreachable, + .@"extern" => {}, + .@"packed" => return c.classifyType(ty.backingIntType(c.zcu)), + }, + .vector => {}, + } + const size = ty.abiSize(c.zcu); + if (size <= @divExact(c.grlen, 8)) return .memory_gar; + if (size <= @divExact(2 * c.grlen, 8)) return .memory_gar_pair; + return .address; + } +}; -- 2.54.0 From f2f770fdd3818d1ec14e51ce752aca5beb08e150 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 4 Jul 2026 13:56:17 -0400 Subject: [PATCH 16/22] llvm: implement c abi for x86 --- lib/std/Target.zig | 9 +- lib/std/lang.zig | 1 + src/Sema.zig | 1 + src/Zcu.zig | 2 + src/codegen.zig | 195 +++++++++++++++++++++++++++++++++++ src/codegen/c.zig | 2 +- src/codegen/llvm.zig | 18 +++- src/codegen/llvm/FuncGen.zig | 117 +++++++++++++++++---- src/link/Dwarf.zig | 3 +- 9 files changed, 315 insertions(+), 33 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 3a6cfabb42be0d191520ef33ae7cbbc190e7c644..2f395dc0f03d6aa5673df31b4aa3bb92d66bf50a 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1797,6 +1797,7 @@ pub const Cpu = struct { .x86_sysv, .x86_win, + .x86_mingw, .x86_stdcall, .x86_fastcall, .x86_thiscall, @@ -3664,18 +3665,14 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention { return switch (target.cpu.arch) { .x86_64 => switch (target.os.tag) { - .windows, - .uefi, - => .{ .x86_64_win = .{} }, + .windows, .uefi => .{ .x86_64_win = .{} }, else => switch (target.abi) { .gnux32, .muslx32, .x32 => .{ .x86_64_x32 = .{} }, else => .{ .x86_64_sysv = .{} }, }, }, .x86 => switch (target.os.tag) { - .windows, - .uefi, - => .{ .x86_win = .{} }, + .windows, .uefi => if (target.isMinGW()) .{ .x86_mingw = .{} } else .{ .x86_win = .{} }, else => .{ .x86_sysv = .{} }, }, .x86_16 => .{ .x86_16_cdecl = .{} }, diff --git a/lib/std/lang.zig b/lib/std/lang.zig index 2f0868c39331456b03f055cafd8546f19ac51b07..f15f26d9f9330431846e52ff9d98b131fbc666e2 100644 --- a/lib/std/lang.zig +++ b/lib/std/lang.zig @@ -214,6 +214,7 @@ pub const CallingConvention = union(enum(u8)) { // Calling conventions for the `x86` architecture. x86_sysv: X86RegparmOptions, x86_win: X86RegparmOptions, + x86_mingw: X86RegparmOptions, x86_stdcall: X86RegparmOptions, x86_fastcall: CommonOptions, x86_thiscall: CommonOptions, diff --git a/src/Sema.zig b/src/Sema.zig index cb8f87836a5e2c8623670cb870f7bf2b4b05a43d..2181fa563b9e9dec42b1123cc3b738874df64ca7 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8501,6 +8501,7 @@ const calling_conventions_supporting_var_args = [_]std.lang.CallingConvention.Ta .x86_64_win, .x86_sysv, .x86_win, + .x86_mingw, .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win, diff --git a/src/Zcu.zig b/src/Zcu.zig index d71d8ecf80ef074a1800c9d637744a023523fede..2af36db254d2edbcfe3ae8a05de265b882d46b01 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4644,6 +4644,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) .x86_sysv, .x86_win, + .x86_mingw, .x86_stdcall, => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, @@ -4678,6 +4679,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) .stage2_x86 => switch (cc) { .x86_sysv, .x86_win, + .x86_mingw, => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, .naked => true, else => false, diff --git a/src/codegen.zig b/src/codegen.zig index a691b36a4811f7cf127de20aa50d33e2b6e8d700..4ad10d48c05c59608f06956209f7f9b66a6d2775 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1124,6 +1124,201 @@ pub fn fieldOffset(ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32, zcu: }; } +pub const FlattenedItem = struct { offset: u64, type: ?Type }; +pub fn flattenType(items_buf: []FlattenedItem, ty: Type, zcu: *Zcu, opts: struct { + offset: u64 = 0, + allow_arrays: bool = true, + fn increaseOffset(opts: @This(), offset: u64) @This() { + return .{ + .offset = opts.offset + offset, + .allow_arrays = opts.allow_arrays, + }; + } +}) ?[]FlattenedItem { + const ip = &zcu.intern_pool; + switch (ip.indexToKey(ty.toIntern())) { + .int_type => |int_type| { + if (int_type.bits == 0) return items_buf[0..0]; + if (items_buf.len < 1) return null; + const items = items_buf[0..1]; + items.* = .{.{ .offset = opts.offset, .type = ty }}; + return items; + }, + .ptr_type => |ptr_type| switch (ptr_type.flags.size) { + .one, .many, .c => { + if (items_buf.len < 1) return null; + const items = items_buf[0..1]; + items.* = .{.{ .offset = opts.offset, .type = ty }}; + return items; + }, + .slice => { + if (items_buf.len < 2) return null; + const items = items_buf[0..2]; + const ptr_field_ty = ty.slicePtrFieldType(zcu); + items.* = .{ + .{ .offset = opts.offset, .type = ptr_field_ty }, + .{ .offset = opts.offset + ptr_field_ty.abiSize(zcu), .type = .usize }, + }; + return items; + }, + }, + .array_type => |array_type| { + const len = array_type.lenIncludingSentinel(); + if (len == 0) return items_buf[0..0]; + const elem_ty: Type = .fromInterned(array_type.child); + const elem_items = flattenType(items_buf, elem_ty, zcu, opts) orelse return null; + if (elem_items.len == 0) return items_buf[0..0]; + if (!opts.allow_arrays) return null; + const items_len, const items_overflow = @mulWithOverflow(elem_items.len, len); + if (items_overflow != 0 or items_buf.len < items_len) return null; + var items_index = elem_items.len; + const elem_size = elem_ty.abiSize(zcu); + var elem_offset: u64 = elem_size; + while (items_index != items_len) : ({ + items_index += elem_items.len; + elem_offset += elem_size; + }) for (items_buf[items_index..][0..elem_items.len], elem_items) |*item, elem_item| { + item.* = .{ .offset = elem_offset + elem_item.offset, .type = elem_item.type }; + }; + return items_buf[0..@intCast(items_len)]; + }, + .vector_type => |vector_type| { + if (vector_type.len == 0) return items_buf[0..0]; + if (items_buf.len < 1) return null; + const items = items_buf[0..1]; + items.* = .{.{ .offset = opts.offset, .type = ty }}; + return items; + }, + .opt_type, .error_union_type => return null, + .simple_type => |simple_type| switch (simple_type) { + .f16, + .f32, + .f64, + .f80, + .f128, + .usize, + .isize, + .c_char, + .c_short, + .c_ushort, + .c_int, + .c_uint, + .c_long, + .c_ulong, + .c_longlong, + .c_ulonglong, + .c_longdouble, + .bool, + .anyerror, + => { + if (items_buf.len < 1) return null; + const items = items_buf[0..1]; + items.* = .{.{ .offset = opts.offset, .type = ty }}; + return items; + }, + .anyopaque, .noreturn => return null, + .void, + .type, + .comptime_int, + .comptime_float, + .null, + .undefined, + .enum_literal, + => return items_buf[0..0], + .adhoc_inferred_error_set, .generic_poison => unreachable, + }, + .struct_type => { + const loaded_struct = ip.loadStructType(ty.toIntern()); + switch (loaded_struct.layout) { + .auto, .@"extern" => {}, + .@"packed" => return flattenType(items_buf, .fromInterned( + loaded_struct.packed_backing_int_type, + ), zcu, opts), + } + var items_len: usize = 0; + var offset: u64 = 0; + var field_it = loaded_struct.iterateRuntimeOrder(ip); + while (field_it.next()) |field_index| { + const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); + const field_offset = loaded_struct.field_offsets.get(ip)[field_index]; + if (field_offset - offset > 0 and + (items_len == 0 or items_buf[items_len - 1].type != null)) + { + if (items_len == items_buf.len) return null; + items_buf[items_len] = .{ .offset = offset, .type = null }; + items_len += 1; + } + items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset( + field_offset, + )) orelse return null).len; + offset = field_offset + field_ty.abiSize(zcu); + } + if (ty.abiSize(zcu) - offset > 0 and + (items_len == 0 or items_buf[items_len - 1].type != null)) + { + if (items_len == items_buf.len) return null; + items_buf[items_len] = .{ .offset = offset, .type = null }; + items_len += 1; + } + return items_buf[0..items_len]; + }, + .tuple_type => |tuple_type| { + if (items_buf.len < tuple_type.types.len) return null; + var items_len: usize = 0; + var offset: u64 = 0; + for (tuple_type.types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + offset = field_ty.abiAlignment(zcu).forward(offset); + items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset( + offset, + )) orelse return null).len; + offset += field_ty.abiSize(zcu); + } + return items_buf[0..items_len]; + }, + .union_type => { + const loaded_union = ip.loadUnionType(ty.toIntern()); + return switch (loaded_union.layout) { + .auto, .@"extern" => return null, + .@"packed" => return flattenType(items_buf, .fromInterned( + loaded_union.packed_backing_int_type, + ), zcu, opts), + }; + }, + .opaque_type, .spirv_type, .func_type => return null, + .enum_type => return flattenType(items_buf, .fromInterned( + ip.loadEnumType(ty.toIntern()).int_tag_type, + ), zcu, opts), + .error_set_type, .inferred_error_set_type => { + if (items_buf.len < 1) return null; + const items = items_buf[0..1]; + items.* = .{.{ .offset = opts.offset, .type = ty }}; + return items; + }, + .anyframe_type, + // values, not types + .undef, + .simple_value, + .@"extern", + .func, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + .bitpack, + // memoization, not types + .memoized_call, + => unreachable, + } +} + test { _ = aarch64; } diff --git a/src/codegen/c.zig b/src/codegen/c.zig index d1605b457e2f3673807c16fd10836612aae804d5..1633321426dfc3044177eebe0cd44e6fda3c6aa9 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -7289,7 +7289,7 @@ fn toCallingConvention(cc: std.lang.CallingConvention, zcu: *Zcu) ?[]const u8 { .x86_16_cdecl => "cdecl", .x86_16_regparmcall => "regparmcall", .x86_64_sysv, .x86_sysv => "sysv_abi", - .x86_64_win, .x86_win => "ms_abi", + .x86_64_win, .x86_win, .x86_mingw => "ms_abi", .x86_16_stdcall, .x86_stdcall => "stdcall", .x86_fastcall => "fastcall", .x86_thiscall => "thiscall", diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 689a0349ce7cf9aa2c49c2101f476303667c50cd..de5f084008896d56c36ff371078b6581a306a45f 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4235,19 +4235,26 @@ pub const Object = struct { }; } + pub const Byval = struct { alignment: InternPool.Alignment = .none }; pub fn addByRefParamAttrs( o: *Object, attributes: *Builder.FunctionAttributes.Wip, llvm_arg_i: u32, - byval: bool, + maybe_byval: ?Byval, param_ty: Type, ) Allocator.Error!void { const llvm_param_ty = try o.lowerType(param_ty, .in_memory); - const alignment = param_ty.abiAlignment(o.zcu).toLlvm(); - try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); - try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(alignment) }, &o.builder); - if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder); + try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); + try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); + const alignment = if (maybe_byval) |byval| alignment: { + try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder); + break :alignment byval.alignment; + } else .none; + try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(switch (alignment) { + .none => param_ty.abiAlignment(o.zcu), + else => alignment, + }.toLlvm()) }, &o.builder); } pub fn getErrorNameTable(o: *Object) Allocator.Error!Builder.Variable.Index { @@ -4598,6 +4605,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const .x86_16_interrupt, .x86_sysv, .x86_win, + .x86_mingw, .x86_thiscall_mingw, .x86_64_x32, .aarch64_aapcs, diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 84a7af8362e91e54003cdf82378ce1037b2f617f..1dfdfba987f0e962049294699bba1bcce3aac4bf 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -218,7 +218,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { switch (lowering) { .no_bits => continue, .byval => { - assert(!it.byval_attr); + assert(it.byval_attr == null); const param_index = it.zig_index - 1; const param_ty: Type = .fromInterned(param_types[param_index]); const param = fg.wip.arg(it.llvm_index - 1); @@ -237,15 +237,16 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { .byref, .byref_mut => { const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); const param = fg.wip.arg(it.llvm_index - 1); + const alignment = if (it.byval_attr) |byval_attr| byval_attr.alignment else .none; - if (isByRef(param_ty, zcu)) { + if (alignment == .none and isByRef(param_ty, zcu)) { args.appendAssumeCapacity(param); } else { - args.appendAssumeCapacity(try fg.load(param, .none, param_ty, .normal)); + args.appendAssumeCapacity(try fg.load(param, alignment, param_ty, .normal)); } }, .abi_sized_int => { - assert(!it.byval_attr); + assert(it.byval_attr == null); const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); const param = fg.wip.arg(it.llvm_index - 1); @@ -260,7 +261,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { } }, .slice => { - assert(!it.byval_attr); + assert(it.byval_attr == null); const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); assert(!isByRef(param_ty, zcu)); const slice_val = try fg.wip.buildAggregate( @@ -271,7 +272,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { args.appendAssumeCapacity(slice_val); }, .multiple_llvm_types => { - assert(!it.byval_attr); + assert(it.byval_attr == null); const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); const param_alignment = param_ty.abiAlignment(zcu); const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8); @@ -963,7 +964,7 @@ fn buildCall( => continue, .slice => { - assert(!it.byval_attr); + assert(it.byval_attr == null); const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); const ptr_info = param_ty.ptrInfo(zcu); const llvm_arg_i = it.llvm_index - 2; @@ -6913,7 +6914,7 @@ const ParamTypeIterator = struct { types_len: u32, types_buffer: [8]Builder.Type, offsets_buffer: [9]u64, - byval_attr: bool, + byval_attr: ?Object.Byval, const Lowering = union(enum) { no_bits, @@ -6931,7 +6932,7 @@ const ParamTypeIterator = struct { pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering { if (it.zig_index >= it.param_types.len) return null; const ty = it.param_types[it.zig_index]; - it.byval_attr = false; + it.byval_attr = null; return nextInner(it, Type.fromInterned(ty)); } @@ -7008,7 +7009,7 @@ const ParamTypeIterator = struct { it.llvm_index += 1; switch (arm_c_abi.classifyType(ty, zcu, .arg)) { .memory => { - it.byval_attr = true; + it.byval_attr = .{}; return .byref; }, .byval => return .byval, @@ -7086,7 +7087,7 @@ const ParamTypeIterator = struct { it.llvm_index += 1; switch (mips_c_abi.classifyType(ty, zcu, .arg)) { .memory => { - it.byval_attr = true; + it.byval_attr = .{}; return .byref; }, .byval => return .byval, @@ -7158,15 +7159,15 @@ const ParamTypeIterator = struct { it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .as_value)}; it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) }; it.types_len = 1; - it.llvm_index += 1; it.zig_index += 1; + it.llvm_index += 1; return .multiple_llvm_types; } }, .indirect => { it.zig_index += 1; it.llvm_index += 1; - it.byval_attr = true; + it.byval_attr = .{}; return .byref; }, }, @@ -7177,10 +7178,56 @@ const ParamTypeIterator = struct { if (isScalar(zcu, ty)) { return .byval; } else { - it.byval_attr = true; + it.byval_attr = .{}; return .byref; } }, + .x86_sysv, .x86_win, .x86_mingw => { + if (isByRef(ty, zcu)) { + var items_buf: [1]codegen.FlattenedItem = undefined; + if (codegen.flattenType(&items_buf, ty, zcu, .{ + .allow_arrays = false, + })) |items| one_float: { + if (items.len != 1 or items[0].offset != 0) break :one_float; + const item_ty = items[0].type orelse break :one_float; + if (!item_ty.isRuntimeFloat()) break :one_float; + it.types_buffer[0..1].*, it.offsets_buffer[0..2].* = + switch (item_ty.floatBits(zcu.getTarget())) { + else => unreachable, + 32 => .{ .{.float}, .{ 0, 4 } }, + 64 => .{ .{.double}, .{ 0, 8 } }, + 16, 80, 128 => break :one_float, + }; + it.types_len = 1; + it.zig_index += 1; + it.llvm_index += 1; + return .multiple_llvm_types; + } + it.zig_index += 1; + it.llvm_index += 1; + it.byval_attr = .{ .alignment = .@"4" }; + return .byref; + } + if (ty.isAbiInt(zcu)) switch (ty.intInfo(zcu).bits) { + else => unreachable, + 8, 16, 32, 64 => { + it.zig_index += 1; + it.llvm_index += 1; + return .byval; + }, + 128 => { + it.types_buffer[0..2].* = .{ .i64, .i64 }; + it.offsets_buffer[0..3].* = .{ 0, 8, 16 }; + it.types_len = 2; + it.zig_index += 1; + it.llvm_index += 2; + return .multiple_llvm_types; + }, + }; + it.zig_index += 1; + it.llvm_index += 1; + return .byval; + }, .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty), .x86_64_win => return it.next_x86_64_win(ty), // TODO investigate other callconvs @@ -7277,7 +7324,7 @@ const ParamTypeIterator = struct { .x87 => { it.zig_index += 1; it.llvm_index += 1; - it.byval_attr = true; + it.byval_attr = .{}; return .byref; }, .x87up => unreachable, @@ -7285,7 +7332,7 @@ const ParamTypeIterator = struct { .memory => { it.zig_index += 1; it.llvm_index += 1; - it.byval_attr = true; + it.byval_attr = .{}; return .byref; }, .win_i128 => unreachable, // windows only @@ -7306,7 +7353,7 @@ const ParamTypeIterator = struct { if (it.llvm_index + classes_len > 6) { it.zig_index += 1; it.llvm_index += 1; - it.byval_attr = true; + it.byval_attr = .{}; return .byref; } } else if (!isByRef(ty, zcu)) { @@ -7340,7 +7387,7 @@ pub fn iterateParamTypes( .types_len = undefined, .types_buffer = undefined, .offsets_buffer = undefined, - .byval_attr = false, + .byval_attr = null, }; } @@ -7466,7 +7513,39 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A return .by_val; } else .sret, .x86_fastcall => fnReturnStrat_x86_fastcall(o, zcu, ret_ty), - .x86_sysv, .x86_win => if (isByRef(ret_ty, zcu)) .sret else .by_val, + .x86_sysv, .x86_win, .x86_mingw => if (isByRef(ret_ty, zcu)) { + switch (cc) { + else => unreachable, + .x86_sysv => return .sret, + .x86_win => {}, + .x86_mingw => { + var items_buf: [1]codegen.FlattenedItem = undefined; + if (codegen.flattenType(&items_buf, ret_ty, zcu, .{})) |items| one_float: { + if (items.len != 1 or items[0].offset != 0) break :one_float; + const item_ty = items[0].type orelse break :one_float; + if (!item_ty.isRuntimeFloat()) break :one_float; + return .{ .mem_cast = switch (item_ty.floatBits(zcu.getTarget())) { + else => unreachable, + 16 => .half, + 32 => .float, + 64 => .double, + 80, 128 => break :one_float, + } }; + } + }, + } + return switch (ret_ty.abiSize(zcu)) { + 0 => .void, + 1 => .{ .mem_cast = .i8 }, + 2 => .{ .mem_cast = .i16 }, + 4 => .{ .mem_cast = .i32 }, + 8 => .{ .mem_cast = .i64 }, + else => .sret, + }; + } else if (ret_ty.isAbiInt(zcu) and ret_ty.intInfo(zcu).bits > 64) + .sret + else + .by_val, .x86_64_sysv, .x86_64_x32 => fnReturnStrat_x86_64_sysv(o, ret_ty), .x86_64_win => fnReturnStrat_x86_64_win(o, ret_ty), // TODO investigate other callconvs diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 1b2aa830d23ee24903085a36db49ce1a42c91c72..52d0fc57a1d5238ac2fd837d10878083a94510c7 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -4151,8 +4151,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co .x86_64_regcall_v3_sysv => .LLVM_X86RegCall, .x86_64_regcall_v4_win => .LLVM_X86RegCall, .x86_64_vectorcall => .LLVM_vectorcall, - .x86_sysv => .normal, - .x86_win => .normal, + .x86_sysv, .x86_win, .x86_mingw => .normal, .x86_stdcall => .BORLAND_stdcall, .x86_fastcall => .BORLAND_msfastcall, .x86_thiscall => .BORLAND_thiscall, -- 2.54.0 From ba23bad8380f023455fed65e1631089f17e0535d Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 17 Jul 2026 06:01:26 -0400 Subject: [PATCH 17/22] x86_64: implement c abi for array fields Closes #36195 --- src/codegen/x86_64/abi.zig | 41 +++-- test/c_abi/cfuncs.c | 240 +++++++++++++++++++++++++ test/c_abi/main.zig | 350 +++++++++++++++++++++++++++++++++++++ 3 files changed, 621 insertions(+), 10 deletions(-) diff --git a/src/codegen/x86_64/abi.zig b/src/codegen/x86_64/abi.zig index 0bff5bd60a2f7e918dda9fd5835d653378686cff..1e01ff508af3a29367f9cfbb1ea74d412147d70a 100644 --- a/src/codegen/x86_64/abi.zig +++ b/src/codegen/x86_64/abi.zig @@ -358,11 +358,10 @@ fn classifySystemVStruct( while (field_it.next()) |field_index| { const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); const field_align = loaded_struct.field_aligns.getOrNone(ip, field_index); - byte_offset = std.mem.alignForward( - u64, - byte_offset, - field_align.toByteUnits() orelse field_ty.abiAlignment(zcu).toByteUnits().?, - ); + byte_offset = switch (field_align) { + .none => field_ty.abiAlignment(zcu), + else => field_align, + }.forward(byte_offset); if (zcu.typeToStruct(field_ty)) |field_loaded_struct| { switch (field_loaded_struct.layout) { .auto => unreachable, @@ -381,6 +380,9 @@ fn classifySystemVStruct( }, .@"packed" => {}, } + } else if (field_ty.zigTypeTag(zcu) == .array) { + byte_offset = classifySystemVArray(result, byte_offset, field_ty, zcu, target); + continue; } const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none); for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class| @@ -388,11 +390,7 @@ fn classifySystemVStruct( byte_offset += field_ty.abiSize(zcu); } const final_byte_offset = starting_byte_offset + loaded_struct.size; - std.debug.assert(final_byte_offset == std.mem.alignForward( - u64, - byte_offset, - loaded_struct.alignment.toByteUnits().?, - )); + std.debug.assert(final_byte_offset == loaded_struct.alignment.forward(byte_offset)); return final_byte_offset; } @@ -424,6 +422,9 @@ fn classifySystemVUnion( }, .@"packed" => {}, } + } else if (field_ty.zigTypeTag(zcu) == .array) { + _ = classifySystemVArray(result, starting_byte_offset, field_ty, zcu, target); + continue; } const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none); for (result[@intCast(starting_byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class| @@ -432,6 +433,26 @@ fn classifySystemVUnion( return starting_byte_offset + loaded_union.size; } +fn classifySystemVArray( + result: *[8]Class, + starting_byte_offset: u64, + array_ty: Type, + zcu: *Zcu, + target: *const std.Target, +) u64 { + const field_classes = std.mem.sliceTo(&classifySystemV(array_ty.childType(zcu), zcu, target, .other), .none); + var byte_offset = starting_byte_offset; + const elem_size = array_ty.childType(zcu).abiSize(zcu); + for (0..@intCast(array_ty.arrayLen(zcu))) |_| { + for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class| + result_class.* = result_class.combineSystemV(field_class); + byte_offset += elem_size; + } + const final_byte_offset = starting_byte_offset + array_ty.abiSize(zcu); + assert(final_byte_offset == byte_offset); + return final_byte_offset; +} + pub const zigcc = struct { pub const stack_align: ?InternPool.Alignment = null; pub const return_in_regs = true; diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index 91a33b24ad4d3ffbefc648495d1291491827677c..a1471283bfbc5ce35b9bdd4edd6e6cb6df81d831 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -15194,6 +15194,126 @@ void c_test_struct_f32_f32_f32_f32_f32(void) { zig_struct_f32_f32_f32_f32_f32((struct Struct_f32_f32_f32_f32_f32){ .a = 6, .b = 7, .c = 8, .d = 9, .e = 10 }, 11); } +struct Struct_array_1_f32 { + float a[1]; +}; + +struct Struct_array_1_f32 zig_ret_struct_array_1_f32(void); +void zig_struct_array_1_f32(struct Struct_array_1_f32, size_t); + +struct Struct_array_1_f32 c_ret_struct_array_1_f32(void) { + return (struct Struct_array_1_f32){ .a = { 4 } }; +} +void c_struct_array_1_f32(struct Struct_array_1_f32 s, size_t i) { + assert_or_panic(s.a[0] == 5); + assert_or_panic(i == 6); +} +void c_test_struct_array_1_f32(void) { + struct Struct_array_1_f32 s = zig_ret_struct_array_1_f32(); + assert_or_panic(s.a[0] == 1); + zig_struct_array_1_f32((struct Struct_array_1_f32){ .a = { 2 } }, 3); +} + +struct Struct_array_2_f32 { + float a[2]; +}; + +struct Struct_array_2_f32 zig_ret_struct_array_2_f32(void); +void zig_struct_array_2_f32(struct Struct_array_2_f32, size_t); + +struct Struct_array_2_f32 c_ret_struct_array_2_f32(void) { + return (struct Struct_array_2_f32){ .a = { 6, 7 } }; +} +void c_struct_array_2_f32(struct Struct_array_2_f32 s, size_t i) { + assert_or_panic(s.a[0] == 8); + assert_or_panic(s.a[1] == 9); + assert_or_panic(i == 10); +} +void c_test_struct_array_2_f32(void) { + struct Struct_array_2_f32 s = zig_ret_struct_array_2_f32(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + zig_struct_array_2_f32((struct Struct_array_2_f32){ .a = { 3, 4 } }, 5); +} + +struct Struct_array_3_f32 { + float a[3]; +}; + +struct Struct_array_3_f32 zig_ret_struct_array_3_f32(void); +void zig_struct_array_3_f32(struct Struct_array_3_f32, size_t); + +struct Struct_array_3_f32 c_ret_struct_array_3_f32(void) { + return (struct Struct_array_3_f32){ .a = { 8, 9, 10 } }; +} +void c_struct_array_3_f32(struct Struct_array_3_f32 s, size_t i) { + assert_or_panic(s.a[0] == 11); + assert_or_panic(s.a[1] == 12); + assert_or_panic(s.a[2] == 13); + assert_or_panic(i == 14); +} +void c_test_struct_array_3_f32(void) { + struct Struct_array_3_f32 s = zig_ret_struct_array_3_f32(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + zig_struct_array_3_f32((struct Struct_array_3_f32){ .a = { 4, 5, 6 } }, 7); +} + +struct Struct_array_4_f32 { + float a[4]; +}; + +struct Struct_array_4_f32 zig_ret_struct_array_4_f32(void); +void zig_struct_array_4_f32(struct Struct_array_4_f32, size_t); + +struct Struct_array_4_f32 c_ret_struct_array_4_f32(void) { + return (struct Struct_array_4_f32){ .a = { 10, 11, 12, 13 } }; +} +void c_struct_array_4_f32(struct Struct_array_4_f32 s, size_t i) { + assert_or_panic(s.a[0] == 14); + assert_or_panic(s.a[1] == 15); + assert_or_panic(s.a[2] == 16); + assert_or_panic(s.a[3] == 17); + assert_or_panic(i == 18); +} +void c_test_struct_array_4_f32(void) { + struct Struct_array_4_f32 s = zig_ret_struct_array_4_f32(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + assert_or_panic(s.a[3] == 4); + zig_struct_array_4_f32((struct Struct_array_4_f32){ .a = { 5, 6, 7, 8 } }, 9); +} + +struct Struct_array_5_f32 { + float a[5]; +}; + +struct Struct_array_5_f32 zig_ret_struct_array_5_f32(void); +void zig_struct_array_5_f32(struct Struct_array_5_f32, size_t); + +struct Struct_array_5_f32 c_ret_struct_array_5_f32(void) { + return (struct Struct_array_5_f32){ .a = { 12, 13, 14, 15, 16 } }; +} +void c_struct_array_5_f32(struct Struct_array_5_f32 s, size_t i) { + assert_or_panic(s.a[0] == 17); + assert_or_panic(s.a[1] == 18); + assert_or_panic(s.a[2] == 19); + assert_or_panic(s.a[3] == 20); + assert_or_panic(s.a[4] == 21); + assert_or_panic(i == 22); +} +void c_test_struct_array_5_f32(void) { + struct Struct_array_5_f32 s = zig_ret_struct_array_5_f32(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + assert_or_panic(s.a[3] == 4); + assert_or_panic(s.a[4] == 5); + zig_struct_array_5_f32((struct Struct_array_5_f32){ .a = { 6, 7, 8, 9, 10 } }, 11); +} + struct Struct_f32a8 { alignas(8) float a; }; @@ -15409,6 +15529,126 @@ void c_test_struct_f64_f64_f64_f64_f64(void) { zig_struct_f64_f64_f64_f64_f64((struct Struct_f64_f64_f64_f64_f64){ .a = 6, .b = 7, .c = 8, .d = 9, .e = 10 }, 11); } +struct Struct_array_1_f64 { + double a[1]; +}; + +struct Struct_array_1_f64 zig_ret_struct_array_1_f64(void); +void zig_struct_array_1_f64(struct Struct_array_1_f64, size_t); + +struct Struct_array_1_f64 c_ret_struct_array_1_f64(void) { + return (struct Struct_array_1_f64){ .a = { 4 } }; +} +void c_struct_array_1_f64(struct Struct_array_1_f64 s, size_t i) { + assert_or_panic(s.a[0] == 5); + assert_or_panic(i == 6); +} +void c_test_struct_array_1_f64(void) { + struct Struct_array_1_f64 s = zig_ret_struct_array_1_f64(); + assert_or_panic(s.a[0] == 1); + zig_struct_array_1_f64((struct Struct_array_1_f64){ .a = { 2 } }, 3); +} + +struct Struct_array_2_f64 { + double a[2]; +}; + +struct Struct_array_2_f64 zig_ret_struct_array_2_f64(void); +void zig_struct_array_2_f64(struct Struct_array_2_f64, size_t); + +struct Struct_array_2_f64 c_ret_struct_array_2_f64(void) { + return (struct Struct_array_2_f64){ .a = { 6, 7 } }; +} +void c_struct_array_2_f64(struct Struct_array_2_f64 s, size_t i) { + assert_or_panic(s.a[0] == 8); + assert_or_panic(s.a[1] == 9); + assert_or_panic(i == 10); +} +void c_test_struct_array_2_f64(void) { + struct Struct_array_2_f64 s = zig_ret_struct_array_2_f64(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + zig_struct_array_2_f64((struct Struct_array_2_f64){ .a = { 3, 4 } }, 5); +} + +struct Struct_array_3_f64 { + double a[3]; +}; + +struct Struct_array_3_f64 zig_ret_struct_array_3_f64(void); +void zig_struct_array_3_f64(struct Struct_array_3_f64, size_t); + +struct Struct_array_3_f64 c_ret_struct_array_3_f64(void) { + return (struct Struct_array_3_f64){ .a = { 8, 9, 10 } }; +} +void c_struct_array_3_f64(struct Struct_array_3_f64 s, size_t i) { + assert_or_panic(s.a[0] == 11); + assert_or_panic(s.a[1] == 12); + assert_or_panic(s.a[2] == 13); + assert_or_panic(i == 14); +} +void c_test_struct_array_3_f64(void) { + struct Struct_array_3_f64 s = zig_ret_struct_array_3_f64(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + zig_struct_array_3_f64((struct Struct_array_3_f64){ .a = { 4, 5, 6 } }, 7); +} + +struct Struct_array_4_f64 { + double a[4]; +}; + +struct Struct_array_4_f64 zig_ret_struct_array_4_f64(void); +void zig_struct_array_4_f64(struct Struct_array_4_f64, size_t); + +struct Struct_array_4_f64 c_ret_struct_array_4_f64(void) { + return (struct Struct_array_4_f64){ .a = { 10, 11, 12, 13 } }; +} +void c_struct_array_4_f64(struct Struct_array_4_f64 s, size_t i) { + assert_or_panic(s.a[0] == 14); + assert_or_panic(s.a[1] == 15); + assert_or_panic(s.a[2] == 16); + assert_or_panic(s.a[3] == 17); + assert_or_panic(i == 18); +} +void c_test_struct_array_4_f64(void) { + struct Struct_array_4_f64 s = zig_ret_struct_array_4_f64(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + assert_or_panic(s.a[3] == 4); + zig_struct_array_4_f64((struct Struct_array_4_f64){ .a = { 5, 6, 7, 8 } }, 9); +} + +struct Struct_array_5_f64 { + double a[5]; +}; + +struct Struct_array_5_f64 zig_ret_struct_array_5_f64(void); +void zig_struct_array_5_f64(struct Struct_array_5_f64, size_t); + +struct Struct_array_5_f64 c_ret_struct_array_5_f64(void) { + return (struct Struct_array_5_f64){ .a = { 12, 13, 14, 15, 16 } }; +} +void c_struct_array_5_f64(struct Struct_array_5_f64 s, size_t i) { + assert_or_panic(s.a[0] == 17); + assert_or_panic(s.a[1] == 18); + assert_or_panic(s.a[2] == 19); + assert_or_panic(s.a[3] == 20); + assert_or_panic(s.a[4] == 21); + assert_or_panic(i == 22); +} +void c_test_struct_array_5_f64(void) { + struct Struct_array_5_f64 s = zig_ret_struct_array_5_f64(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + assert_or_panic(s.a[3] == 4); + assert_or_panic(s.a[4] == 5); + zig_struct_array_5_f64((struct Struct_array_5_f64){ .a = { 6, 7, 8, 9, 10 } }, 11); +} + struct Struct_u32_Union_u32_u32u32 { uint32_t a; union { diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index f1bbd96806d3b507ee0448f4415f811aae2d929a..16b99134cf70bc44a77179f48c68704d7a9041ec 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -16085,6 +16085,181 @@ test "struct f32, f32, f32, f32, f32" { c_test_struct_f32_f32_f32_f32_f32(); } +const Struct_array_1_f32 = extern struct { + a: [1]f32, +}; + +comptime { + skip: { + if (builtin.cpu.arch.isWasm()) break :skip; + + _ = struct { + export fn zig_ret_struct_array_1_f32() Struct_array_1_f32 { + return .{ .a = .{1} }; + } + export fn zig_struct_array_1_f32(s: Struct_array_1_f32, i: usize) void { + expect(s.a[0] == 2) catch @panic("test failure"); + expect(i == 3) catch @panic("test failure"); + } + }; + } +} + +extern fn c_ret_struct_array_1_f32() Struct_array_1_f32; +extern fn c_struct_array_1_f32(Struct_array_1_f32, usize) void; +extern fn c_test_struct_array_1_f32() void; + +test "struct [1]f32" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; + if (builtin.cpu.arch == .s390x) return error.SkipZigTest; + if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; + + const s = c_ret_struct_array_1_f32(); + try expect(s.a[0] == 4); + c_struct_array_1_f32(.{ .a = .{5} }, 6); + c_test_struct_array_1_f32(); +} + +const Struct_array_2_f32 = extern struct { + a: [2]f32, +}; + +export fn zig_ret_struct_array_2_f32() Struct_array_2_f32 { + return .{ .a = .{ 1, 2 } }; +} +export fn zig_struct_array_2_f32(s: Struct_array_2_f32, i: usize) void { + expect(s.a[0] == 3) catch @panic("test failure"); + expect(s.a[1] == 4) catch @panic("test failure"); + expect(i == 5) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_2_f32() Struct_array_2_f32; +extern fn c_struct_array_2_f32(Struct_array_2_f32, usize) void; +extern fn c_test_struct_array_2_f32() void; + +test "struct [2]f32" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64 and builtin.abi.float() == .hard) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; + + const s = c_ret_struct_array_2_f32(); + try expect(s.a[0] == 6); + try expect(s.a[1] == 7); + c_struct_array_2_f32(.{ .a = .{ 8, 9 } }, 10); + c_test_struct_array_2_f32(); +} + +const Struct_array_3_f32 = extern struct { + a: [3]f32, +}; + +export fn zig_ret_struct_array_3_f32() Struct_array_3_f32 { + return .{ .a = .{ 1, 2, 3 } }; +} +export fn zig_struct_array_3_f32(s: Struct_array_3_f32, i: usize) void { + expect(s.a[0] == 4) catch @panic("test failure"); + expect(s.a[1] == 5) catch @panic("test failure"); + expect(s.a[2] == 6) catch @panic("test failure"); + expect(i == 7) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_3_f32() Struct_array_3_f32; +extern fn c_struct_array_3_f32(Struct_array_3_f32, usize) void; +extern fn c_test_struct_array_3_f32() void; + +test "struct [3]f32" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_3_f32(); + try expect(s.a[0] == 8); + try expect(s.a[1] == 9); + try expect(s.a[2] == 10); + c_struct_array_3_f32(.{ .a = .{ 11, 12, 13 } }, 14); + c_test_struct_array_3_f32(); +} + +const Struct_array_4_f32 = extern struct { + a: [4]f32, +}; + +export fn zig_ret_struct_array_4_f32() Struct_array_4_f32 { + return .{ .a = .{ 1, 2, 3, 4 } }; +} +export fn zig_struct_array_4_f32(s: Struct_array_4_f32, i: usize) void { + expect(s.a[0] == 5) catch @panic("test failure"); + expect(s.a[1] == 6) catch @panic("test failure"); + expect(s.a[2] == 7) catch @panic("test failure"); + expect(s.a[3] == 8) catch @panic("test failure"); + expect(i == 9) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_4_f32() Struct_array_4_f32; +extern fn c_struct_array_4_f32(Struct_array_4_f32, usize) void; +extern fn c_test_struct_array_4_f32() void; + +test "struct [4]f32" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_4_f32(); + try expect(s.a[0] == 10); + try expect(s.a[1] == 11); + try expect(s.a[2] == 12); + try expect(s.a[3] == 13); + c_struct_array_4_f32(.{ .a = .{ 14, 15, 16, 17 } }, 18); + c_test_struct_array_4_f32(); +} + +const Struct_array_5_f32 = extern struct { + a: [5]f32, +}; + +export fn zig_ret_struct_array_5_f32() Struct_array_5_f32 { + return .{ .a = .{ 1, 2, 3, 4, 5 } }; +} +export fn zig_struct_array_5_f32(s: Struct_array_5_f32, i: usize) void { + expect(s.a[0] == 6) catch @panic("test failure"); + expect(s.a[1] == 7) catch @panic("test failure"); + expect(s.a[2] == 8) catch @panic("test failure"); + expect(s.a[3] == 9) catch @panic("test failure"); + expect(s.a[4] == 10) catch @panic("test failure"); + expect(i == 11) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_5_f32() Struct_array_5_f32; +extern fn c_struct_array_5_f32(Struct_array_5_f32, usize) void; +extern fn c_test_struct_array_5_f32() void; + +test "struct [5]f32" { + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_5_f32(); + try expect(s.a[0] == 12); + try expect(s.a[1] == 13); + try expect(s.a[2] == 14); + try expect(s.a[3] == 15); + try expect(s.a[4] == 16); + c_struct_array_5_f32(.{ .a = .{ 17, 18, 19, 20, 21 } }, 22); + c_test_struct_array_5_f32(); +} + const Struct_f32a8 = extern struct { a: f32 align(8), }; @@ -16382,6 +16557,181 @@ test "struct f64, f64, f64, f64, f64" { c_test_struct_f64_f64_f64_f64_f64(); } +const Struct_array_1_f64 = extern struct { + a: [1]f64, +}; + +comptime { + skip: { + if (builtin.cpu.arch.isWasm()) break :skip; + + _ = struct { + export fn zig_ret_struct_array_1_f64() Struct_array_1_f64 { + return .{ .a = .{1} }; + } + export fn zig_struct_array_1_f64(s: Struct_array_1_f64, i: usize) void { + expect(s.a[0] == 2) catch @panic("test failure"); + expect(i == 3) catch @panic("test failure"); + } + }; + } +} + +extern fn c_ret_struct_array_1_f64() Struct_array_1_f64; +extern fn c_struct_array_1_f64(Struct_array_1_f64, usize) void; +extern fn c_test_struct_array_1_f64() void; + +test "struct [1]f64" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; + if (builtin.cpu.arch == .s390x) return error.SkipZigTest; + if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; + + const s = c_ret_struct_array_1_f64(); + try expect(s.a[0] == 4); + c_struct_array_1_f64(.{ .a = .{5} }, 6); + c_test_struct_array_1_f64(); +} + +const Struct_array_2_f64 = extern struct { + a: [2]f64, +}; + +export fn zig_ret_struct_array_2_f64() Struct_array_2_f64 { + return .{ .a = .{ 1, 2 } }; +} +export fn zig_struct_array_2_f64(s: Struct_array_2_f64, i: usize) void { + expect(s.a[0] == 3) catch @panic("test failure"); + expect(s.a[1] == 4) catch @panic("test failure"); + expect(i == 5) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_2_f64() Struct_array_2_f64; +extern fn c_struct_array_2_f64(Struct_array_2_f64, usize) void; +extern fn c_test_struct_array_2_f64() void; + +test "struct [2]f64" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64 and builtin.abi.float() == .hard) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; + + const s = c_ret_struct_array_2_f64(); + try expect(s.a[0] == 6); + try expect(s.a[1] == 7); + c_struct_array_2_f64(.{ .a = .{ 8, 9 } }, 10); + c_test_struct_array_2_f64(); +} + +const Struct_array_3_f64 = extern struct { + a: [3]f64, +}; + +export fn zig_ret_struct_array_3_f64() Struct_array_3_f64 { + return .{ .a = .{ 1, 2, 3 } }; +} +export fn zig_struct_array_3_f64(s: Struct_array_3_f64, i: usize) void { + expect(s.a[0] == 4) catch @panic("test failure"); + expect(s.a[1] == 5) catch @panic("test failure"); + expect(s.a[2] == 6) catch @panic("test failure"); + expect(i == 7) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_3_f64() Struct_array_3_f64; +extern fn c_struct_array_3_f64(Struct_array_3_f64, usize) void; +extern fn c_test_struct_array_3_f64() void; + +test "struct [3]f64" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_3_f64(); + try expect(s.a[0] == 8); + try expect(s.a[1] == 9); + try expect(s.a[2] == 10); + c_struct_array_3_f64(.{ .a = .{ 11, 12, 13 } }, 14); + c_test_struct_array_3_f64(); +} + +const Struct_array_4_f64 = extern struct { + a: [4]f64, +}; + +export fn zig_ret_struct_array_4_f64() Struct_array_4_f64 { + return .{ .a = .{ 1, 2, 3, 4 } }; +} +export fn zig_struct_array_4_f64(s: Struct_array_4_f64, i: usize) void { + expect(s.a[0] == 5) catch @panic("test failure"); + expect(s.a[1] == 6) catch @panic("test failure"); + expect(s.a[2] == 7) catch @panic("test failure"); + expect(s.a[3] == 8) catch @panic("test failure"); + expect(i == 9) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_4_f64() Struct_array_4_f64; +extern fn c_struct_array_4_f64(Struct_array_4_f64, usize) void; +extern fn c_test_struct_array_4_f64() void; + +test "struct [4]f64" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_4_f64(); + try expect(s.a[0] == 10); + try expect(s.a[1] == 11); + try expect(s.a[2] == 12); + try expect(s.a[3] == 13); + c_struct_array_4_f64(.{ .a = .{ 14, 15, 16, 17 } }, 18); + c_test_struct_array_4_f64(); +} + +const Struct_array_5_f64 = extern struct { + a: [5]f64, +}; + +export fn zig_ret_struct_array_5_f64() Struct_array_5_f64 { + return .{ .a = .{ 1, 2, 3, 4, 5 } }; +} +export fn zig_struct_array_5_f64(s: Struct_array_5_f64, i: usize) void { + expect(s.a[0] == 6) catch @panic("test failure"); + expect(s.a[1] == 7) catch @panic("test failure"); + expect(s.a[2] == 8) catch @panic("test failure"); + expect(s.a[3] == 9) catch @panic("test failure"); + expect(s.a[4] == 10) catch @panic("test failure"); + expect(i == 11) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_5_f64() Struct_array_5_f64; +extern fn c_struct_array_5_f64(Struct_array_5_f64, usize) void; +extern fn c_test_struct_array_5_f64() void; + +test "struct [5]f64" { + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_5_f64(); + try expect(s.a[0] == 12); + try expect(s.a[1] == 13); + try expect(s.a[2] == 14); + try expect(s.a[3] == 15); + try expect(s.a[4] == 16); + c_struct_array_5_f64(.{ .a = .{ 17, 18, 19, 20, 21 } }, 22); + c_test_struct_array_5_f64(); +} + const Struct_u32_Union_u32_u32u32 = extern struct { a: u32, b: extern union { -- 2.54.0 From 6c003e84338bc1f8ceaf7ca869cb343b31be9fc7 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 17 Jul 2026 20:26:56 -0400 Subject: [PATCH 18/22] x86_64: update for compiler_rt abi changes --- src/codegen/x86_64/CodeGen.zig | 128 --------------------------------- 1 file changed, 128 deletions(-) diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 662fc600b1e863b89bdfc0f8719545786ac64dac..4958d17e304cb7cccc3e4b383bd46e1d09141c0a 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -125531,7 +125531,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ ._, ._, .call, .tmp1d, ._, ._, ._ }, } }, }, .{ - .required_cc_abi = .sysv64, .required_features = .{ .sse, null, null, null }, .src_constraints = .{ .{ .unsigned_int = .xword }, .any, .any }, .dst_constraints = .{ .{ .float = .xword }, .any }, @@ -125557,34 +125556,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .each = .{ .once = &.{ .{ ._, ._, .call, .tmp0d, ._, ._, ._ }, } }, - }, .{ - .required_cc_abi = .win64, - .required_features = .{ .sse, null, null, null }, - .src_constraints = .{ .{ .unsigned_int = .xword }, .any, .any }, - .dst_constraints = .{ .{ .float = .xword }, .any }, - .patterns = &.{ - .{ .src = .{ .to_mem, .none, .none } }, - }, - .call_frame = .{ .alignment = .@"16" }, - .extra_temps = .{ - .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } }, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - }, - .dst_temps = .{ .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } }, .unused }, - .clobbers = .{ .eflags = true, .caller_preserved = .ccc }, - .each = .{ .once = &.{ - .{ ._, ._, .lea, .tmp0p, .mem(.src0), ._, ._ }, - .{ ._, ._, .call, .tmp1d, ._, ._, ._ }, - } }, }, .{ .required_features = .{ .@"64bit", .sse, null, null }, .src_constraints = .{ .{ .remainder_signed_int = .{ .of = .dword, .is = .dword } }, .any, .any }, @@ -126791,7 +126762,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, } }, }, .{ - .required_cc_abi = .sysv64, .required_features = .{ .avx, null, null, null }, .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, @@ -126824,39 +126794,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, } }, }, .{ - .required_cc_abi = .win64, - .required_features = .{ .avx, null, null, null }, - .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, - .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, - .patterns = &.{ - .{ .src = .{ .to_mem, .none, .none } }, - }, - .call_frame = .{ .alignment = .@"16" }, - .extra_temps = .{ - .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, - .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } }, - .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - }, - .dst_temps = .{ .mem, .unused }, - .clobbers = .{ .eflags = true, .caller_preserved = .ccc }, - .each = .{ .once = &.{ - .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ }, - .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ }, - .{ ._, ._, .call, .tmp2d, ._, ._, ._ }, - .{ ._, .v_dqa, .mov, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ }, - .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ }, - .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, - } }, - }, .{ - .required_cc_abi = .sysv64, .required_features = .{ .sse2, null, null, null }, .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, @@ -126889,39 +126826,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, } }, }, .{ - .required_cc_abi = .win64, - .required_features = .{ .sse2, null, null, null }, - .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, - .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, - .patterns = &.{ - .{ .src = .{ .to_mem, .none, .none } }, - }, - .call_frame = .{ .alignment = .@"16" }, - .extra_temps = .{ - .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, - .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } }, - .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - }, - .dst_temps = .{ .mem, .unused }, - .clobbers = .{ .eflags = true, .caller_preserved = .ccc }, - .each = .{ .once = &.{ - .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ }, - .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ }, - .{ ._, ._, .call, .tmp2d, ._, ._, ._ }, - .{ ._, ._dqa, .mov, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ }, - .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ }, - .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, - } }, - }, .{ - .required_cc_abi = .sysv64, .required_features = .{ .sse, null, null, null }, .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, @@ -126953,38 +126857,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ }, .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, } }, - }, .{ - .required_cc_abi = .win64, - .required_features = .{ .sse, null, null, null }, - .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, - .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, - .patterns = &.{ - .{ .src = .{ .to_mem, .none, .none } }, - }, - .call_frame = .{ .alignment = .@"16" }, - .extra_temps = .{ - .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, - .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } }, - .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - }, - .dst_temps = .{ .mem, .unused }, - .clobbers = .{ .eflags = true, .caller_preserved = .ccc }, - .each = .{ .once = &.{ - .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ }, - .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ }, - .{ ._, ._, .call, .tmp2d, ._, ._, ._ }, - .{ ._, ._ps, .mova, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ }, - .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ }, - .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, - } }, }, .{ .required_features = .{ .@"64bit", .avx, null, null }, .src_constraints = .{ .{ .scalar_remainder_signed_int = .{ .of = .dword, .is = .dword } }, .any, .any }, -- 2.54.0 From e03056d45a864c8176cdd897d771457005ead592 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 17 Jul 2026 15:44:14 -0400 Subject: [PATCH 19/22] cbe: various calling convention fixes - Annotate function pointers with calling convention. - Support `incoming_stack_alignment`. - Fix noreturn attribute position. --- lib/zig.h | 19 +--- src/Zcu.zig | 30 +---- src/codegen/c.zig | 142 +++++++---------------- src/codegen/c/type.zig | 177 ++++++++++++++++++++++++++++- src/codegen/c/type/render_defs.zig | 16 +-- src/codegen/llvm.zig | 4 +- 6 files changed, 239 insertions(+), 149 deletions(-) diff --git a/lib/zig.h b/lib/zig.h index 139263d11132833d2c64539c2b39cf44b3bd0b89..30e6f3f96a97f47b6648db1d1587bc75c88b6c3f 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -199,10 +199,8 @@ #endif #if defined(zig_msvc) -#define zig_const_arr #define zig_callconv(c) __##c #else -#define zig_const_arr static const #define zig_callconv(c) __attribute__((c)) #endif @@ -5841,11 +5839,6 @@ typedef zig_u128 zig_f80; #define zig_init_special_f80(sign, name, arg, repr) repr #endif -#if defined(zig_gcc) && defined(zig_x86) -#define zig_f128_has_miscompilations 1 -#else -#define zig_f128_has_miscompilations 0 -#endif #define zig_has_f128 1 #define zig_libc_name_f128(name) name##f128 #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) @@ -5859,22 +5852,22 @@ typedef struct { uint64_t hi, lo; } zig_f128; #define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo } #define zig_lo_repr_f128(arg) (arg).lo #define zig_hi_repr_f128(arg) (arg).hi -#elif !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 +#elif FLT_MANT_DIG == 113 typedef float zig_f128; #define zig_make_f128(fp, repr) fp##f -#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 +#elif DBL_MANT_DIG == 113 typedef double zig_f128; #define zig_make_f128(fp, repr) fp -#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113 +#elif LDBL_MANT_DIG == 113 typedef long double zig_f128; #define zig_make_f128(fp, repr) fp##l -#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113 +#elif FLT128_MANT_DIG == 113 typedef _Float128 zig_f128; #define zig_make_f128(fp, repr) fp##f128 -#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113 +#elif FLT64X_MANT_DIG == 113 typedef _Float64x zig_f128; #define zig_make_f128(fp, repr) fp##f64x -#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__) +#elif defined(__SIZEOF_FLOAT128__) typedef __float128 zig_f128; #define zig_make_f128(fp, repr) fp##q #undef zig_make_special_f128 diff --git a/src/Zcu.zig b/src/Zcu.zig index 2af36db254d2edbcfe3ae8a05de265b882d46b01..875ffd44b29c92738f12e3cf32f300301edf2d7d 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4617,44 +4617,26 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) .m68k_rtd, .m68k_interrupt, .msp430_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .arm_aapcs_vfp, - => |opts| opts.incoming_stack_alignment == null, - .arc_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .arm_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .microblaze_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .mips_interrupt, .mips64_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .riscv32_interrupt, .riscv64_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .sh_interrupt, - => |opts| opts.incoming_stack_alignment == null, + .avr_interrupt, + .avr_signal, + .ez80_tiflags, + .naked, + => true, // incoming stack alignment supported .x86_sysv, .x86_win, .x86_mingw, .x86_stdcall, - => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, - - .avr_interrupt, - .avr_signal, - => true, - - .ez80_tiflags => true, - - .naked => true, + => |opts| opts.register_params == 0, // incoming stack alignment supported else => false, }; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 1633321426dfc3044177eebe0cd44e6fda3c6aa9..5ab86a9a5fad9e1a4391053bd5e1af970de1feeb 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1750,8 +1750,6 @@ pub const DeclGen = struct { try w.writeAll("zig_no_builtin "); } - if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); - // While incomplete types are usually an acceptable substitute for "void", this is not true // in function return types, where "void" is the only incomplete type permitted. const actual_return_type: Type = .fromInterned(fn_info.return_type); @@ -1763,8 +1761,9 @@ pub const DeclGen = struct { const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu); try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)}); - if (toCallingConvention(fn_info.cc, zcu)) |call_conv| { - try w.print("zig_callconv({s}) ", .{call_conv}); + switch (CType.CallingConvention.fromLang(fn_info.cc, zcu.getTarget())) { + .c => {}, + else => |cc| try w.print("zig_callconv({t}) ", .{cc}), } switch (name) { .nav => |nav| try renderNavName(w, nav, ip), @@ -2221,6 +2220,7 @@ pub fn genLazyCallModifierFn( const fn_val = zcu.navValue(fn_nav); + if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn "); try w.print("static zig_{t} ", .{kind}); try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) { .never_tail => .{ .nav_never_tail = fn_nav }, @@ -2326,8 +2326,10 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E const gpa = f.dg.gpa; const nav_index = f.dg.owner_nav.unwrap().?; const nav_val = zcu.navValue(nav_index); + const fn_info = zcu.typeToFunc(nav_val.typeOf(zcu)).?; const nav = ip.getNav(nav_index); + if (Type.fromInterned(fn_info.return_type).isNoReturn(zcu)) try fwd_decl_writer.writeAll("zig_noreturn "); try fwd_decl_writer.writeAll("static "); try f.dg.renderFunctionSignature( fwd_decl_writer, @@ -2354,6 +2356,35 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E const main_body = f.air.getMainBody(); f.indent(); + if (switch (fn_info.cc) { + inline else => |pl| switch (@TypeOf(pl)) { + void, + std.lang.CallingConvention.SpirvKernelOptions, + std.lang.CallingConvention.SpirvFragmentOptions, + std.lang.CallingConvention.SpirvMeshOptions, + => null, + std.lang.CallingConvention.ArcInterruptOptions, + std.lang.CallingConvention.ArmInterruptOptions, + std.lang.CallingConvention.RiscvInterruptOptions, + std.lang.CallingConvention.ShInterruptOptions, + std.lang.CallingConvention.MicroblazeInterruptOptions, + std.lang.CallingConvention.MipsInterruptOptions, + std.lang.CallingConvention.CommonOptions, + std.lang.CallingConvention.X86RegparmOptions, + => pl.incoming_stack_alignment, + else => @compileError(@tagName(pl)), + }, + }) |incoming_stack_alignment| realign_stack: { + const normal_stack_align = zcu.getTarget().stackAlignment(); + if (incoming_stack_alignment >= normal_stack_align) break :realign_stack; + try header_writer.print("char zig_align({d}) zig_realign_stack;\n ", .{ + normal_stack_align << 1, + }); + try f.code.writer.writeAll( + \\__asm volatile("" :: [zig_realign_stack] "m" (zig_realign_stack)); + ); + try f.newline(); + } try genBodyResolveState(f, undefined, &.{}, main_body, true); try f.outdent(); try f.code.writer.writeByte('}'); @@ -2456,10 +2487,12 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void { .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) { .@"fn" => { + const fn_val: Value = .fromInterned(nav.resolved.?.value); + if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn "); try w.writeAll("zig_extern "); try dg.renderFunctionSignature( w, - .fromInterned(nav.resolved.?.value), + fn_val, nav.resolved.?.@"align", .forward_decl, .{ .@"export" = .{ @@ -2560,11 +2593,13 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic const exported_val = exported.getValue(zcu); if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| { const @"export" = export_index.ptr(zcu); + const fn_val = exported.getValue(zcu); + if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn "); try w.writeAll("zig_extern "); if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn "); try dg.renderFunctionSignature( w, - exported.getValue(zcu), + fn_val, exported.getAlign(zcu), .forward_decl, .{ .@"export" = .{ @@ -7277,101 +7312,6 @@ fn writeMemoryOrder(w: *Writer, order: std.lang.AtomicOrder) !void { return w.writeAll(toMemoryOrder(order)); } -fn toCallingConvention(cc: std.lang.CallingConvention, zcu: *Zcu) ?[]const u8 { - if (zcu.getTarget().cCallingConvention()) |ccc| { - if (cc.eql(ccc)) { - return null; - } - } - return switch (cc) { - .auto, .naked => null, - - .x86_16_cdecl => "cdecl", - .x86_16_regparmcall => "regparmcall", - .x86_64_sysv, .x86_sysv => "sysv_abi", - .x86_64_win, .x86_win, .x86_mingw => "ms_abi", - .x86_16_stdcall, .x86_stdcall => "stdcall", - .x86_fastcall => "fastcall", - .x86_thiscall => "thiscall", - - .x86_vectorcall, - .x86_64_vectorcall, - => "vectorcall", - - .x86_64_regcall_v3_sysv, - .x86_64_regcall_v4_win, - .x86_regcall_v3, - .x86_regcall_v4_win, - => "regcall", - - .aarch64_vfabi => "aarch64_vector_pcs", - .aarch64_vfabi_sve => "aarch64_sve_pcs", - - .arm_aapcs => "pcs(\"aapcs\")", - .arm_aapcs_vfp => "pcs(\"aapcs-vfp\")", - - .arc_interrupt => |opts| switch (opts.type) { - inline else => |t| "interrupt(\"" ++ @tagName(t) ++ "\")", - }, - - .arm_interrupt => |opts| switch (opts.type) { - .generic => "interrupt", - .irq => "interrupt(\"IRQ\")", - .fiq => "interrupt(\"FIQ\")", - .swi => "interrupt(\"SWI\")", - .abort => "interrupt(\"ABORT\")", - .undef => "interrupt(\"UNDEF\")", - }, - - .avr_signal => "signal", - - .microblaze_interrupt => |opts| switch (opts.type) { - .user => "save_volatiles", - .regular => "interrupt_handler", - .fast => "fast_interrupt", - .breakpoint => "break_handler", - }, - - .mips_interrupt, - .mips64_interrupt, - => |opts| switch (opts.mode) { - inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")", - }, - - .riscv64_lp64_v, .riscv32_ilp32_v => "riscv_vector_cc", - - .riscv32_interrupt, - .riscv64_interrupt, - => |opts| switch (opts.mode) { - inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")", - }, - - .sh_renesas => "renesas", - .sh_interrupt => |opts| switch (opts.save) { - .fpscr => "trapa_handler", // Implies `interrupt_handler`. - .high => "interrupt_handler, nosave_low_regs", - .full => "interrupt_handler", - .bank => "interrupt_handler, resbank", - }, - - .m68k_rtd => "m68k_rtd", - - .avr_interrupt, - .csky_interrupt, - .m68k_interrupt, - .msp430_interrupt, - .x86_16_interrupt, - .x86_interrupt, - .x86_64_interrupt, - => "interrupt", - - .ez80_tiflags, - => "__tiflags__", - - else => unreachable, // `Zcu.callconvSupported` - }; -} - fn toAtomicRmwSuffix(order: std.lang.AtomicRmwOp) []const u8 { return switch (order) { .Xchg => "xchg", diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 41ce79a2f5ef333ad5d319f0fbbdd544d9347409..347dc7e16e27dce1c3dd41b006f860f5772fce6c 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -44,8 +44,175 @@ pub const CType = union(enum) { param_tys: []const CType, ret_ty: *const CType, varargs: bool, + cc: CallingConvention, }, + pub const CallingConvention = enum { + c, + + cdecl, + regparmcall, + sysv_abi, + ms_abi, + stdcall, + fastcall, + thiscall, + + vectorcall, + + regcall, + + aarch64_vector_pcs, + aarch64_sve_pcs, + + @"pcs(\"aapcs\")", + @"pcs(\"aapcs-vfp\")", + + @"interrupt(\"ilink1\")", + @"interrupt(\"ilink2\")", + @"interrupt(\"ilink\")", + @"interrupt(\"firq\")", + + interrupt, + @"interrupt(\"IRQ\")", + @"interrupt(\"FIQ\")", + @"interrupt(\"SWI\")", + @"interrupt(\"ABORT\")", + @"interrupt(\"UNDEF\")", + + signal, + + save_volatiles, + interrupt_handler, + fast_interrupt, + break_handler, + + @"interrupt(\"eic\")", + @"interrupt(\"sw0\")", + @"interrupt(\"sw1\")", + @"interrupt(\"hw0\")", + @"interrupt(\"hw1\")", + @"interrupt(\"hw2\")", + @"interrupt(\"hw3\")", + @"interrupt(\"hw4\")", + @"interrupt(\"hw5\")", + + riscv_vector_cc, + @"interrupt(\"supervisor\")", + @"interrupt(\"machine\")", + + renesas, + /// Implies `interrupt_handler`. + trapa_handler, + @"interrupt_handler, nosave_low_regs", + @"interrupt_handler, resbank", + + m68k_rtd, + + tiflags, + + pub fn fromLang(cc: std.lang.CallingConvention, target: *const std.Target) CallingConvention { + if (target.cCallingConvention()) |ccc| { + if (cc.eql(ccc)) { + return .c; + } + } + return switch (cc) { + .auto, .naked => .c, + + .x86_16_cdecl => .cdecl, + .x86_16_regparmcall => .regparmcall, + .x86_64_sysv, .x86_sysv => .sysv_abi, + .x86_64_win, .x86_win, .x86_mingw => .ms_abi, + .x86_16_stdcall, .x86_stdcall => .stdcall, + .x86_fastcall => .fastcall, + .x86_thiscall => .thiscall, + + .x86_vectorcall, + .x86_64_vectorcall, + => .vectorcall, + + .x86_64_regcall_v3_sysv, + .x86_64_regcall_v4_win, + .x86_regcall_v3, + .x86_regcall_v4_win, + => .regcall, + + .aarch64_vfabi => .aarch64_vector_pcs, + .aarch64_vfabi_sve => .aarch64_sve_pcs, + + .arm_aapcs => .@"pcs(\"aapcs\")", + .arm_aapcs_vfp => .@"pcs(\"aapcs-vfp\")", + + .arc_interrupt => |opts| switch (opts.type) { + .ilink1 => .@"interrupt(\"ilink1\")", + .ilink2 => .@"interrupt(\"ilink2\")", + .ilink => .@"interrupt(\"ilink\")", + .firq => .@"interrupt(\"firq\")", + }, + + .arm_interrupt => |opts| switch (opts.type) { + .generic => .interrupt, + .irq => .@"interrupt(\"IRQ\")", + .fiq => .@"interrupt(\"FIQ\")", + .swi => .@"interrupt(\"SWI\")", + .abort => .@"interrupt(\"ABORT\")", + .undef => .@"interrupt(\"UNDEF\")", + }, + + .avr_signal => .signal, + + .microblaze_interrupt => |opts| switch (opts.type) { + .user => .save_volatiles, + .regular => .interrupt_handler, + .fast => .fast_interrupt, + .breakpoint => .break_handler, + }, + + .mips_interrupt, .mips64_interrupt => |opts| switch (opts.mode) { + .eic => .@"interrupt(\"eic\")", + .sw0 => .@"interrupt(\"sw0\")", + .sw1 => .@"interrupt(\"sw1\")", + .hw0 => .@"interrupt(\"hw0\")", + .hw1 => .@"interrupt(\"hw1\")", + .hw2 => .@"interrupt(\"hw2\")", + .hw3 => .@"interrupt(\"hw3\")", + .hw4 => .@"interrupt(\"hw4\")", + .hw5 => .@"interrupt(\"hw5\")", + }, + + .riscv64_lp64_v, .riscv32_ilp32_v => .riscv_vector_cc, + .riscv32_interrupt, .riscv64_interrupt => |opts| switch (opts.mode) { + .supervisor => .@"interrupt(\"supervisor\")", + .machine => .@"interrupt(\"machine\")", + }, + + .sh_renesas => .renesas, + .sh_interrupt => |opts| switch (opts.save) { + .fpscr => .trapa_handler, + .high => .@"interrupt_handler, nosave_low_regs", + .full => .interrupt_handler, + .bank => .@"interrupt_handler, resbank", + }, + + .m68k_rtd => .m68k_rtd, + + .avr_interrupt, + .csky_interrupt, + .m68k_interrupt, + .msp430_interrupt, + .x86_16_interrupt, + .x86_interrupt, + .x86_64_interrupt, + => .interrupt, + + .ez80_tiflags => .tiflags, + + else => unreachable, // `Zcu.callconvSupported` + }; + } + }; + /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears /// after the identifier in a declarator with this type. In this case, if this node is wrapped /// in a pointer type, we will need to add parentheses due to operator precedence. @@ -376,6 +543,7 @@ pub const CType = union(enum) { .ret_ty = ret_cty_buf, .param_tys = param_cty_buf, .varargs = func_type.is_var_args, + .cc = .fromLang(func_type.cc, zcu.getTarget()), } }; } try deps.addType(gpa, cur_ty, allow_incomplete); @@ -763,6 +931,13 @@ pub const CType = union(enum) { try w.writeByte('('); }, } + switch (ptr.elem_ty.*) { + else => {}, + .function => |function| switch (function.cc) { + .c => {}, + else => |cc| try w.print("zig_callconv({t}) ", .{cc}), + }, + } try w.writeByte('*'); }, @@ -812,7 +987,7 @@ pub const CType = union(enum) { => {}, .pointer => |ptr| { - // Match opening paren "(" write `writeTypePrefix`. + // Match opening paren "(" in `writeTypePrefix`. switch (ptr.elem_ty.kind()) { .specifier, .pointer => {}, .postfix_op => try w.writeByte(')'), diff --git a/src/codegen/c/type/render_defs.zig b/src/codegen/c/type/render_defs.zig index d591c09bf16d71b77c4d7b2dc3c4659665dd94a1..2ba76d64eda0073dc0cdb032d117fedf16fba0ae 100644 --- a/src/codegen/c/type/render_defs.zig +++ b/src/codegen/c/type/render_defs.zig @@ -203,10 +203,12 @@ pub fn defineComplete( const name_cty: CType = .{ .@"fn" = ty }; const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu); - try w.print("typedef {f}{f}(", .{ - ret_cty.fmtDeclaratorPrefix(zcu), - name_cty.fmtTypeName(zcu), - }); + try w.print("typedef {f}", .{ret_cty.fmtDeclaratorPrefix(zcu)}); + switch (CType.CallingConvention.fromLang(func_type.cc, zcu.getTarget())) { + .c => {}, + else => |cc| try w.print("zig_callconv({t}) ", .{cc}), + } + try w.print("{f}(", .{name_cty.fmtTypeName(zcu)}); var any_params = false; for (func_type.param_types.get(ip)) |param_ty_ip| { const param_ty: Type = .fromInterned(param_ty_ip); @@ -222,9 +224,7 @@ pub fn defineComplete( } else if (!any_params) { try w.writeAll("void"); } - try w.print("){f};", .{ - ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu), - }); + try w.print("){f};", .{ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu)}); break :check_cty null; }, .@"enum" => { @@ -254,7 +254,7 @@ pub fn defineComplete( try w.print( \\{f} {{ \\ {f}ptr{f}; - \\ size_t len; + \\ uintptr_t len; \\}}; , .{ name_cty.fmtTypeName(zcu), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index de5f084008896d56c36ff371078b6581a306a45f..31e67026821a109d79a6e677014fa0bcf8712615 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2550,7 +2550,7 @@ pub const Object = struct { llvm_function.setCallConv(cc_info.llvm_cc, &o.builder); if (cc_info.align_stack) { - try attributes.addFnAttr(.{ .alignstack = .wrap(.fromByteUnits(target.stackAlignment())) }, &o.builder); + try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("stackrealign"), .value = .empty } }, &o.builder); } if (cc_info.naked) { @@ -4522,7 +4522,7 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target) std.lang.CallingConvention.SpirvFragmentOptions, std.lang.CallingConvention.SpirvMeshOptions, => .{ null, 0, 0 }, - else => @compileError("TODO: toLlvmCallConv" ++ @tagName(pl)), + else => @compileError("TODO: toLlvmCallConv(." ++ @tagName(pl) ++ ")"), }, }; return .{ -- 2.54.0 From 556e9a455c1372d39bf7e73513d879aa199acc07 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 16 Jul 2026 12:48:14 -0400 Subject: [PATCH 20/22] llvm: work around bizarre upstream llvm behavior --- src/codegen/llvm/FuncGen.zig | 50 ++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 1dfdfba987f0e962049294699bba1bcce3aac4bf..2bdd059f1fe217c8675e5faa9acead19208c2cf3 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -2040,7 +2040,7 @@ fn airFloatFromInt(fg: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { const dest_scalar_ty = dest_ty.scalarType(zcu); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_scalar_ty, target)) + if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target)) return fg.wip.conv(.fromStdLang(operand_scalar_info.signedness), operand, try o.lowerType(dest_ty, .as_value), ""); const rt_int_ty = compilerRtPromoteInt(operand_scalar_info) orelse { @@ -2093,7 +2093,7 @@ fn airIntFromFloat( const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const dest_scalar_info = dest_scalar_ty.intInfo(zcu); - if (intrinsicsAllowed(operand_scalar_ty, target)) { + if (intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) { // TODO set fast math flag return fg.wip.conv(.fromStdLang(dest_scalar_info.signedness), operand, dest_llvm_ty, ""); } @@ -3888,7 +3888,7 @@ fn buildFloatCmp( const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - if (intrinsicsAllowed(scalar_ty, target)) { + if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) { const cond: Builder.FloatCondition = switch (pred) { .eq => .oeq, .neq => .une, @@ -3968,10 +3968,14 @@ fn buildFloatOp( const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) { + switch (op) { // Some operations are dedicated LLVM instructions, not available as intrinsics - .neg => return fg.wip.un(.fneg, params[0], ""), - .add, .sub, .mul, .div, .fmod => return fg.wip.bin(switch (fast) { + .neg => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) return fg.wip.un(.fneg, params[0], ""), + .add, .sub, .mul, .div, .fmod => if (intrinsicsAllowed(switch (op) { + else => unreachable, + .add, .sub, .mul, .div => .compiler_rt, + .fmod => .libc, + }, scalar_ty, target)) return fg.wip.bin(switch (fast) { .normal => switch (op) { .add => .fadd, .sub => .fsub, @@ -3989,6 +3993,7 @@ fn buildFloatOp( else => unreachable, }, }, params[0], params[1], ""), + .fma, .fmax, .fmin, .ceil, @@ -4003,9 +4008,10 @@ fn buildFloatOp( .round, .sin, .sqrt, + .tan, .trunc, - .fma, - => return fg.wip.callIntrinsic(fast, .none, switch (op) { + => if (intrinsicsAllowed(.libc, scalar_ty, target)) return fg.wip.callIntrinsic(fast, .none, switch (op) { + .fma => .fma, .fmax => .maxnum, .fmin => .minnum, .ceil => .ceil, @@ -4020,12 +4026,11 @@ fn buildFloatOp( .round => .round, .sin => .sin, .sqrt => .sqrt, + .tan => .tan, .trunc => .trunc, - .fma => .fma, else => unreachable, }, &.{try o.lowerType(ty, .as_value)}, ¶ms, ""), - .tan => unreachable, - }; + } const float_bits = scalar_ty.floatBits(target); const fn_name = switch (op) { @@ -4589,7 +4594,8 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu const dest_scalar_ty = dest_ty.scalarType(zcu); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_scalar_ty, target) and intrinsicsAllowed(operand_scalar_ty, target)) + if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and + intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .as_value), ""); const dest_bits = dest_scalar_ty.floatBits(target); const src_bits = operand_scalar_ty.floatBits(target); @@ -4610,7 +4616,8 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const dest_scalar_ty = dest_ty.scalarType(zcu); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_scalar_ty, target) and intrinsicsAllowed(operand_scalar_ty, target)) + if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and + intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .as_value), ""); const dest_bits = dest_scalar_ty.floatBits(target); const src_bits = operand_scalar_ty.floatBits(target); @@ -6161,7 +6168,7 @@ fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) All .@"vector.reduce.umax", else => unreachable, }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), - .float => if (intrinsicsAllowed(scalar_ty, target)) + .float => if (intrinsicsAllowed(.libc, scalar_ty, target)) return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) { .Min => .@"vector.reduce.fmin", .Max => .@"vector.reduce.fmax", @@ -6175,7 +6182,7 @@ fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) All .Mul => .@"vector.reduce.mul", else => unreachable, }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), - .float => if (intrinsicsAllowed(scalar_ty, target)) + .float => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) { .Add => .@"vector.reduce.fadd", .Mul => .@"vector.reduce.fmul", @@ -7936,9 +7943,18 @@ fn appendConstraints( /// LLVM does not support all relevant intrinsics for all targets, so we /// may need to manually generate a compiler-rt call using a soft type. -fn intrinsicsAllowed(scalar_ty: Type, target: *const std.Target) bool { +fn intrinsicsAllowed(kind: enum { compiler_rt, libc }, scalar_ty: Type, target: *const std.Target) bool { if (!scalar_ty.isRuntimeFloat()) return true; - return switch (std.zig.target.compilerRtFloatAbi(target, scalar_ty.floatBits(target))) { + const bits = scalar_ty.floatBits(target); + // Since upstream musl/msvc do not actually define the *f128 functions, llvm decides + // that it is a much better idea to just emit a call to the entirely wrong function as + // a fallback. We wouldn't want any linker errors when trying to perform an operation + // that isn't actually implemented anywhere, now would we! + if (bits == 128 and target.cpu.arch.isX86() and !target.abi.isGnu()) return switch (kind) { + .compiler_rt => true, + .libc => false, + }; + return switch (std.zig.target.compilerRtFloatAbi(target, bits)) { .hard => true, .soft => false, }; -- 2.54.0 From 3b8913a321dbd0ff7de7ac5ac9d4dd82a4235a2e Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 23 Jul 2026 09:49:03 -0400 Subject: [PATCH 21/22] llvm: enable passing tests Closes #10875 Closes #12396 Closes #20680 Closes #25734 Closes #30854 Closes #35519 --- lib/std/http/test.zig | 21 +-------------------- lib/std/math.zig | 2 +- lib/std/math/acos.zig | 4 ---- lib/std/math/asin.zig | 4 ---- lib/std/math/atan.zig | 4 ---- lib/std/math/hypot.zig | 9 --------- lib/std/math/isnan.zig | 8 +------- lib/std/math/modf.zig | 4 ---- lib/std/os/linux/IoUring/test.zig | 7 ------- test/behavior/align.zig | 1 - test/behavior/basic.zig | 1 - test/behavior/cast.zig | 6 ------ test/behavior/field_parent_ptr.zig | 1 - test/behavior/floatop.zig | 13 +------------ test/behavior/threadlocal.zig | 5 ----- test/behavior/union.zig | 6 ++++-- test/behavior/vector.zig | 7 ------- test/behavior/widening.zig | 1 - 18 files changed, 8 insertions(+), 96 deletions(-) diff --git a/lib/std/http/test.zig b/lib/std/http/test.zig index 39f2063f65d7c1b175ce0750e9512abaee3f2c20..e7a37daa68de6751d5762b7639e25bd1401a37c0 100644 --- a/lib/std/http/test.zig +++ b/lib/std/http/test.zig @@ -1,5 +1,4 @@ const builtin = @import("builtin"); -const native_endian = builtin.cpu.arch.endian(); const std = @import("std"); const http = std.http; @@ -34,7 +33,6 @@ test "content length reader state update" { } test "trailers" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -121,7 +119,6 @@ test "trailers" { } test "HTTP server handles a chunked transfer coding request" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -190,7 +187,6 @@ test "HTTP server handles a chunked transfer coding request" { } test "echo content server" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -281,12 +277,11 @@ test "echo content server" { } test "Server.Request.respondStreaming non-chunked, unknown content-length" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; - if (builtin.os.tag == .windows) { + if (builtin.cpu.arch == .aarch64 and builtin.os.tag == .windows) { // https://github.com/ziglang/zig/issues/21457 return error.SkipZigTest; } @@ -360,7 +355,6 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" { } test "receiving arbitrary http headers from the client" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -426,16 +420,10 @@ test "receiving arbitrary http headers from the client" { } test "general client/server API coverage" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; - if (builtin.os.tag == .windows) { - // This test was never passing on Windows. - return error.SkipZigTest; - } - const test_server = try createTestServer(io, struct { fn run(test_server: *TestServer) anyerror!void { const net_server = &test_server.net_server; @@ -922,7 +910,6 @@ test "general client/server API coverage" { } test "Server streams both reading and writing" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -1162,10 +1149,6 @@ const TestServer = struct { fn createTestServer(io: Io, S: type) !*TestServer { if (builtin.single_threaded) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and native_endian == .big) { - // https://github.com/ziglang/zig/issues/13782 - return error.SkipZigTest; - } const address = try net.IpAddress.parse("127.0.0.1", 0); @@ -1192,7 +1175,6 @@ fn createTestServer(io: Io, S: type) !*TestServer { } test "redirect to different connection" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -1280,7 +1262,6 @@ test "redirect to different connection" { } test "boot failed connections from the pool" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; diff --git a/lib/std/math.zig b/lib/std/math.zig index ae644d6fceff795c5cb1864acada365867a19521..27d5e0d584dca43e838d31eabec11ca2134045d9 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -461,7 +461,7 @@ pub fn wrap(x: anytype, r: anytype) @TypeOf(x) { } } test wrap { - if (builtin.os.tag == .windows and builtin.cpu.arch == .x86) { + if (builtin.os.tag == .windows and builtin.cpu.arch == .x86 and builtin.abi == .msvc) { // https://codeberg.org/ziglang/zig/issues/35520 return error.SkipZigTest; } diff --git a/lib/std/math/acos.zig b/lib/std/math/acos.zig index 285190227c75b5780d3b2678656272b2e01d068a..d79c36182e0aa6ebd784c45f56c0232905a9c1a2 100644 --- a/lib/std/math/acos.zig +++ b/lib/std/math/acos.zig @@ -337,8 +337,6 @@ fn acosBinary128(x: f128) f128 { } test "acosBinary16.special" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectApproxEqAbs(0x1.92p0, acosBinary16(0x0p+0), math.floatEpsAt(f16, 0x1.92p0)); try testing.expectApproxEqAbs(0x1.92p1, acosBinary16(-0x1p+0), math.floatEpsAt(f16, 0x1.92p1)); try testing.expectEqual(0x0p+0, acosBinary16(0x1p+0)); @@ -350,8 +348,6 @@ test "acosBinary16.special" { } test "acosBinary16" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectApproxEqAbs(0x1.834p0, acosBinary16(0x1.db4p-5), math.floatEpsAt(f16, 0x1.834p0)); try testing.expectApproxEqAbs(0x1.d48p0, acosBinary16(-0x1.068p-2), math.floatEpsAt(f16, 0x1.d48p0)); try testing.expectApproxEqAbs(0x1.b7cp0, acosBinary16(-0x1.2c4p-3), math.floatEpsAt(f16, 0x1.b7cp0)); diff --git a/lib/std/math/asin.zig b/lib/std/math/asin.zig index 68efd182aaf93db9ba5824cd76be55854c5c5f40..dfd3f063954c68d25230993b0875873273eb9ff8 100644 --- a/lib/std/math/asin.zig +++ b/lib/std/math/asin.zig @@ -326,8 +326,6 @@ fn asinBinary128(x: f128) f128 { } test "asinBinary16.special" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectApproxEqAbs(0x1.92p0, asinBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p0)); try testing.expectApproxEqAbs(-0x1.92p0, asinBinary16(-0x1p+0), math.floatEpsAt(f16, -0x1.92p0)); try testing.expectEqual(0x0p+0, asinBinary16(0x0p+0)); @@ -340,8 +338,6 @@ test "asinBinary16.special" { } test "asinBinary16" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectApproxEqAbs(-0x1.e4cp-6, asinBinary16(-0x1.e4cp-6), math.floatEpsAt(f16, -0x1.e4cp-6)); try testing.expectApproxEqAbs(0x1.2a8p0, asinBinary16(0x1.d68p-1), math.floatEpsAt(f16, 0x1.2a8p0)); try testing.expectApproxEqAbs(-0x1.eep-1, asinBinary16(-0x1.a4cp-1), math.floatEpsAt(f16, -0x1.eep-1)); diff --git a/lib/std/math/atan.zig b/lib/std/math/atan.zig index 2d55b8bc1343d95f6671a96636d55b2b4a269c8e..75dab1b0c19732b229000d62634e7944491db254 100644 --- a/lib/std/math/atan.zig +++ b/lib/std/math/atan.zig @@ -481,8 +481,6 @@ fn atanBinary128(x: f128) f128 { } test "atanBinary16.special" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectEqual(0x0p+0, atanBinary16(0x0p+0)); try testing.expectEqual(-0x0p+0, atanBinary16(-0x0p+0)); try testing.expectApproxEqAbs(0x1.92p-1, atanBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p-1)); @@ -493,8 +491,6 @@ test "atanBinary16.special" { } test "atanBinary16" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectApproxEqAbs(-0x1.74cp-2, atanBinary16(-0x1.864p-2), math.floatEpsAt(f16, -0x1.74cp-2)); try testing.expectApproxEqAbs(-0x1.374p0, atanBinary16(-0x1.59cp1), math.floatEpsAt(f16, -0x1.374p0)); try testing.expectApproxEqAbs(-0x1.11cp0, atanBinary16(-0x1.d2cp0), math.floatEpsAt(f16, -0x1.11cp0)); diff --git a/lib/std/math/hypot.zig b/lib/std/math/hypot.zig index ef3fc97af3d3ea21b7cb525c616d248ffc20da7d..99da74c335c342a277778f79bafe53e7fb2d7766 100644 --- a/lib/std/math/hypot.zig +++ b/lib/std/math/hypot.zig @@ -1,4 +1,3 @@ -const builtin = @import("builtin"); const std = @import("../std.zig"); const math = std.math; const expect = std.testing.expect; @@ -93,14 +92,10 @@ const hypot_test_cases = .{ }; test hypot { - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 try expect(hypot(0.3, 0.4) == 0.5); } test "hypot.correct" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 - inline for (.{ f16, f32, f64, f128 }) |T| { inline for (hypot_test_cases) |v| { const a: T, const b: T, const c: T = v; @@ -110,9 +105,6 @@ test "hypot.correct" { } test "hypot.precise" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 - inline for (.{ f16, f32, f64 }) |T| { // f128 seems to be 5 ulp inline for (hypot_test_cases) |v| { const a: T, const b: T, const c: T = v; @@ -122,7 +114,6 @@ test "hypot.precise" { } test "hypot.special" { - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 @setEvalBranchQuota(2000); inline for (.{ f16, f32, f64, f128 }) |T| { try expect(math.isNan(hypot(nan(T), 0.0))); diff --git a/lib/std/math/isnan.zig b/lib/std/math/isnan.zig index bf2af9be1db7472aaceae82c3d052e606ce454b7..cfbe172ecdbe22890c9e928103b328f7fe23a256 100644 --- a/lib/std/math/isnan.zig +++ b/lib/std/math/isnan.zig @@ -27,13 +27,6 @@ test isNan { } test isSignalNan { - if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest; - - if (builtin.os.tag == .windows) { - // https://codeberg.org/ziglang/zig/issues/35519 - return error.SkipZigTest; - } - inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| { // TODO: Signalling NaN values get converted to quiet NaN values in // some cases where they shouldn't such that this can fail. @@ -43,6 +36,7 @@ test isSignalNan { builtin.cpu.arch != .hexagon and !builtin.cpu.arch.isMIPS32() and !builtin.cpu.arch.isPowerPC() and + !(builtin.cpu.arch.isX86() and builtin.os.tag == .windows and builtin.abi == .msvc) and // https://codeberg.org/ziglang/zig/issues/35519 builtin.zig_backend != .stage2_c) { try expect(isSignalNan(math.snan(T))); diff --git a/lib/std/math/modf.zig b/lib/std/math/modf.zig index 15515cde204a727d0191db34ace8adc68feb39e3..ea0433906958619572ad604d113f149c6fada392 100644 --- a/lib/std/math/modf.zig +++ b/lib/std/math/modf.zig @@ -1,5 +1,4 @@ const std = @import("../std.zig"); -const builtin = @import("builtin"); const math = std.math; const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; @@ -85,9 +84,6 @@ fn ModfTests(comptime T: type) type { try expectApproxEqAbs(expected_c, r.fpart, epsilon); } test "vector" { - if (builtin.os.tag.isDarwin() and builtin.cpu.arch == .aarch64) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194256 - const widths = [_]comptime_int{ 1, 2, 3, 4, 8, 16 }; inline for (widths) |len| { diff --git a/lib/std/os/linux/IoUring/test.zig b/lib/std/os/linux/IoUring/test.zig index 40429fbaab1cb7fb35a90427c69c2640ad907ed6..891ce5a397f61e2b6c655192d714e35d21f7e32c 100644 --- a/lib/std/os/linux/IoUring/test.zig +++ b/lib/std/os/linux/IoUring/test.zig @@ -1836,8 +1836,6 @@ test "accept/connect/send_zc/recv" { } test "accept_direct" { - if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30854 - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); var ring = IoUring.init(1, 0) catch |err| switch (err) { @@ -1925,11 +1923,6 @@ test "accept_direct" { test "accept_multishot_direct" { try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - if (builtin.cpu.arch == .riscv64) { - // https://github.com/ziglang/zig/issues/25734 - return error.SkipZigTest; - } - var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, diff --git a/test/behavior/align.zig b/test/behavior/align.zig index d79d2d07ba75c4660478753dc4d9a23d48fdfe2c..c9294e953b8d2c907a8b86e2c6b5916b1d75941a 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -569,7 +569,6 @@ test "sub-aligned pointer field access" { } test "alignment of zero-bit types is respected" { - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 964de5d20ff8754e81d3c0deae59fd44a672b6f8..d1acfb366dbfe0620409a81ef565b0902237a81b 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -1397,7 +1397,6 @@ test "allocation and looping over 3-byte integer" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag.isDarwin()) return error.SkipZigTest; // TODO try expect(@sizeOf(u24) == 4); try expect(@sizeOf([1]u24) == 4); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 697da63db23d14bb9e583745c80c8aca350d8a8d..077d3faeddc080357b48304a3f46240ad83e1fdd 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1719,7 +1719,6 @@ test "cast f16 to wider types" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; const S = struct { fn doTheTest() !void { @@ -1828,11 +1827,6 @@ test "coerce between pointers of compatible differently-named floats" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12396 - return error.SkipZigTest; - } - const F = switch (@typeInfo(c_longdouble).float.bits) { 64 => f64, 80 => f80, diff --git a/test/behavior/field_parent_ptr.zig b/test/behavior/field_parent_ptr.zig index c3d0c0087cc7eb9694310d5f8ff3755e35ca8077..8694f366a586cd4a756f7f1acb7862c656b04f02 100644 --- a/test/behavior/field_parent_ptr.zig +++ b/test/behavior/field_parent_ptr.zig @@ -1895,7 +1895,6 @@ test "@fieldParentPtr packed union" { } test "@fieldParentPtr tagged union all zero-bit fields" { - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index ea01c8a88fe3ebf590d71027a7a5516cd57eeedb..583b6bf6aba3f0596a452e5f311bc1a388cd4691 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -216,7 +216,6 @@ test "vector cmp f16" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; try testCmpVector(f16); @@ -378,11 +377,6 @@ test "@sqrt f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - if (builtin.os.tag == .freebsd) { - // TODO https://github.com/ziglang/zig/issues/10875 - return error.SkipZigTest; - } - try testSqrt(f80); try comptime testSqrt(f80); try testSqrt(f128); @@ -943,7 +937,7 @@ test "@log2 with vectors" { builtin.cpu.arch == .aarch64 and builtin.os.tag == .windows) return error.SkipZigTest; - if (builtin.os.tag == .windows and builtin.cpu.arch == .x86) { + if (builtin.os.tag == .windows and builtin.cpu.arch == .x86 and builtin.abi == .msvc) { // https://codeberg.org/ziglang/zig/issues/35518 return error.SkipZigTest; } @@ -1411,11 +1405,6 @@ test "neg f16" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.os.tag == .freebsd) { - // TODO file issue to track this failure - return error.SkipZigTest; - } - try testNeg(f16); try comptime testNeg(f16); } diff --git a/test/behavior/threadlocal.zig b/test/behavior/threadlocal.zig index cb4480f759af537ee0824d400fda530eb21a69b7..ec1ce0b62677b9cbb4988814e4c69f94ae65548c 100644 --- a/test/behavior/threadlocal.zig +++ b/test/behavior/threadlocal.zig @@ -9,11 +9,6 @@ test "thread local variable" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag.isDarwin()) { - // Fails due to register hazards. - return error.SkipZigTest; - } - const S = struct { threadlocal var t: i32 = 1234; }; diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 8ed483d02278160bc13f52b60a6b5cf5344eb40e..0ba364aabe557a0bac5832d285cc4595dc9cec25 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1609,6 +1609,10 @@ fn littleToNativeEndian(comptime T: type, v: T) T { } test "reinterpret extern union" { + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isRiscv32() and builtin.link_libc) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isWasm()) return error.SkipZigTest; + if (true) { // https://github.com/ziglang/zig/issues/19389 return error.SkipZigTest; @@ -1676,8 +1680,6 @@ test "reinterpret extern union" { }; try comptime S.doTheTest(); - - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO try S.doTheTest(); } diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 861b2e77db418adbb23343bf0a90db3733ad82f6..1b7d354e19c92996c8b6f30dde1acc2ad5914a4a 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -129,12 +129,6 @@ test "vector float operators" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) { - // Triggers an assertion with LLVM 18: - // https://github.com/ziglang/zig/issues/20680 - return error.SkipZigTest; - } - const S = struct { fn doTheTest(T: type) !void { var v: @Vector(4, T) = .{ 10, 20, 30, 40 }; @@ -279,7 +273,6 @@ test "array to vector with element type coercion" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; const S = struct { fn doTheTest() !void { diff --git a/test/behavior/widening.zig b/test/behavior/widening.zig index c6571319d4fbb3a2265dd48fd31e67a9061e2055..6277c3acf6790cd769ac86dc885959e8281e7a71 100644 --- a/test/behavior/widening.zig +++ b/test/behavior/widening.zig @@ -41,7 +41,6 @@ test "float widening" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; var a: f16 = 12.34; var b: f32 = a; -- 2.54.0 From 47396c903cb118df9e5562f383026b0f460d38f6 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Mon, 27 Jul 2026 14:47:34 -0400 Subject: [PATCH 22/22] stage1: update zig1.wasm --- stage1/zig.h | 3950 +++++++++++++++++++++++++++++++++++----------- stage1/zig1.wasm | Bin 3223935 -> 3246758 bytes 2 files changed, 3019 insertions(+), 931 deletions(-) diff --git a/stage1/zig.h b/stage1/zig.h index fc2f9479bea2bf9599dfcaebe35294fed98b4db4..30e6f3f96a97f47b6648db1d1587bc75c88b6c3f 100644 --- a/stage1/zig.h +++ b/stage1/zig.h @@ -166,6 +166,12 @@ #endif #define zig_expand_has_builtin(b) zig_has_builtin(b) +#if defined(__has_feature) +#define zig_has_feature(feature) __has_feature(feature) +#else +#define zig_has_feature(feature) 0 +#endif + #if defined(__has_attribute) #define zig_has_attribute(attribute) __has_attribute(attribute) #else @@ -175,9 +181,9 @@ #if __STDC_VERSION__ >= 201112L #define zig_static_assert(cond, msg) _Static_assert(cond, msg) #elif zig_has_attribute(unused) -#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused)) +#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] __attribute__((unused)) #else -#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] +#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] #endif #if __STDC_VERSION__ >= 202311L @@ -193,10 +199,8 @@ #endif #if defined(zig_msvc) -#define zig_const_arr #define zig_callconv(c) __##c #else -#define zig_const_arr static const #define zig_callconv(c) __attribute__((c)) #endif @@ -267,12 +271,20 @@ #if __STDC_VERSION__ >= 202311L #define zig_align(alignment) alignas(alignment) -#elif __STDC_VERSION__ >= 201112L +#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas) #define zig_align(alignment) _Alignas(alignment) #else #define zig_align(alignment) zig_under_align(alignment) #endif +#if __STDC_VERSION__ >= 202311L +#define zig_alignOf(Type) alignof(Type) +#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignof) +#define zig_alignOf(Type) _Alignof(Type) +#else +#define zig_alignOf(Type) (sizeof(struct { char c; Type t; }) - sizeof(Type)) +#endif + #if zig_has_attribute(aligned) || defined(zig_tinyc) #define zig_align_fn(alignment) __attribute__((aligned(alignment))) #elif defined(zig_msvc) @@ -350,11 +362,9 @@ #define zig_export(symbol, name) __attribute__((alias(symbol))) #else #define zig_export(symbol, name) ; \ - __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol)) + __asm("\t.globl\t" zig_mangle_c(name) "\n" zig_mangle_c(name) " = " zig_mangle_c(symbol)) #endif -#define zig_mangled_tentative zig_mangled -#define zig_mangled_final zig_mangled #if defined(zig_msvc) #define zig_mangled(mangled, unmangled) ; \ zig_export(#mangled, unmangled) @@ -364,7 +374,7 @@ #else /* zig_msvc */ #define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled)) #define zig_mangled_export(mangled, unmangled, symbol) \ - zig_mangled_final(mangled, unmangled) \ + zig_mangled(mangled, unmangled) \ zig_export(symbol, unmangled) #endif /* zig_msvc */ @@ -550,6 +560,9 @@ #define zig_noreturn #endif +#define zig_has_always 1 +#define zig_has_never 0 + #define zig_compiler_rt_abbrev_uint32_t si #define zig_compiler_rt_abbrev_int32_t si #define zig_compiler_rt_abbrev_uint64_t di @@ -560,7 +573,11 @@ #define zig_compiler_rt_abbrev_zig_f32 sf #define zig_compiler_rt_abbrev_zig_f64 df #define zig_compiler_rt_abbrev_zig_f80 xf +#ifdef zig_powerpc +#define zig_compiler_rt_abbrev_zig_f128 kf +#else #define zig_compiler_rt_abbrev_zig_f128 tf +#endif zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t); zig_extern void *memset (void *, int, size_t); @@ -645,16 +662,6 @@ typedef signed long long int16_t; #define INT16_MAX ( INT16_C(0x7FFF)) #define UINT16_MAX ( INT16_C(0xFFFF)) -#if defined(zig_ez80) -typedef unsigned int uint24_t; -typedef signed int int24_t; -#define INT24_C(c) c -#define UINT24_C(c) c##U -#endif -#define INT24_MIN (~INT24_C(0x7FFF)) -#define INT24_MAX ( INT24_C(0x7FFF)) -#define UINT24_MAX ( INT24_C(0xFFFF)) - #if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF typedef unsigned char uint32_t; typedef signed char int32_t; @@ -685,17 +692,6 @@ typedef signed long long int32_t; #define INT32_MAX ( INT32_C(0x7FFFFFFF)) #define UINT32_MAX ( INT32_C(0xFFFFFFFF)) -#if defined(zig_ez80) -typedef unsigned __int48 uint48_t; -typedef signed __int48 int48_t; -#define INT48_C(c) c -/* no suffix */ -#define UINT48_C(c) ((uint48_t)(c)) -#endif -#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF)) -#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF)) -#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF)) - #if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF typedef unsigned char uint64_t; typedef signed char int64_t; @@ -726,6 +722,27 @@ typedef signed long long int64_t; #define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF)) #define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF)) +#if defined(zig_ez80) + +typedef unsigned int uint24_t; +typedef signed int int24_t; +#define INT24_C(c) c +#define UINT24_C(c) c##U +#define INT24_MIN (~INT24_C(0x7FFF)) +#define INT24_MAX ( INT24_C(0x7FFF)) +#define UINT24_MAX ( INT24_C(0xFFFF)) + +typedef unsigned __int48 uint48_t; +typedef signed __int48 int48_t; +#define INT48_C(c) c +/* no suffix */ +#define UINT48_C(c) ((uint48_t)(c)) +#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF)) +#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF)) +#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF)) + +#endif + typedef size_t uintptr_t; typedef ptrdiff_t intptr_t; @@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t; #define zig_maxInt_i16 INT16_MAX #define zig_minInt_u16 UINT16_C(0) #define zig_maxInt_u16 UINT16_MAX -#define zig_minInt_i24 INT24_MIN -#define zig_maxInt_i24 INT24_MAX -#define zig_minInt_u24 UINT24_C(0) -#define zig_maxInt_u24 UINT24_MAX #define zig_minInt_i32 INT32_MIN #define zig_maxInt_i32 INT32_MAX #define zig_minInt_u32 UINT32_C(0) #define zig_maxInt_u32 UINT32_MAX -#define zig_minInt_i48 INT48_MIN -#define zig_maxInt_i48 INT48_MAX -#define zig_minInt_u48 UINT48_C(0) -#define zig_maxInt_u48 UINT48_MAX #define zig_minInt_i64 INT64_MIN #define zig_maxInt_i64 INT64_MAX #define zig_minInt_u64 UINT64_C(0) #define zig_maxInt_u64 UINT64_MAX +// zig_promoted_T implements C integral promotions except with signedness preserved, which +// allows wrapping operations to avoid the ub that would be caused by the normal promotion. + +#if INT8_MAX <= INT_MAX +typedef unsigned int zig_promoted_i8; +#elif INT8_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i8; +#elif INT8_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i8; +#else +typedef int8_t zig_promoted_i8; +#endif +#if UINT8_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u8; +#elif UINT8_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u8; +#elif UINT8_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u8; +#else +typedef uint8_t zig_promoted_u8; +#endif + +#if INT16_MAX <= INT_MAX +typedef unsigned int zig_promoted_i16; +#elif INT16_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i16; +#elif INT16_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i16; +#else +typedef int16_t zig_promoted_i16; +#endif +#if UINT16_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u16; +#elif UINT16_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u16; +#elif UINT16_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u16; +#else +typedef uint16_t zig_promoted_u16; +#endif + +#if INT32_MAX <= INT_MAX +typedef unsigned int zig_promoted_i32; +#elif INT32_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i32; +#elif INT32_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i32; +#else +typedef int32_t zig_promoted_i32; +#endif +#if UINT32_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u32; +#elif UINT32_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u32; +#elif UINT32_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u32; +#else +typedef uint32_t zig_promoted_u32; +#endif + +#if INT64_MAX <= INT_MAX +typedef unsigned int zig_promoted_i64; +#elif INT64_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i64; +#elif INT64_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i64; +#else +typedef int64_t zig_promoted_i64; +#endif +#if UINT64_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u64; +#elif UINT64_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u64; +#elif UINT64_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u64; +#else +typedef uint64_t zig_promoted_u64; +#endif + +#ifdef zig_ez80 + +#define zig_minInt_i24 INT24_MIN +#define zig_maxInt_i24 INT24_MAX +#define zig_minInt_u24 UINT24_C(0) +#define zig_maxInt_u24 UINT24_MAX +#define zig_minInt_i48 INT48_MIN +#define zig_maxInt_i48 INT48_MAX +#define zig_minInt_u48 UINT48_C(0) +#define zig_maxInt_u48 UINT48_MAX + +#if INT24_MAX <= INT_MAX +typedef unsigned int zig_promoted_i24; +#elif INT24_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i24; +#elif INT24_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i24; +#else +typedef int24_t zig_promoted_i24; +#endif +#if UINT24_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u24; +#elif UINT24_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u24; +#elif UINT24_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u24; +#else +typedef uint24_t zig_promoted_u24; +#endif + +#if INT48_MAX <= INT_MAX +typedef unsigned int zig_promoted_i48; +#elif INT48_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i48; +#elif INT48_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i48; +#else +typedef int48_t zig_promoted_i48; +#endif +#if UINT48_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u48; +#elif UINT48_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u48; +#elif UINT48_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u48; +#else +typedef uint48_t zig_promoted_u48; +#endif + +#endif + #define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits)) #define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits) #define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits) @@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t; zig_operator(Type, Type, operation, operator) #define zig_shift_operator(Type, operation, operator) \ zig_operator(Type, uint8_t, operation, operator) -#define zig_int_helpers(w, PromotedUnsigned) \ + +#define zig_int_casts_common(bw, sw) \ + static inline uint##bw##_t zig_u##bw##_intCast_u##sw(uint##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline uint##bw##_t zig_u##bw##_intCast_i##sw(int##sw##_t arg) { \ + return (uint##bw##_t)arg; \ + } \ +\ + static inline int##bw##_t zig_i##bw##_intCast_u##sw(uint##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline int##bw##_t zig_i##bw##_intCast_i##sw(int##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline uint##sw##_t zig_u##sw##_truncate_u##bw(uint##bw##_t arg, uint8_t bits) { \ + return (uint##sw##_t)arg & zig_maxInt_u(sw, bits); \ + } \ +\ + static inline int##sw##_t zig_i##sw##_truncate_i##bw(int##bw##_t arg, uint8_t bits) { \ + return ((uint##sw##_t)arg & UINT##sw##_C(1) << (bits - UINT8_C(1))) != UINT##sw##_C(0) \ + ? (int##sw##_t)arg | zig_minInt_i(sw, bits) : (int##sw##_t)arg & zig_maxInt_i(sw, bits); \ + } +#define zig_int_operators(w) \ zig_basic_operator(uint##w##_t, and_u##w, &) \ zig_basic_operator( int##w##_t, and_i##w, &) \ zig_basic_operator(uint##w##_t, or_u##w, |) \ @@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t; return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \ } \ \ - static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \ - return val ^ zig_maxInt_u(w, bits); \ + static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \ + return arg ^ zig_maxInt_u(w, bits); \ } \ \ - static inline int##w##_t zig_not_i##w(int##w##_t val, uint8_t bits) { \ + static inline int##w##_t zig_not_i##w(int##w##_t arg, uint8_t bits) { \ (void)bits; \ - return ~val; \ + return ~arg; \ } \ \ - static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \ - return val & zig_maxInt_u(w, bits); \ - } \ -\ - static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \ - return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \ - ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \ - } \ -\ - static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \ - return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \ - } \ -\ - zig_basic_operator(uint##w##_t, div_floor_u##w, /) \ + zig_basic_operator(uint##w##_t, divFloor_u##w, /) \ \ - static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \ + static inline int##w##_t zig_divFloor_i##w(int##w##_t lhs, int##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \ } \ \ - static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \ } \ \ - static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \ + static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != INT##w##_C(0) \ ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \ } \ \ zig_basic_operator(uint##w##_t, mod_u##w, %) \ + zig_int_casts_common(w, w) \ +\ + static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_u##w##_truncate_u##w(arg, bits); \ + } \ +\ + static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_i##w##_truncate_i##w(arg, bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_i##w##_bitCast_i##w((int##w##_t)arg, bits); \ + } \ \ static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \ int##w##_t rem = lhs % rhs; \ @@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t; } \ \ static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \ + return zig_u##w##_truncate_u##w(zig_shl_u##w(lhs, rhs), bits); \ } \ \ static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_shl_u##w(zig_u##w##_bitCast_i##w(lhs, bits), rhs), bits); \ } \ \ static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(lhs + rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs + rhs, bits); \ } \ \ static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_addw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ } \ \ static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(lhs - rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs - rhs, bits); \ } \ \ static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_subw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ } \ \ static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w((PromotedUnsigned)lhs * rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs * rhs, bits); \ } \ \ static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_mulw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ + } \ +\ + static inline uint##w##_t zig_abs_i##w(int##w##_t arg) { \ + int##w##_t tmp = zig_shr_i##w(arg, UINT8_C(w) - UINT8_C(1)); \ + return zig_u##w##_bitCast_i##w(zig_subw_i##w(zig_xor_i##w(arg, tmp), tmp, UINT8_C(w)), UINT8_C(w)); \ + } \ +\ + static inline uint##w##_t zig_min_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + return lhs < rhs ? lhs : rhs; \ + } \ +\ + static inline int##w##_t zig_min_i##w(int##w##_t lhs, int##w##_t rhs) { \ + return lhs < rhs ? lhs : rhs; \ + } \ +\ + static inline uint##w##_t zig_max_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + return lhs >= rhs ? lhs : rhs; \ + } \ +\ + static inline int##w##_t zig_max_i##w(int##w##_t lhs, int##w##_t rhs) { \ + return lhs >= rhs ? lhs : rhs; \ } -#if UINT8_MAX <= UINT_MAX -zig_int_helpers(8, unsigned int) -#elif UINT8_MAX <= ULONG_MAX -zig_int_helpers(8, unsigned long) -#elif UINT8_MAX <= ULLONG_MAX -zig_int_helpers(8, unsigned long long) -#else -zig_int_helpers(8, uint8_t) +zig_int_operators(8) +zig_int_operators(16) +zig_int_operators(32) +zig_int_operators(64) +#ifdef zig_ez80 +zig_int_operators(24) +zig_int_operators(48) #endif -#if UINT16_MAX <= UINT_MAX -zig_int_helpers(16, unsigned int) -#elif UINT16_MAX <= ULONG_MAX -zig_int_helpers(16, unsigned long) -#elif UINT16_MAX <= ULLONG_MAX -zig_int_helpers(16, unsigned long long) -#else -zig_int_helpers(16, uint16_t) -#endif -#if defined(zig_ez80) -#if UINT24_MAX <= UINT_MAX -zig_int_helpers(24, unsigned int) -#elif UINT24_MAX <= ULONG_MAX -zig_int_helpers(24, unsigned long) -#elif UINT24_MAX <= ULLONG_MAX -zig_int_helpers(24, unsigned long long) -#else -zig_int_helpers(24, uint24_t) -#endif -#endif -#if UINT32_MAX <= UINT_MAX -zig_int_helpers(32, unsigned int) -#elif UINT32_MAX <= ULONG_MAX -zig_int_helpers(32, unsigned long) -#elif UINT32_MAX <= ULLONG_MAX -zig_int_helpers(32, unsigned long long) -#else -zig_int_helpers(32, uint32_t) -#endif -#if defined(zig_ez80) -#if UINT24_MAX <= UINT_MAX -zig_int_helpers(48, unsigned int) -#elif UINT24_MAX <= ULONG_MAX -zig_int_helpers(48, unsigned long) -#elif UINT24_MAX <= ULLONG_MAX -zig_int_helpers(48, unsigned long long) -#else -zig_int_helpers(48, uint48_t) -#endif -#endif -#if UINT64_MAX <= UINT_MAX -zig_int_helpers(64, unsigned int) -#elif UINT64_MAX <= ULONG_MAX -zig_int_helpers(64, unsigned long) -#elif UINT64_MAX <= ULLONG_MAX -zig_int_helpers(64, unsigned long long) -#else -zig_int_helpers(64, uint64_t) + +#define zig_int_casts(bw, sw) \ + static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \ + return (uint##sw##_t)arg; \ + } \ +\ + static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \ + return (uint##sw##_t)arg; \ + } \ +\ + static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \ + return (int##sw##_t)arg; \ + } \ +\ + static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \ + return (int##sw##_t)arg; \ + } \ +\ + zig_int_casts_common(bw, sw) +zig_int_casts(16, 8) +zig_int_casts(32, 8) +zig_int_casts(64, 8) +zig_int_casts(32, 16) +zig_int_casts(64, 16) +zig_int_casts(64, 32) +#ifdef zig_ez80 +zig_int_casts(32, 24) +zig_int_casts(48, 24) +zig_int_casts(64, 24) +zig_int_casts(64, 48) #endif static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_addw_u32(lhs, rhs, bits); @@ -936,19 +1107,19 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_i32_truncate_i32(full_res, bits); + return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); #else - int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs); - bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; + *res = zig_addw_i32(lhs, rhs, bits); + return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0); #endif - *res = zig_wrap_i32(full_res, bits); - return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_addw_u64(lhs, rhs, bits); @@ -960,24 +1131,24 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_i64_truncate_i64(full_res, bits); + return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); #else - int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs); - bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; + *res = zig_addw_i64(lhs, rhs, bits); + return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0); #endif - *res = zig_wrap_i64(full_res, bits); - return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -986,12 +1157,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(add_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1014,27 +1185,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1043,28 +1215,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1073,22 +1243,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_subw_u32(lhs, rhs, bits); @@ -1100,20 +1271,19 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_i32_truncate_i32(full_res, bits); + return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); #else - int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs); - bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; + *res = zig_subw_i32(lhs, rhs, bits); + return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0); #endif - *res = zig_wrap_i32(full_res, bits); - return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } - static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_subw_u64(lhs, rhs, bits); @@ -1125,24 +1295,24 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_i64_truncate_i64(full_res, bits); + return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); #else - int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs); - bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; + *res = zig_subw_i64(lhs, rhs, bits); + return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0); #endif - *res = zig_wrap_i64(full_res, bits); - return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -1151,12 +1321,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1179,27 +1349,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1208,28 +1379,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1238,22 +1407,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_mulw_u32(lhs, rhs, bits); @@ -1261,8 +1431,8 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8 #endif } -zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) { + zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -1271,7 +1441,7 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t int32_t full_res = __mulosi4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i32(full_res, bits); + *res = zig_i32_truncate_i32(full_res, bits); return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } @@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_mulw_u64(lhs, rhs, bits); @@ -1287,8 +1457,8 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #endif } -zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) { + zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -1297,7 +1467,7 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t int64_t full_res = __mulodi4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i64(full_res, bits); + *res = zig_i64_truncate_i64(full_res, bits); return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } @@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -1319,12 +1489,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1347,27 +1517,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1376,28 +1547,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1406,18 +1575,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif -#define zig_int_builtins(w) \ +#define zig_shls_builtins(lw, rw) \ + static inline uint##lw##_t zig_shls_u##lw##_u##rw(uint##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \ + uint##lw##_t res; \ + if (rhs < bits && !zig_shlo_u##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + return lhs == INT##lw##_C(0) ? zig_minInt_u(lw, bits) : zig_maxInt_u(lw, bits); \ + } \ +\ + static inline int##lw##_t zig_shls_i##lw##_u##rw(int##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \ + int##lw##_t res; \ + if (rhs < bits && !zig_shlo_i##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + return lhs == INT##lw##_C(0) ? INT##lw##_C(0) : \ + lhs < INT##lw##_C(0) ? zig_minInt_i(lw, bits) : zig_maxInt_i(lw, bits); \ + } +#define zig_int_sat_builtins(w) \ static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ *res = zig_shlw_u##w(lhs, rhs, bits); \ return lhs > zig_maxInt_u(w, bits) >> rhs; \ @@ -1429,18 +1612,10 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \ } \ \ - static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - uint##w##_t res; \ - if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \ - return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \ - } \ -\ - static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - int##w##_t res; \ - if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \ - return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ - lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ - } \ + zig_shls_builtins(w, 8) \ + zig_shls_builtins(w, 16) \ + zig_shls_builtins(w, 32) \ + zig_shls_builtins(w, 64) \ \ static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ uint##w##_t res; \ @@ -1474,332 +1649,321 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \ return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ } -zig_int_builtins(8) -zig_int_builtins(16) +zig_int_sat_builtins(8) +zig_int_sat_builtins(16) +zig_int_sat_builtins(32) +zig_int_sat_builtins(64) #if defined(zig_ez80) -zig_int_builtins(24) +zig_int_sat_builtins(24) +zig_int_sat_builtins(48) #endif -zig_int_builtins(32) -#if defined(zig_ez80) -zig_int_builtins(48) -#endif -zig_int_builtins(64) -#define zig_builtin8(name, val) __builtin_##name(val) +#define zig_builtin8(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin8; -#define zig_builtin16(name, val) __builtin_##name(val) +#define zig_builtin16(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin16; -#if defined(zig_ez80) -#define zig_builtin24(name, val) __builtin_##name(val) -typedef unsigned int zig_Builtin24; -#endif - #if INT_MIN <= INT32_MIN -#define zig_builtin32(name, val) __builtin_##name(val) +#define zig_builtin32(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin32; #elif LONG_MIN <= INT32_MIN -#define zig_builtin32(name, val) __builtin_##name##l(val) +#define zig_builtin32(name, arg) __builtin_##name##l(arg) typedef unsigned long zig_Builtin32; #endif -#if defined(zig_ez80) -#define zig_builtin48(name, val) __builtin_##name(val) -typedef unsigned long long zig_Builtin48; -#endif - #if INT_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name(val) +#define zig_builtin64(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin64; #elif LONG_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name##l(val) +#define zig_builtin64(name, arg) __builtin_##name##l(arg) typedef unsigned long zig_Builtin64; #elif LLONG_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name##ll(val) +#define zig_builtin64(name, arg) __builtin_##name##ll(arg) typedef unsigned long long zig_Builtin64; #endif -static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) { - return zig_wrap_u8(val >> (8 - bits), bits); +#if defined(zig_ez80) +#define zig_builtin24(name, arg) __builtin_##name(arg) +typedef unsigned int zig_Builtin24; +#define zig_builtin48(name, arg) __builtin_##name(arg) +typedef unsigned long long zig_Builtin48; +#endif + +static inline uint8_t zig_byteSwap_u8(uint8_t arg, uint8_t bits) { + return zig_u8_truncate_u8(arg >> (8 - bits), bits); } -static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) { - return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits); +static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) { + return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits); } -static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) { +static inline uint16_t zig_byteSwap_u16(uint16_t arg, uint8_t bits) { uint16_t full_res; #if zig_has_builtin(bswap16) || defined(zig_gcc) - full_res = __builtin_bswap16(val); + full_res = __builtin_bswap16(arg); #else - full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 | - (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0; + full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 | + (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0; #endif - return zig_wrap_u16(full_res >> (16 - bits), bits); + return zig_u16_truncate_u16(full_res >> (16 - bits), bits); } -static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) { - return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits); +static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) { + return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) { +static inline uint16_t zig_byteSwap_u24(uint24_t arg, uint8_t bits) { uint24_t full_res; #if zig_has_builtin(bswap24) || defined(zig_gcc) - full_res = __builtin_bswap24(val); + full_res = __builtin_bswap24(arg); #else - full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 | - (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0; + full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 | + (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0; #endif - return zig_wrap_u24(full_res >> (24 - bits), bits); + return zig_u24_truncate_u24(full_res >> (24 - bits), bits); } -static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) { - return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits); +static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) { + return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits); } #endif -static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) { +static inline uint32_t zig_byteSwap_u32(uint32_t arg, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bswap32) || defined(zig_gcc) - full_res = __builtin_bswap32(val); + full_res = __builtin_bswap32(arg); #else - full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 | - (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0; + full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 | + (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0; #endif - return zig_wrap_u32(full_res >> (32 - bits), bits); + return zig_u32_truncate_u32(full_res >> (32 - bits), bits); } -static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) { - return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits); +static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) { + return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) { +static inline uint32_t zig_byteSwap_u48(uint48_t arg, uint8_t bits) { uint48_t full_res; #if zig_has_builtin(bswap48) || defined(zig_gcc) - full_res = __builtin_bswap48(val); + full_res = __builtin_bswap48(arg); #else - full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 | - (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0; + full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 | + (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0; #endif - return zig_wrap_u48(full_res >> (48 - bits), bits); + return zig_u48_truncate_u48(full_res >> (48 - bits), bits); } -static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) { - return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits); +static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) { + return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits); } #endif -static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) { +static inline uint64_t zig_byteSwap_u64(uint64_t arg, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bswap64) || defined(zig_gcc) - full_res = __builtin_bswap64(val); + full_res = __builtin_bswap64(arg); #else - full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 | - (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0; + full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 | + (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0; #endif - return zig_wrap_u64(full_res >> (64 - bits), bits); + return zig_u64_truncate_u64(full_res >> (64 - bits), bits); } -static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) { - return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits); +static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) { + return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits); } -static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) { +static inline uint8_t zig_bitReverse_u8(uint8_t arg, uint8_t bits) { uint8_t full_res; #if zig_has_builtin(bitreverse8) - full_res = __builtin_bitreverse8(val); + full_res = __builtin_bitreverse8(arg); #else static uint8_t const lut[0x10] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; - full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0; + full_res = lut[arg >> 0 & 0xF] << 4 | lut[arg >> 4 & 0xF] << 0; #endif - return zig_wrap_u8(full_res >> (8 - bits), bits); + return zig_u8_truncate_u8(full_res >> (8 - bits), bits); } -static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) { - return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits); +static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) { + return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits); } -static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) { +static inline uint16_t zig_bitReverse_u16(uint16_t arg, uint8_t bits) { uint16_t full_res; #if zig_has_builtin(bitreverse16) - full_res = __builtin_bitreverse16(val); + full_res = __builtin_bitreverse16(arg); #else - full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 | - (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0; + full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 | + (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0; #endif - return zig_wrap_u16(full_res >> (16 - bits), bits); + return zig_u16_truncate_u16(full_res >> (16 - bits), bits); } -static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) { - return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits); +static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) { + return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) { +static inline uint24_t zig_bitReverse_u24(uint24_t arg, uint8_t bits) { uint24_t full_res; #if zig_has_builtin(bitreverse24) - full_res = __builtin_bitreverse24(val); + full_res = __builtin_bitreverse24(arg); #else - full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 | - (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0; + full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 | + (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0; #endif - return zig_wrap_u24(full_res >> (24 - bits), bits); + return zig_u24_truncate_u24(full_res >> (24 - bits), bits); } -static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) { - return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits); +static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) { + return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits); } #endif -static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) { +static inline uint32_t zig_bitReverse_u32(uint32_t arg, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bitreverse32) - full_res = __builtin_bitreverse32(val); + full_res = __builtin_bitreverse32(arg); #else - full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 | - (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0; + full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 | + (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0; #endif - return zig_wrap_u32(full_res >> (32 - bits), bits); + return zig_u32_truncate_u32(full_res >> (32 - bits), bits); } -static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) { - return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits); +static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) { + return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) { +static inline uint32_t zig_bitReverse_u48(uint48_t arg, uint8_t bits) { uint48_t full_res; #if zig_has_builtin(bitreverse48) - full_res = __builtin_bitreverse48(val); + full_res = __builtin_bitreverse48(arg); #else - full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 | - (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0; + full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 | + (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0; #endif - return zig_wrap_u32(full_res >> (48 - bits), bits); + return zig_u48_truncate_u48(full_res >> (48 - bits), bits); } -static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) { - return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits); +static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) { + return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits); } #endif -static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) { +static inline uint64_t zig_bitReverse_u64(uint64_t arg, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bitreverse64) - full_res = __builtin_bitreverse64(val); + full_res = __builtin_bitreverse64(arg); #else - full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 | - (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0; + full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 | + (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0; #endif - return zig_wrap_u64(full_res >> (64 - bits), bits); + return zig_u64_truncate_u64(full_res >> (64 - bits), bits); } -static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) { - return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits); +static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) { + return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits); } -#define zig_builtin_popcount_common(w) \ - static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \ - return zig_popcount_u##w((uint##w##_t)val, bits); \ +#define zig_builtin_popCount_common(w) \ + static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_popCount_u##w((uint##w##_t)arg, bits); \ } -#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc) -#define zig_builtin_popcount(w) \ - static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ +#if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc) +#define zig_builtin_popCount(w) \ + static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ (void)bits; \ - return zig_builtin##w(popcount, val); \ + return zig_builtin##w(popcount, arg); \ } \ \ - zig_builtin_popcount_common(w) + zig_builtin_popCount_common(w) #else -#define zig_builtin_popcount(w) \ - static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ +#define zig_builtin_popCount(w) \ + static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ (void)bits; \ - uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \ + uint##w##_t temp = arg - ((arg >> 1) & (UINT##w##_MAX / 3)); \ temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \ temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \ return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \ } \ \ - zig_builtin_popcount_common(w) + zig_builtin_popCount_common(w) #endif -zig_builtin_popcount(8) -zig_builtin_popcount(16) +zig_builtin_popCount(8) +zig_builtin_popCount(16) +zig_builtin_popCount(32) +zig_builtin_popCount(64) #if defined(zig_ez80) -zig_builtin_popcount(24) +zig_builtin_popCount(24) +zig_builtin_popCount(48) #endif -zig_builtin_popcount(32) -#if defined(zig_ez80) -zig_builtin_popcount(48) -#endif -zig_builtin_popcount(64) #define zig_builtin_ctz_common(w) \ - static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \ - return zig_ctz_u##w((uint##w##_t)val, bits); \ + static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_ctz_u##w((uint##w##_t)arg, bits); \ } #if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_ctz(w) \ - static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ - if (val == 0) return bits; \ - return zig_builtin##w(ctz, val); \ + static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ + if (arg == 0) return bits; \ + return zig_builtin##w(ctz, arg); \ } \ \ zig_builtin_ctz_common(w) #else #define zig_builtin_ctz(w) \ - static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ - return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \ + static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \ } \ \ zig_builtin_ctz_common(w) #endif zig_builtin_ctz(8) zig_builtin_ctz(16) -#if defined(zig_ez80) -zig_builtin_ctz(24) -#endif zig_builtin_ctz(32) -#if defined(zig_ez80) -zig_builtin_ctz(48) -#endif zig_builtin_ctz(64) +#if defined(zig_ez80) +zig_builtin_ctz(24) +zig_builtin_ctz(48) +#endif #define zig_builtin_clz_common(w) \ - static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \ - return zig_clz_u##w((uint##w##_t)val, bits); \ + static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_clz_u##w((uint##w##_t)arg, bits); \ } #if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_clz(w) \ - static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ - if (val == 0) return bits; \ - return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ + static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ + if (arg == 0) return bits; \ + return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ } \ \ zig_builtin_clz_common(w) #else #define zig_builtin_clz(w) \ - static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ - return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \ + static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \ } \ \ zig_builtin_clz_common(w) #endif zig_builtin_clz(8) zig_builtin_clz(16) -#if defined(zig_ez80) -zig_builtin_clz(24) -#endif zig_builtin_clz(32) -#if defined(zig_ez80) -zig_builtin_clz(48) -#endif zig_builtin_clz(64) +#if defined(zig_ez80) +zig_builtin_clz(24) +zig_builtin_clz(48) +#endif /* ======================== 128-bit Integer Support ========================= */ @@ -1816,16 +1980,14 @@ zig_builtin_clz(64) typedef unsigned __int128 zig_u128; typedef signed __int128 zig_i128; -#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) -#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) -#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) -#define zig_hi_u128(val) ((uint64_t)((val) >> 64)) -#define zig_lo_u128(val) ((uint64_t)((val) >> 0)) -#define zig_hi_i128(val) (( int64_t)((val) >> 64)) -#define zig_lo_i128(val) ((uint64_t)((val) >> 0)) -#define zig_bitCast_u128(val) ((zig_u128)(val)) -#define zig_bitCast_i128(val) ((zig_i128)(val)) +#define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) +#define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) +#define zig_make_u128(hi, lo) zig_init_u128(hi, lo) +#define zig_make_i128(hi, lo) zig_init_i128(hi, lo) +#define zig_hi_u128(arg) ((uint64_t)((arg) >> 64)) +#define zig_lo_u128(arg) ((uint64_t)((arg) >> 0)) +#define zig_hi_i128(arg) (( int64_t)((arg) >> 64)) +#define zig_lo_i128(arg) ((uint64_t)((arg) >> 0)) #define zig_cmp_int128(Type) \ static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ return (lhs > rhs) - (lhs < rhs); \ @@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128; return lhs operator rhs; \ } +static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { + return lhs << rhs; +} + +static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { + return lhs >> rhs; +} + +static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { + return lhs << rhs; +} + +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + // This works around a GCC miscompilation, but it has the side benefit of + // emitting better code. It is behind the `#if` because it depends on + // arithmetic right shift, which is implementation-defined in C, but should + // be guaranteed on any GCC-compatible compiler. +#if defined(zig_gnuc) + return lhs >> rhs; +#else + zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); + return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; +#endif +} + #else /* zig_has_int128 */ #if zig_little_endian -typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128; -typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128; #else -typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128; -typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128; #endif -#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) }) -#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) }) - -#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */ -#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) } -#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) } -#else /* But non-MSVC doesn't like the unprotected commas */ -#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) -#endif -#define zig_hi_u128(val) ((val).hi) -#define zig_lo_u128(val) ((val).lo) -#define zig_hi_i128(val) ((val).hi) -#define zig_lo_i128(val) ((val).lo) -#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo) -#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo) +#define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo) +#define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo) +#define zig_hi_u128(arg) (arg).hi +#define zig_lo_u128(arg) (arg).lo +#define zig_hi_i128(arg) (arg).hi +#define zig_lo_i128(arg) (arg).lo #define zig_cmp_int128(Type) \ static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ return (lhs.hi == rhs.hi) \ @@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \ } +static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; + return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +} + +static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) }; + return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs }; +} + +static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; + return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +} + +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) }; + return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) }; +} + #endif /* zig_has_int128 */ #define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64) @@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |) zig_bit_int128(u128, xor, ^) zig_bit_int128(i128, xor, ^) -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs); +static inline uint8_t zig_u8_intCast_u128(zig_u128 arg) { + return (uint8_t)zig_lo_u128(arg); +} +static inline uint8_t zig_u8_intCast_i128(zig_i128 arg) { + return (uint8_t)zig_lo_i128(arg); +} +static inline int8_t zig_i8_intCast_i128(zig_i128 arg) { + return (int8_t)zig_lo_i128(arg); +} +static inline int8_t zig_i8_intCast_u128(zig_u128 arg) { + return (int8_t)zig_lo_u128(arg); +} -#if zig_has_int128 +static inline uint16_t zig_u16_intCast_u128(zig_u128 arg) { + return (uint16_t)zig_lo_u128(arg); +} +static inline uint16_t zig_u16_intCast_i128(zig_i128 arg) { + return (uint16_t)zig_lo_i128(arg); +} +static inline int16_t zig_i16_intCast_i128(zig_i128 arg) { + return (int16_t)zig_lo_i128(arg); +} +static inline int16_t zig_i16_intCast_u128(zig_u128 arg) { + return (int16_t)zig_lo_u128(arg); +} -static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { - return val ^ zig_maxInt_u(128, bits); +static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) { + return (uint32_t)zig_lo_u128(arg); +} +static inline uint32_t zig_u32_intCast_i128(zig_i128 arg) { + return (uint32_t)zig_lo_i128(arg); +} +static inline int32_t zig_i32_intCast_i128(zig_i128 arg) { + return (int32_t)zig_lo_i128(arg); +} +static inline int32_t zig_i32_intCast_u128(zig_u128 arg) { + return (int32_t)zig_lo_u128(arg); } -static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { - (void)bits; - return ~val; +static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) { + return zig_lo_u128(arg); +} +static inline uint64_t zig_u64_intCast_i128(zig_i128 arg) { + return zig_lo_i128(arg); +} +static inline int64_t zig_i64_intCast_i128(zig_i128 arg) { + return (int64_t)zig_lo_i128(arg); +} +static inline int64_t zig_i64_intCast_u128(zig_u128 arg) { + return (int64_t)zig_lo_u128(arg); +} + +static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) { + return zig_make_u128(UINT8_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i8(int8_t arg) { + return zig_make_u128(UINT8_C(0), (uint8_t)arg); +} +static inline zig_i128 zig_i128_intCast_i8(int8_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint8_t)arg); +} +static inline zig_i128 zig_i128_intCast_u8(uint8_t arg) { + return zig_make_i128(INT8_C(0), arg); } -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { - return lhs >> rhs; +static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) { + return zig_make_u128(UINT16_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i16(int16_t arg) { + return zig_make_u128(UINT16_C(0), (uint16_t)arg); +} +static inline zig_i128 zig_i128_intCast_i16(int16_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint16_t)arg); +} +static inline zig_i128 zig_i128_intCast_u16(uint16_t arg) { + return zig_make_i128(INT16_C(0), arg); } -static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { - return lhs << rhs; +static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) { + return zig_make_u128(UINT32_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i32(int32_t arg) { + return zig_make_u128(UINT32_C(0), (uint32_t)arg); +} +static inline zig_i128 zig_i128_intCast_i32(int32_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint32_t)arg); +} +static inline zig_i128 zig_i128_intCast_u32(uint32_t arg) { + return zig_make_i128(INT32_C(0), arg); } -static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { - // This works around a GCC miscompilation, but it has the side benefit of - // emitting better code. It is behind the `#if` because it depends on - // arithmetic right shift, which is implementation-defined in C, but should - // be guaranteed on any GCC-compatible compiler. -#if defined(zig_gnuc) - return lhs >> rhs; +static inline zig_u128 zig_u128_intCast_u64(uint64_t arg) { + return zig_make_u128(UINT64_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i64(int64_t arg) { + return zig_make_u128(UINT64_C(0), (uint64_t)arg); +} +static inline zig_i128 zig_i128_intCast_i64(int64_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint64_t)arg); +} +static inline zig_i128 zig_i128_intCast_u64(uint64_t arg) { + return zig_make_i128(INT64_C(0), arg); +} + +static inline zig_u128 zig_u128_intCast_u128(zig_u128 arg) { + return arg; +} +static inline zig_u128 zig_u128_intCast_i128(zig_i128 arg) { +#if zig_has_int128 + return (zig_u128)arg; +#else + return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); +#endif +} +static inline zig_i128 zig_i128_intCast_i128(zig_i128 arg) { + return arg; +} +static inline zig_i128 zig_i128_intCast_u128(zig_u128 arg) { +#if zig_has_int128 + return (zig_i128)arg; #else - zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); - return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; + return zig_make_i128(zig_i64_bitCast_u64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); #endif } -static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { - return lhs << rhs; +#define zig_int128_cast_builtins(w) \ + static inline uint##w##_t zig_u##w##_truncate_u128(zig_u128 arg, uint8_t bits) { \ + return zig_u##w##_truncate_u##w((uint##w##_t)zig_lo_u128(arg), bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_truncate_i128(zig_i128 arg, uint8_t bits) { \ + return zig_i##w##_truncate_i##w((int##w##_t)zig_lo_i128(arg), bits); \ + } +zig_int128_cast_builtins(8) +zig_int128_cast_builtins(16) +zig_int128_cast_builtins(32) +zig_int128_cast_builtins(64) + +static inline zig_u128 zig_u128_truncate_u128(zig_u128 arg, uint8_t bits) { + return zig_and_u128(arg, zig_maxInt_u(128, bits)); +} +static inline zig_i128 zig_i128_truncate_i128(zig_i128 arg, uint8_t bits) { + if (bits > UINT8_C(64)) return zig_make_i128(zig_i64_truncate_i64(zig_hi_i128(arg), bits - UINT8_C(64)), zig_lo_i128(arg)); + int64_t lo = zig_i64_truncate_i128(arg, bits); + return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); +} + +static inline zig_u128 zig_u128_bitCast_u128(zig_u128 arg, uint8_t bits) { + (void)bits; + return arg; +} +static inline zig_u128 zig_u128_bitCast_i128(zig_i128 arg, uint8_t bits) { + return zig_u128_truncate_u128(zig_u128_intCast_i128(arg), bits); +} +static inline zig_i128 zig_i128_bitCast_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return arg; +} +static inline zig_i128 zig_i128_bitCast_u128(zig_u128 arg, uint8_t bits) { + return zig_i128_truncate_i128(zig_i128_intCast_u128(arg), bits); +} + +#if zig_has_int128 + +static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { + return arg ^ zig_maxInt_u(128, bits); +} + +static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return ~arg; } static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { @@ -1953,11 +2291,11 @@ static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { return lhs * rhs; } -static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { +static inline zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { return lhs / rhs; } -static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { return lhs / rhs; } @@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { #else /* zig_has_int128 */ -static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { - return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; +static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { + if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) }; + return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) }; } -static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { - return (zig_i128){ .hi = zig_not_i64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; -} - -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) }; - return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs }; -} - -static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; - return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; -} - -static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) }; - return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) }; -} - -static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; - return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo }; } static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { @@ -2027,59 +2343,59 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) { return res; } -zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); return __multi3(lhs, rhs); } static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) { - return zig_bitCast_u128(zig_mul_i128(zig_bitCast_i128(lhs), zig_bitCast_i128(rhs))); + return zig_u128_bitCast_i128(zig_mul_i128(zig_i128_bitCast_u128(lhs, UINT8_C(128)), zig_i128_bitCast_u128(rhs, UINT8_C(128))), UINT8_C(128)); } -zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); -static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { +static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { + zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); return __udivti3(lhs, rhs); } -zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); -static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { +static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); return __divti3(lhs, rhs); } -zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) { + zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); return __umodti3(lhs, rhs); } -zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); return __modti3(lhs, rhs); } #endif /* zig_has_int128 */ -#define zig_div_floor_u128 zig_div_trunc_u128 +#define zig_divFloor_u128 zig_divTrunc_u128 -static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divFloor_i128(zig_i128 lhs, zig_i128 rhs) { zig_i128 rem = zig_rem_i128(lhs, rhs); int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0); - return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask)); + return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask)); } -static inline zig_u128 zig_div_ceil_u128(zig_u128 lhs, zig_u128 rhs) { +static inline zig_u128 zig_divCeil_u128(zig_u128 lhs, zig_u128 rhs) { zig_u128 rem = zig_rem_u128(lhs, rhs); uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0) ? UINT64_C(1) : UINT64_C(0); - return zig_add_u128(zig_div_trunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask)); + return zig_add_u128(zig_divTrunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask)); } -static inline zig_i128 zig_div_ceil_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divCeil_i128(zig_i128 lhs, zig_i128 rhs) { zig_i128 rem = zig_rem_i128(lhs, rhs); int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1) : INT64_C(0); - return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask)); + return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask)); } #define zig_mod_u128 zig_rem_u128 @@ -2107,51 +2423,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) { return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs; } -static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) { - return zig_and_u128(val, zig_maxInt_u(128, bits)); -} - -static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) { - if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val)); - int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits); - return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); -} - static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) { - return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_shl_u128(lhs, rhs), bits); } static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_shl_u128(zig_bitCast_u128(lhs), rhs)), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_shl_u128(zig_u128_bitCast_i128(lhs, bits), rhs), bits), bits); } static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_add_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_add_u128(lhs, rhs), bits); } static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_add_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_add_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_sub_u128(lhs, rhs), bits); } static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_sub_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_sub_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_mul_u128(lhs, rhs), bits); } static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_mul_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } -static inline zig_u128 zig_abs_i128(zig_i128 val) { - zig_i128 tmp = zig_shr_i128(val, 127); - return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp)); +static inline zig_u128 zig_abs_i128(zig_i128 arg) { + zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128)); + return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp); } #if zig_has_int128 @@ -2160,7 +2466,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(add_overflow) zig_u128 full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_addw_u128(lhs, rhs, bits); @@ -2176,7 +2482,7 @@ static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs); bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } @@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(sub_overflow) zig_u128 full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_subw_u128(lhs, rhs, bits); @@ -2200,7 +2506,7 @@ static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs); bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } @@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(mul_overflow) zig_u128 full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_mulw_u128(lhs, rhs, bits); @@ -2216,8 +2522,8 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #endif } -zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { + zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); #if zig_has_builtin(mul_overflow) zig_i128 full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -2226,50 +2532,78 @@ static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } #else /* zig_has_int128 */ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - uint64_t hi; - bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + uint64_t lo; + bool overflow = zig_addo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); + *res = zig_u128_intCast_u64(lo); + return overflow; + } else { + uint64_t hi; + bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int64_t hi; - bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + int64_t lo; + bool overflow = zig_addo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); + *res = zig_i128_intCast_i64(lo); + return overflow; + } else { + int64_t hi; + bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - uint64_t hi; - bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + uint64_t lo; + bool overflow = zig_subo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); + *res = zig_u128_intCast_u64(lo); + return overflow; + } else { + uint64_t hi; + bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int64_t hi; - bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + int64_t lo; + bool overflow = zig_subo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); + *res = zig_i128_intCast_i64(lo); + return overflow; + } else { + int64_t hi; + bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { *res = zig_mulw_u128(lhs, rhs, bits); - return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) && - zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); + return zig_cmp_u128(rhs, zig_make_u128(0, 0)) != INT32_C(0) && + zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); } -zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { + zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); int overflow_int; zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0 || zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) || zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0); - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow; } @@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8 static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) { *res = zig_shlw_i128(lhs, rhs, bits); - zig_i128 mask = zig_bitCast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1))); + zig_i128 mask = zig_i128_bitCast_u128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)), bits); return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) && zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0); } -static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { +#define zig_int128_shls_builtins(rw) \ + static inline zig_u128 zig_shls_u128_u##rw(zig_u128 lhs, uint##rw##_t rhs, uint8_t bits) { \ + zig_u128 res; \ + if (rhs < bits && !zig_shlo_u128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + switch (zig_cmp_u128(lhs, zig_make_u128(UINT64_C(0), UINT64_C(0)))) { \ + case 0: return zig_minInt_u(128, bits); \ + case 1: return zig_maxInt_u(128, bits); \ + default: zig_unreachable(); \ + } \ + } \ +\ + static inline zig_i128 zig_shls_i128_u##rw(zig_i128 lhs, uint##rw##_t rhs, uint8_t bits) { \ + zig_i128 res; \ + if (rhs < bits && !zig_shlo_i128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + switch (zig_cmp_i128(lhs, zig_make_i128(INT64_C(0), UINT64_C(0)))) { \ + case -1: return zig_minInt_i(128, bits); \ + case 0: return zig_make_i128(INT64_C(0), UINT64_C(0)); \ + case 1: return zig_maxInt_i(128, bits); \ + default: zig_unreachable(); \ + } \ + } +zig_int128_shls_builtins(8) +zig_int128_shls_builtins(16) +zig_int128_shls_builtins(32) +zig_int128_shls_builtins(64) + +static inline zig_u128 zig_shls_u128_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { zig_u128 res; if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) { - case 0: return zig_make_u128(0, 0); - case 1: return zig_maxInt_u(128, bits); + case INT32_C(0): return zig_make_u128(0, 0); + case INT32_C(1): return zig_maxInt_u(128, bits); default: zig_unreachable(); } } -static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { +static inline zig_i128 zig_shls_i128_u128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { zig_i128 res; if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) { - case -1: return zig_minInt_i(128, bits); - case 0: return zig_make_i128(0, 0); - case 1: return zig_maxInt_i(128, bits); + case -INT32_C(1): return zig_minInt_i(128, bits); + case INT32_C(0): return zig_make_i128(0, 0); + case INT32_C(1): return zig_maxInt_i(128, bits); default: zig_unreachable(); } } @@ -2341,57 +2701,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits); } -static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) { - if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits); - if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64)); - return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64)); +static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) { + if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits); + if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64)); + return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64)); } -static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) { - return zig_clz_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) { + return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) { - if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64)); - return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64); +static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) { + if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64)); + return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64); } -static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) { - return zig_ctz_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) { + return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) { - return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) + - zig_popcount_u64(zig_lo_u128(val), UINT8_C(64)); +static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) { + return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) + + zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64)); } -static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) { - return zig_popcount_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) { + return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) { +static inline zig_u128 zig_byteSwap_u128(zig_u128 arg, uint8_t bits) { zig_u128 full_res; #if zig_has_builtin(bswap128) - full_res = __builtin_bswap128(val); + full_res = __builtin_bswap128(arg); #else - full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)), - zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64))); + full_res = zig_make_u128( + zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)), + zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64)) + ); #endif return zig_shr_u128(full_res, UINT8_C(128) - bits); } -static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) { - return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits)); +static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) { + return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); } -static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) { - return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)), - zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))), - UINT8_C(128) - bits); +static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) { + return zig_shr_u128(zig_make_u128( + zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)), + zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64)) + ), UINT8_C(128) - bits); } -static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { - return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits)); +static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) { + return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); } #if zig_has_int128 @@ -2411,12 +2774,378 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { /* ========================== Big Integer Support =========================== */ static inline uint16_t zig_int_bytes(uint16_t bits) { - uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT; + uint16_t bytes = (bits - UINT16_C(1)) / CHAR_BIT + UINT16_C(1); uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT; + while (alignment / 2 >= bytes) alignment /= 2; return (bytes + alignment - 1) / alignment * alignment; } +static inline void zig_minInt_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + + if (is_signed) { + int8_t signed_sign_byte = zig_minInt_i(8, remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_minInt_u(8, remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memset(&res_bytes[0], zig_minInt_u8, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + byte_offset = size - UINT16_C(1) - byte_offset; + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], zig_minInt_u8, size - byte_offset); +#endif +} + +static inline void zig_maxInt_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + + if (is_signed) { + int8_t signed_sign_byte = zig_maxInt_i(8, remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_maxInt_u(8, remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memset(&res_bytes[0], zig_maxInt_u8, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + byte_offset = size - UINT16_C(1) - byte_offset; + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], zig_maxInt_u8, size - byte_offset); +#endif +} + +static inline int8_t zig_signFill_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + + if (!is_signed) return INT8_C(0); +#if zig_little_endian + byte_offset = zig_int_bytes(bits) - 1; +#endif + return zig_shr_i8(zig_i8_bitCast_u8(arg_bytes[byte_offset], UINT8_C(8)), UINT8_C(7)); +} + +static inline void zig_big_intCast_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_size = zig_int_bytes(res_bits); + uint16_t arg_size = zig_int_bytes(arg_bits); + uint16_t copy_size = zig_min_u16(res_size, arg_size); + uint8_t sign_fill = zig_u8_bitCast_i8(zig_signFill_big(arg, arg_is_signed, arg_bits), UINT8_C(8)); + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], copy_size); + memset(&res_bytes[copy_size], sign_fill, res_size - copy_size); +#else + memset(&res_bytes[0], sign_fill, res_size - copy_size); + memcpy(&res_bytes[res_size - copy_size], &arg_bytes[arg_size - copy_size], copy_size); +#endif +} + +static inline void zig_big_truncate_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_size = zig_int_bytes(res_bits); + + if (res_is_signed != arg_is_signed) zig_unreachable(); + if (res_bits > arg_bits) zig_unreachable(); + + if (res_is_signed) { + uint16_t arg_byte_offset = UINT16_C(0); + +#if zig_big_endian + arg_byte_offset = zig_int_bytes(arg_bits) - res_size; +#endif + + memcpy(&res_bytes[0], &arg_bytes[arg_byte_offset], res_size); + } else { + uint16_t res_byte_offset = zig_shr_u16(res_bits - UINT16_C(1), UINT8_C(3)); + uint16_t arg_byte_offset = res_byte_offset; + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], res_byte_offset); +#else + res_byte_offset = res_size - UINT16_C(1) - res_byte_offset; + arg_byte_offset = zig_int_bytes(arg_bits) - UINT16_C(1) - arg_byte_offset; + + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#endif + + res_bytes[res_byte_offset] = zig_u8_truncate_u8( + arg_bytes[arg_byte_offset], + zig_u8_truncate_u8(res_bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1) + ); + res_byte_offset += UINT16_C(1); + arg_byte_offset += UINT16_C(1); + +#if zig_little_endian + memset(&res_bytes[res_byte_offset], zig_minInt_u8, res_size - res_byte_offset); +#else + memcpy(&res_bytes[res_byte_offset], &arg_bytes[arg_byte_offset], res_size - res_byte_offset); +#endif + } +} + +#define zig_big_casts(is, s, w, IntType) \ + static inline IntType zig_##s##w##_intCast_big(const void *arg, bool arg_is_signed, uint16_t arg_bits) { \ + IntType res; \ + zig_big_intCast_big(&res, arg, is, w, arg_is_signed, arg_bits); \ + return res; \ + } \ +\ + static inline void zig_big_intCast_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \ + zig_big_intCast_big(res, &arg, res_is_signed, res_bits, is, w); \ + } \ +\ + static inline IntType zig_##s##w##_truncate_big(const void *arg, uint8_t res_bits, bool arg_is_signed, uint16_t arg_bits) { \ + IntType res; \ + zig_big_truncate_big(&res, arg, is, res_bits, arg_is_signed, arg_bits); \ + return res; \ + } \ +\ + static inline void zig_big_truncate_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \ + zig_big_truncate_big(res, &arg, res_is_signed, res_bits, is, w); \ + } +zig_big_casts(false, u, 8, uint8_t) +zig_big_casts(true , i, 8, int8_t) +zig_big_casts(false, u, 16, uint16_t) +zig_big_casts(true , i, 16, int16_t) +zig_big_casts(false, u, 32, uint32_t) +zig_big_casts(true , i, 32, int32_t) +zig_big_casts(false, u, 64, uint64_t) +zig_big_casts(true , i, 64, int64_t) +zig_big_casts(false, u, 128, zig_u128) +zig_big_casts(true , i, 128, zig_i128) + +static inline void zig_big_bitCast_big(void *res, const void *arg, bool res_is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + +#if zig_big_endian + byte_offset = size - UINT16_C(1) - byte_offset; +#endif + + if (res_is_signed) { + int8_t signed_sign_byte = zig_i8_bitCast_u8(arg_bytes[byte_offset], remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_u8_bitCast_u8(arg_bytes[byte_offset], remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memcpy(&res_bytes[byte_offset], &arg_bytes[byte_offset], size - byte_offset); +#endif +} + +static inline int32_t zig_cmp_big_u8(const void *lhs, uint8_t rhs, bool is_signed, uint16_t bits) { + const uint8_t *lhs_bytes = lhs; + uint16_t byte_offset = 0; + bool do_signed = is_signed; + uint16_t remaining_bytes = zig_int_bytes(bits); + +#if zig_little_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0); + int32_t limb_cmp; + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (do_signed) { + zig_i128 lhs_limb; + zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb); + do_signed = false; + } else { + zig_u128 lhs_limb; + zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb); + } + + if (limb_cmp != 0) return limb_cmp; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (do_signed) { + int64_t lhs_limb; + int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint64_t lhs_limb; + uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (do_signed) { + int32_t lhs_limb; + int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint32_t lhs_limb; + uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (do_signed) { + int16_t lhs_limb; + int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint16_t lhs_limb; + uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (do_signed) { + int8_t lhs_limb; + int16_t lhs_cmp_limb; + int16_t rhs_cmp_limb = zig_i16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb); + if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb); + do_signed = false; + } else { + uint8_t lhs_limb; + uint8_t rhs_limb = rhs_byte; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return 0; +} + static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { const uint8_t *lhs_bytes = lhs; const uint8_t *rhs_bytes = rhs; @@ -2579,6 +3308,168 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign return 0; } +static inline void zig_not_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (remaining_bytes != 128 / CHAR_BIT || is_signed) { + zig_i128 res_limb; + zig_i128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i128(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + zig_u128 res_limb; + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u128(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (remaining_bytes != 64 / CHAR_BIT || is_signed) { + int64_t res_limb; + int64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i64(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint64_t res_limb; + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u64(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (remaining_bytes != 32 / CHAR_BIT || is_signed) { + int32_t res_limb; + int32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i32(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint32_t res_limb; + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u32(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (remaining_bytes != 16 / CHAR_BIT || is_signed) { + int16_t res_limb; + int16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i16(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint16_t res_limb; + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u16(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (remaining_bytes != 8 / CHAR_BIT || is_signed) { + int8_t res_limb; + int8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i8(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint8_t res_limb; + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u8(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { uint8_t *res_bytes = res; const uint8_t *lhs_bytes = lhs; @@ -2816,13 +3707,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool } } +static inline void zig_increment_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_decrement_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_abs_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + if (zig_signFill_big(arg, is_signed, bits) >= INT8_C(0)) { + memcpy(res, arg, remaining_bytes); + return; + } + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + bool overflow = true; + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u128(&res_limb, zig_not_u128(arg_limb, UINT8_C(128)), zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u64(&res_limb, zig_not_u64(arg_limb, UINT8_C(64)), overflow ? UINT64_C(1) : UINT64_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u32(&res_limb, zig_not_u32(arg_limb, UINT8_C(32)), overflow ? UINT32_C(1) : UINT32_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u16(&res_limb, zig_not_u16(arg_limb, UINT8_C(16)), overflow ? UINT16_C(1) : UINT16_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u8(&res_limb, zig_not_u8(arg_limb, UINT8_C(8)), overflow ? UINT8_C(1) : UINT8_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_min_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) < INT32_C(0) ? lhs : rhs, zig_int_bytes(bits)); +} + +static inline void zig_max_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) >= INT32_C(0) ? lhs : rhs, zig_int_bytes(bits)); +} + static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { uint8_t *res_bytes = res; const uint8_t *lhs_bytes = lhs; const uint8_t *rhs_bytes = rhs; uint16_t byte_offset = 0; uint16_t remaining_bytes = zig_int_bytes(bits); - uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); bool overflow = false; #if zig_big_endian @@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo const uint8_t *rhs_bytes = rhs; uint16_t byte_offset = 0; uint16_t remaining_bytes = zig_int_bytes(bits); - uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); bool overflow = false; #if zig_big_endian @@ -3248,323 +4541,755 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo return overflow; } +static inline void zig_add_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_addo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow +} + static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { (void)zig_addo_big(res, lhs, rhs, is_signed, bits); } +static inline void zig_adds_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits); + + if (!zig_addo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); + } +} + +static inline void zig_sub_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_subo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow +} + static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { (void)zig_subo_big(res, lhs, rhs, is_signed, bits); } -zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); -static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - __udivei4(res, lhs, rhs, bits); - return; - } +static inline void zig_subs_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = is_signed ? zig_signFill_big(lhs, is_signed, bits) : -INT8_C(1); - zig_trap(); + if (!zig_subo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); + } } -static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - zig_div_trunc_big(res, lhs, rhs, is_signed, bits); - return; +static inline bool zig_mulo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + const uint8_t *rhs_bytes = rhs; + uint16_t size = zig_int_bytes(bits); + uint16_t sign_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8)); + uint8_t rhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(rhs, is_signed, bits), UINT8_C(8)); + uint16_t lhs_byte_offset = sign_byte_offset; + uint16_t lhs_end_byte_offset = UINT16_C(0); + bool overflow = false; + +#if zig_big_endian + lhs_byte_offset = size - lhs_byte_offset; + lhs_end_byte_offset = size - lhs_end_byte_offset; +#endif + + while (lhs_byte_offset != lhs_end_byte_offset) { + uint16_t rhs_byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint16_t res_byte_offset; + uint16_t lhs_byte; + uint8_t res_byte = UINT8_C(0); + uint16_t mul_res = UINT16_C(0); + uint8_t carry = UINT8_C(0); + +#if zig_little_endian + lhs_byte_offset -= UINT16_C(1); +#else + rhs_byte_offset = size - rhs_byte_offset; + end_byte_offset = size - end_byte_offset; +#endif + + lhs_byte = zig_u16_intCast_u8(lhs_bytes[lhs_byte_offset]) ^ lhs_sign_fill; + +#if zig_big_endian + lhs_byte_offset += UINT16_C(1); +#endif + + res_byte_offset = lhs_byte_offset; + + while (res_byte_offset != end_byte_offset) { + bool res_byte_initialized = res_byte_offset != lhs_byte_offset; + +#if zig_big_endian + rhs_byte_offset -= UINT16_C(1); + res_byte_offset -= UINT16_C(1); +#endif + + if (res_byte_initialized) res_byte = res_bytes[res_byte_offset]; + carry = zig_addo_u8(&res_byte, res_byte, carry, UINT8_C(8)); + carry += zig_addo_u8(&res_byte, res_byte, zig_u8_intCast_u16( + zig_shr_u16(mul_res, UINT8_C(8)) + ), UINT8_C(8)); + mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill); + carry += zig_addo_u8(&res_bytes[res_byte_offset], res_byte, zig_u8_truncate_u16( + mul_res, + UINT8_C(8) + ), UINT8_C(8)); + +#if zig_little_endian + rhs_byte_offset += UINT16_C(1); + res_byte_offset += UINT16_C(1); +#endif + } + + while (rhs_byte_offset != end_byte_offset) { +#if zig_big_endian + rhs_byte_offset -= UINT16_C(1); +#endif + + carry = zig_addo_u8( + &res_byte, + zig_u8_intCast_u16(zig_shr_u16(mul_res, UINT8_C(8))), + carry, + UINT8_C(8) + ); + mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill); + carry += zig_addo_u8(&res_byte, res_byte, zig_u8_truncate_u16( + mul_res, + UINT8_C(8) + ), UINT8_C(8)); + overflow |= res_byte != UINT8_C(0); + +#if zig_little_endian + rhs_byte_offset += UINT16_C(1); +#endif + } + + overflow |= zig_shr_u16(mul_res, UINT8_C(8)) != UINT16_C(0); + overflow |= carry != UINT8_C(0); } - zig_trap(); +#if zig_little_endian + sign_byte_offset -= UINT64_C(1); +#else + sign_byte_offset = size - sign_byte_offset; +#endif + + if (lhs_sign_fill != rhs_sign_fill) { + uint16_t byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint8_t res_byte; + int8_t signed_res_byte; + uint8_t carry = UINT8_C(0); + +#if zig_big_endian + byte_offset = size - byte_offset; + end_byte_offset += UINT16_C(1); +#endif + + while (byte_offset != end_byte_offset) { +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + carry = zig_subo_u8(&res_byte, UINT8_C(0), carry, UINT8_C(8)); + carry += zig_subo_u8(&res_byte, res_byte, res_bytes[byte_offset], UINT8_C(8)); + carry += zig_subo_u8( + &res_bytes[byte_offset], + res_byte, + (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset], + UINT8_C(8) + ); + +#if zig_little_endian + byte_offset += UINT16_C(1); +#endif + } + +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8)); + overflow |= signed_res_byte < INT8_C(0); + overflow |= zig_subo_i8(&signed_res_byte, INT8_C(0), signed_res_byte, UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8)); + } else if (lhs_sign_fill != UINT8_C(0)) { + uint16_t byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint8_t res_byte; + int8_t signed_res_byte; + uint8_t carry = UINT8_C(1); + +#if zig_big_endian + byte_offset = size - byte_offset; + end_byte_offset += UINT16_C(1); +#endif + + while (byte_offset != end_byte_offset) { +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + carry = zig_subo_u8(&res_byte, res_bytes[byte_offset], carry, UINT8_C(8)); + carry += zig_subo_u8(&res_byte, res_byte, lhs_bytes[byte_offset], UINT8_C(8)); + carry += zig_subo_u8(&res_bytes[byte_offset], res_byte, rhs_bytes[byte_offset], UINT8_C(8)); + +#if zig_little_endian + byte_offset += UINT16_C(1); +#endif + } + +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8)); + overflow |= signed_res_byte < INT8_C(0); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + lhs_bytes[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + rhs_bytes[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8)); + } else if (is_signed) { + int8_t signed_res_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8)); + + overflow |= signed_res_byte < INT8_C(0); + } + + { + uint8_t truncate_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t fill_byte = UINT8_C(0); + + if (is_signed) { + int8_t sign_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8)); + int8_t truncated = zig_i8_truncate_i8(sign_byte, truncate_bits); + + overflow |= sign_byte != truncated; + res_bytes[sign_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8)); + } else { + uint8_t sign_byte = res_bytes[sign_byte_offset]; + uint8_t truncated = zig_u8_truncate_u8(sign_byte, truncate_bits); + + overflow |= sign_byte != truncated; + res_bytes[sign_byte_offset] = truncated; + } + +#if zig_little_endian + sign_byte_offset += UINT16_C(1); + memset(&res_bytes[sign_byte_offset], fill_byte, size - sign_byte_offset); +#else + memset(&res_bytes[0], fill_byte, sign_byte_offset); +#endif + } + + return overflow; +} + +static inline void zig_mul_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_mulo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow } -static inline void zig_div_ceil_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - zig_trap(); +static inline void zig_mulw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + (void)zig_mulo_big(res, lhs, rhs, is_signed, bits); } -zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); -static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - __umodei4(res, lhs, rhs, bits); - return; +static inline void zig_muls_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits) ^ zig_signFill_big(rhs, is_signed, bits); + + if (!zig_mulo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); } +} + +static inline void zig_divTrunc_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + if (is_signed) { + zig_extern void __divei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __divei5(res, lhs, rhs, temp, bits); + } else { + zig_extern void __udivei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __udivei5(res, lhs, rhs, temp, bits); + } +} - zig_trap(); +static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + if (is_signed) { + zig_extern void __modei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __modei5(res, lhs, rhs, temp, bits); + } else { + zig_extern void __umodei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __umodei5(res, lhs, rhs, temp, bits); + } } -static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - zig_rem_big(res, lhs, rhs, is_signed, bits); - return; +static inline void zig_divFloor_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool decrement = false; + + if (is_signed) { + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + decrement = zig_u32_bitCast_i32(zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32)); } + zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits); + if (decrement) zig_decrement_big(res, is_signed, bits); +} - zig_trap(); +static inline void zig_divCeil_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool increment = false; + + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + increment = zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ) > INT32_C(0); + zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits); + if (increment) zig_increment_big(res, is_signed, bits); } -static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; - uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); - uint16_t skip_bits = remaining_bytes * 8 - bits; - uint16_t total_lz = 0; - uint16_t limb_lz; - (void)is_signed; +static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool fixup = false; -#if zig_little_endian - byte_offset = remaining_bytes; + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + if (is_signed && zig_u32_bitCast_i32(zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32))) zig_add_big(res, res, rhs, is_signed, bits); +} + +static inline void zig_shr_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = UINT16_C(0); + uint16_t lhs_byte_offset = zig_shr_u16(rhs, UINT8_C(3)); + uint16_t end_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t lhs_prev_byte; + uint8_t byte_shift = zig_u8_truncate_u16(rhs, UINT8_C(3)); + +#if zig_big_endian + res_byte_offset = size - res_byte_offset; + lhs_byte_offset = size - lhs_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - while (remaining_bytes >= 128 / CHAR_BIT) { + { +#if zig_big_endian + lhs_byte_offset -= UINT16_C(1); +#endif + + lhs_prev_byte = lhs_bytes[lhs_byte_offset]; + #if zig_little_endian - byte_offset -= 128 / CHAR_BIT; + lhs_byte_offset += UINT16_C(1); +#endif + } + + while (lhs_byte_offset != end_byte_offset) { +#if zig_big_endian + res_byte_offset -= UINT16_C(1); + lhs_byte_offset -= UINT16_C(1); #endif { - zig_u128 val_limb; + uint8_t lhs_byte = lhs_bytes[lhs_byte_offset]; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u128(val_limb, 128 - skip_bits); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_prev_byte) + ), byte_shift)); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 128 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 128 / CHAR_BIT; - -#if zig_big_endian - byte_offset += 128 / CHAR_BIT; +#if zig_little_endian + res_byte_offset += UINT16_C(1); + lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 64 / CHAR_BIT) { -#if zig_little_endian - byte_offset -= 64 / CHAR_BIT; + { + uint8_t lhs_sign_fill = UINT8_C(0); + +#if zig_big_endian + res_byte_offset -= UINT16_C(1); #endif - { - uint64_t val_limb; + if (is_signed) { + int8_t signed_byte = zig_i8_bitCast_u8(lhs_prev_byte, UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u64(val_limb, 64 - skip_bits); + res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift); + lhs_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8)); + } else { + res_bytes[res_byte_offset] = zig_shr_u8(lhs_prev_byte, byte_shift); } - total_lz += limb_lz; - if (limb_lz < 64 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 64 / CHAR_BIT; - -#if zig_big_endian - byte_offset += 64 / CHAR_BIT; +#if zig_little_endian + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], lhs_sign_fill, size - res_byte_offset); +#else + memset(&res_bytes[0], lhs_sign_fill, res_byte_offset); #endif } +} + +static inline bool zig_shlo_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8)); + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t lhs_byte_offset = UINT16_C(0); + uint16_t end_byte_offset = res_byte_offset - UINT16_C(1) - zig_shr_u16(rhs, UINT8_C(3)); + uint8_t lhs_prev_byte = lhs_sign_fill; + uint8_t byte_shift = UINT8_C(8) - zig_u8_truncate_u16(rhs, UINT8_C(3)); + bool overflow = false; - while (remaining_bytes >= 32 / CHAR_BIT) { #if zig_little_endian - byte_offset -= 32 / CHAR_BIT; + lhs_byte_offset = size - lhs_byte_offset; +#else + res_byte_offset = size - res_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - { - uint32_t val_limb; - - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u32(val_limb, 32 - skip_bits); - } + while (lhs_byte_offset != end_byte_offset) { +#if zig_little_endian + lhs_byte_offset -= UINT16_C(1); +#endif - total_lz += limb_lz; - if (limb_lz < 32 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 32 / CHAR_BIT; + overflow |= lhs_prev_byte != lhs_sign_fill; + lhs_prev_byte = lhs_bytes[lhs_byte_offset]; #if zig_big_endian - byte_offset += 32 / CHAR_BIT; + lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 16 / CHAR_BIT) { #if zig_little_endian - byte_offset -= 16 / CHAR_BIT; + end_byte_offset = UINT16_C(0); +#else + end_byte_offset = size; +#endif + + { + bool lhs_more_bytes = lhs_byte_offset != end_byte_offset; + +#if zig_little_endian + if (lhs_more_bytes) lhs_byte_offset -= UINT16_C(1); #endif { - uint16_t val_limb; + uint8_t lhs_byte = UINT8_C(0); + + if (lhs_more_bytes) lhs_byte = lhs_bytes[lhs_byte_offset]; + + if (is_signed) { + int16_t shifted = zig_shr_i16(zig_or_i16( + zig_shl_i16(zig_i16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_i16_intCast_u8(lhs_byte) + ), byte_shift); + int8_t truncated = zig_i8_truncate_i16( + shifted, + zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1) + ); + uint8_t fill = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8)); + + overflow |= zig_i16_intCast_i8(truncated) != shifted; +#if zig_little_endian + memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); + res_byte_offset -= UINT16_C(1); +#else + memset(&res_bytes[0], fill, res_byte_offset); +#endif + res_bytes[res_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8)); + } else { + uint16_t shifted = zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_byte) + ), byte_shift); + uint8_t truncated = zig_u8_truncate_u16( + shifted, + zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1) + ); + + overflow |= zig_u16_intCast_u8(truncated) != shifted; +#if zig_little_endian + memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset); + res_byte_offset -= UINT16_C(1); +#else + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#endif + res_bytes[res_byte_offset] = truncated; + } - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u16(val_limb, 16 - skip_bits); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 16 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 16 / CHAR_BIT; - #if zig_big_endian - byte_offset += 16 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + if (lhs_more_bytes) lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 8 / CHAR_BIT) { + while (lhs_byte_offset != end_byte_offset) { #if zig_little_endian - byte_offset -= 8 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); + lhs_byte_offset -= UINT16_C(1); #endif { - uint8_t val_limb; + uint8_t lhs_byte = lhs_bytes[lhs_byte_offset]; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u8(val_limb, 8 - skip_bits); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_byte) + ), byte_shift)); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 8 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 8 / CHAR_BIT; - #if zig_big_endian - byte_offset += 8 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + lhs_byte_offset += UINT16_C(1); #endif } - return total_lz; -} + { +#if zig_little_endian + res_byte_offset -= UINT16_C(1); +#endif -static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; - uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); - uint16_t total_tz = 0; - uint16_t limb_tz; - (void)is_signed; + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + byte_shift + )); #if zig_big_endian - byte_offset = remaining_bytes; + res_byte_offset += UINT16_C(1); #endif + } - while (remaining_bytes >= 128 / CHAR_BIT) { -#if zig_big_endian - byte_offset -= 128 / CHAR_BIT; +#if zig_little_endian + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#else + memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset); #endif - { - zig_u128 val_limb; + return overflow; +} - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u128(val_limb, 128); - } +static inline void zig_shl_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + if (zig_shlo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: left shift overflowed bits +} - total_tz += limb_tz; - if (limb_tz < 128) return total_tz; - remaining_bytes -= 128 / CHAR_BIT; +static inline void zig_shlw_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + (void)zig_shlo_big(res, lhs, rhs, is_signed, bits); +} -#if zig_little_endian - byte_offset += 128 / CHAR_BIT; -#endif +#define zig_big_shls_builtin(w) \ + static inline uint##w##_t zig_shls_u##w##_big(uint##w##_t lhs, const void *rhs, \ + uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \ + uint##w##_t res; \ + const uint8_t *rhs_bytes = rhs; \ + if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \ + !zig_shlo_u##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \ + return lhs == INT##w##_C(0) ? zig_minInt_u(w, lhs_bits) : zig_maxInt_u(w, lhs_bits); \ + } \ +\ + static inline int##w##_t zig_shls_i##w##_big(int##w##_t lhs, const void *rhs, \ + uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \ + int##w##_t res; \ + const uint8_t *rhs_bytes = rhs; \ + if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \ + !zig_shlo_i##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \ + return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ + lhs < INT##w##_C(0) ? zig_minInt_i(w, lhs_bits) : zig_maxInt_i(w, lhs_bits); \ + } \ +\ + static inline void zig_shls_big_u##w(void *res, const void *lhs, uint##w##_t rhs, bool is_signed, uint16_t bits) { \ + const uint8_t *lhs_bytes = lhs; \ + if (rhs < bits && !zig_shlo_big(res, lhs, zig_u16_intCast_u##w(rhs), is_signed, bits)) return; \ + switch (zig_cmp_big_u8(lhs, UINT8_C(0), is_signed, bits)) { \ + case -INT32_C(1): return zig_minInt_big(res, is_signed, bits); \ + case INT32_C(0): return zig_minInt_big(res, false, bits); \ + case INT32_C(1): return zig_maxInt_big(res, is_signed, bits); \ + default: zig_unreachable(); \ + } \ } +zig_big_shls_builtin(8) +zig_big_shls_builtin(16) +zig_big_shls_builtin(32) +zig_big_shls_builtin(64) + +static inline void zig_byteSwap_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_byte_offset = UINT16_C(0); + uint16_t arg_byte_offset = bits / CHAR_BIT; + uint16_t end_byte_offset = UINT16_C(1); + uint16_t size = zig_int_bytes(bits); - while (remaining_bytes >= 64 / CHAR_BIT) { #if zig_big_endian - byte_offset -= 64 / CHAR_BIT; + res_byte_offset = size - res_byte_offset; + arg_byte_offset = size - arg_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - { - uint64_t val_limb; - - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u64(val_limb, 64); - } + while (arg_byte_offset != end_byte_offset) { +#if zig_little_endian + arg_byte_offset -= UINT16_C(1); +#else + res_byte_offset -= UINT16_C(1); +#endif - total_tz += limb_tz; - if (limb_tz < 64) return total_tz; - remaining_bytes -= 64 / CHAR_BIT; + res_bytes[res_byte_offset] = arg_bytes[arg_byte_offset]; #if zig_little_endian - byte_offset += 64 / CHAR_BIT; + res_byte_offset += UINT16_C(1); +#else + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 32 / CHAR_BIT) { -#if zig_big_endian - byte_offset -= 32 / CHAR_BIT; + { +#if zig_little_endian + arg_byte_offset -= UINT16_C(1); +#else + res_byte_offset -= UINT16_C(1); #endif { - uint32_t val_limb; + uint8_t byte = arg_bytes[arg_byte_offset]; + uint8_t fill = is_signed + ? zig_u8_bitCast_i8(zig_shr_i8(zig_i8_bitCast_u8(byte, UINT8_C(8)), UINT8_C(7)), UINT8_C(8)) + : UINT8_C(0); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u32(val_limb, 32); + res_bytes[res_byte_offset] = byte; + +#if zig_little_endian + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); +#else + memset(&res_bytes[0], fill, res_byte_offset); +#endif } + } +} - total_tz += limb_tz; - if (limb_tz < 32) return total_tz; - remaining_bytes -= 32 / CHAR_BIT; +static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = UINT16_C(0); + uint16_t arg_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t end_byte_offset = UINT16_C(0); + uint8_t arg_prev_byte; + uint8_t byte_shift = zig_u8_intCast_u16(zig_subw_u16(UINT16_C(0), bits, UINT8_C(3))); + +#if zig_big_endian + res_byte_offset = size - res_byte_offset; + arg_byte_offset = size - arg_byte_offset; + end_byte_offset = size - end_byte_offset; +#endif + { #if zig_little_endian - byte_offset += 32 / CHAR_BIT; + arg_byte_offset -= UINT16_C(1); +#endif + + arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); + +#if zig_big_endian + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 16 / CHAR_BIT) { + while (arg_byte_offset != end_byte_offset) { #if zig_big_endian - byte_offset -= 16 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); +#else + arg_byte_offset -= UINT16_C(1); #endif { - uint16_t val_limb; + uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u16(val_limb, 16); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(arg_byte), UINT8_C(8)), + zig_u16_intCast_u8(arg_prev_byte) + ), byte_shift)); + arg_prev_byte = arg_byte; } - total_tz += limb_tz; - if (limb_tz < 16) return total_tz; - remaining_bytes -= 16 / CHAR_BIT; - #if zig_little_endian - byte_offset += 16 / CHAR_BIT; + res_byte_offset += UINT16_C(1); +#else + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 8 / CHAR_BIT) { + { + uint8_t arg_sign_fill = UINT8_C(0); + #if zig_big_endian - byte_offset -= 8 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); #endif - { - uint8_t val_limb; + if (is_signed) { + int8_t signed_byte = zig_i8_bitCast_u8(arg_prev_byte, UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u8(val_limb, 8); + res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift); + arg_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8)); + } else { + res_bytes[res_byte_offset] = zig_shr_u8(arg_prev_byte, byte_shift); } - total_tz += limb_tz; - if (limb_tz < 8) return total_tz; - remaining_bytes -= 8 / CHAR_BIT; - #if zig_little_endian - byte_offset += 8 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], arg_sign_fill, size - res_byte_offset); +#else + memset(&res_bytes[0], arg_sign_fill, res_byte_offset); #endif } - - return total_tz; } -static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; +static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); + uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); uint16_t total_pc = 0; (void)is_signed; #if zig_big_endian - byte_offset = remaining_bytes; + byte_offset = zig_int_bytes(bits); #endif while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 128 / CHAR_BIT; #endif { - zig_u128 val_limb; + zig_u128 arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u128(val_limb, 128); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 128 / CHAR_BIT; @@ -3575,15 +5300,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 64 / CHAR_BIT; #endif { - uint64_t val_limb; + uint64_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u64(val_limb, 64); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 64 / CHAR_BIT; @@ -3594,15 +5321,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 32 / CHAR_BIT; #endif { - uint32_t val_limb; + uint32_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u32(val_limb, 32); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 32 / CHAR_BIT; @@ -3613,15 +5342,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 16 / CHAR_BIT; #endif { - uint16_t val_limb; + uint16_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc = zig_popcount_u16(val_limb, 16); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 16 / CHAR_BIT; @@ -3632,15 +5363,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 8 / CHAR_BIT; #endif { - uint8_t val_limb; + uint8_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc = zig_popcount_u8(val_limb, 8); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 8 / CHAR_BIT; @@ -3653,6 +5386,274 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ return total_pc; } +static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = UINT16_C(0); + uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + uint16_t total_tz = UINT16_C(0); + uint16_t limb_tz; + (void)is_signed; + +#if zig_big_endian + byte_offset = zig_int_bytes(bits); +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_tz; +} + +static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t remaining_bytes = byte_offset; + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + bool sign_limb = true; + uint16_t total_lz = UINT16_C(0); + uint16_t limb_lz; + (void)is_signed; + +#if zig_big_endian + byte_offset = zig_int_bytes(bits) - remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_lz; +} + /* ========================= Floating Point Support ========================= */ #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ @@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input); #define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg) #define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg) #else -#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr) -#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr) -#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr) -#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr) -#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr) +#define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr) +#define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr) +#define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr) +#define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr) +#define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr) #endif #define zig_has_f16 1 #define zig_libc_name_f16(name) __##name##h #define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr) -#if FLT_MANT_DIG == 11 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11 typedef float zig_f16; #define zig_make_f16(fp, repr) fp##f -#elif DBL_MANT_DIG == 11 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11 typedef double zig_f16; #define zig_make_f16(fp, repr) fp -#elif LDBL_MANT_DIG == 11 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11 typedef long double zig_f16; #define zig_make_f16(fp, repr) fp##l -#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc)) +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc)) typedef _Float16 zig_f16; #define zig_make_f16(fp, repr) fp##f16 -#elif defined(__SIZEOF_FP16__) +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && defined(__SIZEOF_FP16__) typedef __fp16 zig_f16; #define zig_make_f16(fp, repr) fp##f16 #else @@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16; #undef zig_init_special_f16 #define zig_init_special_f16(sign, name, arg, repr) repr #endif -#if defined(zig_darwin) && defined(zig_x86) -typedef uint16_t zig_compiler_rt_f16; -#else -typedef zig_f16 zig_compiler_rt_f16; -#endif #define zig_has_f32 1 #define zig_libc_name_f32(name) name##f @@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16; #else #define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr) #endif -#if FLT_MANT_DIG == 24 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24 typedef float zig_f32; #define zig_make_f32(fp, repr) fp##f -#elif DBL_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24 typedef double zig_f32; #define zig_make_f32(fp, repr) fp -#elif LDBL_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24 typedef long double zig_f32; #define zig_make_f32(fp, repr) fp##l -#elif FLT32_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24 typedef _Float32 zig_f32; #define zig_make_f32(fp, repr) fp##f32 #else @@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32; #else #define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr) #endif -#if FLT_MANT_DIG == 53 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53 typedef float zig_f64; #define zig_make_f64(fp, repr) fp##f -#elif DBL_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53 typedef double zig_f64; #define zig_make_f64(fp, repr) fp -#elif LDBL_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53 typedef long double zig_f64; #define zig_make_f64(fp, repr) fp##l -#elif FLT64_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53 typedef _Float64 zig_f64; #define zig_make_f64(fp, repr) fp##f64 -#elif FLT32X_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53 typedef _Float32x zig_f64; #define zig_make_f64(fp, repr) fp##f32x #else @@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64; #define zig_has_f80 1 #define zig_libc_name_f80(name) __##name##x #define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr) -#if FLT_MANT_DIG == 64 +#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F80_ABI +#undef zig_has_f80 +typedef struct { uint64_t mantissa; uint16_t exponent; } zig_f80; +#define zig_init_repr_f80(mantissa, exponent) { .mant##issa = mantissa, .expo##nent = exponent } +#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent) +#define zig_mantissa_repr_f80(arg) (arg).mantissa +#define zig_exponent_repr_f80(arg) (arg).exponent +#elif FLT_MANT_DIG == 64 typedef float zig_f80; #define zig_make_f80(fp, repr) fp##f #elif DBL_MANT_DIG == 64 @@ -3818,68 +5821,91 @@ typedef __float80 zig_f80; #define zig_make_f80(fp, repr) fp##l #else #undef zig_has_f80 -#define zig_has_f80 0 -#define zig_repr_f80 u128 typedef zig_u128 zig_f80; +#define zig_init_repr_f80(mantissa, exponent) zig_init_u128(exponent, mantissa) +#define zig_make_repr_f80(mantissa, exponent) zig_make_u128(exponent, mantissa) +#define zig_mantissa_repr_f80(arg) zig_lo_u128(arg) +#define zig_exponent_repr_f80(arg) (uint16_t)zig_hi_u128(arg) +#endif +#ifndef zig_has_f80 +#define zig_has_f80 0 #define zig_make_f80(fp, repr) repr +#ifndef zig_make_repr_f80 +#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent) +#endif #undef zig_make_special_f80 #define zig_make_special_f80(sign, name, arg, repr) repr #undef zig_init_special_f80 #define zig_init_special_f80(sign, name, arg, repr) repr #endif -#if defined(zig_gcc) && defined(zig_x86) -#define zig_f128_has_miscompilations 1 -#else -#define zig_f128_has_miscompilations 0 -#endif - #define zig_has_f128 1 #define zig_libc_name_f128(name) name##f128 #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) -#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 +#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F128_ABI +#undef zig_has_f128 +#if zig_little_endian +typedef struct { uint64_t lo, hi; } zig_f128; +#else +typedef struct { uint64_t hi, lo; } zig_f128; +#endif +#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_lo_repr_f128(arg) (arg).lo +#define zig_hi_repr_f128(arg) (arg).hi +#elif FLT_MANT_DIG == 113 typedef float zig_f128; #define zig_make_f128(fp, repr) fp##f -#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 +#elif DBL_MANT_DIG == 113 typedef double zig_f128; #define zig_make_f128(fp, repr) fp -#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113 +#elif LDBL_MANT_DIG == 113 typedef long double zig_f128; #define zig_make_f128(fp, repr) fp##l -#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113 +#elif FLT128_MANT_DIG == 113 typedef _Float128 zig_f128; #define zig_make_f128(fp, repr) fp##f128 -#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113 +#elif FLT64X_MANT_DIG == 113 typedef _Float64x zig_f128; #define zig_make_f128(fp, repr) fp##f64x -#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__) +#elif defined(__SIZEOF_FLOAT128__) typedef __float128 zig_f128; #define zig_make_f128(fp, repr) fp##q #undef zig_make_special_f128 #define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg) #else #undef zig_has_f128 -#define zig_has_f128 0 -#undef zig_make_special_f128 -#undef zig_init_special_f128 -#if defined(zig_darwin) || defined(zig_aarch64) -typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64; -zig_basic_operator(zig_v2u64, xor_v2u64, ^) -#define zig_repr_f128 v2u64 -typedef zig_v2u64 zig_f128; -#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi } -#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128 -#define zig_make_f128(fp, repr) zig_make_f128_##repr -#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr -#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr +#if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC) +#if defined(zig_msvc) && !defined(__clang__) +#include +typedef __m128i zig_f128; +#define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } } +#define zig_lo_repr_f128(arg) (arg).m128i_u64[0] +#define zig_hi_repr_f128(arg) (arg).m128i_u64[1] +#else +typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128; +#define zig_init_repr_f128(hi, lo) { lo, hi } +#define zig_lo_repr_f128(arg) (arg)[0] +#define zig_hi_repr_f128(arg) (arg)[1] +#endif #else -#define zig_repr_f128 u128 typedef zig_u128 zig_f128; +#define zig_init_repr_f128(hi, lo) zig_init_u128(hi, lo) +#define zig_make_repr_f128(hi, lo) zig_make_u128(hi, lo) +#define zig_lo_repr_f128(arg) zig_lo_u128(arg) +#define zig_hi_repr_f128(arg) zig_hi_u128(arg) +#endif +#endif +#ifndef zig_has_f128 +#define zig_has_f128 0 #define zig_make_f128(fp, repr) repr +#ifndef zig_make_repr_f128 +#define zig_make_repr_f128(hi, lo) (zig_f128)zig_init_repr_f128(hi, lo) +#endif +#undef zig_make_special_f128 #define zig_make_special_f128(sign, name, arg, repr) repr +#undef zig_init_special_f128 #define zig_init_special_f128(sign, name, arg, repr) repr #endif -#endif #if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC) /* Emulate msvc abi on a gnu compiler */ @@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble; typedef long double zig_c_longdouble; #endif -#define zig_bitCast_float(Type, ReprType) \ - static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \ - zig_##Type result; \ - memcpy(&result, &repr, sizeof(result)); \ - return result; \ +#if __AVR__ +typedef signed char zig_FloatCompareResult; +#elif defined(zig_aarch64) +typedef signed int zig_FloatCompareResult; +#elif __SIZEOF_LONG__ >= __SIZEOF_POINTER__ +typedef signed long zig_FloatCompareResult; +#else +typedef signed long long zig_FloatCompareResult; +#endif + +#define zig_bitCast_float(w, iw, UnsignedReprType, SignedReprType) \ + static inline zig_f##w zig_f##w##_bitCast_u##iw(UnsignedReprType arg) { \ + zig_f##w res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return res; \ + } \ + static inline zig_f##w zig_f##w##_bitCast_i##iw(SignedReprType arg) { \ + zig_f##w res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return res; \ + } \ + static inline UnsignedReprType zig_u##iw##_bitCast_f##w(zig_f##w arg) { \ + UnsignedReprType res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return zig_u##iw##_truncate_u##iw(res, w); \ + } \ + static inline SignedReprType zig_i##iw##_bitCast_f##w(zig_f##w arg) { \ + SignedReprType res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return zig_i##iw##_truncate_i##iw(res, w); \ + } +zig_bitCast_float(16, 16, uint16_t, int16_t) +zig_bitCast_float(32, 32, uint32_t, int32_t) +zig_bitCast_float(64, 64, uint64_t, int64_t) +#if zig_has_f80 +zig_bitCast_float(80, 128, zig_u128, zig_i128) +#else +static inline zig_f80 zig_f80_bitCast_u128(zig_u128 arg) { + return zig_make_repr_f80(zig_lo_u128(arg), (uint16_t)zig_hi_u128(arg)); +} +static inline zig_f80 zig_f80_bitCast_i128(zig_i128 arg) { + return zig_make_repr_f80(zig_lo_i128(arg), (uint16_t)zig_hi_i128(arg)); +} +static inline zig_u128 zig_u128_bitCast_f80(zig_f80 arg) { + return zig_make_u128(zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg)); +} +static inline zig_i128 zig_i128_bitCast_f80(zig_f80 arg) { + return zig_make_i128((int16_t)zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg)); +} +#endif +static inline zig_f80 zig_f80_bitCast_big(const void *arg) { + return zig_f80_bitCast_u128(zig_u128_truncate_big(arg, UINT8_C(80), false, UINT16_C(80))); +} +static inline void zig_big_bitCast_f80(void *res, zig_f80 arg, bool res_is_signed, uint16_t res_bits) { + if (res_is_signed) { + zig_big_truncate_i128(res, zig_i128_bitCast_f80(arg), res_is_signed, res_bits); + } else { + zig_big_truncate_u128(res, zig_u128_bitCast_f80(arg), res_is_signed, res_bits); } -zig_bitCast_float(f16, uint16_t) -zig_bitCast_float(f32, uint32_t) -zig_bitCast_float(f64, uint64_t) -zig_bitCast_float(f80, zig_u128) -zig_bitCast_float(f128, zig_u128) +} +#if zig_has_f128 +zig_bitCast_float(128, 128, zig_u128, zig_i128) +#else +static inline zig_f128 zig_f128_bitCast_u128(zig_u128 arg) { + return zig_make_repr_f128(zig_hi_u128(arg), zig_lo_u128(arg)); +} +static inline zig_f128 zig_f128_bitCast_i128(zig_i128 arg) { + return zig_make_repr_f128((uint64_t)zig_hi_i128(arg), zig_lo_i128(arg)); +} +static inline zig_u128 zig_u128_bitCast_f128(zig_f128 arg) { + return zig_make_u128(zig_hi_repr_f128(arg), zig_lo_repr_f128(arg)); +} +static inline zig_i128 zig_i128_bitCast_f128(zig_f128 arg) { + return zig_make_i128((int64_t)zig_hi_repr_f128(arg), zig_lo_repr_f128(arg)); +} +#endif -#define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \ - zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ - zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \ +#define zig_convert_float_00(ResType, operation, ArgType, version) \ + zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType arg); \ + return zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(arg) +#define zig_convert_float_01(ResType, operation, ArgType, version) \ + zig_convert_float_00(ResType, operation, ArgType, version) +#define zig_convert_float_10(ResType, operation, ArgType, version) \ + zig_convert_float_00(ResType, operation, ArgType, version) +#define zig_convert_float_11(ResType, operation, ArgType, version) \ + return (ResType)arg +#define zig_convert_float(res_when, ResType, operation, arg_when, ArgType, version) \ static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \ zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \ - ResType res; \ - ExternResType extern_res; \ - ExternArgType extern_arg; \ - memcpy(&extern_arg, &arg, sizeof(extern_arg)); \ - extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ - zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \ - memcpy(&res, &extern_res, sizeof(res)); \ - return extern_res; \ + zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \ + zig_has_##arg_when)(ResType, operation, ArgType, version); \ } -zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2) -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2) -zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2) -#ifdef __ARM_EABI__ +#define zig_convert_floats(SmallType, BigType) \ + zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \ + zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2) +zig_convert_floats(f16, f32) +zig_convert_floats(f16, f64) +zig_convert_floats(f16, f80) +zig_convert_floats(f16, f128) +zig_convert_floats(f32, f64) +zig_convert_floats(f32, f80) +zig_convert_floats(f32, f128) +zig_convert_floats(f64, f80) +zig_convert_floats(f64, f128) +zig_convert_floats(f80, f128) -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64); -static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32); -static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); } - -#else /* __ARM_EABI__ */ - -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2) - -#endif /* __ARM_EABI__ */ - -#define zig_float_negate_builtin_0(w, c, sb) \ - zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb)) -#define zig_float_negate_builtin_1(w, c, sb) -arg -#define zig_float_negate_builtin(w, c, sb) \ +#define zig_float_negate_builtin_0(w, sb) \ + zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb)) +#define zig_float_negate_builtin_1(w, sb) -arg +#define zig_float_negate_builtin(w, sb) \ static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \ - return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, c, sb); \ + return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, sb); \ } -zig_float_negate_builtin(16, , UINT16_C(1) << 15 ) -zig_float_negate_builtin(32, , UINT32_C(1) << 31 ) -zig_float_negate_builtin(64, , UINT64_C(1) << 63 ) -zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0))) -zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) +zig_float_negate_builtin(16, UINT16_C(1) << 15) +zig_float_negate_builtin(32, UINT32_C(1) << 31) +zig_float_negate_builtin(64, UINT64_C(1) << 63) + +#undef zig_float_negate_builtin_0 +#define zig_float_negate_builtin_0(w, sb) \ + zig_make_repr_f##w(zig_mantissa_repr_f##w(arg), zig_xor_u16(zig_exponent_repr_f##w(arg), sb)) +zig_float_negate_builtin(80, UINT16_C(1) << 15) + +#undef zig_float_negate_builtin_0 +#define zig_float_negate_builtin_0(w, sb) \ + zig_make_repr_f##w(zig_xor_u64(zig_hi_repr_f##w(arg), sb), zig_lo_repr_f##w(arg)) +zig_float_negate_builtin(128, UINT64_C(1) << 63) #define zig_float_less_builtin_0(Type, operation) \ - zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \ + zig_extern zig_FloatCompareResult zig_expand_concat(zig_expand_concat(__##operation, \ zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \ static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ - return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \ + return (int32_t)zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \ } #define zig_float_less_builtin_1(Type, operation) \ static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ @@ -3994,13 +6077,52 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) return lhs operator rhs; \ } +#define zig_float_builtins(w) \ + zig_common_float_builtins(w) \ + zig_convert_float(f##w, zig_f##w, float, int128, zig_i128, ) \ + zig_convert_float(f##w, zig_f##w, floatun, int128, zig_u128, ) #define zig_common_float_builtins(w) \ - zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \ + zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \ + zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \ + zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \ + zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(int128, zig_u128, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(f##w, zig_f##w, float, always, int32_t, ) \ + zig_convert_float(f##w, zig_f##w, float, always, int64_t, ) \ + zig_convert_float(f##w, zig_f##w, floatun, always, uint32_t, ) \ + zig_convert_float(f##w, zig_f##w, floatun, always, uint64_t, ) \ +\ + static inline void zig_expand_concat(zig_expand_concat(zig_fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ + zig_extern void zig_expand_concat(zig_expand_concat(__fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ + zig_expand_concat(zig_expand_concat(__fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ + } \ +\ + static inline void zig_expand_concat(zig_expand_concat(zig_fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ + zig_extern void zig_expand_concat(zig_expand_concat(__fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ + zig_expand_concat(zig_expand_concat(__fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ + } \ +\ + static inline zig_f##w zig_expand_concat(zig_floatei, \ + zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ + zig_extern zig_f##w zig_expand_concat(__floatei, \ + zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ + return zig_expand_concat(__floatei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ + } \ +\ + static inline zig_f##w zig_expand_concat(zig_floatunei, \ + zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ + zig_extern zig_f##w zig_expand_concat(__floatunei, \ + zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ + return zig_expand_concat(__floatunei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ + } \ +\ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, eq) \ @@ -4031,82 +6153,48 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmax)))(zig_f##w, zig_max_f##w, zig_libc_name_f##w(fmax), (zig_f##w x, zig_f##w y), (x, y)) \ zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fma)))(zig_f##w, zig_fma_f##w, zig_libc_name_f##w(fma), (zig_f##w x, zig_f##w y, zig_f##w z), (x, y, z)) \ \ - static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divTrunc_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ - static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divFloor_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ - static inline zig_f##w zig_div_ceil_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divCeil_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \ - return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \ + return zig_sub_f##w(lhs, zig_mul_f##w(zig_divFloor_f##w(lhs, rhs), rhs)); \ } -zig_common_float_builtins(16) -zig_common_float_builtins(32) -zig_common_float_builtins(64) -zig_common_float_builtins(80) -zig_common_float_builtins(128) - -#define zig_float_builtins(w) \ - zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, ) zig_float_builtins(16) -zig_float_builtins(80) -zig_float_builtins(128) - -#ifdef __ARM_EABI__ - -zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32); -static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32); -static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32); -static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t); -static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t); -static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t); -static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64); -static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64); -static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64); -static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t); -static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t); -static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t); -static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); } - -#else /* __ARM_EABI__ */ - zig_float_builtins(32) zig_float_builtins(64) - -#endif /* __ARM_EABI__ */ +zig_float_builtins(80) +#if defined(zig_x86_32) +zig_common_float_builtins(128) +static inline zig_f128 zig_floattitf(zig_i128 arg) { + extern zig_f128 __floattitf(zig_f128 arg); + return __floattitf(zig_f128_bitCast_i128(arg)); +} +static inline zig_f128 zig_floatuntitf(zig_u128 arg) { + extern zig_f128 __floatuntitf(zig_f128 arg); + return __floatuntitf(zig_f128_bitCast_u128(arg)); +} +#elif defined(zig_x86_64) && defined(zig_windows) +zig_common_float_builtins(128) +static inline zig_f128 zig_floattitf(zig_i128 arg) { + extern zig_f128 __floattitf(zig_i128 arg); + return __floattitf(arg); +} +static inline zig_f128 zig_floatuntitf(zig_u128 arg) { + extern zig_f128 __floatuntitf(uint64_t arg_lo, uint64_t arg_hi); + return __floatuntitf(zig_lo_u128(arg), zig_hi_u128(arg)); +} +#else +zig_float_builtins(128) +#endif /* ============================ Atomics Support ============================= */ @@ -4410,19 +6498,19 @@ typedef int zig_memory_order; } \ static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \ (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \ - } \ + } \ static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \ return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ } \ static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \ - Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ + Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - return val; \ + return value; \ } \ static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \ - Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ + Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - return val; \ + return value; \ } zig_msvc_atomics( u8, uint8_t, char, 8, 8) @@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64) zig_##Type result; \ SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - memcpy(&result, &initial, sizeof(result)); \ + memcpy(&result, &initial, sizeof(result)); \ return result; \ } \ static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \ zig_##Type result; \ SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - memcpy(&result, &initial, sizeof(result)); \ + memcpy(&result, &initial, sizeof(result)); \ return result; \ } @@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat } static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) { - void* val = (void*)__iso_volatile_load32(obj); + void* value = (void*)__iso_volatile_load32(obj); _ReadWriteBarrier(); - return val; + return value; } static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) { @@ -4532,9 +6620,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volat } static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) { - void* val = (void*)__iso_volatile_load64(obj); + void* value = (void*)__iso_volatile_load64(obj); _ReadWriteBarrier(); - return val; + return value; } static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) { diff --git a/stage1/zig1.wasm b/stage1/zig1.wasm index 1664bd4095df86103a6e4bacfc682054a0cb8fc1..8587696fd79e5f385e8ea9fcf56614213bcce485 100644 GIT binary patch delta 934419 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⁡t(S}!kO9?41Ks*%I< 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

?R+U9Bx>%N{n`FA|_8ow`wE5=8Wvo2?D{ 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 NZegOU!(Ti6zW~KQF&6*; delta 911066 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%0Dl>H4UsjM;8 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%0A(pHUzF0rVFo=sjC@R2 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

h~M<#l(8-@WtzzLfPfj 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

p`u3 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 -- 2.54.0