| author | |
| committer | |
| log | 69abc945e45af3f447f9ee07d426d1ec40cf3f15 |
| tree | 457a9ee76f91135cf7a71192a09c317a63c05961 |
| parent | 1274254c48ee105623c513dfc01451fee2912c5b |
Closes #24553124 files changed, 1078 insertions(+), 365 deletions(-)
src/Compilation.zig+6-4| ... | ... | @@ -1816,10 +1816,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1816 | 1816 | if (options.skip_linker_dependencies) break :s .none; |
| 1817 | 1817 | const want = options.want_compiler_rt orelse is_exe_or_dyn_lib; |
| 1818 | 1818 | if (!want) break :s .none; |
| 1819 | if (have_zcu) { | |
| 1819 | if (have_zcu and target_util.canBuildLibCompilerRt(target, use_llvm, build_options.have_llvm and use_llvm)) { | |
| 1820 | 1820 | if (output_mode == .Obj) break :s .zcu; |
| 1821 | if (target.ofmt == .coff and target_util.zigBackend(target, use_llvm) == .stage2_x86_64) | |
| 1822 | break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu; | |
| 1821 | if (switch (target_util.zigBackend(target, use_llvm)) { | |
| 1822 | else => false, | |
| 1823 | .stage2_aarch64, .stage2_x86_64 => target.ofmt == .coff, | |
| 1824 | }) break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu; | |
| 1823 | 1825 | } |
| 1824 | 1826 | if (is_exe_or_dyn_lib) break :s .lib; |
| 1825 | 1827 | break :s .obj; |
| ... | ... | @@ -1854,7 +1856,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1854 | 1856 | const want_ubsan_rt = options.want_ubsan_rt orelse (can_build_ubsan_rt and any_sanitize_c == .full and is_exe_or_dyn_lib); |
| 1855 | 1857 | if (!want_ubsan_rt) break :s .none; |
| 1856 | 1858 | if (options.skip_linker_dependencies) break :s .none; |
| 1857 | if (have_zcu) break :s .zcu; | |
| 1859 | if (have_zcu and target_util.canBuildLibUbsanRt(target, use_llvm, build_options.have_llvm and use_llvm)) break :s .zcu; | |
| 1858 | 1860 | if (is_exe_or_dyn_lib) break :s .lib; |
| 1859 | 1861 | break :s .obj; |
| 1860 | 1862 | }; |
src/arch/x86_64/CodeGen.zig+3-3| ... | ... | @@ -168141,7 +168141,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 168141 | 168141 | .unused, |
| 168142 | 168142 | .unused, |
| 168143 | 168143 | }, |
| 168144 | .dst_temps = .{ .{ .cc = .b }, .unused }, | |
| 168144 | .dst_temps = .{ .{ .cc = .be }, .unused }, | |
| 168145 | 168145 | .clobbers = .{ .eflags = true }, |
| 168146 | 168146 | .each = .{ .once = &.{ |
| 168147 | 168147 | .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ }, |
| ... | ... | @@ -168165,7 +168165,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 168165 | 168165 | .unused, |
| 168166 | 168166 | .unused, |
| 168167 | 168167 | }, |
| 168168 | .dst_temps = .{ .{ .cc = .b }, .unused }, | |
| 168168 | .dst_temps = .{ .{ .cc = .be }, .unused }, | |
| 168169 | 168169 | .clobbers = .{ .eflags = true }, |
| 168170 | 168170 | .each = .{ .once = &.{ |
| 168171 | 168171 | .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ }, |
| ... | ... | @@ -168189,7 +168189,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 168189 | 168189 | .unused, |
| 168190 | 168190 | .unused, |
| 168191 | 168191 | }, |
| 168192 | .dst_temps = .{ .{ .cc = .b }, .unused }, | |
| 168192 | .dst_temps = .{ .{ .cc = .be }, .unused }, | |
| 168193 | 168193 | .clobbers = .{ .eflags = true }, |
| 168194 | 168194 | .each = .{ .once = &.{ |
| 168195 | 168195 | .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ }, |
src/arch/x86_64/Emit.zig+6-5| ... | ... | @@ -168,11 +168,12 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 168 | 168 | else if (emit.bin_file.cast(.macho)) |macho_file| |
| 169 | 169 | macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err| |
| 170 | 170 | return emit.fail("{s} creating lazy symbol", .{@errorName(err)}) |
| 171 | else if (emit.bin_file.cast(.coff)) |coff_file| sym_index: { | |
| 172 | const atom = coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err| | |
| 173 | return emit.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 174 | break :sym_index coff_file.getAtom(atom).getSymbolIndex().?; | |
| 175 | } else if (emit.bin_file.cast(.plan9)) |p9_file| | |
| 171 | else if (emit.bin_file.cast(.coff)) |coff_file| | |
| 172 | if (coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym)) |atom| | |
| 173 | coff_file.getAtom(atom).getSymbolIndex().? | |
| 174 | else |err| | |
| 175 | return emit.fail("{s} creating lazy symbol", .{@errorName(err)}) | |
| 176 | else if (emit.bin_file.cast(.plan9)) |p9_file| | |
| 176 | 177 | p9_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err| |
| 177 | 178 | return emit.fail("{s} creating lazy symbol", .{@errorName(err)}) |
| 178 | 179 | else |
src/codegen/aarch64.zig+5-2| ... | ... | @@ -47,6 +47,7 @@ pub fn generate( |
| 47 | 47 | .literals = .empty, |
| 48 | 48 | .nav_relocs = .empty, |
| 49 | 49 | .uav_relocs = .empty, |
| 50 | .lazy_relocs = .empty, | |
| 50 | 51 | .global_relocs = .empty, |
| 51 | 52 | .literal_relocs = .empty, |
| 52 | 53 | |
| ... | ... | @@ -101,8 +102,8 @@ pub fn generate( |
| 101 | 102 | }; |
| 102 | 103 | switch (passed_vi.parent(&isel)) { |
| 103 | 104 | .unallocated => if (!mod.strip) { |
| 104 | var part_it = arg_vi.parts(&isel); | |
| 105 | const first_passed_part_vi = part_it.next() orelse passed_vi; | |
| 105 | var part_it = passed_vi.parts(&isel); | |
| 106 | const first_passed_part_vi = part_it.next().?; | |
| 106 | 107 | const hint_ra = first_passed_part_vi.hint(&isel).?; |
| 107 | 108 | passed_vi.setParent(&isel, .{ .stack_slot = if (hint_ra.isVector()) |
| 108 | 109 | isel.va_list.__vr_top.withOffset(@as(i8, -16) * |
| ... | ... | @@ -167,6 +168,7 @@ pub fn generate( |
| 167 | 168 | .literals = &.{}, |
| 168 | 169 | .nav_relocs = &.{}, |
| 169 | 170 | .uav_relocs = &.{}, |
| 171 | .lazy_relocs = &.{}, | |
| 170 | 172 | .global_relocs = &.{}, |
| 171 | 173 | .literal_relocs = &.{}, |
| 172 | 174 | }; |
| ... | ... | @@ -174,6 +176,7 @@ pub fn generate( |
| 174 | 176 | mir.literals = try isel.literals.toOwnedSlice(gpa); |
| 175 | 177 | mir.nav_relocs = try isel.nav_relocs.toOwnedSlice(gpa); |
| 176 | 178 | mir.uav_relocs = try isel.uav_relocs.toOwnedSlice(gpa); |
| 179 | mir.lazy_relocs = try isel.lazy_relocs.toOwnedSlice(gpa); | |
| 177 | 180 | mir.global_relocs = try isel.global_relocs.toOwnedSlice(gpa); |
| 178 | 181 | mir.literal_relocs = try isel.literal_relocs.toOwnedSlice(gpa); |
| 179 | 182 | return mir; |
src/codegen/aarch64/Assemble.zig+26-6| ... | ... | @@ -6,14 +6,19 @@ pub const Operand = union(enum) { |
| 6 | 6 | }; |
| 7 | 7 | |
| 8 | 8 | pub fn nextInstruction(as: *Assemble) !?Instruction { |
| 9 | @setEvalBranchQuota(37_000); | |
| 9 | @setEvalBranchQuota(42_000); | |
| 10 | 10 | comptime var ct_token_buf: [token_buf_len]u8 = undefined; |
| 11 | 11 | var token_buf: [token_buf_len]u8 = undefined; |
| 12 | 12 | const original_source = while (true) { |
| 13 | 13 | const original_source = as.source; |
| 14 | 14 | const source_token = try as.nextToken(&token_buf, .{}); |
| 15 | if (source_token.len == 0) return null; | |
| 16 | if (source_token[0] != '\n') break original_source; | |
| 15 | switch (source_token.len) { | |
| 16 | 0 => return null, | |
| 17 | else => switch (source_token[0]) { | |
| 18 | else => break original_source, | |
| 19 | '\n', ';' => {}, | |
| 20 | }, | |
| 21 | } | |
| 17 | 22 | }; |
| 18 | 23 | log.debug( |
| 19 | 24 | \\. |
| ... | ... | @@ -52,7 +57,13 @@ pub fn nextInstruction(as: *Assemble) !?Instruction { |
| 52 | 57 | std.zig.fmtString(source_token), |
| 53 | 58 | }); |
| 54 | 59 | if (pattern_token.len == 0) { |
| 55 | if (source_token.len > 0 and source_token[0] != '\n') break :next_pattern; | |
| 60 | switch (source_token.len) { | |
| 61 | 0 => {}, | |
| 62 | else => switch (source_token[0]) { | |
| 63 | else => break :next_pattern, | |
| 64 | '\n', ';' => {}, | |
| 65 | }, | |
| 66 | } | |
| 56 | 67 | const encode = @field(Instruction, @tagName(instruction.encode[0])); |
| 57 | 68 | const Encode = @TypeOf(encode); |
| 58 | 69 | var args: std.meta.ArgsTuple(Encode) = undefined; |
| ... | ... | @@ -65,7 +76,7 @@ pub fn nextInstruction(as: *Assemble) !?Instruction { |
| 65 | 76 | const symbol = &@field(symbols, symbol_name); |
| 66 | 77 | symbol.* = zonCast(SymbolSpec, @field(instruction.symbols, symbol_name), .{}).parse(source_token) orelse break :next_pattern; |
| 67 | 78 | log.debug("{s} = {any}", .{ symbol_name, symbol.* }); |
| 68 | } else if (!std.ascii.eqlIgnoreCase(pattern_token, source_token)) break :next_pattern; | |
| 79 | } else if (!toUpperEqlAssertUpper(source_token, pattern_token)) break :next_pattern; | |
| 69 | 80 | } |
| 70 | 81 | } |
| 71 | 82 | log.debug("'{s}' not matched...", .{instruction.pattern}); |
| ... | ... | @@ -125,6 +136,15 @@ fn zonCast(comptime Result: type, zon_value: anytype, symbols: anytype) Result { |
| 125 | 136 | } |
| 126 | 137 | } |
| 127 | 138 | |
| 139 | fn toUpperEqlAssertUpper(lhs: []const u8, rhs: []const u8) bool { | |
| 140 | if (lhs.len != rhs.len) return false; | |
| 141 | for (lhs, rhs) |l, r| { | |
| 142 | assert(!std.ascii.isLower(r)); | |
| 143 | if (std.ascii.toUpper(l) != r) return false; | |
| 144 | } | |
| 145 | return true; | |
| 146 | } | |
| 147 | ||
| 128 | 148 | const token_buf_len = "v31.b[15]".len; |
| 129 | 149 | fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct { |
| 130 | 150 | operands: bool = false, |
| ... | ... | @@ -134,7 +154,7 @@ fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct { |
| 134 | 154 | while (true) c: switch (as.source[0]) { |
| 135 | 155 | 0 => return as.source[0..0], |
| 136 | 156 | '\t', '\n' + 1...'\r', ' ' => as.source = as.source[1..], |
| 137 | '\n', '!', '#', ',', '[', ']' => { | |
| 157 | '\n', '!', '#', ',', ';', '[', ']' => { | |
| 138 | 158 | defer as.source = as.source[1..]; |
| 139 | 159 | return as.source[0..1]; |
| 140 | 160 | }, |
src/codegen/aarch64/Mir.zig+106-33| ... | ... | @@ -4,6 +4,7 @@ epilogue: []const Instruction, |
| 4 | 4 | literals: []const u32, |
| 5 | 5 | nav_relocs: []const Reloc.Nav, |
| 6 | 6 | uav_relocs: []const Reloc.Uav, |
| 7 | lazy_relocs: []const Reloc.Lazy, | |
| 7 | 8 | global_relocs: []const Reloc.Global, |
| 8 | 9 | literal_relocs: []const Reloc.Literal, |
| 9 | 10 | |
| ... | ... | @@ -21,8 +22,13 @@ pub const Reloc = struct { |
| 21 | 22 | reloc: Reloc, |
| 22 | 23 | }; |
| 23 | 24 | |
| 25 | pub const Lazy = struct { | |
| 26 | symbol: link.File.LazySymbol, | |
| 27 | reloc: Reloc, | |
| 28 | }; | |
| 29 | ||
| 24 | 30 | pub const Global = struct { |
| 25 | global: [*:0]const u8, | |
| 31 | name: [*:0]const u8, | |
| 26 | 32 | reloc: Reloc, |
| 27 | 33 | }; |
| 28 | 34 | |
| ... | ... | @@ -38,6 +44,7 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void { |
| 38 | 44 | gpa.free(mir.literals); |
| 39 | 45 | gpa.free(mir.nav_relocs); |
| 40 | 46 | gpa.free(mir.uav_relocs); |
| 47 | gpa.free(mir.lazy_relocs); | |
| 41 | 48 | gpa.free(mir.global_relocs); |
| 42 | 49 | gpa.free(mir.literal_relocs); |
| 43 | 50 | mir.* = undefined; |
| ... | ... | @@ -119,16 +126,37 @@ pub fn emit( |
| 119 | 126 | body_end - Instruction.size * (1 + uav_reloc.reloc.label), |
| 120 | 127 | uav_reloc.reloc.addend, |
| 121 | 128 | ); |
| 129 | for (mir.lazy_relocs) |lazy_reloc| try emitReloc( | |
| 130 | lf, | |
| 131 | zcu, | |
| 132 | func.owner_nav, | |
| 133 | if (lf.cast(.elf)) |ef| | |
| 134 | ef.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(ef, pt, lazy_reloc.symbol) catch |err| | |
| 135 | return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)}) | |
| 136 | else if (lf.cast(.macho)) |mf| | |
| 137 | mf.getZigObject().?.getOrCreateMetadataForLazySymbol(mf, pt, lazy_reloc.symbol) catch |err| | |
| 138 | return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)}) | |
| 139 | else if (lf.cast(.coff)) |cf| | |
| 140 | if (cf.getOrCreateAtomForLazySymbol(pt, lazy_reloc.symbol)) |atom| | |
| 141 | cf.getAtom(atom).getSymbolIndex().? | |
| 142 | else |err| | |
| 143 | return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)}) | |
| 144 | else | |
| 145 | return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}), | |
| 146 | mir.body[lazy_reloc.reloc.label], | |
| 147 | body_end - Instruction.size * (1 + lazy_reloc.reloc.label), | |
| 148 | lazy_reloc.reloc.addend, | |
| 149 | ); | |
| 122 | 150 | for (mir.global_relocs) |global_reloc| try emitReloc( |
| 123 | 151 | lf, |
| 124 | 152 | zcu, |
| 125 | 153 | func.owner_nav, |
| 126 | 154 | if (lf.cast(.elf)) |ef| |
| 127 | try ef.getGlobalSymbol(std.mem.span(global_reloc.global), null) | |
| 155 | try ef.getGlobalSymbol(std.mem.span(global_reloc.name), null) | |
| 128 | 156 | else if (lf.cast(.macho)) |mf| |
| 129 | try mf.getGlobalSymbol(std.mem.span(global_reloc.global), null) | |
| 157 | try mf.getGlobalSymbol(std.mem.span(global_reloc.name), null) | |
| 130 | 158 | else if (lf.cast(.coff)) |cf| |
| 131 | try cf.getGlobalSymbol(std.mem.span(global_reloc.global), "compiler_rt") | |
| 159 | try cf.getGlobalSymbol(std.mem.span(global_reloc.name), "compiler_rt") | |
| 132 | 160 | else |
| 133 | 161 | return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}), |
| 134 | 162 | mir.body[global_reloc.reloc.label], |
| ... | ... | @@ -172,35 +200,6 @@ fn emitReloc( |
| 172 | 200 | const gpa = zcu.gpa; |
| 173 | 201 | switch (instruction.decode()) { |
| 174 | 202 | else => unreachable, |
| 175 | .branch_exception_generating_system => |decoded| if (lf.cast(.elf)) |ef| { | |
| 176 | const zo = ef.zigObjectPtr().?; | |
| 177 | const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; | |
| 178 | const r_type: std.elf.R_AARCH64 = switch (decoded.decode().unconditional_branch_immediate.group.op) { | |
| 179 | .b => .JUMP26, | |
| 180 | .bl => .CALL26, | |
| 181 | }; | |
| 182 | try atom.addReloc(gpa, .{ | |
| 183 | .r_offset = offset, | |
| 184 | .r_info = @as(u64, sym_index) << 32 | @intFromEnum(r_type), | |
| 185 | .r_addend = @bitCast(addend), | |
| 186 | }, zo); | |
| 187 | } else if (lf.cast(.macho)) |mf| { | |
| 188 | const zo = mf.getZigObject().?; | |
| 189 | const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?; | |
| 190 | try atom.addReloc(mf, .{ | |
| 191 | .tag = .@"extern", | |
| 192 | .offset = offset, | |
| 193 | .target = sym_index, | |
| 194 | .addend = @bitCast(addend), | |
| 195 | .type = .branch, | |
| 196 | .meta = .{ | |
| 197 | .pcrel = true, | |
| 198 | .has_subtractor = false, | |
| 199 | .length = 2, | |
| 200 | .symbolnum = @intCast(sym_index), | |
| 201 | }, | |
| 202 | }); | |
| 203 | }, | |
| 204 | 203 | .data_processing_immediate => |decoded| if (lf.cast(.elf)) |ef| { |
| 205 | 204 | const zo = ef.zigObjectPtr().?; |
| 206 | 205 | const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; |
| ... | ... | @@ -259,6 +258,80 @@ fn emitReloc( |
| 259 | 258 | }, |
| 260 | 259 | } |
| 261 | 260 | }, |
| 261 | .branch_exception_generating_system => |decoded| if (lf.cast(.elf)) |ef| { | |
| 262 | const zo = ef.zigObjectPtr().?; | |
| 263 | const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; | |
| 264 | const r_type: std.elf.R_AARCH64 = switch (decoded.decode().unconditional_branch_immediate.group.op) { | |
| 265 | .b => .JUMP26, | |
| 266 | .bl => .CALL26, | |
| 267 | }; | |
| 268 | try atom.addReloc(gpa, .{ | |
| 269 | .r_offset = offset, | |
| 270 | .r_info = @as(u64, sym_index) << 32 | @intFromEnum(r_type), | |
| 271 | .r_addend = @bitCast(addend), | |
| 272 | }, zo); | |
| 273 | } else if (lf.cast(.macho)) |mf| { | |
| 274 | const zo = mf.getZigObject().?; | |
| 275 | const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?; | |
| 276 | try atom.addReloc(mf, .{ | |
| 277 | .tag = .@"extern", | |
| 278 | .offset = offset, | |
| 279 | .target = sym_index, | |
| 280 | .addend = @bitCast(addend), | |
| 281 | .type = .branch, | |
| 282 | .meta = .{ | |
| 283 | .pcrel = true, | |
| 284 | .has_subtractor = false, | |
| 285 | .length = 2, | |
| 286 | .symbolnum = @intCast(sym_index), | |
| 287 | }, | |
| 288 | }); | |
| 289 | }, | |
| 290 | .load_store => |decoded| if (lf.cast(.elf)) |ef| { | |
| 291 | const zo = ef.zigObjectPtr().?; | |
| 292 | const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; | |
| 293 | const r_type: std.elf.R_AARCH64 = switch (decoded.decode().register_unsigned_immediate.decode()) { | |
| 294 | .integer => |integer| switch (integer.decode()) { | |
| 295 | .unallocated, .prfm => unreachable, | |
| 296 | .strb, .ldrb, .ldrsb => .LDST8_ABS_LO12_NC, | |
| 297 | .strh, .ldrh, .ldrsh => .LDST16_ABS_LO12_NC, | |
| 298 | .ldrsw => .LDST32_ABS_LO12_NC, | |
| 299 | inline .str, .ldr => |encoded| switch (encoded.sf) { | |
| 300 | .word => .LDST32_ABS_LO12_NC, | |
| 301 | .doubleword => .LDST64_ABS_LO12_NC, | |
| 302 | }, | |
| 303 | }, | |
| 304 | .vector => |vector| switch (vector.group.opc1.decode(vector.group.size)) { | |
| 305 | .byte => .LDST8_ABS_LO12_NC, | |
| 306 | .half => .LDST16_ABS_LO12_NC, | |
| 307 | .single => .LDST32_ABS_LO12_NC, | |
| 308 | .double => .LDST64_ABS_LO12_NC, | |
| 309 | .quad => .LDST128_ABS_LO12_NC, | |
| 310 | .scalable, .predicate => unreachable, | |
| 311 | }, | |
| 312 | }; | |
| 313 | try atom.addReloc(gpa, .{ | |
| 314 | .r_offset = offset, | |
| 315 | .r_info = @as(u64, sym_index) << 32 | @intFromEnum(r_type), | |
| 316 | .r_addend = @bitCast(addend), | |
| 317 | }, zo); | |
| 318 | } else if (lf.cast(.macho)) |mf| { | |
| 319 | const zo = mf.getZigObject().?; | |
| 320 | const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?; | |
| 321 | try atom.addReloc(mf, .{ | |
| 322 | .tag = .@"extern", | |
| 323 | .offset = offset, | |
| 324 | .target = sym_index, | |
| 325 | .addend = @bitCast(addend), | |
| 326 | .type = .pageoff, | |
| 327 | .meta = .{ | |
| 328 | .pcrel = false, | |
| 329 | .has_subtractor = false, | |
| 330 | .length = 2, | |
| 331 | .symbolnum = @intCast(sym_index), | |
| 332 | }, | |
| 333 | }); | |
| 334 | }, | |
| 262 | 335 | } |
| 263 | 336 | } |
| 264 | 337 |
src/codegen/aarch64/Select.zig+618-188| ... | ... | @@ -22,6 +22,7 @@ instructions: std.ArrayListUnmanaged(codegen.aarch64.encoding.Instruction), |
| 22 | 22 | literals: std.ArrayListUnmanaged(u32), |
| 23 | 23 | nav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Nav), |
| 24 | 24 | uav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Uav), |
| 25 | lazy_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Lazy), | |
| 25 | 26 | global_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Global), |
| 26 | 27 | literal_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Literal), |
| 27 | 28 | |
| ... | ... | @@ -50,11 +51,11 @@ pub const Block = struct { |
| 50 | 51 | std.math.maxInt(@typeInfo(Air.Inst.Index).@"enum".tag_type), |
| 51 | 52 | ); |
| 52 | 53 | |
| 53 | fn branch(block: *const Block, isel: *Select) !void { | |
| 54 | if (isel.instructions.items.len > block.target_label) { | |
| 55 | try isel.emit(.b(@intCast((isel.instructions.items.len + 1 - block.target_label) << 2))); | |
| 54 | fn branch(target_block: *const Block, isel: *Select) !void { | |
| 55 | if (isel.instructions.items.len > target_block.target_label) { | |
| 56 | try isel.emit(.b(@intCast((isel.instructions.items.len + 1 - target_block.target_label) << 2))); | |
| 56 | 57 | } |
| 57 | try isel.merge(&block.live_registers, .{}); | |
| 58 | try isel.merge(&target_block.live_registers, .{}); | |
| 58 | 59 | } |
| 59 | 60 | }; |
| 60 | 61 | |
| ... | ... | @@ -84,12 +85,12 @@ pub const Loop = struct { |
| 84 | 85 | |
| 85 | 86 | pub const empty_list: u32 = std.math.maxInt(u32); |
| 86 | 87 | |
| 87 | fn branch(loop: *Loop, isel: *Select) !void { | |
| 88 | fn branch(target_loop: *Loop, isel: *Select) !void { | |
| 88 | 89 | try isel.instructions.ensureUnusedCapacity(isel.pt.zcu.gpa, 1); |
| 89 | const repeat_list_tail = loop.repeat_list; | |
| 90 | loop.repeat_list = @intCast(isel.instructions.items.len); | |
| 90 | const repeat_list_tail = target_loop.repeat_list; | |
| 91 | target_loop.repeat_list = @intCast(isel.instructions.items.len); | |
| 91 | 92 | isel.instructions.appendAssumeCapacity(@bitCast(repeat_list_tail)); |
| 92 | try isel.merge(&loop.live_registers, .{}); | |
| 93 | try isel.merge(&target_loop.live_registers, .{}); | |
| 93 | 94 | } |
| 94 | 95 | }; |
| 95 | 96 | |
| ... | ... | @@ -108,6 +109,7 @@ pub fn deinit(isel: *Select) void { |
| 108 | 109 | isel.literals.deinit(gpa); |
| 109 | 110 | isel.nav_relocs.deinit(gpa); |
| 110 | 111 | isel.uav_relocs.deinit(gpa); |
| 112 | isel.lazy_relocs.deinit(gpa); | |
| 111 | 113 | isel.global_relocs.deinit(gpa); |
| 112 | 114 | isel.literal_relocs.deinit(gpa); |
| 113 | 115 | |
| ... | ... | @@ -864,7 +866,7 @@ pub fn finishAnalysis(isel: *Select) !void { |
| 864 | 866 | } |
| 865 | 867 | } |
| 866 | 868 | |
| 867 | pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | |
| 869 | pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, CodegenFail }!void { | |
| 868 | 870 | const zcu = isel.pt.zcu; |
| 869 | 871 | const ip = &zcu.intern_pool; |
| 870 | 872 | const gpa = zcu.gpa; |
| ... | ... | @@ -946,7 +948,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 946 | 948 | } |
| 947 | 949 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 948 | 950 | }, |
| 949 | .add, .add_optimized, .add_wrap, .sub, .sub_optimized, .sub_wrap => |air_tag| { | |
| 951 | .add, .add_safe, .add_optimized, .add_wrap, .sub, .sub_safe, .sub_optimized, .sub_wrap => |air_tag| { | |
| 950 | 952 | if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { |
| 951 | 953 | defer res_vi.value.deref(isel); |
| 952 | 954 | |
| ... | ... | @@ -954,13 +956,16 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 954 | 956 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| 955 | 957 | if (!ty.isRuntimeFloat()) try res_vi.value.addOrSubtract(isel, ty, try isel.use(bin_op.lhs), switch (air_tag) { |
| 956 | 958 | else => unreachable, |
| 957 | .add, .add_wrap => .add, | |
| 958 | .sub, .sub_wrap => .sub, | |
| 959 | }, try isel.use(bin_op.rhs), .{ .wrap = switch (air_tag) { | |
| 960 | else => unreachable, | |
| 961 | .add, .sub => false, | |
| 962 | .add_wrap, .sub_wrap => true, | |
| 963 | } }) else switch (ty.floatBits(isel.target)) { | |
| 959 | .add, .add_safe, .add_wrap => .add, | |
| 960 | .sub, .sub_safe, .sub_wrap => .sub, | |
| 961 | }, try isel.use(bin_op.rhs), .{ | |
| 962 | .overflow = switch (air_tag) { | |
| 963 | else => unreachable, | |
| 964 | .add, .sub => .@"unreachable", | |
| 965 | .add_safe, .sub_safe => .{ .panic = .integer_overflow }, | |
| 966 | .add_wrap, .sub_wrap => .wrap, | |
| 967 | }, | |
| 968 | }) else switch (ty.floatBits(isel.target)) { | |
| 964 | 969 | else => unreachable, |
| 965 | 970 | 16, 32, 64 => |bits| { |
| 966 | 971 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; |
| ... | ... | @@ -1021,7 +1026,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1021 | 1026 | |
| 1022 | 1027 | try call.prepareCallee(isel); |
| 1023 | 1028 | try isel.global_relocs.append(gpa, .{ |
| 1024 | .global = switch (air_tag) { | |
| 1029 | .name = switch (air_tag) { | |
| 1025 | 1030 | else => unreachable, |
| 1026 | 1031 | .add, .add_optimized => switch (bits) { |
| 1027 | 1032 | else => unreachable, |
| ... | ... | @@ -1336,7 +1341,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1336 | 1341 | |
| 1337 | 1342 | try call.prepareCallee(isel); |
| 1338 | 1343 | try isel.global_relocs.append(gpa, .{ |
| 1339 | .global = switch (bits) { | |
| 1344 | .name = switch (bits) { | |
| 1340 | 1345 | else => unreachable, |
| 1341 | 1346 | 16 => "__mulhf3", |
| 1342 | 1347 | 32 => "__mulsf3", |
| ... | ... | @@ -1379,6 +1384,143 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1379 | 1384 | } |
| 1380 | 1385 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 1381 | 1386 | }, |
| 1387 | .mul_safe => |air_tag| { | |
| 1388 | if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { | |
| 1389 | defer res_vi.value.deref(isel); | |
| 1390 | ||
| 1391 | const bin_op = air.data(air.inst_index).bin_op; | |
| 1392 | const ty = isel.air.typeOf(bin_op.lhs, ip); | |
| 1393 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | |
| 1394 | const int_info = ty.intInfo(zcu); | |
| 1395 | switch (int_info.signedness) { | |
| 1396 | .signed => switch (int_info.bits) { | |
| 1397 | 0 => unreachable, | |
| 1398 | 1 => { | |
| 1399 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | |
| 1400 | const lhs_vi = try isel.use(bin_op.lhs); | |
| 1401 | const rhs_vi = try isel.use(bin_op.rhs); | |
| 1402 | const lhs_mat = try lhs_vi.matReg(isel); | |
| 1403 | const rhs_mat = try rhs_vi.matReg(isel); | |
| 1404 | try isel.emit(.orr(res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() })); | |
| 1405 | const skip_label = isel.instructions.items.len; | |
| 1406 | try isel.emitPanic(.integer_overflow); | |
| 1407 | try isel.emit(.@"b."( | |
| 1408 | .invert(.ne), | |
| 1409 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | |
| 1410 | )); | |
| 1411 | try isel.emit(.ands(.wzr, lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() })); | |
| 1412 | try rhs_mat.finish(isel); | |
| 1413 | try lhs_mat.finish(isel); | |
| 1414 | }, | |
| 1415 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | |
| 1416 | }, | |
| 1417 | .unsigned => switch (int_info.bits) { | |
| 1418 | 0 => unreachable, | |
| 1419 | 1 => { | |
| 1420 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | |
| 1421 | const lhs_vi = try isel.use(bin_op.lhs); | |
| 1422 | const rhs_vi = try isel.use(bin_op.rhs); | |
| 1423 | const lhs_mat = try lhs_vi.matReg(isel); | |
| 1424 | const rhs_mat = try rhs_vi.matReg(isel); | |
| 1425 | try isel.emit(.@"and"(res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() })); | |
| 1426 | try rhs_mat.finish(isel); | |
| 1427 | try lhs_mat.finish(isel); | |
| 1428 | }, | |
| 1429 | 2...16 => |bits| { | |
| 1430 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | |
| 1431 | const lhs_vi = try isel.use(bin_op.lhs); | |
| 1432 | const rhs_vi = try isel.use(bin_op.rhs); | |
| 1433 | const lhs_mat = try lhs_vi.matReg(isel); | |
| 1434 | const rhs_mat = try rhs_vi.matReg(isel); | |
| 1435 | const skip_label = isel.instructions.items.len; | |
| 1436 | try isel.emitPanic(.integer_overflow); | |
| 1437 | try isel.emit(.@"b."( | |
| 1438 | .eq, | |
| 1439 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | |
| 1440 | )); | |
| 1441 | try isel.emit(.ands(.wzr, res_ra.w(), .{ .immediate = .{ | |
| 1442 | .N = .word, | |
| 1443 | .immr = @intCast(32 - bits), | |
| 1444 | .imms = @intCast(32 - bits - 1), | |
| 1445 | } })); | |
| 1446 | try isel.emit(.madd(res_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w(), .wzr)); | |
| 1447 | try rhs_mat.finish(isel); | |
| 1448 | try lhs_mat.finish(isel); | |
| 1449 | }, | |
| 1450 | 17...32 => |bits| { | |
| 1451 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | |
| 1452 | const lhs_vi = try isel.use(bin_op.lhs); | |
| 1453 | const rhs_vi = try isel.use(bin_op.rhs); | |
| 1454 | const lhs_mat = try lhs_vi.matReg(isel); | |
| 1455 | const rhs_mat = try rhs_vi.matReg(isel); | |
| 1456 | const skip_label = isel.instructions.items.len; | |
| 1457 | try isel.emitPanic(.integer_overflow); | |
| 1458 | try isel.emit(.@"b."( | |
| 1459 | .eq, | |
| 1460 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | |
| 1461 | )); | |
| 1462 | try isel.emit(.ands(.xzr, res_ra.x(), .{ .immediate = .{ | |
| 1463 | .N = .doubleword, | |
| 1464 | .immr = @intCast(64 - bits), | |
| 1465 | .imms = @intCast(64 - bits - 1), | |
| 1466 | } })); | |
| 1467 | try isel.emit(.umaddl(res_ra.x(), lhs_mat.ra.w(), rhs_mat.ra.w(), .xzr)); | |
| 1468 | try rhs_mat.finish(isel); | |
| 1469 | try lhs_mat.finish(isel); | |
| 1470 | }, | |
| 1471 | 33...63 => |bits| { | |
| 1472 | const lo64_ra = try res_vi.value.defReg(isel) orelse break :unused; | |
| 1473 | const lhs_vi = try isel.use(bin_op.lhs); | |
| 1474 | const rhs_vi = try isel.use(bin_op.rhs); | |
| 1475 | const lhs_mat = try lhs_vi.matReg(isel); | |
| 1476 | const rhs_mat = try rhs_vi.matReg(isel); | |
| 1477 | const hi64_ra = hi64_ra: { | |
| 1478 | const lo64_lock = isel.tryLockReg(lo64_ra); | |
| 1479 | defer lo64_lock.unlock(isel); | |
| 1480 | break :hi64_ra try isel.allocIntReg(); | |
| 1481 | }; | |
| 1482 | defer isel.freeReg(hi64_ra); | |
| 1483 | const skip_label = isel.instructions.items.len; | |
| 1484 | try isel.emitPanic(.integer_overflow); | |
| 1485 | try isel.emit(.cbz( | |
| 1486 | hi64_ra.x(), | |
| 1487 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | |
| 1488 | )); | |
| 1489 | try isel.emit(.orr(hi64_ra.x(), hi64_ra.x(), .{ .shifted_register = .{ | |
| 1490 | .register = lo64_ra.x(), | |
| 1491 | .shift = .{ .lsr = @intCast(bits) }, | |
| 1492 | } })); | |
| 1493 | try isel.emit(.madd(lo64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), .xzr)); | |
| 1494 | try isel.emit(.umulh(hi64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x())); | |
| 1495 | try rhs_mat.finish(isel); | |
| 1496 | try lhs_mat.finish(isel); | |
| 1497 | }, | |
| 1498 | 64 => { | |
| 1499 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | |
| 1500 | const lhs_vi = try isel.use(bin_op.lhs); | |
| 1501 | const rhs_vi = try isel.use(bin_op.rhs); | |
| 1502 | const lhs_mat = try lhs_vi.matReg(isel); | |
| 1503 | const rhs_mat = try rhs_vi.matReg(isel); | |
| 1504 | try isel.emit(.madd(res_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), .xzr)); | |
| 1505 | const hi64_ra = try isel.allocIntReg(); | |
| 1506 | defer isel.freeReg(hi64_ra); | |
| 1507 | const skip_label = isel.instructions.items.len; | |
| 1508 | try isel.emitPanic(.integer_overflow); | |
| 1509 | try isel.emit(.cbz( | |
| 1510 | hi64_ra.x(), | |
| 1511 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | |
| 1512 | )); | |
| 1513 | try isel.emit(.umulh(hi64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x())); | |
| 1514 | try rhs_mat.finish(isel); | |
| 1515 | try lhs_mat.finish(isel); | |
| 1516 | }, | |
| 1517 | 65...128 => return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | |
| 1518 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | |
| 1519 | }, | |
| 1520 | } | |
| 1521 | } | |
| 1522 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 1523 | }, | |
| 1382 | 1524 | .mul_sat => |air_tag| { |
| 1383 | 1525 | if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { |
| 1384 | 1526 | defer res_vi.value.deref(isel); |
| ... | ... | @@ -1674,7 +1816,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1674 | 1816 | |
| 1675 | 1817 | try call.prepareCallee(isel); |
| 1676 | 1818 | try isel.global_relocs.append(gpa, .{ |
| 1677 | .global = switch (bits) { | |
| 1819 | .name = switch (bits) { | |
| 1678 | 1820 | else => unreachable, |
| 1679 | 1821 | 16 => "__divhf3", |
| 1680 | 1822 | 32 => "__divsf3", |
| ... | ... | @@ -1813,7 +1955,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1813 | 1955 | |
| 1814 | 1956 | try call.prepareCallee(isel); |
| 1815 | 1957 | try isel.global_relocs.append(gpa, .{ |
| 1816 | .global = switch (int_info.signedness) { | |
| 1958 | .name = switch (int_info.signedness) { | |
| 1817 | 1959 | .signed => "__divti3", |
| 1818 | 1960 | .unsigned => "__udivti3", |
| 1819 | 1961 | }, |
| ... | ... | @@ -1917,7 +2059,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1917 | 2059 | else => unreachable, |
| 1918 | 2060 | .div_trunc, .div_trunc_optimized => { |
| 1919 | 2061 | try isel.global_relocs.append(gpa, .{ |
| 1920 | .global = switch (bits) { | |
| 2062 | .name = switch (bits) { | |
| 1921 | 2063 | else => unreachable, |
| 1922 | 2064 | 16 => "__trunch", |
| 1923 | 2065 | 32 => "truncf", |
| ... | ... | @@ -1931,7 +2073,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1931 | 2073 | }, |
| 1932 | 2074 | .div_floor, .div_floor_optimized => { |
| 1933 | 2075 | try isel.global_relocs.append(gpa, .{ |
| 1934 | .global = switch (bits) { | |
| 2076 | .name = switch (bits) { | |
| 1935 | 2077 | else => unreachable, |
| 1936 | 2078 | 16 => "__floorh", |
| 1937 | 2079 | 32 => "floorf", |
| ... | ... | @@ -1946,7 +2088,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1946 | 2088 | .div_exact, .div_exact_optimized => {}, |
| 1947 | 2089 | } |
| 1948 | 2090 | try isel.global_relocs.append(gpa, .{ |
| 1949 | .global = switch (bits) { | |
| 2091 | .name = switch (bits) { | |
| 1950 | 2092 | else => unreachable, |
| 1951 | 2093 | 16 => "__divhf3", |
| 1952 | 2094 | 32 => "__divsf3", |
| ... | ... | @@ -2046,7 +2188,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 2046 | 2188 | |
| 2047 | 2189 | try call.prepareCallee(isel); |
| 2048 | 2190 | try isel.global_relocs.append(gpa, .{ |
| 2049 | .global = switch (bits) { | |
| 2191 | .name = switch (bits) { | |
| 2050 | 2192 | else => unreachable, |
| 2051 | 2193 | 16 => "__fmodh", |
| 2052 | 2194 | 32 => "fmodf", |
| ... | ... | @@ -2212,7 +2354,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 2212 | 2354 | |
| 2213 | 2355 | try call.prepareCallee(isel); |
| 2214 | 2356 | try isel.global_relocs.append(gpa, .{ |
| 2215 | .global = switch (air_tag) { | |
| 2357 | .name = switch (air_tag) { | |
| 2216 | 2358 | else => unreachable, |
| 2217 | 2359 | .max => switch (bits) { |
| 2218 | 2360 | else => unreachable, |
| ... | ... | @@ -2284,7 +2426,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 2284 | 2426 | else => unreachable, |
| 2285 | 2427 | .add_with_overflow => .add, |
| 2286 | 2428 | .sub_with_overflow => .sub, |
| 2287 | }, rhs_vi, .{ .wrap = true, .overflow_ra = try overflow_vi.?.defReg(isel) orelse .zr }); | |
| 2429 | }, rhs_vi, .{ | |
| 2430 | .overflow = if (try overflow_vi.?.defReg(isel)) |overflow_ra| .{ .ra = overflow_ra } else .wrap, | |
| 2431 | }); | |
| 2288 | 2432 | } |
| 2289 | 2433 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 2290 | 2434 | }, |
| ... | ... | @@ -3092,7 +3236,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3092 | 3236 | |
| 3093 | 3237 | try call.prepareCallee(isel); |
| 3094 | 3238 | try isel.global_relocs.append(gpa, .{ |
| 3095 | .global = "memcpy", | |
| 3239 | .name = "memcpy", | |
| 3096 | 3240 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 3097 | 3241 | }); |
| 3098 | 3242 | try isel.emit(.bl(0)); |
| ... | ... | @@ -3119,7 +3263,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3119 | 3263 | |
| 3120 | 3264 | try call.prepareCallee(isel); |
| 3121 | 3265 | try isel.global_relocs.append(gpa, .{ |
| 3122 | .global = "memcpy", | |
| 3266 | .name = "memcpy", | |
| 3123 | 3267 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 3124 | 3268 | }); |
| 3125 | 3269 | try isel.emit(.bl(0)); |
| ... | ... | @@ -3139,19 +3283,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3139 | 3283 | .block => { |
| 3140 | 3284 | const ty_pl = air.data(air.inst_index).ty_pl; |
| 3141 | 3285 | const extra = isel.air.extraData(Air.Block, ty_pl.payload); |
| 3142 | ||
| 3143 | if (ty_pl.ty != .noreturn_type) { | |
| 3144 | isel.blocks.putAssumeCapacityNoClobber(air.inst_index, .{ | |
| 3145 | .live_registers = isel.live_registers, | |
| 3146 | .target_label = @intCast(isel.instructions.items.len), | |
| 3147 | }); | |
| 3148 | } | |
| 3149 | try isel.body(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len])); | |
| 3150 | if (ty_pl.ty != .noreturn_type) { | |
| 3151 | const block_entry = isel.blocks.pop().?; | |
| 3152 | assert(block_entry.key == air.inst_index); | |
| 3153 | if (isel.live_values.fetchRemove(air.inst_index)) |result_vi| result_vi.value.deref(isel); | |
| 3154 | } | |
| 3286 | try isel.block(air.inst_index, ty_pl.ty.toType(), @ptrCast( | |
| 3287 | isel.air.extra.items[extra.end..][0..extra.data.body_len], | |
| 3288 | )); | |
| 3155 | 3289 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 3156 | 3290 | }, |
| 3157 | 3291 | .loop => { |
| ... | ... | @@ -3175,11 +3309,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3175 | 3309 | } |
| 3176 | 3310 | |
| 3177 | 3311 | // IT'S DOM TIME!!! |
| 3178 | for (isel.blocks.values(), 0..) |*block, dom_index| { | |
| 3312 | for (isel.blocks.values(), 0..) |*dom_block, dom_index| { | |
| 3179 | 3313 | if (@as(u1, @truncate(isel.dom.items[ |
| 3180 | 3314 | loop.dom + dom_index / @bitSizeOf(DomInt) |
| 3181 | 3315 | ] >> @truncate(dom_index))) == 0) continue; |
| 3182 | var live_reg_it = block.live_registers.iterator(); | |
| 3316 | var live_reg_it = dom_block.live_registers.iterator(); | |
| 3183 | 3317 | while (live_reg_it.next()) |live_reg_entry| switch (live_reg_entry.value.*) { |
| 3184 | 3318 | _ => |live_vi| try live_vi.mat(isel), |
| 3185 | 3319 | .allocating => unreachable, |
| ... | ... | @@ -3211,8 +3345,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3211 | 3345 | }, |
| 3212 | 3346 | .br => { |
| 3213 | 3347 | const br = air.data(air.inst_index).br; |
| 3214 | const block = isel.blocks.getPtr(br.block_inst).?; | |
| 3215 | try block.branch(isel); | |
| 3348 | try isel.blocks.getPtr(br.block_inst).?.branch(isel); | |
| 3216 | 3349 | if (isel.live_values.get(br.block_inst)) |dst_vi| try dst_vi.move(isel, br.operand); |
| 3217 | 3350 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 3218 | 3351 | }, |
| ... | ... | @@ -3224,6 +3357,22 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3224 | 3357 | try isel.emit(.brk(0xf000)); |
| 3225 | 3358 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 3226 | 3359 | }, |
| 3360 | .ret_addr => { | |
| 3361 | if (isel.live_values.fetchRemove(air.inst_index)) |addr_vi| unused: { | |
| 3362 | defer addr_vi.value.deref(isel); | |
| 3363 | const addr_ra = try addr_vi.value.defReg(isel) orelse break :unused; | |
| 3364 | try isel.emit(.ldr(addr_ra.x(), .{ .unsigned_offset = .{ .base = .fp, .offset = 8 } })); | |
| 3365 | } | |
| 3366 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 3367 | }, | |
| 3368 | .frame_addr => { | |
| 3369 | if (isel.live_values.fetchRemove(air.inst_index)) |addr_vi| unused: { | |
| 3370 | defer addr_vi.value.deref(isel); | |
| 3371 | const addr_ra = try addr_vi.value.defReg(isel) orelse break :unused; | |
| 3372 | try isel.emit(.orr(addr_ra.x(), .xzr, .{ .register = .fp })); | |
| 3373 | } | |
| 3374 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 3375 | }, | |
| 3227 | 3376 | .call => { |
| 3228 | 3377 | const pl_op = air.data(air.inst_index).pl_op; |
| 3229 | 3378 | const extra = isel.air.extraData(Air.Call, pl_op.payload); |
| ... | ... | @@ -3312,7 +3461,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3312 | 3461 | var param_part_it = passed_vi.parts(isel); |
| 3313 | 3462 | var arg_part_it = arg_vi.parts(isel); |
| 3314 | 3463 | if (arg_part_it.only()) |_| { |
| 3315 | try isel.values.ensureUnusedCapacity(isel.pt.zcu.gpa, param_part_it.remaining); | |
| 3464 | try isel.values.ensureUnusedCapacity(gpa, param_part_it.remaining); | |
| 3316 | 3465 | arg_vi.setParts(isel, param_part_it.remaining); |
| 3317 | 3466 | while (param_part_it.next()) |param_part_vi| _ = arg_vi.addPart( |
| 3318 | 3467 | isel, |
| ... | ... | @@ -3659,7 +3808,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3659 | 3808 | |
| 3660 | 3809 | try call.prepareCallee(isel); |
| 3661 | 3810 | try isel.global_relocs.append(gpa, .{ |
| 3662 | .global = switch (air_tag) { | |
| 3811 | .name = switch (air_tag) { | |
| 3663 | 3812 | else => unreachable, |
| 3664 | 3813 | .sqrt => switch (bits) { |
| 3665 | 3814 | else => unreachable, |
| ... | ... | @@ -3751,7 +3900,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3751 | 3900 | |
| 3752 | 3901 | try call.prepareCallee(isel); |
| 3753 | 3902 | try isel.global_relocs.append(gpa, .{ |
| 3754 | .global = switch (air_tag) { | |
| 3903 | .name = switch (air_tag) { | |
| 3755 | 3904 | else => unreachable, |
| 3756 | 3905 | .sin => switch (bits) { |
| 3757 | 3906 | else => unreachable, |
| ... | ... | @@ -4239,7 +4388,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4239 | 4388 | |
| 4240 | 4389 | try call.prepareCallee(isel); |
| 4241 | 4390 | try isel.global_relocs.append(gpa, .{ |
| 4242 | .global = switch (bits) { | |
| 4391 | .name = switch (bits) { | |
| 4243 | 4392 | else => unreachable, |
| 4244 | 4393 | 16 => "__cmphf2", |
| 4245 | 4394 | 32 => "__cmpsf2", |
| ... | ... | @@ -4629,6 +4778,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4629 | 4778 | try isel.emit(.nop()); |
| 4630 | 4779 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 4631 | 4780 | }, |
| 4781 | .dbg_inline_block => { | |
| 4782 | const ty_pl = air.data(air.inst_index).ty_pl; | |
| 4783 | const extra = isel.air.extraData(Air.DbgInlineBlock, ty_pl.payload); | |
| 4784 | try isel.block(air.inst_index, ty_pl.ty.toType(), @ptrCast( | |
| 4785 | isel.air.extra.items[extra.end..][0..extra.data.body_len], | |
| 4786 | )); | |
| 4787 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 4788 | }, | |
| 4632 | 4789 | .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => { |
| 4633 | 4790 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 4634 | 4791 | }, |
| ... | ... | @@ -4724,7 +4881,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4724 | 4881 | |
| 4725 | 4882 | try call.prepareCallee(isel); |
| 4726 | 4883 | try isel.global_relocs.append(gpa, .{ |
| 4727 | .global = "memcpy", | |
| 4884 | .name = "memcpy", | |
| 4728 | 4885 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 4729 | 4886 | }); |
| 4730 | 4887 | try isel.emit(.bl(0)); |
| ... | ... | @@ -4816,10 +4973,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4816 | 4973 | const ptr_ty = isel.air.typeOf(bin_op.lhs, ip); |
| 4817 | 4974 | const ptr_info = ptr_ty.ptrInfo(zcu); |
| 4818 | 4975 | if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed store", .{}); |
| 4819 | if (bin_op.rhs.toInterned()) |rhs_val| if (ip.isUndef(rhs_val)) { | |
| 4820 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 4821 | break :air_tag; | |
| 4822 | }; | |
| 4976 | if (bin_op.rhs.toInterned()) |rhs_val| if (ip.isUndef(rhs_val)) | |
| 4977 | break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 4823 | 4978 | |
| 4824 | 4979 | const src_vi = try isel.use(bin_op.rhs); |
| 4825 | 4980 | const size = src_vi.size(isel); |
| ... | ... | @@ -4833,8 +4988,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4833 | 4988 | }); |
| 4834 | 4989 | try ptr_mat.finish(isel); |
| 4835 | 4990 | |
| 4836 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 4837 | break :air_tag; | |
| 4991 | break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 4838 | 4992 | }, |
| 4839 | 4993 | else => {}, |
| 4840 | 4994 | }; |
| ... | ... | @@ -4843,7 +4997,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4843 | 4997 | |
| 4844 | 4998 | try call.prepareCallee(isel); |
| 4845 | 4999 | try isel.global_relocs.append(gpa, .{ |
| 4846 | .global = "memcpy", | |
| 5000 | .name = "memcpy", | |
| 4847 | 5001 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 4848 | 5002 | }); |
| 4849 | 5003 | try isel.emit(.bl(0)); |
| ... | ... | @@ -4906,7 +5060,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4906 | 5060 | |
| 4907 | 5061 | try call.prepareCallee(isel); |
| 4908 | 5062 | try isel.global_relocs.append(gpa, .{ |
| 4909 | .global = switch (dst_bits) { | |
| 5063 | .name = switch (dst_bits) { | |
| 4910 | 5064 | else => unreachable, |
| 4911 | 5065 | 16 => switch (src_bits) { |
| 4912 | 5066 | else => unreachable, |
| ... | ... | @@ -5060,6 +5214,108 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 5060 | 5214 | } |
| 5061 | 5215 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 5062 | 5216 | }, |
| 5217 | .intcast_safe => |air_tag| { | |
| 5218 | if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: { | |
| 5219 | defer dst_vi.value.deref(isel); | |
| 5220 | ||
| 5221 | const ty_op = air.data(air.inst_index).ty_op; | |
| 5222 | const dst_ty = ty_op.ty.toType(); | |
| 5223 | const dst_int_info = dst_ty.intInfo(zcu); | |
| 5224 | const src_ty = isel.air.typeOf(ty_op.operand, ip); | |
| 5225 | const src_int_info = src_ty.intInfo(zcu); | |
| 5226 | const can_be_negative = dst_int_info.signedness == .signed and | |
| 5227 | src_int_info.signedness == .signed; | |
| 5228 | const panic_id: Zcu.SimplePanicId = panic_id: switch (dst_ty.zigTypeTag(zcu)) { | |
| 5229 | else => unreachable, | |
| 5230 | .int => .integer_out_of_bounds, | |
| 5231 | .@"enum" => { | |
| 5232 | if (!dst_ty.isNonexhaustiveEnum(zcu)) { | |
| 5233 | return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | |
| 5234 | } | |
| 5235 | break :panic_id .invalid_enum_value; | |
| 5236 | }, | |
| 5237 | }; | |
| 5238 | if (dst_ty.toIntern() == src_ty.toIntern()) { | |
| 5239 | try dst_vi.value.move(isel, ty_op.operand); | |
| 5240 | } else if (dst_int_info.bits <= 64 and src_int_info.bits <= 64) { | |
| 5241 | const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused; | |
| 5242 | const src_vi = try isel.use(ty_op.operand); | |
| 5243 | const dst_active_bits = dst_int_info.bits - @intFromBool(dst_int_info.signedness == .signed); | |
| 5244 | const src_active_bits = src_int_info.bits - @intFromBool(src_int_info.signedness == .signed); | |
| 5245 | if ((dst_int_info.signedness != .unsigned or src_int_info.signedness != .signed) and dst_active_bits >= src_active_bits) { | |
| 5246 | const src_mat = try src_vi.matReg(isel); | |
| 5247 | try isel.emit(if (can_be_negative and dst_active_bits > 32 and src_active_bits <= 32) | |
| 5248 | .sbfm(dst_ra.x(), src_mat.ra.x(), .{ | |
| 5249 | .N = .doubleword, | |
| 5250 | .immr = 0, | |
| 5251 | .imms = @intCast(src_int_info.bits - 1), | |
| 5252 | }) | |
| 5253 | else switch (src_int_info.bits) { | |
| 5254 | else => unreachable, | |
| 5255 | 1...32 => .orr(dst_ra.w(), .wzr, .{ .register = src_mat.ra.w() }), | |
| 5256 | 33...64 => .orr(dst_ra.x(), .xzr, .{ .register = src_mat.ra.x() }), | |
| 5257 | }); | |
| 5258 | try src_mat.finish(isel); | |
| 5259 | } else { | |
| 5260 | const skip_label = isel.instructions.items.len; | |
| 5261 | try isel.emitPanic(panic_id); | |
| 5262 | try isel.emit(.@"b."( | |
| 5263 | .eq, | |
| 5264 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | |
| 5265 | )); | |
| 5266 | if (can_be_negative) { | |
| 5267 | const src_mat = src_mat: { | |
| 5268 | const dst_lock = isel.lockReg(dst_ra); | |
| 5269 | defer dst_lock.unlock(isel); | |
| 5270 | break :src_mat try src_vi.matReg(isel); | |
| 5271 | }; | |
| 5272 | try isel.emit(switch (src_int_info.bits) { | |
| 5273 | else => unreachable, | |
| 5274 | 1...32 => .subs(.wzr, dst_ra.w(), .{ .register = src_mat.ra.w() }), | |
| 5275 | 33...64 => .subs(.xzr, dst_ra.x(), .{ .register = src_mat.ra.x() }), | |
| 5276 | }); | |
| 5277 | try isel.emit(switch (@max(dst_int_info.bits, src_int_info.bits)) { | |
| 5278 | else => unreachable, | |
| 5279 | 1...32 => .sbfm(dst_ra.w(), src_mat.ra.w(), .{ | |
| 5280 | .N = .word, | |
| 5281 | .immr = 0, | |
| 5282 | .imms = @intCast(dst_int_info.bits - 1), | |
| 5283 | }), | |
| 5284 | 33...64 => .sbfm(dst_ra.x(), src_mat.ra.x(), .{ | |
| 5285 | .N = .doubleword, | |
| 5286 | .immr = 0, | |
| 5287 | .imms = @intCast(dst_int_info.bits - 1), | |
| 5288 | }), | |
| 5289 | }); | |
| 5290 | try src_mat.finish(isel); | |
| 5291 | } else { | |
| 5292 | const src_mat = try src_vi.matReg(isel); | |
| 5293 | try isel.emit(switch (@min(dst_int_info.bits, src_int_info.bits)) { | |
| 5294 | else => unreachable, | |
| 5295 | 1...32 => .orr(dst_ra.w(), .wzr, .{ .register = src_mat.ra.w() }), | |
| 5296 | 33...64 => .orr(dst_ra.x(), .xzr, .{ .register = src_mat.ra.x() }), | |
| 5297 | }); | |
| 5298 | const active_bits = @min(dst_active_bits, src_active_bits); | |
| 5299 | try isel.emit(switch (src_int_info.bits) { | |
| 5300 | else => unreachable, | |
| 5301 | 1...32 => .ands(.wzr, src_mat.ra.w(), .{ .immediate = .{ | |
| 5302 | .N = .word, | |
| 5303 | .immr = @intCast(32 - active_bits), | |
| 5304 | .imms = @intCast(32 - active_bits - 1), | |
| 5305 | } }), | |
| 5306 | 33...64 => .ands(.xzr, src_mat.ra.x(), .{ .immediate = .{ | |
| 5307 | .N = .doubleword, | |
| 5308 | .immr = @intCast(64 - active_bits), | |
| 5309 | .imms = @intCast(64 - active_bits - 1), | |
| 5310 | } }), | |
| 5311 | }); | |
| 5312 | try src_mat.finish(isel); | |
| 5313 | } | |
| 5314 | } | |
| 5315 | } else return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | |
| 5316 | } | |
| 5317 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 5318 | }, | |
| 5063 | 5319 | .trunc => |air_tag| { |
| 5064 | 5320 | if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: { |
| 5065 | 5321 | defer dst_vi.value.deref(isel); |
| ... | ... | @@ -5832,7 +6088,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 5832 | 6088 | |
| 5833 | 6089 | try call.prepareCallee(isel); |
| 5834 | 6090 | try isel.global_relocs.append(gpa, .{ |
| 5835 | .global = switch (dst_int_info.bits) { | |
| 6091 | .name = switch (dst_int_info.bits) { | |
| 5836 | 6092 | else => unreachable, |
| 5837 | 6093 | 1...32 => switch (dst_int_info.signedness) { |
| 5838 | 6094 | .signed => switch (src_bits) { |
| ... | ... | @@ -5972,7 +6228,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 5972 | 6228 | |
| 5973 | 6229 | try call.prepareCallee(isel); |
| 5974 | 6230 | try isel.global_relocs.append(gpa, .{ |
| 5975 | .global = switch (src_int_info.bits) { | |
| 6231 | .name = switch (src_int_info.bits) { | |
| 5976 | 6232 | else => unreachable, |
| 5977 | 6233 | 1...32 => switch (src_int_info.signedness) { |
| 5978 | 6234 | .signed => switch (dst_bits) { |
| ... | ... | @@ -6055,14 +6311,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6055 | 6311 | } |
| 6056 | 6312 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 6057 | 6313 | }, |
| 6058 | .memset => |air_tag| { | |
| 6314 | .memset, .memset_safe => |air_tag| { | |
| 6059 | 6315 | const bin_op = air.data(air.inst_index).bin_op; |
| 6060 | 6316 | const dst_ty = isel.air.typeOf(bin_op.lhs, ip); |
| 6061 | 6317 | const dst_info = dst_ty.ptrInfo(zcu); |
| 6062 | 6318 | const fill_byte: union(enum) { constant: u8, value: Air.Inst.Ref } = fill_byte: { |
| 6063 | if (bin_op.rhs.toInterned()) |fill_val| | |
| 6319 | if (bin_op.rhs.toInterned()) |fill_val| { | |
| 6320 | if (ip.isUndef(fill_val)) switch (air_tag) { | |
| 6321 | else => unreachable, | |
| 6322 | .memset => break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag, | |
| 6323 | .memset_safe => break :fill_byte .{ .constant = 0xaa }, | |
| 6324 | }; | |
| 6064 | 6325 | if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte| |
| 6065 | 6326 | break :fill_byte .{ .constant = fill_byte }; |
| 6327 | } | |
| 6066 | 6328 | switch (dst_ty.elemType2(zcu).abiSize(zcu)) { |
| 6067 | 6329 | 0 => unreachable, |
| 6068 | 6330 | 1 => break :fill_byte .{ .value = bin_op.rhs }, |
| ... | ... | @@ -6121,8 +6383,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6121 | 6383 | .c => unreachable, |
| 6122 | 6384 | } |
| 6123 | 6385 | |
| 6124 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 6125 | break :air_tag; | |
| 6386 | break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 6126 | 6387 | }, |
| 6127 | 6388 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty) }), |
| 6128 | 6389 | } |
| ... | ... | @@ -6133,7 +6394,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6133 | 6394 | |
| 6134 | 6395 | try call.prepareCallee(isel); |
| 6135 | 6396 | try isel.global_relocs.append(gpa, .{ |
| 6136 | .global = "memset", | |
| 6397 | .name = "memset", | |
| 6137 | 6398 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6138 | 6399 | }); |
| 6139 | 6400 | try isel.emit(.bl(0)); |
| ... | ... | @@ -6179,7 +6440,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6179 | 6440 | |
| 6180 | 6441 | try call.prepareCallee(isel); |
| 6181 | 6442 | try isel.global_relocs.append(gpa, .{ |
| 6182 | .global = @tagName(air_tag), | |
| 6443 | .name = @tagName(air_tag), | |
| 6183 | 6444 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6184 | 6445 | }); |
| 6185 | 6446 | try isel.emit(.bl(0)); |
| ... | ... | @@ -6268,6 +6529,72 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6268 | 6529 | |
| 6269 | 6530 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 6270 | 6531 | }, |
| 6532 | .error_name => { | |
| 6533 | if (isel.live_values.fetchRemove(air.inst_index)) |name_vi| unused: { | |
| 6534 | defer name_vi.value.deref(isel); | |
| 6535 | var ptr_part_it = name_vi.value.field(.slice_const_u8_sentinel_0, 0, 8); | |
| 6536 | const ptr_part_vi = try ptr_part_it.only(isel); | |
| 6537 | const ptr_part_ra = try ptr_part_vi.?.defReg(isel); | |
| 6538 | var len_part_it = name_vi.value.field(.slice_const_u8_sentinel_0, 8, 8); | |
| 6539 | const len_part_vi = try len_part_it.only(isel); | |
| 6540 | const len_part_ra = try len_part_vi.?.defReg(isel); | |
| 6541 | if (ptr_part_ra == null and len_part_ra == null) break :unused; | |
| 6542 | ||
| 6543 | const un_op = air.data(air.inst_index).un_op; | |
| 6544 | const err_vi = try isel.use(un_op); | |
| 6545 | const err_mat = try err_vi.matReg(isel); | |
| 6546 | const ptr_ra = try isel.allocIntReg(); | |
| 6547 | defer isel.freeReg(ptr_ra); | |
| 6548 | const start_ra, const end_ra = range_ras: { | |
| 6549 | const name_lock: RegLock = if (len_part_ra != null) if (ptr_part_ra) |name_ptr_ra| | |
| 6550 | isel.tryLockReg(name_ptr_ra) | |
| 6551 | else | |
| 6552 | .empty else .empty; | |
| 6553 | defer name_lock.unlock(isel); | |
| 6554 | break :range_ras .{ try isel.allocIntReg(), try isel.allocIntReg() }; | |
| 6555 | }; | |
| 6556 | defer { | |
| 6557 | isel.freeReg(start_ra); | |
| 6558 | isel.freeReg(end_ra); | |
| 6559 | } | |
| 6560 | if (len_part_ra) |name_len_ra| try isel.emit(.sub( | |
| 6561 | name_len_ra.w(), | |
| 6562 | end_ra.w(), | |
| 6563 | .{ .register = start_ra.w() }, | |
| 6564 | )); | |
| 6565 | if (ptr_part_ra) |name_ptr_ra| try isel.emit(.add( | |
| 6566 | name_ptr_ra.x(), | |
| 6567 | ptr_ra.x(), | |
| 6568 | .{ .extended_register = .{ | |
| 6569 | .register = start_ra.w(), | |
| 6570 | .extend = .{ .uxtw = 0 }, | |
| 6571 | } }, | |
| 6572 | )); | |
| 6573 | if (len_part_ra) |_| try isel.emit(.sub(end_ra.w(), end_ra.w(), .{ .immediate = 1 })); | |
| 6574 | try isel.emit(.ldp(start_ra.w(), end_ra.w(), .{ .base = start_ra.x() })); | |
| 6575 | try isel.emit(.add(start_ra.x(), ptr_ra.x(), .{ .extended_register = .{ | |
| 6576 | .register = err_mat.ra.w(), | |
| 6577 | .extend = switch (zcu.errorSetBits()) { | |
| 6578 | else => unreachable, | |
| 6579 | 1...8 => .{ .uxtb = 2 }, | |
| 6580 | 9...16 => .{ .uxth = 2 }, | |
| 6581 | 17...32 => .{ .uxtw = 2 }, | |
| 6582 | }, | |
| 6583 | } })); | |
| 6584 | try isel.lazy_relocs.append(gpa, .{ | |
| 6585 | .symbol = .{ .kind = .const_data, .ty = .anyerror_type }, | |
| 6586 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | |
| 6587 | }); | |
| 6588 | try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 })); | |
| 6589 | try isel.lazy_relocs.append(gpa, .{ | |
| 6590 | .symbol = .{ .kind = .const_data, .ty = .anyerror_type }, | |
| 6591 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | |
| 6592 | }); | |
| 6593 | try isel.emit(.adrp(ptr_ra.x(), 0)); | |
| 6594 | try err_mat.finish(isel); | |
| 6595 | } | |
| 6596 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 6597 | }, | |
| 6271 | 6598 | .aggregate_init => { |
| 6272 | 6599 | if (isel.live_values.fetchRemove(air.inst_index)) |agg_vi| { |
| 6273 | 6600 | defer agg_vi.value.deref(isel); |
| ... | ... | @@ -6362,7 +6689,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6362 | 6689 | |
| 6363 | 6690 | try call.prepareCallee(isel); |
| 6364 | 6691 | try isel.global_relocs.append(gpa, .{ |
| 6365 | .global = "memcpy", | |
| 6692 | .name = "memcpy", | |
| 6366 | 6693 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6367 | 6694 | }); |
| 6368 | 6695 | try isel.emit(.bl(0)); |
| ... | ... | @@ -6478,7 +6805,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6478 | 6805 | |
| 6479 | 6806 | try call.prepareCallee(isel); |
| 6480 | 6807 | try isel.global_relocs.append(gpa, .{ |
| 6481 | .global = switch (bits) { | |
| 6808 | .name = switch (bits) { | |
| 6482 | 6809 | else => unreachable, |
| 6483 | 6810 | 16 => "__fmah", |
| 6484 | 6811 | 32 => "fmaf", |
| ... | ... | @@ -6559,6 +6886,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6559 | 6886 | } |
| 6560 | 6887 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 6561 | 6888 | }, |
| 6889 | .cmp_lt_errors_len => { | |
| 6890 | if (isel.live_values.fetchRemove(air.inst_index)) |is_vi| unused: { | |
| 6891 | defer is_vi.value.deref(isel); | |
| 6892 | const is_ra = try is_vi.value.defReg(isel) orelse break :unused; | |
| 6893 | try isel.emit(.csinc(is_ra.w(), .wzr, .wzr, .invert(.ls))); | |
| 6894 | ||
| 6895 | const un_op = air.data(air.inst_index).un_op; | |
| 6896 | const err_vi = try isel.use(un_op); | |
| 6897 | const err_mat = try err_vi.matReg(isel); | |
| 6898 | const ptr_ra = try isel.allocIntReg(); | |
| 6899 | defer isel.freeReg(ptr_ra); | |
| 6900 | try isel.emit(.subs(.wzr, err_mat.ra.w(), .{ .register = ptr_ra.w() })); | |
| 6901 | try isel.lazy_relocs.append(gpa, .{ | |
| 6902 | .symbol = .{ .kind = .const_data, .ty = .anyerror_type }, | |
| 6903 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | |
| 6904 | }); | |
| 6905 | try isel.emit(.ldr(ptr_ra.w(), .{ .base = ptr_ra.x() })); | |
| 6906 | try isel.lazy_relocs.append(gpa, .{ | |
| 6907 | .symbol = .{ .kind = .const_data, .ty = .anyerror_type }, | |
| 6908 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | |
| 6909 | }); | |
| 6910 | try isel.emit(.adrp(ptr_ra.x(), 0)); | |
| 6911 | try err_mat.finish(isel); | |
| 6912 | } | |
| 6913 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | |
| 6914 | }, | |
| 6562 | 6915 | .runtime_nav_ptr => { |
| 6563 | 6916 | if (isel.live_values.fetchRemove(air.inst_index)) |ptr_vi| unused: { |
| 6564 | 6917 | defer ptr_vi.value.deref(isel); |
| ... | ... | @@ -6567,19 +6920,19 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6567 | 6920 | const ty_nav = air.data(air.inst_index).ty_nav; |
| 6568 | 6921 | if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) { |
| 6569 | 6922 | false => { |
| 6570 | try isel.nav_relocs.append(zcu.gpa, .{ | |
| 6923 | try isel.nav_relocs.append(gpa, .{ | |
| 6571 | 6924 | .nav = ty_nav.nav, |
| 6572 | 6925 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6573 | 6926 | }); |
| 6574 | 6927 | try isel.emit(.adr(ptr_ra.x(), 0)); |
| 6575 | 6928 | }, |
| 6576 | 6929 | true => { |
| 6577 | try isel.nav_relocs.append(zcu.gpa, .{ | |
| 6930 | try isel.nav_relocs.append(gpa, .{ | |
| 6578 | 6931 | .nav = ty_nav.nav, |
| 6579 | 6932 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6580 | 6933 | }); |
| 6581 | 6934 | try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 })); |
| 6582 | try isel.nav_relocs.append(zcu.gpa, .{ | |
| 6935 | try isel.nav_relocs.append(gpa, .{ | |
| 6583 | 6936 | .nav = ty_nav.nav, |
| 6584 | 6937 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6585 | 6938 | }); |
| ... | ... | @@ -6589,9 +6942,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6589 | 6942 | } |
| 6590 | 6943 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 6591 | 6944 | }, |
| 6592 | .add_safe, | |
| 6593 | .sub_safe, | |
| 6594 | .mul_safe, | |
| 6595 | 6945 | .inferred_alloc, |
| 6596 | 6946 | .inferred_alloc_comptime, |
| 6597 | 6947 | .int_from_float_safe, |
| ... | ... | @@ -6822,6 +7172,9 @@ pub fn layout( |
| 6822 | 7172 | saves_len += 1; |
| 6823 | 7173 | saves_size += 8; |
| 6824 | 7174 | deferred_gr = null; |
| 7175 | } else switch (@as(u1, @truncate(saved_gra_len))) { | |
| 7176 | 0 => {}, | |
| 7177 | 1 => saves_size += 8, | |
| 6825 | 7178 | } |
| 6826 | 7179 | save_ra = if (mod.strip) incoming.ngrn else CallAbiIterator.ngrn_start; |
| 6827 | 7180 | while (save_ra != if (have_va) CallAbiIterator.ngrn_end else incoming.ngrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) { |
| ... | ... | @@ -6844,42 +7197,42 @@ pub fn layout( |
| 6844 | 7197 | { |
| 6845 | 7198 | wip_mir_log.debug("{f}<prologue>:", .{nav.fqn.fmt(ip)}); |
| 6846 | 7199 | var save_index: usize = 0; |
| 6847 | while (save_index < saves.len) { | |
| 6848 | if (save_index + 2 <= saves.len and saves[save_index + 0].class == saves[save_index + 1].class and | |
| 6849 | saves[save_index + 0].offset + saves[save_index + 0].size == saves[save_index + 1].offset) | |
| 6850 | { | |
| 6851 | try isel.emit(.stp( | |
| 6852 | saves[save_index + 0].register, | |
| 6853 | saves[save_index + 1].register, | |
| 6854 | switch (saves[save_index + 0].offset) { | |
| 6855 | 0 => .{ .pre_index = .{ | |
| 6856 | .base = .sp, | |
| 6857 | .index = @intCast(-@as(i11, saves_size)), | |
| 6858 | } }, | |
| 6859 | else => |offset| .{ .signed_offset = .{ | |
| 6860 | .base = .sp, | |
| 6861 | .offset = @intCast(offset), | |
| 6862 | } }, | |
| 6863 | }, | |
| 6864 | )); | |
| 6865 | save_index += 2; | |
| 6866 | } else { | |
| 6867 | try isel.emit(.str( | |
| 6868 | saves[save_index].register, | |
| 6869 | switch (saves[save_index].offset) { | |
| 6870 | 0 => .{ .pre_index = .{ | |
| 6871 | .base = .sp, | |
| 6872 | .index = @intCast(-@as(i11, saves_size)), | |
| 6873 | } }, | |
| 6874 | else => |offset| .{ .unsigned_offset = .{ | |
| 6875 | .base = .sp, | |
| 6876 | .offset = @intCast(offset), | |
| 6877 | } }, | |
| 6878 | }, | |
| 6879 | )); | |
| 6880 | save_index += 1; | |
| 6881 | } | |
| 6882 | } | |
| 7200 | while (save_index < saves.len) if (save_index + 2 <= saves.len and | |
| 7201 | saves[save_index + 0].class == saves[save_index + 1].class and | |
| 7202 | saves[save_index + 0].size == saves[save_index + 1].size and | |
| 7203 | saves[save_index + 0].offset + saves[save_index + 0].size == saves[save_index + 1].offset) | |
| 7204 | { | |
| 7205 | try isel.emit(.stp( | |
| 7206 | saves[save_index + 0].register, | |
| 7207 | saves[save_index + 1].register, | |
| 7208 | switch (saves[save_index + 0].offset) { | |
| 7209 | 0 => .{ .pre_index = .{ | |
| 7210 | .base = .sp, | |
| 7211 | .index = @intCast(-@as(i11, saves_size)), | |
| 7212 | } }, | |
| 7213 | else => |offset| .{ .signed_offset = .{ | |
| 7214 | .base = .sp, | |
| 7215 | .offset = @intCast(offset), | |
| 7216 | } }, | |
| 7217 | }, | |
| 7218 | )); | |
| 7219 | save_index += 2; | |
| 7220 | } else { | |
| 7221 | try isel.emit(.str( | |
| 7222 | saves[save_index].register, | |
| 7223 | switch (saves[save_index].offset) { | |
| 7224 | 0 => .{ .pre_index = .{ | |
| 7225 | .base = .sp, | |
| 7226 | .index = @intCast(-@as(i11, saves_size)), | |
| 7227 | } }, | |
| 7228 | else => |offset| .{ .unsigned_offset = .{ | |
| 7229 | .base = .sp, | |
| 7230 | .offset = @intCast(offset), | |
| 7231 | } }, | |
| 7232 | }, | |
| 7233 | )); | |
| 7234 | save_index += 1; | |
| 7235 | }; | |
| 6883 | 7236 | |
| 6884 | 7237 | try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset })); |
| 6885 | 7238 | const scratch_reg: Register = if (isel.stack_align == .@"16") |
| ... | ... | @@ -7053,11 +7406,43 @@ fn fmtConstant(isel: *Select, constant: Constant) @typeInfo(@TypeOf(Constant.fmt |
| 7053 | 7406 | return constant.fmtValue(isel.pt); |
| 7054 | 7407 | } |
| 7055 | 7408 | |
| 7409 | fn block( | |
| 7410 | isel: *Select, | |
| 7411 | air_inst_index: Air.Inst.Index, | |
| 7412 | res_ty: ZigType, | |
| 7413 | air_body: []const Air.Inst.Index, | |
| 7414 | ) !void { | |
| 7415 | if (res_ty.toIntern() != .noreturn_type) { | |
| 7416 | isel.blocks.putAssumeCapacityNoClobber(air_inst_index, .{ | |
| 7417 | .live_registers = isel.live_registers, | |
| 7418 | .target_label = @intCast(isel.instructions.items.len), | |
| 7419 | }); | |
| 7420 | } | |
| 7421 | try isel.body(air_body); | |
| 7422 | if (res_ty.toIntern() != .noreturn_type) { | |
| 7423 | const block_entry = isel.blocks.pop().?; | |
| 7424 | assert(block_entry.key == air_inst_index); | |
| 7425 | if (isel.live_values.fetchRemove(air_inst_index)) |result_vi| result_vi.value.deref(isel); | |
| 7426 | } | |
| 7427 | } | |
| 7428 | ||
| 7056 | 7429 | fn emit(isel: *Select, instruction: codegen.aarch64.encoding.Instruction) !void { |
| 7057 | 7430 | wip_mir_log.debug(" | {f}", .{instruction}); |
| 7058 | 7431 | try isel.instructions.append(isel.pt.zcu.gpa, instruction); |
| 7059 | 7432 | } |
| 7060 | 7433 | |
| 7434 | fn emitPanic(isel: *Select, panic_id: Zcu.SimplePanicId) !void { | |
| 7435 | const zcu = isel.pt.zcu; | |
| 7436 | try isel.nav_relocs.append(zcu.gpa, .{ | |
| 7437 | .nav = switch (zcu.intern_pool.indexToKey(zcu.builtin_decl_values.get(panic_id.toBuiltin()))) { | |
| 7438 | else => unreachable, | |
| 7439 | inline .@"extern", .func => |func| func.owner_nav, | |
| 7440 | }, | |
| 7441 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | |
| 7442 | }); | |
| 7443 | try isel.emit(.bl(0)); | |
| 7444 | } | |
| 7445 | ||
| 7061 | 7446 | fn emitLiteral(isel: *Select, bytes: []const u8) !void { |
| 7062 | 7447 | const words: []align(1) const u32 = @ptrCast(bytes); |
| 7063 | 7448 | const literals = try isel.literals.addManyAsSlice(isel.pt.zcu.gpa, words.len); |
| ... | ... | @@ -8104,6 +8489,32 @@ pub const Value = struct { |
| 8104 | 8489 | } |
| 8105 | 8490 | } |
| 8106 | 8491 | |
| 8492 | const AddOrSubtractOptions = struct { | |
| 8493 | overflow: Overflow, | |
| 8494 | ||
| 8495 | const Overflow = union(enum) { | |
| 8496 | @"unreachable", | |
| 8497 | panic: Zcu.SimplePanicId, | |
| 8498 | wrap, | |
| 8499 | ra: Register.Alias, | |
| 8500 | ||
| 8501 | fn defCond(overflow: Overflow, isel: *Select, cond: codegen.aarch64.encoding.ConditionCode) !void { | |
| 8502 | switch (overflow) { | |
| 8503 | .@"unreachable" => unreachable, | |
| 8504 | .panic => |panic_id| { | |
| 8505 | const skip_label = isel.instructions.items.len; | |
| 8506 | try isel.emitPanic(panic_id); | |
| 8507 | try isel.emit(.@"b."( | |
| 8508 | cond.invert(), | |
| 8509 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | |
| 8510 | )); | |
| 8511 | }, | |
| 8512 | .wrap => {}, | |
| 8513 | .ra => |overflow_ra| try isel.emit(.csinc(overflow_ra.w(), .wzr, .wzr, cond.invert())), | |
| 8514 | } | |
| 8515 | } | |
| 8516 | }; | |
| 8517 | }; | |
| 8107 | 8518 | fn addOrSubtract( |
| 8108 | 8519 | res_vi: Value.Index, |
| 8109 | 8520 | isel: *Select, |
| ... | ... | @@ -8111,19 +8522,21 @@ pub const Value = struct { |
| 8111 | 8522 | lhs_vi: Value.Index, |
| 8112 | 8523 | op: codegen.aarch64.encoding.Instruction.AddSubtractOp, |
| 8113 | 8524 | rhs_vi: Value.Index, |
| 8114 | opts: struct { | |
| 8115 | wrap: bool, | |
| 8116 | overflow_ra: Register.Alias = .zr, | |
| 8117 | }, | |
| 8525 | opts: AddOrSubtractOptions, | |
| 8118 | 8526 | ) !void { |
| 8119 | assert(opts.wrap or opts.overflow_ra == .zr); | |
| 8120 | 8527 | const zcu = isel.pt.zcu; |
| 8121 | 8528 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(op), isel.fmtType(ty) }); |
| 8122 | 8529 | const int_info = ty.intInfo(zcu); |
| 8123 | 8530 | if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(op), isel.fmtType(ty) }); |
| 8124 | 8531 | var part_offset = res_vi.size(isel); |
| 8125 | var need_wrap = opts.wrap; | |
| 8126 | var need_carry = opts.overflow_ra != .zr; | |
| 8532 | var need_wrap = switch (opts.overflow) { | |
| 8533 | .@"unreachable" => false, | |
| 8534 | .panic, .wrap, .ra => true, | |
| 8535 | }; | |
| 8536 | var need_carry = switch (opts.overflow) { | |
| 8537 | .@"unreachable", .wrap => false, | |
| 8538 | .panic, .ra => true, | |
| 8539 | }; | |
| 8127 | 8540 | while (part_offset > 0) : (need_wrap = false) { |
| 8128 | 8541 | const part_size = @min(part_offset, 8); |
| 8129 | 8542 | part_offset -= part_size; |
| ... | ... | @@ -8133,48 +8546,87 @@ pub const Value = struct { |
| 8133 | 8546 | const unwrapped_res_part_ra = unwrapped_res_part_ra: { |
| 8134 | 8547 | if (!need_wrap) break :unwrapped_res_part_ra wrapped_res_part_ra; |
| 8135 | 8548 | if (int_info.bits % 32 == 0) { |
| 8136 | if (opts.overflow_ra != .zr) try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(switch (int_info.signedness) { | |
| 8549 | try opts.overflow.defCond(isel, switch (int_info.signedness) { | |
| 8137 | 8550 | .signed => .vs, |
| 8138 | 8551 | .unsigned => switch (op) { |
| 8139 | 8552 | .add => .cs, |
| 8140 | 8553 | .sub => .cc, |
| 8141 | 8554 | }, |
| 8142 | }))); | |
| 8555 | }); | |
| 8143 | 8556 | break :unwrapped_res_part_ra wrapped_res_part_ra; |
| 8144 | 8557 | } |
| 8145 | const wrapped_part_ra, const unwrapped_part_ra = if (opts.overflow_ra != .zr) part_ra: { | |
| 8146 | switch (op) { | |
| 8147 | .add => {}, | |
| 8148 | .sub => switch (int_info.signedness) { | |
| 8149 | .signed => {}, | |
| 8150 | .unsigned => { | |
| 8151 | try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.cc))); | |
| 8152 | break :part_ra .{ wrapped_res_part_ra, wrapped_res_part_ra }; | |
| 8153 | }, | |
| 8558 | need_carry = false; | |
| 8559 | const wrapped_part_ra, const unwrapped_part_ra = part_ra: switch (opts.overflow) { | |
| 8560 | .@"unreachable" => unreachable, | |
| 8561 | .panic, .ra => switch (int_info.signedness) { | |
| 8562 | .signed => { | |
| 8563 | try opts.overflow.defCond(isel, .ne); | |
| 8564 | const wrapped_part_ra = switch (wrapped_res_part_ra) { | |
| 8565 | else => |res_part_ra| res_part_ra, | |
| 8566 | .zr => try isel.allocIntReg(), | |
| 8567 | }; | |
| 8568 | errdefer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra); | |
| 8569 | const unwrapped_part_ra = unwrapped_part_ra: { | |
| 8570 | const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) { | |
| 8571 | else => |res_part_ra| isel.lockReg(res_part_ra), | |
| 8572 | .zr => .empty, | |
| 8573 | }; | |
| 8574 | defer wrapped_res_part_lock.unlock(isel); | |
| 8575 | break :unwrapped_part_ra try isel.allocIntReg(); | |
| 8576 | }; | |
| 8577 | errdefer isel.freeReg(unwrapped_part_ra); | |
| 8578 | switch (part_size) { | |
| 8579 | else => unreachable, | |
| 8580 | 1...4 => try isel.emit(.subs(.wzr, wrapped_part_ra.w(), .{ .register = unwrapped_part_ra.w() })), | |
| 8581 | 5...8 => try isel.emit(.subs(.xzr, wrapped_part_ra.x(), .{ .register = unwrapped_part_ra.x() })), | |
| 8582 | } | |
| 8583 | break :part_ra .{ wrapped_part_ra, unwrapped_part_ra }; | |
| 8154 | 8584 | }, |
| 8155 | } | |
| 8156 | try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.ne))); | |
| 8157 | const wrapped_part_ra = switch (wrapped_res_part_ra) { | |
| 8158 | else => |res_part_ra| res_part_ra, | |
| 8159 | .zr => try isel.allocIntReg(), | |
| 8160 | }; | |
| 8161 | errdefer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra); | |
| 8162 | const unwrapped_part_ra = unwrapped_part_ra: { | |
| 8163 | const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) { | |
| 8164 | else => |res_part_ra| isel.lockReg(res_part_ra), | |
| 8165 | .zr => .empty, | |
| 8166 | }; | |
| 8167 | defer wrapped_res_part_lock.unlock(isel); | |
| 8168 | break :unwrapped_part_ra try isel.allocIntReg(); | |
| 8169 | }; | |
| 8170 | errdefer isel.freeReg(unwrapped_part_ra); | |
| 8171 | switch (part_size) { | |
| 8172 | else => unreachable, | |
| 8173 | 1...4 => try isel.emit(.subs(.wzr, wrapped_part_ra.w(), .{ .register = unwrapped_part_ra.w() })), | |
| 8174 | 5...8 => try isel.emit(.subs(.xzr, wrapped_part_ra.x(), .{ .register = unwrapped_part_ra.x() })), | |
| 8175 | } | |
| 8176 | break :part_ra .{ wrapped_part_ra, unwrapped_part_ra }; | |
| 8177 | } else .{ wrapped_res_part_ra, wrapped_res_part_ra }; | |
| 8585 | .unsigned => { | |
| 8586 | const unwrapped_part_ra = unwrapped_part_ra: { | |
| 8587 | const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) { | |
| 8588 | else => |res_part_ra| isel.lockReg(res_part_ra), | |
| 8589 | .zr => .empty, | |
| 8590 | }; | |
| 8591 | defer wrapped_res_part_lock.unlock(isel); | |
| 8592 | break :unwrapped_part_ra try isel.allocIntReg(); | |
| 8593 | }; | |
| 8594 | errdefer isel.freeReg(unwrapped_part_ra); | |
| 8595 | const bit: u6 = @truncate(int_info.bits); | |
| 8596 | switch (opts.overflow) { | |
| 8597 | .@"unreachable", .wrap => unreachable, | |
| 8598 | .panic => |panic_id| { | |
| 8599 | const skip_label = isel.instructions.items.len; | |
| 8600 | try isel.emitPanic(panic_id); | |
| 8601 | try isel.emit(.tbz( | |
| 8602 | switch (bit) { | |
| 8603 | 0, 32 => unreachable, | |
| 8604 | 1...31 => unwrapped_part_ra.w(), | |
| 8605 | 33...63 => unwrapped_part_ra.x(), | |
| 8606 | }, | |
| 8607 | bit, | |
| 8608 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | |
| 8609 | )); | |
| 8610 | }, | |
| 8611 | .ra => |overflow_ra| try isel.emit(switch (bit) { | |
| 8612 | 0, 32 => unreachable, | |
| 8613 | 1...31 => .ubfm(overflow_ra.w(), unwrapped_part_ra.w(), .{ | |
| 8614 | .N = .word, | |
| 8615 | .immr = bit, | |
| 8616 | .imms = bit, | |
| 8617 | }), | |
| 8618 | 33...63 => .ubfm(overflow_ra.x(), unwrapped_part_ra.x(), .{ | |
| 8619 | .N = .doubleword, | |
| 8620 | .immr = bit, | |
| 8621 | .imms = bit, | |
| 8622 | }), | |
| 8623 | }), | |
| 8624 | } | |
| 8625 | break :part_ra .{ wrapped_res_part_ra, unwrapped_part_ra }; | |
| 8626 | }, | |
| 8627 | }, | |
| 8628 | .wrap => .{ wrapped_res_part_ra, wrapped_res_part_ra }, | |
| 8629 | }; | |
| 8178 | 8630 | defer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra); |
| 8179 | 8631 | errdefer if (unwrapped_part_ra != wrapped_res_part_ra) isel.freeReg(unwrapped_part_ra); |
| 8180 | 8632 | if (wrapped_part_ra != .zr) try isel.emit(switch (part_size) { |
| ... | ... | @@ -8650,41 +9102,15 @@ pub const Value = struct { |
| 8650 | 9102 | expected_live_registers: *const LiveRegisters, |
| 8651 | 9103 | ) !void { |
| 8652 | 9104 | try vi.liveIn(isel, src_ra, expected_live_registers); |
| 8653 | const offset_from_parent: i65, const parent_vi = vi.valueParent(isel); | |
| 9105 | const offset_from_parent, const parent_vi = vi.valueParent(isel); | |
| 8654 | 9106 | switch (parent_vi.parent(isel)) { |
| 8655 | 9107 | .unallocated => {}, |
| 8656 | .stack_slot => |stack_slot| { | |
| 8657 | const offset = stack_slot.offset + offset_from_parent; | |
| 8658 | try isel.emit(switch (vi.size(isel)) { | |
| 8659 | else => unreachable, | |
| 8660 | 1 => if (src_ra.isVector()) .str(src_ra.b(), .{ .unsigned_offset = .{ | |
| 8661 | .base = stack_slot.base.x(), | |
| 8662 | .offset = @intCast(offset), | |
| 8663 | } }) else .strb(src_ra.w(), .{ .unsigned_offset = .{ | |
| 8664 | .base = stack_slot.base.x(), | |
| 8665 | .offset = @intCast(offset), | |
| 8666 | } }), | |
| 8667 | 2 => if (src_ra.isVector()) .str(src_ra.h(), .{ .unsigned_offset = .{ | |
| 8668 | .base = stack_slot.base.x(), | |
| 8669 | .offset = @intCast(offset), | |
| 8670 | } }) else .strh(src_ra.w(), .{ .unsigned_offset = .{ | |
| 8671 | .base = stack_slot.base.x(), | |
| 8672 | .offset = @intCast(offset), | |
| 8673 | } }), | |
| 8674 | 4 => .str(if (src_ra.isVector()) src_ra.s() else src_ra.w(), .{ .unsigned_offset = .{ | |
| 8675 | .base = stack_slot.base.x(), | |
| 8676 | .offset = @intCast(offset), | |
| 8677 | } }), | |
| 8678 | 8 => .str(if (src_ra.isVector()) src_ra.d() else src_ra.x(), .{ .unsigned_offset = .{ | |
| 8679 | .base = stack_slot.base.x(), | |
| 8680 | .offset = @intCast(offset), | |
| 8681 | } }), | |
| 8682 | 16 => .str(src_ra.q(), .{ .unsigned_offset = .{ | |
| 8683 | .base = stack_slot.base.x(), | |
| 8684 | .offset = @intCast(offset), | |
| 8685 | } }), | |
| 8686 | }); | |
| 8687 | }, | |
| 9108 | .stack_slot => |stack_slot| if (stack_slot.base != Register.Alias.fp) try isel.storeReg( | |
| 9109 | src_ra, | |
| 9110 | vi.size(isel), | |
| 9111 | stack_slot.base, | |
| 9112 | @as(i65, stack_slot.offset) + offset_from_parent, | |
| 9113 | ), | |
| 8688 | 9114 | else => unreachable, |
| 8689 | 9115 | } |
| 8690 | 9116 | try vi.spillReg(isel, src_ra, 0, expected_live_registers); |
| ... | ... | @@ -9631,14 +10057,18 @@ pub const Value = struct { |
| 9631 | 10057 | var base_ptr = ip.indexToKey(base).ptr; |
| 9632 | 10058 | const eu_ty = ip.indexToKey(base_ptr.ty).ptr_type.child; |
| 9633 | 10059 | const payload_ty = ip.indexToKey(eu_ty).error_union_type.payload_type; |
| 9634 | base_ptr.byte_offset += codegen.errUnionPayloadOffset(.fromInterned(payload_ty), zcu); | |
| 10060 | base_ptr.byte_offset += codegen.errUnionPayloadOffset(.fromInterned(payload_ty), zcu) + ptr.byte_offset; | |
| 10061 | continue :constant_key .{ .ptr = base_ptr }; | |
| 10062 | }, | |
| 10063 | .opt_payload => |base| { | |
| 10064 | var base_ptr = ip.indexToKey(base).ptr; | |
| 10065 | base_ptr.byte_offset += ptr.byte_offset; | |
| 9635 | 10066 | continue :constant_key .{ .ptr = base_ptr }; |
| 9636 | 10067 | }, |
| 9637 | .opt_payload => |base| continue :constant_key .{ .ptr = ip.indexToKey(base).ptr }, | |
| 9638 | 10068 | .field => |field| { |
| 9639 | 10069 | var base_ptr = ip.indexToKey(field.base).ptr; |
| 9640 | 10070 | const agg_ty: ZigType = .fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child); |
| 9641 | base_ptr.byte_offset += agg_ty.structFieldOffset(@intCast(field.index), zcu); | |
| 10071 | base_ptr.byte_offset += agg_ty.structFieldOffset(@intCast(field.index), zcu) + ptr.byte_offset; | |
| 9642 | 10072 | continue :constant_key .{ .ptr = base_ptr }; |
| 9643 | 10073 | }, |
| 9644 | 10074 | .comptime_alloc, .comptime_field, .arr_elem => unreachable, |
src/codegen/aarch64/instructions.zon+190| ... | ... | @@ -213,6 +213,63 @@ |
| 213 | 213 | }, |
| 214 | 214 | .encode = .{ .ands, .Xd, .Xn, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } }, |
| 215 | 215 | }, |
| 216 | // C6.2.16 ASR (register) | |
| 217 | .{ | |
| 218 | .pattern = "ASR <Wd>, <Wn>, <Wm>", | |
| 219 | .symbols = .{ | |
| 220 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 221 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 222 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 223 | }, | |
| 224 | .encode = .{ .asrv, .Wd, .Wn, .Wm }, | |
| 225 | }, | |
| 226 | .{ | |
| 227 | .pattern = "ASR <Xd>, <Xn>, <Xm>", | |
| 228 | .symbols = .{ | |
| 229 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 230 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 231 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 232 | }, | |
| 233 | .encode = .{ .asrv, .Xd, .Xn, .Xm }, | |
| 234 | }, | |
| 235 | // C6.2.17 ASR (immediate) | |
| 236 | .{ | |
| 237 | .pattern = "ASR <Wd>, <Wn>, #<shift>", | |
| 238 | .symbols = .{ | |
| 239 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 240 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 241 | .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } }, | |
| 242 | }, | |
| 243 | .encode = .{ .sbfm, .Wd, .Wn, .{ .N = .word, .immr = .shift, .imms = 31 } }, | |
| 244 | }, | |
| 245 | .{ | |
| 246 | .pattern = "ASR <Xd>, <Xn>, #<shift>", | |
| 247 | .symbols = .{ | |
| 248 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 249 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 250 | .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } }, | |
| 251 | }, | |
| 252 | .encode = .{ .sbfm, .Xd, .Xn, .{ .N = .doubleword, .immr = .shift, .imms = 63 } }, | |
| 253 | }, | |
| 254 | // C6.2.18 ASRV | |
| 255 | .{ | |
| 256 | .pattern = "ASRV <Wd>, <Wn>, <Wm>", | |
| 257 | .symbols = .{ | |
| 258 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 259 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 260 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 261 | }, | |
| 262 | .encode = .{ .asrv, .Wd, .Wn, .Wm }, | |
| 263 | }, | |
| 264 | .{ | |
| 265 | .pattern = "ASRV <Xd>, <Xn>, <Xm>", | |
| 266 | .symbols = .{ | |
| 267 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 268 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 269 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 270 | }, | |
| 271 | .encode = .{ .asrv, .Xd, .Xn, .Xm }, | |
| 272 | }, | |
| 216 | 273 | // C6.2.35 BLR |
| 217 | 274 | .{ |
| 218 | 275 | .pattern = "BLR <Xn>", |
| ... | ... | @@ -681,6 +738,82 @@ |
| 681 | 738 | }, |
| 682 | 739 | .encode = .{ .ldr, .Xt, .{ .unsigned_offset = .{ .base = .Xn, .offset = .pimm } } }, |
| 683 | 740 | }, |
| 741 | // C6.2.212 LSL (register) | |
| 742 | .{ | |
| 743 | .pattern = "LSL <Wd>, <Wn>, <Wm>", | |
| 744 | .symbols = .{ | |
| 745 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 746 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 747 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 748 | }, | |
| 749 | .encode = .{ .lslv, .Wd, .Wn, .Wm }, | |
| 750 | }, | |
| 751 | .{ | |
| 752 | .pattern = "LSL <Xd>, <Xn>, <Xm>", | |
| 753 | .symbols = .{ | |
| 754 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 755 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 756 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 757 | }, | |
| 758 | .encode = .{ .lslv, .Xd, .Xn, .Xm }, | |
| 759 | }, | |
| 760 | // C6.2.214 LSLV | |
| 761 | .{ | |
| 762 | .pattern = "LSLV <Wd>, <Wn>, <Wm>", | |
| 763 | .symbols = .{ | |
| 764 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 765 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 766 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 767 | }, | |
| 768 | .encode = .{ .lslv, .Wd, .Wn, .Wm }, | |
| 769 | }, | |
| 770 | .{ | |
| 771 | .pattern = "LSLV <Xd>, <Xn>, <Xm>", | |
| 772 | .symbols = .{ | |
| 773 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 774 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 775 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 776 | }, | |
| 777 | .encode = .{ .lslv, .Xd, .Xn, .Xm }, | |
| 778 | }, | |
| 779 | // C6.2.215 LSR (register) | |
| 780 | .{ | |
| 781 | .pattern = "LSR <Wd>, <Wn>, <Wm>", | |
| 782 | .symbols = .{ | |
| 783 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 784 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 785 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 786 | }, | |
| 787 | .encode = .{ .lsrv, .Wd, .Wn, .Wm }, | |
| 788 | }, | |
| 789 | .{ | |
| 790 | .pattern = "LSR <Xd>, <Xn>, <Xm>", | |
| 791 | .symbols = .{ | |
| 792 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 793 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 794 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 795 | }, | |
| 796 | .encode = .{ .lsrv, .Xd, .Xn, .Xm }, | |
| 797 | }, | |
| 798 | // C6.2.217 LSRV | |
| 799 | .{ | |
| 800 | .pattern = "LSRV <Wd>, <Wn>, <Wm>", | |
| 801 | .symbols = .{ | |
| 802 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 803 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 804 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 805 | }, | |
| 806 | .encode = .{ .lsrv, .Wd, .Wn, .Wm }, | |
| 807 | }, | |
| 808 | .{ | |
| 809 | .pattern = "LSRV <Xd>, <Xn>, <Xm>", | |
| 810 | .symbols = .{ | |
| 811 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 812 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 813 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 814 | }, | |
| 815 | .encode = .{ .lsrv, .Xd, .Xn, .Xm }, | |
| 816 | }, | |
| 684 | 817 | // C6.2.220 MOV (to/from SP) |
| 685 | 818 | .{ |
| 686 | 819 | .pattern = "MOV WSP, <Wn|WSP>", |
| ... | ... | @@ -964,6 +1097,63 @@ |
| 964 | 1097 | }, |
| 965 | 1098 | .encode = .{ .ret, .Xn }, |
| 966 | 1099 | }, |
| 1100 | // C6.2.261 ROR (immediate) | |
| 1101 | .{ | |
| 1102 | .pattern = "ROR <Wd>, <Ws>, #<shift>", | |
| 1103 | .symbols = .{ | |
| 1104 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 1105 | .Ws = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 1106 | .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } }, | |
| 1107 | }, | |
| 1108 | .encode = .{ .extr, .Wd, .Ws, .Ws, .shift }, | |
| 1109 | }, | |
| 1110 | .{ | |
| 1111 | .pattern = "ROR <Xd>, <Xs>, #<shift>", | |
| 1112 | .symbols = .{ | |
| 1113 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 1114 | .Xs = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 1115 | .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } }, | |
| 1116 | }, | |
| 1117 | .encode = .{ .extr, .Xd, .Xs, .Xs, .shift }, | |
| 1118 | }, | |
| 1119 | // C6.2.262 ROR (register) | |
| 1120 | .{ | |
| 1121 | .pattern = "ROR <Wd>, <Wn>, <Wm>", | |
| 1122 | .symbols = .{ | |
| 1123 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 1124 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 1125 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 1126 | }, | |
| 1127 | .encode = .{ .rorv, .Wd, .Wn, .Wm }, | |
| 1128 | }, | |
| 1129 | .{ | |
| 1130 | .pattern = "ROR <Xd>, <Xn>, <Xm>", | |
| 1131 | .symbols = .{ | |
| 1132 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 1133 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 1134 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 1135 | }, | |
| 1136 | .encode = .{ .rorv, .Xd, .Xn, .Xm }, | |
| 1137 | }, | |
| 1138 | // C6.2.263 RORV | |
| 1139 | .{ | |
| 1140 | .pattern = "RORV <Wd>, <Wn>, <Wm>", | |
| 1141 | .symbols = .{ | |
| 1142 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 1143 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 1144 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | |
| 1145 | }, | |
| 1146 | .encode = .{ .rorv, .Wd, .Wn, .Wm }, | |
| 1147 | }, | |
| 1148 | .{ | |
| 1149 | .pattern = "RORV <Xd>, <Xn>, <Xm>", | |
| 1150 | .symbols = .{ | |
| 1151 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 1152 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 1153 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | |
| 1154 | }, | |
| 1155 | .encode = .{ .rorv, .Xd, .Xn, .Xm }, | |
| 1156 | }, | |
| 967 | 1157 | // C6.2.268 SBFM |
| 968 | 1158 | .{ |
| 969 | 1159 | .pattern = "SBFM <Wd>, <Wn>, #<immr>, #<imms>", |
src/target.zig+4-2| ... | ... | @@ -351,7 +351,7 @@ pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.builtin.Opti |
| 351 | 351 | } |
| 352 | 352 | } |
| 353 | 353 | |
| 354 | pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime have_llvm: bool) bool { | |
| 354 | pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, have_llvm: bool) bool { | |
| 355 | 355 | switch (target.os.tag) { |
| 356 | 356 | .plan9 => return false, |
| 357 | 357 | else => {}, |
| ... | ... | @@ -373,7 +373,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime |
| 373 | 373 | }; |
| 374 | 374 | } |
| 375 | 375 | |
| 376 | pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, comptime have_llvm: bool) bool { | |
| 376 | pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, have_llvm: bool) bool { | |
| 377 | 377 | switch (target.cpu.arch) { |
| 378 | 378 | .spirv32, .spirv64 => return false, |
| 379 | 379 | // Remove this once https://github.com/ziglang/zig/issues/23715 is fixed |
| ... | ... | @@ -382,6 +382,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, comptime ha |
| 382 | 382 | } |
| 383 | 383 | return switch (zigBackend(target, use_llvm)) { |
| 384 | 384 | .stage2_llvm => true, |
| 385 | .stage2_wasm => false, | |
| 385 | 386 | .stage2_x86_64 => switch (target.ofmt) { |
| 386 | 387 | .elf, .macho => true, |
| 387 | 388 | else => have_llvm, |
| ... | ... | @@ -860,6 +861,7 @@ pub fn zigBackend(target: *const std.Target, use_llvm: bool) std.builtin.Compile |
| 860 | 861 | pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, comptime feature: Feature) bool { |
| 861 | 862 | return switch (feature) { |
| 862 | 863 | .panic_fn => switch (backend) { |
| 864 | .stage2_aarch64, | |
| 863 | 865 | .stage2_c, |
| 864 | 866 | .stage2_llvm, |
| 865 | 867 | .stage2_x86_64, |
test/behavior/error.zig-3| ... | ... | @@ -590,7 +590,6 @@ test "error union comptime caching" { |
| 590 | 590 | } |
| 591 | 591 | |
| 592 | 592 | test "@errorName" { |
| 593 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 594 | 593 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 595 | 594 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 596 | 595 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| ... | ... | @@ -605,7 +604,6 @@ fn gimmeItBroke() anyerror { |
| 605 | 604 | } |
| 606 | 605 | |
| 607 | 606 | test "@errorName sentinel length matches slice length" { |
| 608 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 609 | 607 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 610 | 608 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 611 | 609 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| ... | ... | @@ -883,7 +881,6 @@ test "catch within a function that calls no errorable functions" { |
| 883 | 881 | } |
| 884 | 882 | |
| 885 | 883 | test "error from comptime string" { |
| 886 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 887 | 884 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 888 | 885 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 889 | 886 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
test/behavior/return_address.zig-1| ... | ... | @@ -6,7 +6,6 @@ fn retAddr() usize { |
| 6 | 6 | } |
| 7 | 7 | |
| 8 | 8 | test "return address" { |
| 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 10 | 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 11 | 10 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 12 | 11 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
test/cases/array_in_anon_struct.zig+1-1| ... | ... | @@ -19,4 +19,4 @@ pub fn main() !void { |
| 19 | 19 | |
| 20 | 20 | // run |
| 21 | 21 | // backend=stage2,llvm |
| 22 | // target=native | |
| 22 | // target=x86_64-linux,aarch64-linux |
test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig+2-2| ... | ... | @@ -7,5 +7,5 @@ export fn entry3() callconv(.avr_interrupt) void {} |
| 7 | 7 | // target=aarch64-linux-none |
| 8 | 8 | // |
| 9 | 9 | // :1:30: error: calling convention 'x86_64_interrupt' only available on architectures 'x86_64' |
| 10 | // :1:30: error: calling convention 'x86_interrupt' only available on architectures 'x86' | |
| 11 | // :1:30: error: calling convention 'avr_interrupt' only available on architectures 'avr' | |
| 10 | // :2:30: error: calling convention 'x86_interrupt' only available on architectures 'x86' | |
| 11 | // :3:30: error: calling convention 'avr_interrupt' only available on architectures 'avr' |
test/cases/compile_errors/error_set_membership.zig+1-1| ... | ... | @@ -25,7 +25,7 @@ pub fn main() Error!void { |
| 25 | 25 | |
| 26 | 26 | // error |
| 27 | 27 | // backend=stage2 |
| 28 | // target=native | |
| 28 | // target=x86_64-linux | |
| 29 | 29 | // |
| 30 | 30 | // :23:29: error: expected type 'error{InvalidCharacter}', found '@typeInfo(@typeInfo(@TypeOf(tmp.fooey)).@"fn".return_type.?).error_union.error_set' |
| 31 | 31 | // :23:29: note: 'error.InvalidDirection' not a member of destination error set |
test/cases/compile_errors/function_ptr_alignment.zig+1-1| ... | ... | @@ -10,7 +10,7 @@ comptime { |
| 10 | 10 | |
| 11 | 11 | // error |
| 12 | 12 | // backend=stage2 |
| 13 | // target=native | |
| 13 | // target=x86_64-linux | |
| 14 | 14 | // |
| 15 | 15 | // :8:41: error: expected type '*align(2) const fn () void', found '*const fn () void' |
| 16 | 16 | // :8:41: note: pointer alignment '1' cannot cast into pointer alignment '2' |
test/cases/compile_errors/issue_15572_break_on_inline_while.zig+1-1| ... | ... | @@ -15,6 +15,6 @@ pub fn main() void { |
| 15 | 15 | |
| 16 | 16 | // error |
| 17 | 17 | // backend=stage2 |
| 18 | // target=native | |
| 18 | // target=x86_64-linux | |
| 19 | 19 | // |
| 20 | 20 | // :9:28: error: incompatible types: 'builtin.Type.EnumField' and 'void' |
test/cases/compile_errors/switch_on_non_err_union.zig+1-1| ... | ... | @@ -6,6 +6,6 @@ pub fn main() void { |
| 6 | 6 | |
| 7 | 7 | // error |
| 8 | 8 | // backend=stage2 |
| 9 | // target=native | |
| 9 | // target=x86_64-linux | |
| 10 | 10 | // |
| 11 | 11 | // :2:23: error: expected error union type, found 'bool' |
test/cases/pic_freestanding.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | 2 | const std = @import("std"); |
| 3 | 3 | |
| 4 | fn _start() callconv(.naked) void {} | |
| 4 | pub fn _start() callconv(.naked) void {} | |
| 5 | 5 | |
| 6 | 6 | comptime { |
| 7 | 7 | @export(&_start, .{ .name = if (builtin.cpu.arch.isMIPS()) "__start" else "_start" }); |
test/cases/safety/@alignCast misaligned.zig	+1-1| ... | ... | @@ -22,4 +22,4 @@ fn foo(bytes: []u8) u32 { |
| 22 | 22 | } |
| 23 | 23 | // run |
| 24 | 24 | // backend=stage2,llvm |
| 25 | // target=native | |
| 25 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@enumFromInt - no matching tag value.zig	+1-1| ... | ... | @@ -23,4 +23,4 @@ fn baz(_: Foo) void {} |
| 23 | 23 | |
| 24 | 24 | // run |
| 25 | 25 | // backend=stage2,llvm |
| 26 | // target=native | |
| 26 | // target=x86_64-linux |
test/cases/safety/@enumFromInt truncated bits - exhaustive.zig	+1-1| ... | ... | @@ -20,4 +20,4 @@ pub fn main() u8 { |
| 20 | 20 | |
| 21 | 21 | // run |
| 22 | 22 | // backend=stage2,llvm |
| 23 | // target=native | |
| 23 | // target=x86_64-linux |
test/cases/safety/@enumFromInt truncated bits - nonexhaustive.zig	+1-1| ... | ... | @@ -20,4 +20,4 @@ pub fn main() u8 { |
| 20 | 20 | |
| 21 | 21 | // run |
| 22 | 22 | // backend=stage2,llvm |
| 23 | // target=native | |
| 23 | // target=x86_64-linux |
test/cases/safety/@errorCast error not present in destination.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn foo(set1: Set1) Set2 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux |
test/cases/safety/@errorCast error union casted to disjoint set.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ fn foo() anyerror!i32 { |
| 17 | 17 | } |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux |
test/cases/safety/@intCast to u0.zig	+1-1| ... | ... | @@ -19,4 +19,4 @@ fn bar(one: u1, not_zero: i32) void { |
| 19 | 19 | } |
| 20 | 20 | // run |
| 21 | 21 | // backend=stage2,llvm |
| 22 | // target=native | |
| 22 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - i0 max.zig	+1-1| ... | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | 13 | } |
| 14 | 14 | // run |
| 15 | 15 | // backend=stage2,llvm |
| 16 | // target=native | |
| 16 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - i0 min.zig	+1-1| ... | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | 13 | } |
| 14 | 14 | // run |
| 15 | 15 | // backend=stage2,llvm |
| 16 | // target=native | |
| 16 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - signed max.zig	+1-1| ... | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | 13 | } |
| 14 | 14 | // run |
| 15 | 15 | // backend=stage2,llvm |
| 16 | // target=native | |
| 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - signed min.zig	+1-1| ... | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | 13 | } |
| 14 | 14 | // run |
| 15 | 15 | // backend=stage2,llvm |
| 16 | // target=native | |
| 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - u0 max.zig	+1-1| ... | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | 13 | } |
| 14 | 14 | // run |
| 15 | 15 | // backend=stage2,llvm |
| 16 | // target=native | |
| 16 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - u0 min.zig	+1-1| ... | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | 13 | } |
| 14 | 14 | // run |
| 15 | 15 | // backend=stage2,llvm |
| 16 | // target=native | |
| 16 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned max.zig	+1-1| ... | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | 13 | } |
| 14 | 14 | // run |
| 15 | 15 | // backend=stage2,llvm |
| 16 | // target=native | |
| 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned min.zig	+1-1| ... | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | 13 | } |
| 14 | 14 | // run |
| 15 | 15 | // backend=stage2,llvm |
| 16 | // target=native | |
| 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - vector max.zig	+1-1| ... | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | 13 | } |
| 14 | 14 | // run |
| 15 | 15 | // backend=stage2,llvm |
| 16 | // target=native | |
| 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - vector min.zig	+1-1| ... | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | 13 | } |
| 14 | 14 | // run |
| 15 | 15 | // backend=stage2,llvm |
| 16 | // target=native | |
| 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - negative out of range.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ fn bar(a: f32) i8 { |
| 17 | 17 | fn baz(_: i8) void {} |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - negative to unsigned.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ fn bar(a: f32) u8 { |
| 17 | 17 | fn baz(_: u8) void {} |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - positive out of range.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ fn bar(a: f32) u8 { |
| 17 | 17 | fn baz(_: u8) void {} |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux |
test/cases/safety/@ptrFromInt address zero to non-optional byte-aligned pointer.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@ptrFromInt address zero to non-optional pointer.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@ptrFromInt with misaligned address.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@tagName on corrupted enum value.zig	+1-1| ... | ... | @@ -23,4 +23,4 @@ pub fn main() !void { |
| 23 | 23 | |
| 24 | 24 | // run |
| 25 | 25 | // backend=stage2,llvm |
| 26 | // target=native | |
| 26 | // target=x86_64-linux |
test/cases/safety/@tagName on corrupted union value.zig	+1-1| ... | ... | @@ -24,4 +24,4 @@ pub fn main() !void { |
| 24 | 24 | |
| 25 | 25 | // run |
| 26 | 26 | // backend=stage2,llvm |
| 27 | // target=native | |
| 27 | // target=x86_64-linux |
test/cases/safety/array slice sentinel mismatch vector.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux |
test/cases/safety/array slice sentinel mismatch.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/bad union field access.zig	+1-1| ... | ... | @@ -24,4 +24,4 @@ fn bar(f: *Foo) void { |
| 24 | 24 | } |
| 25 | 25 | // run |
| 26 | 26 | // backend=stage2,llvm |
| 27 | // target=native | |
| 27 | // target=x86_64-linux |
test/cases/safety/calling panic.zig	+1-1| ... | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | 13 | } |
| 14 | 14 | // run |
| 15 | 15 | // backend=stage2,llvm |
| 16 | // target=native | |
| 16 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/cast []u8 to bigger slice of wrong size.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn widenSlice(slice: []align(1) const u8) []align(1) const i32 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/cast integer to global error and no code matches.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ fn bar(x: u16) anyerror { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/empty slice with sentinel out of bounds.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/exact division failure - vectors.zig	+1-1| ... | ... | @@ -20,4 +20,4 @@ fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { |
| 20 | 20 | } |
| 21 | 21 | // run |
| 22 | 22 | // backend=stage2,llvm |
| 23 | // target=native | |
| 23 | // target=x86_64-linux |
test/cases/safety/exact division failure.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn divExact(a: i32, b: i32) i32 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/for_len_mismatch.zig+1-1| ... | ... | @@ -22,4 +22,4 @@ pub fn main() !void { |
| 22 | 22 | } |
| 23 | 23 | // run |
| 24 | 24 | // backend=stage2,llvm |
| 25 | // target=native | |
| 25 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/for_len_mismatch_three.zig+1-1| ... | ... | @@ -21,4 +21,4 @@ pub fn main() !void { |
| 21 | 21 | } |
| 22 | 22 | // run |
| 23 | 23 | // backend=stage2,llvm |
| 24 | // target=native | |
| 24 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/ignored expression integer overflow.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux |
test/cases/safety/integer addition overflow.zig	+1-1| ... | ... | @@ -20,4 +20,4 @@ fn add(a: u16, b: u16) u16 { |
| 20 | 20 | |
| 21 | 21 | // run |
| 22 | 22 | // backend=stage2,llvm |
| 23 | // target=native | |
| 23 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/integer division by zero - vectors.zig	+1-1| ... | ... | @@ -19,4 +19,4 @@ fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { |
| 19 | 19 | } |
| 20 | 20 | // run |
| 21 | 21 | // backend=stage2,llvm |
| 22 | // target=native | |
| 22 | // target=x86_64-linux |
test/cases/safety/integer division by zero.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ fn div0(a: i32, b: i32) i32 { |
| 17 | 17 | } |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/integer multiplication overflow.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn mul(a: u16, b: u16) u16 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/integer negation overflow.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn neg(a: i16) i16 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/integer subtraction overflow.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn sub(a: u16, b: u16) u16 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memcpy_alias.zig+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memcpy_len_mismatch.zig+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memmove_len_mismatch.zig+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memset_array_undefined_bytes.zig+1-1| ... | ... | @@ -15,4 +15,4 @@ pub fn main() !void { |
| 15 | 15 | } |
| 16 | 16 | // run |
| 17 | 17 | // backend=stage2,llvm |
| 18 | // target=native | |
| 18 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memset_array_undefined_large.zig+1-1| ... | ... | @@ -15,4 +15,4 @@ pub fn main() !void { |
| 15 | 15 | } |
| 16 | 16 | // run |
| 17 | 17 | // backend=stage2,llvm |
| 18 | // target=native | |
| 18 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memset_slice_undefined_bytes.zig+1-1| ... | ... | @@ -17,4 +17,4 @@ pub fn main() !void { |
| 17 | 17 | } |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memset_slice_undefined_large.zig+1-1| ... | ... | @@ -17,4 +17,4 @@ pub fn main() !void { |
| 17 | 17 | } |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/modrem by zero.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ fn div0(a: u32, b: u32) u32 { |
| 17 | 17 | } |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/modulus by zero.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ fn mod0(a: i32, b: i32) i32 { |
| 17 | 17 | } |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux |
test/cases/safety/noreturn returned.zig	+1-1| ... | ... | @@ -20,4 +20,4 @@ pub fn main() void { |
| 20 | 20 | } |
| 21 | 21 | // run |
| 22 | 22 | // backend=stage2,llvm |
| 23 | // target=native | |
| 23 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/optional unwrap operator on C pointer.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/optional unwrap operator on null pointer.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/optional_empty_error_set.zig+1-1| ... | ... | @@ -19,4 +19,4 @@ fn foo() !void { |
| 19 | 19 | } |
| 20 | 20 | // run |
| 21 | 21 | // backend=stage2,llvm |
| 22 | // target=native | |
| 22 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/out of bounds array slice by length.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ fn foo(a: u32) u32 { |
| 17 | 17 | } |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/out of bounds slice access.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn bar(a: []const i32) i32 { |
| 18 | 18 | fn baz(_: i32) void {} |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/pointer casting null to non-optional pointer.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/pointer casting to null function pointer.zig	+1-1| ... | ... | @@ -20,4 +20,4 @@ pub fn main() !void { |
| 20 | 20 | |
| 21 | 21 | // run |
| 22 | 22 | // backend=stage2,llvm |
| 23 | // target=native | |
| 23 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/pointer slice sentinel mismatch.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/remainder division by zero.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ fn rem0(a: i32, b: i32) i32 { |
| 17 | 17 | } |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/shift left by huge amount.zig	+1-1| ... | ... | @@ -19,4 +19,4 @@ pub fn main() !void { |
| 19 | 19 | |
| 20 | 20 | // run |
| 21 | 21 | // backend=stage2,llvm |
| 22 | // target=native | |
| 22 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/shift right by huge amount.zig	+1-1| ... | ... | @@ -19,4 +19,4 @@ pub fn main() !void { |
| 19 | 19 | |
| 20 | 20 | // run |
| 21 | 21 | // backend=stage2,llvm |
| 22 | // target=native | |
| 22 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/signed integer division overflow - vectors.zig	+1-1| ... | ... | @@ -20,4 +20,4 @@ fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) { |
| 20 | 20 | } |
| 21 | 21 | // run |
| 22 | 22 | // backend=stage2,llvm |
| 23 | // target=native | |
| 23 | // target=x86_64-linux |
test/cases/safety/signed integer division overflow.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn div(a: i16, b: i16) i16 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux |
test/cases/safety/signed integer not fitting in cast to unsigned integer.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ fn unsigned_cast(x: i32) u32 { |
| 17 | 17 | } |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/signed shift left overflow.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn shl(a: i16, b: u4) i16 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux |
test/cases/safety/signed shift right overflow.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn shr(a: i16, b: u4) i16 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/signed-unsigned vector cast.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux |
test/cases/safety/slice by length sentinel mismatch on lhs.zig	+1-1| ... | ... | @@ -15,4 +15,4 @@ pub fn main() !void { |
| 15 | 15 | } |
| 16 | 16 | // run |
| 17 | 17 | // backend=stage2,llvm |
| 18 | // target=native | |
| 18 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice by length sentinel mismatch on rhs.zig	+1-1| ... | ... | @@ -15,4 +15,4 @@ pub fn main() !void { |
| 15 | 15 | } |
| 16 | 16 | // run |
| 17 | 17 | // backend=stage2,llvm |
| 18 | // target=native | |
| 18 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice sentinel mismatch - floats.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ pub fn main() !void { |
| 17 | 17 | |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux |
test/cases/safety/slice sentinel mismatch - optional pointers.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ pub fn main() !void { |
| 17 | 17 | |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice slice sentinel mismatch.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice start index greater than end index.zig	+1-1| ... | ... | @@ -21,4 +21,4 @@ pub fn main() !void { |
| 21 | 21 | |
| 22 | 22 | // run |
| 23 | 23 | // backend=stage2,llvm |
| 24 | // target=native | |
| 24 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice with sentinel out of bounds - runtime len.zig	+1-1| ... | ... | @@ -20,4 +20,4 @@ pub fn main() !void { |
| 20 | 20 | |
| 21 | 21 | // run |
| 22 | 22 | // backend=stage2,llvm |
| 23 | // target=native | |
| 23 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice with sentinel out of bounds.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice_cast_change_len_0.zig+1-1| ... | ... | @@ -24,4 +24,4 @@ const std = @import("std"); |
| 24 | 24 | |
| 25 | 25 | // run |
| 26 | 26 | // backend=stage2,llvm |
| 27 | // target=x86_64-linux | |
| 27 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice_cast_change_len_1.zig+1-1| ... | ... | @@ -24,4 +24,4 @@ const std = @import("std"); |
| 24 | 24 | |
| 25 | 25 | // run |
| 26 | 26 | // backend=stage2,llvm |
| 27 | // target=x86_64-linux | |
| 27 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice_cast_change_len_2.zig+1-1| ... | ... | @@ -24,4 +24,4 @@ const std = @import("std"); |
| 24 | 24 | |
| 25 | 25 | // run |
| 26 | 26 | // backend=stage2,llvm |
| 27 | // target=x86_64-linux | |
| 27 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slicing null C pointer - runtime len.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slicing null C pointer.zig	+1-1| ... | ... | @@ -17,4 +17,4 @@ pub fn main() !void { |
| 17 | 17 | } |
| 18 | 18 | // run |
| 19 | 19 | // backend=stage2,llvm |
| 20 | // target=native | |
| 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/switch else on corrupt enum value - one prong.zig	+1-1| ... | ... | @@ -21,4 +21,4 @@ pub fn main() !void { |
| 21 | 21 | } |
| 22 | 22 | // run |
| 23 | 23 | // backend=stage2,llvm |
| 24 | // target=native | |
| 24 | // target=x86_64-linux |
test/cases/safety/switch else on corrupt enum value - union.zig	+1-1| ... | ... | @@ -26,4 +26,4 @@ pub fn main() !void { |
| 26 | 26 | } |
| 27 | 27 | // run |
| 28 | 28 | // backend=stage2,llvm |
| 29 | // target=native | |
| 29 | // target=x86_64-linux |
test/cases/safety/switch else on corrupt enum value.zig	+1-1| ... | ... | @@ -20,4 +20,4 @@ pub fn main() !void { |
| 20 | 20 | } |
| 21 | 21 | // run |
| 22 | 22 | // backend=stage2,llvm |
| 23 | // target=native | |
| 23 | // target=x86_64-linux |
test/cases/safety/switch on corrupted enum value.zig	+1-1| ... | ... | @@ -24,4 +24,4 @@ pub fn main() !void { |
| 24 | 24 | |
| 25 | 25 | // run |
| 26 | 26 | // backend=stage2,llvm |
| 27 | // target=native | |
| 27 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/switch on corrupted union value.zig	+1-1| ... | ... | @@ -24,4 +24,4 @@ pub fn main() !void { |
| 24 | 24 | |
| 25 | 25 | // run |
| 26 | 26 | // backend=stage2,llvm |
| 27 | // target=native | |
| 27 | // target=x86_64-linux |
test/cases/safety/truncating vector cast.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux |
test/cases/safety/unreachable.zig+1-1| ... | ... | @@ -12,4 +12,4 @@ pub fn main() !void { |
| 12 | 12 | } |
| 13 | 13 | // run |
| 14 | 14 | // backend=stage2,llvm |
| 15 | // target=native | |
| 15 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux |
test/cases/safety/unsigned shift left overflow.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn shl(a: u16, b: u4) u16 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux |
test/cases/safety/unsigned shift right overflow.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn shr(a: u16, b: u4) u16 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/unsigned-signed vector cast.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux |
test/cases/safety/unwrap error switch.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn bar() !void { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/unwrap error.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ fn bar() !void { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/value does not fit in shortening cast - u0.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn shorten_cast(x: u8) u0 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/value does not fit in shortening cast.zig	+1-1| ... | ... | @@ -18,4 +18,4 @@ fn shorten_cast(x: i32) i8 { |
| 18 | 18 | } |
| 19 | 19 | // run |
| 20 | 20 | // backend=stage2,llvm |
| 21 | // target=native | |
| 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/vector integer addition overflow.zig	+1-1| ... | ... | @@ -19,4 +19,4 @@ fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { |
| 19 | 19 | } |
| 20 | 20 | // run |
| 21 | 21 | // backend=stage2,llvm |
| 22 | // target=native | |
| 22 | // target=x86_64-linux |
test/cases/safety/vector integer multiplication overflow.zig	+1-1| ... | ... | @@ -19,4 +19,4 @@ fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) { |
| 19 | 19 | } |
| 20 | 20 | // run |
| 21 | 21 | // backend=stage2,llvm |
| 22 | // target=native | |
| 22 | // target=x86_64-linux |
test/cases/safety/vector integer negation overflow.zig	+1-1| ... | ... | @@ -19,4 +19,4 @@ fn neg(a: @Vector(4, i16)) @Vector(4, i16) { |
| 19 | 19 | } |
| 20 | 20 | // run |
| 21 | 21 | // backend=stage2,llvm |
| 22 | // target=native | |
| 22 | // target=x86_64-linux |
test/cases/safety/vector integer subtraction overflow.zig	+1-1| ... | ... | @@ -19,4 +19,4 @@ fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) { |
| 19 | 19 | } |
| 20 | 20 | // run |
| 21 | 21 | // backend=stage2,llvm |
| 22 | // target=native | |
| 22 | // target=x86_64-linux |
test/cases/safety/zero casted to error.zig	+1-1| ... | ... | @@ -16,4 +16,4 @@ fn bar(x: u16) anyerror { |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | 18 | // backend=stage2,llvm |
| 19 | // target=native | |
| 19 | // target=x86_64-linux,aarch64-linux |
test/cases/taking_pointer_of_global_tagged_union.zig+1-1| ... | ... | @@ -23,4 +23,4 @@ pub fn main() !void { |
| 23 | 23 | |
| 24 | 24 | // run |
| 25 | 25 | // backend=stage2,llvm |
| 26 | // target=native | |
| 26 | // target=x86_64-linux |
test/src/Cases.zig+1-5| ... | ... | @@ -436,7 +436,7 @@ fn addFromDirInner( |
| 436 | 436 | const target = &resolved_target.result; |
| 437 | 437 | for (backends) |backend| { |
| 438 | 438 | if (backend == .stage2 and |
| 439 | target.cpu.arch != .wasm32 and target.cpu.arch != .x86_64 and target.cpu.arch != .spirv64) | |
| 439 | target.cpu.arch != .aarch64 and target.cpu.arch != .wasm32 and target.cpu.arch != .x86_64 and target.cpu.arch != .spirv64) | |
| 440 | 440 | { |
| 441 | 441 | // Other backends don't support new liveness format |
| 442 | 442 | continue; |
| ... | ... | @@ -447,10 +447,6 @@ fn addFromDirInner( |
| 447 | 447 | // Rosetta has issues with ZLD |
| 448 | 448 | continue; |
| 449 | 449 | } |
| 450 | if (backend == .stage2 and target.ofmt == .coff) { | |
| 451 | // COFF linker has bitrotted | |
| 452 | continue; | |
| 453 | } | |
| 454 | 450 | |
| 455 | 451 | const next = ctx.cases.items.len; |
| 456 | 452 | try ctx.cases.append(.{ |