| author | |
| committer | |
| log | 6198f7afb76b7a5a6d359bfd24f8fbdabc77939b |
| tree | 8acd0c84bde1d8e05e87a89b222a2d3c6ced2781 |
| parent | b4a0a082dca22b47fe394908c44eec7102def417 |
Backends can instead ask legalization on a per-instruction basis.15 files changed, 224 insertions(+), 197 deletions(-)
src/Air/Legalize.zig+13-6| ... | ... | @@ -42,6 +42,7 @@ pub const Feature = enum { |
| 42 | 42 | scalarize_shl_sat, |
| 43 | 43 | scalarize_xor, |
| 44 | 44 | scalarize_not, |
| 45 | scalarize_bitcast, | |
| 45 | 46 | scalarize_clz, |
| 46 | 47 | scalarize_ctz, |
| 47 | 48 | scalarize_popcount, |
| ... | ... | @@ -76,7 +77,7 @@ pub const Feature = enum { |
| 76 | 77 | scalarize_mul_add, |
| 77 | 78 | |
| 78 | 79 | /// Legalize (shift lhs, (splat rhs)) -> (shift lhs, rhs) |
| 79 | remove_shift_vector_rhs_splat, | |
| 80 | unsplat_shift_rhs, | |
| 80 | 81 | /// Legalize reduce of a one element vector to a bitcast |
| 81 | 82 | reduce_one_elem_to_bitcast, |
| 82 | 83 | |
| ... | ... | @@ -121,6 +122,7 @@ pub const Feature = enum { |
| 121 | 122 | .shl_sat => .scalarize_shl_sat, |
| 122 | 123 | .xor => .scalarize_xor, |
| 123 | 124 | .not => .scalarize_not, |
| 125 | .bitcast => .scalarize_bitcast, | |
| 124 | 126 | .clz => .scalarize_clz, |
| 125 | 127 | .ctz => .scalarize_ctz, |
| 126 | 128 | .popcount => .scalarize_popcount, |
| ... | ... | @@ -259,9 +261,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { |
| 259 | 261 | => |air_tag| done: { |
| 260 | 262 | const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 261 | 263 | if (!l.typeOf(bin_op.rhs).isVector(zcu)) break :done; |
| 262 | if (l.features.contains(comptime .scalarize(air_tag))) { | |
| 263 | continue :inst try l.scalarize(inst, .bin_op); | |
| 264 | } else if (l.features.contains(.remove_shift_vector_rhs_splat)) { | |
| 264 | if (l.features.contains(.unsplat_shift_rhs)) { | |
| 265 | 265 | if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) { |
| 266 | 266 | else => {}, |
| 267 | 267 | .aggregate => |aggregate| switch (aggregate.storage) { |
| ... | ... | @@ -282,6 +282,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { |
| 282 | 282 | } |
| 283 | 283 | } |
| 284 | 284 | } |
| 285 | if (l.features.contains(comptime .scalarize(air_tag))) continue :inst try l.scalarize(inst, .bin_op); | |
| 285 | 286 | }, |
| 286 | 287 | inline .not, |
| 287 | 288 | .clz, |
| ... | ... | @@ -302,8 +303,14 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { |
| 302 | 303 | const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 303 | 304 | if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op); |
| 304 | 305 | }, |
| 305 | .bitcast, | |
| 306 | => {}, | |
| 306 | inline .bitcast, | |
| 307 | => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) { | |
| 308 | const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op; | |
| 309 | const to_ty = ty_op.ty.toType(); | |
| 310 | const from_ty = l.typeOf(ty_op.operand); | |
| 311 | if (to_ty.isVector(zcu) and from_ty.isVector(zcu) and to_ty.vectorLen(zcu) == from_ty.vectorLen(zcu)) | |
| 312 | continue :inst try l.scalarize(inst, .ty_op); | |
| 313 | }, | |
| 307 | 314 | .block, |
| 308 | 315 | .loop, |
| 309 | 316 | => { |
src/Sema.zig+47-140| ... | ... | @@ -10165,16 +10165,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10165 | 10165 | try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src); |
| 10166 | 10166 | try sema.validateRuntimeValue(block, ptr_src, operand); |
| 10167 | 10167 | try sema.checkLogicalPtrOperation(block, ptr_src, ptr_ty); |
| 10168 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 10169 | return block.addBitCast(dest_ty, operand); | |
| 10170 | } | |
| 10171 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); | |
| 10172 | for (new_elems, 0..) |*new_elem, i| { | |
| 10173 | const idx_ref = try pt.intRef(.usize, i); | |
| 10174 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); | |
| 10175 | new_elem.* = try block.addBitCast(.usize, old_elem); | |
| 10176 | } | |
| 10177 | return block.addAggregateInit(dest_ty, new_elems); | |
| 10168 | return block.addBitCast(dest_ty, operand); | |
| 10178 | 10169 | } |
| 10179 | 10170 | |
| 10180 | 10171 | fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -10640,17 +10631,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 10640 | 10631 | if (dst_bits >= src_bits) { |
| 10641 | 10632 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 10642 | 10633 | } |
| 10643 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 10644 | return block.addTyOp(.fptrunc, dest_ty, operand); | |
| 10645 | } | |
| 10646 | const vec_len = operand_ty.vectorLen(zcu); | |
| 10647 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, vec_len); | |
| 10648 | for (new_elems, 0..) |*new_elem, i| { | |
| 10649 | const idx_ref = try pt.intRef(.usize, i); | |
| 10650 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); | |
| 10651 | new_elem.* = try block.addTyOp(.fptrunc, dest_scalar_ty, old_elem); | |
| 10652 | } | |
| 10653 | return block.addAggregateInit(dest_ty, new_elems); | |
| 10634 | return block.addTyOp(.fptrunc, dest_ty, operand); | |
| 10654 | 10635 | } |
| 10655 | 10636 | |
| 10656 | 10637 | fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -20722,16 +20703,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 20722 | 20703 | .storage = .{ .elems = new_elems }, |
| 20723 | 20704 | } })); |
| 20724 | 20705 | } |
| 20725 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 20726 | return block.addBitCast(dest_ty, operand); | |
| 20727 | } | |
| 20728 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); | |
| 20729 | for (new_elems, 0..) |*new_elem, i| { | |
| 20730 | const idx_ref = try pt.intRef(.usize, i); | |
| 20731 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); | |
| 20732 | new_elem.* = try block.addBitCast(.u1, old_elem); | |
| 20733 | } | |
| 20734 | return block.addAggregateInit(dest_ty, new_elems); | |
| 20706 | return block.addBitCast(dest_ty, operand); | |
| 20735 | 20707 | } |
| 20736 | 20708 | |
| 20737 | 20709 | fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -22327,42 +22299,23 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 22327 | 22299 | .storage = .{ .repeated_elem = (try pt.intValue(dest_scalar_ty, 0)).toIntern() }, |
| 22328 | 22300 | } })); |
| 22329 | 22301 | } |
| 22330 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 22331 | const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand); | |
| 22332 | if (block.wantSafety()) { | |
| 22333 | const back = try block.addTyOp(.float_from_int, operand_ty, result); | |
| 22334 | const diff = try block.addBinOp(if (block.float_mode == .optimized) .sub_optimized else .sub, operand, back); | |
| 22335 | const ok = if (is_vector) ok: { | |
| 22336 | const ok_pos = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, 1.0))).toIntern()), .lt); | |
| 22337 | const ok_neg = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, -1.0))).toIntern()), .gt); | |
| 22338 | const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg); | |
| 22339 | break :ok try block.addReduce(ok, .And); | |
| 22340 | } else ok: { | |
| 22341 | const ok_pos = try block.addBinOp(if (block.float_mode == .optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try pt.floatValue(operand_ty, 1.0)).toIntern())); | |
| 22342 | const ok_neg = try block.addBinOp(if (block.float_mode == .optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try pt.floatValue(operand_ty, -1.0)).toIntern())); | |
| 22343 | break :ok try block.addBinOp(.bool_and, ok_pos, ok_neg); | |
| 22344 | }; | |
| 22345 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); | |
| 22346 | } | |
| 22347 | return result; | |
| 22348 | } | |
| 22349 | const len = dest_ty.vectorLen(zcu); | |
| 22350 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); | |
| 22351 | for (new_elems, 0..) |*new_elem, i| { | |
| 22352 | const idx_ref = try pt.intRef(.usize, i); | |
| 22353 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); | |
| 22354 | const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_scalar_ty, old_elem); | |
| 22355 | if (block.wantSafety()) { | |
| 22356 | const back = try block.addTyOp(.float_from_int, operand_scalar_ty, result); | |
| 22357 | const diff = try block.addBinOp(.sub, old_elem, back); | |
| 22358 | const ok_pos = try block.addBinOp(if (block.float_mode == .optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try pt.floatValue(operand_scalar_ty, 1.0)).toIntern())); | |
| 22359 | const ok_neg = try block.addBinOp(if (block.float_mode == .optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try pt.floatValue(operand_scalar_ty, -1.0)).toIntern())); | |
| 22360 | const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg); | |
| 22361 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); | |
| 22362 | } | |
| 22363 | new_elem.* = result; | |
| 22302 | const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand); | |
| 22303 | if (block.wantSafety()) { | |
| 22304 | const back = try block.addTyOp(.float_from_int, operand_ty, result); | |
| 22305 | const diff = try block.addBinOp(if (block.float_mode == .optimized) .sub_optimized else .sub, operand, back); | |
| 22306 | const ok = if (is_vector) ok: { | |
| 22307 | const ok_pos = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, 1.0))).toIntern()), .lt); | |
| 22308 | const ok_neg = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, -1.0))).toIntern()), .gt); | |
| 22309 | const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg); | |
| 22310 | break :ok try block.addReduce(ok, .And); | |
| 22311 | } else ok: { | |
| 22312 | const ok_pos = try block.addBinOp(if (block.float_mode == .optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try pt.floatValue(operand_ty, 1.0)).toIntern())); | |
| 22313 | const ok_neg = try block.addBinOp(if (block.float_mode == .optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try pt.floatValue(operand_ty, -1.0)).toIntern())); | |
| 22314 | break :ok try block.addBinOp(.bool_and, ok_pos, ok_neg); | |
| 22315 | }; | |
| 22316 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); | |
| 22364 | 22317 | } |
| 22365 | return block.addAggregateInit(dest_ty, new_elems); | |
| 22318 | return result; | |
| 22366 | 22319 | } |
| 22367 | 22320 | |
| 22368 | 22321 | fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -22377,7 +22330,6 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 22377 | 22330 | const operand_ty = sema.typeOf(operand); |
| 22378 | 22331 | |
| 22379 | 22332 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); |
| 22380 | const is_vector = dest_ty.zigTypeTag(zcu) == .vector; | |
| 22381 | 22333 | |
| 22382 | 22334 | const dest_scalar_ty = dest_ty.scalarType(zcu); |
| 22383 | 22335 | const operand_scalar_ty = operand_ty.scalarType(zcu); |
| ... | ... | @@ -22393,17 +22345,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 22393 | 22345 | } |
| 22394 | 22346 | |
| 22395 | 22347 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 22396 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 22397 | return block.addTyOp(.float_from_int, dest_ty, operand); | |
| 22398 | } | |
| 22399 | const len = operand_ty.vectorLen(zcu); | |
| 22400 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); | |
| 22401 | for (new_elems, 0..) |*new_elem, i| { | |
| 22402 | const idx_ref = try pt.intRef(.usize, i); | |
| 22403 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); | |
| 22404 | new_elem.* = try block.addTyOp(.float_from_int, dest_scalar_ty, old_elem); | |
| 22405 | } | |
| 22406 | return block.addAggregateInit(dest_ty, new_elems); | |
| 22348 | return block.addTyOp(.float_from_int, dest_ty, operand); | |
| 22407 | 22349 | } |
| 22408 | 22350 | |
| 22409 | 22351 | fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -22473,69 +22415,34 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 22473 | 22415 | } |
| 22474 | 22416 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 22475 | 22417 | try sema.checkLogicalPtrOperation(block, src, ptr_ty); |
| 22476 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 22477 | if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) { | |
| 22478 | if (!ptr_ty.isAllowzeroPtr(zcu)) { | |
| 22479 | const is_non_zero = if (is_vector) all_non_zero: { | |
| 22480 | const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); | |
| 22481 | const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq); | |
| 22482 | break :all_non_zero try block.addReduce(is_non_zero, .And); | |
| 22483 | } else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize); | |
| 22484 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | |
| 22485 | } | |
| 22486 | if (ptr_align.compare(.gt, .@"1")) { | |
| 22487 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; | |
| 22488 | const align_mask = Air.internedToRef((try sema.splat(operand_ty, try pt.intValue( | |
| 22489 | .usize, | |
| 22490 | if (elem_ty.fnPtrMaskOrNull(zcu)) |mask| | |
| 22491 | align_bytes_minus_1 & mask | |
| 22492 | else | |
| 22493 | align_bytes_minus_1, | |
| 22494 | ))).toIntern()); | |
| 22495 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_mask); | |
| 22496 | const is_aligned = if (is_vector) all_aligned: { | |
| 22497 | const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); | |
| 22498 | const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq); | |
| 22499 | break :all_aligned try block.addReduce(is_aligned, .And); | |
| 22500 | } else try block.addBinOp(.cmp_eq, remainder, .zero_usize); | |
| 22501 | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); | |
| 22502 | } | |
| 22503 | } | |
| 22504 | return block.addBitCast(dest_ty, operand_coerced); | |
| 22505 | } | |
| 22506 | ||
| 22507 | const len = dest_ty.vectorLen(zcu); | |
| 22508 | 22418 | if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) { |
| 22509 | for (0..len) |i| { | |
| 22510 | const idx_ref = try pt.intRef(.usize, i); | |
| 22511 | const elem_coerced = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref); | |
| 22512 | if (!ptr_ty.isAllowzeroPtr(zcu)) { | |
| 22513 | const is_non_zero = try block.addBinOp(.cmp_neq, elem_coerced, .zero_usize); | |
| 22514 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | |
| 22515 | } | |
| 22516 | if (ptr_align.compare(.gt, .@"1")) { | |
| 22517 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; | |
| 22518 | const align_mask = Air.internedToRef((try pt.intValue( | |
| 22519 | .usize, | |
| 22520 | if (elem_ty.fnPtrMaskOrNull(zcu)) |mask| | |
| 22521 | align_bytes_minus_1 & mask | |
| 22522 | else | |
| 22523 | align_bytes_minus_1, | |
| 22524 | )).toIntern()); | |
| 22525 | const remainder = try block.addBinOp(.bit_and, elem_coerced, align_mask); | |
| 22526 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); | |
| 22527 | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); | |
| 22528 | } | |
| 22529 | } | |
| 22530 | } | |
| 22531 | ||
| 22532 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); | |
| 22533 | for (new_elems, 0..) |*new_elem, i| { | |
| 22534 | const idx_ref = try pt.intRef(.usize, i); | |
| 22535 | const old_elem = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref); | |
| 22536 | new_elem.* = try block.addBitCast(ptr_ty, old_elem); | |
| 22537 | } | |
| 22538 | return block.addAggregateInit(dest_ty, new_elems); | |
| 22419 | if (!ptr_ty.isAllowzeroPtr(zcu)) { | |
| 22420 | const is_non_zero = if (is_vector) all_non_zero: { | |
| 22421 | const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); | |
| 22422 | const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq); | |
| 22423 | break :all_non_zero try block.addReduce(is_non_zero, .And); | |
| 22424 | } else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize); | |
| 22425 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | |
| 22426 | } | |
| 22427 | if (ptr_align.compare(.gt, .@"1")) { | |
| 22428 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; | |
| 22429 | const align_mask = Air.internedToRef((try sema.splat(operand_ty, try pt.intValue( | |
| 22430 | .usize, | |
| 22431 | if (elem_ty.fnPtrMaskOrNull(zcu)) |mask| | |
| 22432 | align_bytes_minus_1 & mask | |
| 22433 | else | |
| 22434 | align_bytes_minus_1, | |
| 22435 | ))).toIntern()); | |
| 22436 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_mask); | |
| 22437 | const is_aligned = if (is_vector) all_aligned: { | |
| 22438 | const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); | |
| 22439 | const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq); | |
| 22440 | break :all_aligned try block.addReduce(is_aligned, .And); | |
| 22441 | } else try block.addBinOp(.cmp_eq, remainder, .zero_usize); | |
| 22442 | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); | |
| 22443 | } | |
| 22444 | } | |
| 22445 | return block.addBitCast(dest_ty, operand_coerced); | |
| 22539 | 22446 | } |
| 22540 | 22447 | |
| 22541 | 22448 | fn ptrFromIntVal( |
src/Zcu.zig-9| ... | ... | @@ -3840,15 +3840,6 @@ pub const Feature = enum { |
| 3840 | 3840 | safety_checked_instructions, |
| 3841 | 3841 | /// If the backend supports running from another thread. |
| 3842 | 3842 | separate_thread, |
| 3843 | /// If the backend supports the following AIR instructions with vector types: | |
| 3844 | /// * `Air.Inst.Tag.bit_and` | |
| 3845 | /// * `Air.Inst.Tag.bit_or` | |
| 3846 | /// * `Air.Inst.Tag.bitcast` | |
| 3847 | /// * `Air.Inst.Tag.float_from_int` | |
| 3848 | /// * `Air.Inst.Tag.fptrunc` | |
| 3849 | /// * `Air.Inst.Tag.int_from_float` | |
| 3850 | /// If not supported, Sema will scalarize the operation. | |
| 3851 | all_vector_instructions, | |
| 3852 | 3843 | }; |
| 3853 | 3844 | |
| 3854 | 3845 | pub fn backendSupportsFeature(zcu: *const Zcu, comptime feature: Feature) bool { |
src/arch/aarch64/CodeGen.zig+23-6| ... | ... | @@ -40,6 +40,10 @@ const gp = abi.RegisterClass.gp; |
| 40 | 40 | |
| 41 | 41 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 42 | 42 | |
| 43 | pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 44 | return comptime &.initEmpty(); | |
| 45 | } | |
| 46 | ||
| 43 | 47 | gpa: Allocator, |
| 44 | 48 | pt: Zcu.PerThread, |
| 45 | 49 | air: Air, |
| ... | ... | @@ -2261,12 +2265,13 @@ fn shiftExact( |
| 2261 | 2265 | rhs_ty: Type, |
| 2262 | 2266 | maybe_inst: ?Air.Inst.Index, |
| 2263 | 2267 | ) InnerError!MCValue { |
| 2264 | _ = rhs_ty; | |
| 2265 | ||
| 2266 | 2268 | const pt = self.pt; |
| 2267 | 2269 | const zcu = pt.zcu; |
| 2268 | 2270 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 2269 | .vector => return self.fail("TODO binary operations on vectors", .{}), | |
| 2271 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 2272 | return self.fail("TODO vector shift with scalar rhs", .{}) | |
| 2273 | else | |
| 2274 | return self.fail("TODO binary operations on vectors", .{}), | |
| 2270 | 2275 | .int => { |
| 2271 | 2276 | const int_info = lhs_ty.intInfo(zcu); |
| 2272 | 2277 | if (int_info.bits <= 64) { |
| ... | ... | @@ -2317,7 +2322,10 @@ fn shiftNormal( |
| 2317 | 2322 | const pt = self.pt; |
| 2318 | 2323 | const zcu = pt.zcu; |
| 2319 | 2324 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 2320 | .vector => return self.fail("TODO binary operations on vectors", .{}), | |
| 2325 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 2326 | return self.fail("TODO vector shift with scalar rhs", .{}) | |
| 2327 | else | |
| 2328 | return self.fail("TODO binary operations on vectors", .{}), | |
| 2321 | 2329 | .int => { |
| 2322 | 2330 | const int_info = lhs_ty.intInfo(zcu); |
| 2323 | 2331 | if (int_info.bits <= 64) { |
| ... | ... | @@ -2874,7 +2882,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 2874 | 2882 | const overflow_bit_offset = @as(u32, @intCast(tuple_ty.structFieldOffset(1, zcu))); |
| 2875 | 2883 | |
| 2876 | 2884 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 2877 | .vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}), | |
| 2885 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 2886 | return self.fail("TODO implement vector shl_with_overflow with scalar rhs", .{}) | |
| 2887 | else | |
| 2888 | return self.fail("TODO implement shl_with_overflow for vectors", .{}), | |
| 2878 | 2889 | .int => { |
| 2879 | 2890 | const int_info = lhs_ty.intInfo(zcu); |
| 2880 | 2891 | if (int_info.bits <= 64) { |
| ... | ... | @@ -2993,8 +3004,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 2993 | 3004 | } |
| 2994 | 3005 | |
| 2995 | 3006 | fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 3007 | const zcu = self.pt.zcu; | |
| 2996 | 3008 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 2997 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 3009 | const result: MCValue = if (self.liveness.isUnused(inst)) | |
| 3010 | .dead | |
| 3011 | else if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 3012 | return self.fail("TODO implement vector shl_sat with scalar rhs for {}", .{self.target.cpu.arch}) | |
| 3013 | else | |
| 3014 | return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 2998 | 3015 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2999 | 3016 | } |
| 3000 | 3017 |
src/arch/arm/CodeGen.zig+23-4| ... | ... | @@ -41,6 +41,10 @@ const gp = abi.RegisterClass.gp; |
| 41 | 41 | |
| 42 | 42 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 43 | 43 | |
| 44 | pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 45 | return comptime &.initEmpty(); | |
| 46 | } | |
| 47 | ||
| 44 | 48 | gpa: Allocator, |
| 45 | 49 | pt: Zcu.PerThread, |
| 46 | 50 | air: Air, |
| ... | ... | @@ -1857,7 +1861,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1857 | 1861 | const overflow_bit_offset: u32 = @intCast(tuple_ty.structFieldOffset(1, zcu)); |
| 1858 | 1862 | |
| 1859 | 1863 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 1860 | .vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}), | |
| 1864 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 1865 | return self.fail("TODO implement vector shl_with_overflow with scalar rhs", .{}) | |
| 1866 | else | |
| 1867 | return self.fail("TODO implement shl_with_overflow for vectors", .{}), | |
| 1861 | 1868 | .int => { |
| 1862 | 1869 | const int_info = lhs_ty.intInfo(zcu); |
| 1863 | 1870 | if (int_info.bits <= 32) { |
| ... | ... | @@ -1978,8 +1985,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1978 | 1985 | } |
| 1979 | 1986 | |
| 1980 | 1987 | fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1988 | const zcu = self.pt.zcu; | |
| 1981 | 1989 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 1982 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 1990 | const result: MCValue = if (self.liveness.isUnused(inst)) | |
| 1991 | .dead | |
| 1992 | else if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 1993 | return self.fail("TODO implement vector shl_sat with scalar rhs for {}", .{self.target.cpu.arch}) | |
| 1994 | else | |
| 1995 | return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 1983 | 1996 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1984 | 1997 | } |
| 1985 | 1998 | |
| ... | ... | @@ -3788,7 +3801,10 @@ fn shiftExact( |
| 3788 | 3801 | const pt = self.pt; |
| 3789 | 3802 | const zcu = pt.zcu; |
| 3790 | 3803 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 3791 | .vector => return self.fail("TODO ARM binary operations on vectors", .{}), | |
| 3804 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 3805 | return self.fail("TODO ARM vector shift with scalar rhs", .{}) | |
| 3806 | else | |
| 3807 | return self.fail("TODO ARM binary operations on vectors", .{}), | |
| 3792 | 3808 | .int => { |
| 3793 | 3809 | const int_info = lhs_ty.intInfo(zcu); |
| 3794 | 3810 | if (int_info.bits <= 32) { |
| ... | ... | @@ -3828,7 +3844,10 @@ fn shiftNormal( |
| 3828 | 3844 | const pt = self.pt; |
| 3829 | 3845 | const zcu = pt.zcu; |
| 3830 | 3846 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 3831 | .vector => return self.fail("TODO ARM binary operations on vectors", .{}), | |
| 3847 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 3848 | return self.fail("TODO ARM vector shift with scalar rhs", .{}) | |
| 3849 | else | |
| 3850 | return self.fail("TODO ARM binary operations on vectors", .{}), | |
| 3832 | 3851 | .int => { |
| 3833 | 3852 | const int_info = lhs_ty.intInfo(zcu); |
| 3834 | 3853 | if (int_info.bits <= 32) { |
src/arch/powerpc/CodeGen.zig+4| ... | ... | @@ -10,6 +10,10 @@ const Zcu = @import("../../Zcu.zig"); |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | 11 | const log = std.log.scoped(.codegen); |
| 12 | 12 | |
| 13 | pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 14 | return comptime &.initEmpty(); | |
| 15 | } | |
| 16 | ||
| 13 | 17 | pub fn generate( |
| 14 | 18 | bin_file: *link.File, |
| 15 | 19 | pt: Zcu.PerThread, |
src/arch/riscv64/CodeGen.zig+19-2| ... | ... | @@ -51,6 +51,10 @@ const Instruction = encoding.Instruction; |
| 51 | 51 | |
| 52 | 52 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 53 | 53 | |
| 54 | pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 55 | return comptime &.initEmpty(); | |
| 56 | } | |
| 57 | ||
| 54 | 58 | pt: Zcu.PerThread, |
| 55 | 59 | air: Air, |
| 56 | 60 | liveness: Air.Liveness, |
| ... | ... | @@ -2764,6 +2768,7 @@ fn genBinOp( |
| 2764 | 2768 | .shl, |
| 2765 | 2769 | .shl_exact, |
| 2766 | 2770 | => { |
| 2771 | if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) return func.fail("TODO: vector shift with scalar rhs", .{}); | |
| 2767 | 2772 | if (bit_size > 64) return func.fail("TODO: genBinOp shift > 64 bits, {}", .{bit_size}); |
| 2768 | 2773 | try func.truncateRegister(rhs_ty, rhs_reg); |
| 2769 | 2774 | |
| ... | ... | @@ -3248,8 +3253,14 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3248 | 3253 | } |
| 3249 | 3254 | |
| 3250 | 3255 | fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3256 | const zcu = func.pt.zcu; | |
| 3251 | 3257 | const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3252 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShlWithOverflow", .{}); | |
| 3258 | const result: MCValue = if (func.liveness.isUnused(inst)) | |
| 3259 | .unreach | |
| 3260 | else if (func.typeOf(bin_op.lhs).isVector(zcu) and !func.typeOf(bin_op.rhs).isVector(zcu)) | |
| 3261 | return func.fail("TODO implement vector airShlWithOverflow with scalar rhs", .{}) | |
| 3262 | else | |
| 3263 | return func.fail("TODO implement airShlWithOverflow", .{}); | |
| 3253 | 3264 | return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 3254 | 3265 | } |
| 3255 | 3266 | |
| ... | ... | @@ -3266,8 +3277,14 @@ fn airMulSat(func: *Func, inst: Air.Inst.Index) !void { |
| 3266 | 3277 | } |
| 3267 | 3278 | |
| 3268 | 3279 | fn airShlSat(func: *Func, inst: Air.Inst.Index) !void { |
| 3280 | const zcu = func.pt.zcu; | |
| 3269 | 3281 | const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3270 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShlSat", .{}); | |
| 3282 | const result: MCValue = if (func.liveness.isUnused(inst)) | |
| 3283 | .unreach | |
| 3284 | else if (func.typeOf(bin_op.lhs).isVector(zcu) and !func.typeOf(bin_op.rhs).isVector(zcu)) | |
| 3285 | return func.fail("TODO implement vector airShlSat with scalar rhs", .{}) | |
| 3286 | else | |
| 3287 | return func.fail("TODO implement airShlSat", .{}); | |
| 3271 | 3288 | return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 3272 | 3289 | } |
| 3273 | 3290 |
src/arch/sparc64/CodeGen.zig+23-4| ... | ... | @@ -41,6 +41,10 @@ const Self = @This(); |
| 41 | 41 | |
| 42 | 42 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 43 | 43 | |
| 44 | pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 45 | return comptime &.initEmpty(); | |
| 46 | } | |
| 47 | ||
| 44 | 48 | const RegisterView = enum(u1) { |
| 45 | 49 | caller, |
| 46 | 50 | callee, |
| ... | ... | @@ -2270,8 +2274,14 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 2270 | 2274 | } |
| 2271 | 2275 | |
| 2272 | 2276 | fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2277 | const zcu = self.pt.zcu; | |
| 2273 | 2278 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 2274 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 2279 | const result: MCValue = if (self.liveness.isUnused(inst)) | |
| 2280 | .dead | |
| 2281 | else if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 2282 | return self.fail("TODO implement vector shl_sat with scalar rhs for {}", .{self.target.cpu.arch}) | |
| 2283 | else | |
| 2284 | return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 2275 | 2285 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2276 | 2286 | } |
| 2277 | 2287 | |
| ... | ... | @@ -2287,7 +2297,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2287 | 2297 | const rhs_ty = self.typeOf(extra.rhs); |
| 2288 | 2298 | |
| 2289 | 2299 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 2290 | .vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), | |
| 2300 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 2301 | return self.fail("TODO implement vector shl_with_overflow with scalar rhs", .{}) | |
| 2302 | else | |
| 2303 | return self.fail("TODO implement mul_with_overflow for vectors", .{}), | |
| 2291 | 2304 | .int => { |
| 2292 | 2305 | const int_info = lhs_ty.intInfo(zcu); |
| 2293 | 2306 | if (int_info.bits <= 64) { |
| ... | ... | @@ -3002,7 +3015,10 @@ fn binOp( |
| 3002 | 3015 | |
| 3003 | 3016 | // Truncate if necessary |
| 3004 | 3017 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 3005 | .vector => return self.fail("TODO binary operations on vectors", .{}), | |
| 3018 | .vector => if (rhs_ty.isVector(zcu)) | |
| 3019 | return self.fail("TODO vector shift with scalar rhs", .{}) | |
| 3020 | else | |
| 3021 | return self.fail("TODO binary operations on vectors", .{}), | |
| 3006 | 3022 | .int => { |
| 3007 | 3023 | const int_info = lhs_ty.intInfo(zcu); |
| 3008 | 3024 | if (int_info.bits <= 64) { |
| ... | ... | @@ -3024,7 +3040,10 @@ fn binOp( |
| 3024 | 3040 | .shr_exact, |
| 3025 | 3041 | => { |
| 3026 | 3042 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 3027 | .vector => return self.fail("TODO binary operations on vectors", .{}), | |
| 3043 | .vector => if (rhs_ty.isVector(zcu)) | |
| 3044 | return self.fail("TODO vector shift with scalar rhs", .{}) | |
| 3045 | else | |
| 3046 | return self.fail("TODO binary operations on vectors", .{}), | |
| 3028 | 3047 | .int => { |
| 3029 | 3048 | const int_info = lhs_ty.intInfo(zcu); |
| 3030 | 3049 | if (int_info.bits <= 64) { |
src/arch/wasm/CodeGen.zig+26-5| ... | ... | @@ -31,6 +31,10 @@ const libcFloatSuffix = target_util.libcFloatSuffix; |
| 31 | 31 | const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev; |
| 32 | 32 | const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; |
| 33 | 33 | |
| 34 | pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 35 | return comptime &.initEmpty(); | |
| 36 | } | |
| 37 | ||
| 34 | 38 | /// Reference to the function declaration the code |
| 35 | 39 | /// section belongs to |
| 36 | 40 | owner_nav: InternPool.Nav.Index, |
| ... | ... | @@ -2638,6 +2642,10 @@ fn airBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 2638 | 2642 | // For big integers we can ignore this as we will call into compiler-rt which handles this. |
| 2639 | 2643 | const result = switch (op) { |
| 2640 | 2644 | .shr, .shl => result: { |
| 2645 | if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) { | |
| 2646 | return cg.fail("TODO: implement vector '{s}' with scalar rhs", .{@tagName(op)}); | |
| 2647 | } | |
| 2648 | ||
| 2641 | 2649 | const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(zcu))) orelse { |
| 2642 | 2650 | return cg.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)}); |
| 2643 | 2651 | }; |
| ... | ... | @@ -3055,8 +3063,12 @@ fn airWrapBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 3055 | 3063 | const lhs_ty = cg.typeOf(bin_op.lhs); |
| 3056 | 3064 | const rhs_ty = cg.typeOf(bin_op.rhs); |
| 3057 | 3065 | |
| 3058 | if (lhs_ty.zigTypeTag(zcu) == .vector or rhs_ty.zigTypeTag(zcu) == .vector) { | |
| 3059 | return cg.fail("TODO: Implement wrapping arithmetic for vectors", .{}); | |
| 3066 | if (lhs_ty.isVector(zcu)) { | |
| 3067 | if ((op == .shr or op == .shl) and !rhs_ty.isVector(zcu)) { | |
| 3068 | return cg.fail("TODO: implement wrapping vector '{s}' with scalar rhs", .{@tagName(op)}); | |
| 3069 | } else { | |
| 3070 | return cg.fail("TODO: implement wrapping '{s}' for vectors", .{@tagName(op)}); | |
| 3071 | } | |
| 3060 | 3072 | } |
| 3061 | 3073 | |
| 3062 | 3074 | // For certain operations, such as shifting, the types are different. |
| ... | ... | @@ -6067,13 +6079,17 @@ fn airShlWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6067 | 6079 | const ty = cg.typeOf(extra.lhs); |
| 6068 | 6080 | const rhs_ty = cg.typeOf(extra.rhs); |
| 6069 | 6081 | |
| 6070 | if (ty.zigTypeTag(zcu) == .vector) { | |
| 6071 | return cg.fail("TODO: Implement overflow arithmetic for vectors", .{}); | |
| 6082 | if (ty.isVector(zcu)) { | |
| 6083 | if (!rhs_ty.isVector(zcu)) { | |
| 6084 | return cg.fail("TODO: implement vector 'shl_with_overflow' with scalar rhs", .{}); | |
| 6085 | } else { | |
| 6086 | return cg.fail("TODO: implement vector 'shl_with_overflow'", .{}); | |
| 6087 | } | |
| 6072 | 6088 | } |
| 6073 | 6089 | |
| 6074 | 6090 | const int_info = ty.intInfo(zcu); |
| 6075 | 6091 | const wasm_bits = toWasmBits(int_info.bits) orelse { |
| 6076 | return cg.fail("TODO: Implement shl_with_overflow for integer bitsize: {d}", .{int_info.bits}); | |
| 6092 | return cg.fail("TODO: implement 'shl_with_overflow' for integer bitsize: {d}", .{int_info.bits}); | |
| 6077 | 6093 | }; |
| 6078 | 6094 | |
| 6079 | 6095 | // Ensure rhs is coerced to lhs as they must have the same WebAssembly types |
| ... | ... | @@ -6994,6 +7010,11 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6994 | 7010 | |
| 6995 | 7011 | const pt = cg.pt; |
| 6996 | 7012 | const zcu = pt.zcu; |
| 7013 | ||
| 7014 | if (cg.typeOf(bin_op.lhs).isVector(zcu) and !cg.typeOf(bin_op.rhs).isVector(zcu)) { | |
| 7015 | return cg.fail("TODO: implement vector 'shl_sat' with scalar rhs", .{}); | |
| 7016 | } | |
| 7017 | ||
| 6997 | 7018 | const ty = cg.typeOfIndex(inst); |
| 6998 | 7019 | const int_info = ty.intInfo(zcu); |
| 6999 | 7020 | const is_signed = int_info.signedness == .signed; |
src/arch/x86_64/CodeGen.zig+2-2| ... | ... | @@ -32,7 +32,7 @@ const FrameIndex = bits.FrameIndex; |
| 32 | 32 | |
| 33 | 33 | const InnerError = codegen.CodeGenError || error{OutOfRegisters}; |
| 34 | 34 | |
| 35 | pub inline fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features { | |
| 35 | pub fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features { | |
| 36 | 36 | @setEvalBranchQuota(1_200); |
| 37 | 37 | return switch (target.ofmt == .coff) { |
| 38 | 38 | inline false, true => |use_old| comptime &.init(.{ |
| ... | ... | @@ -86,7 +86,7 @@ pub inline fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Fe |
| 86 | 86 | .scalarize_float_from_int = use_old, |
| 87 | 87 | .scalarize_mul_add = use_old, |
| 88 | 88 | |
| 89 | .remove_shift_vector_rhs_splat = false, | |
| 89 | .unsplat_shift_rhs = false, | |
| 90 | 90 | .reduce_one_elem_to_bitcast = true, |
| 91 | 91 | }), |
| 92 | 92 | }; |
src/codegen.zig+3-6| ... | ... | @@ -52,7 +52,7 @@ fn importBackend(comptime backend: std.builtin.CompilerBackend) type { |
| 52 | 52 | pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *const Air.Legalize.Features { |
| 53 | 53 | const zcu = pt.zcu; |
| 54 | 54 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; |
| 55 | switch (target_util.zigBackend(target.*, zcu.comp.config.use_llvm)) { | |
| 55 | return switch (target_util.zigBackend(target.*, zcu.comp.config.use_llvm)) { | |
| 56 | 56 | else => unreachable, |
| 57 | 57 | inline .stage2_llvm, |
| 58 | 58 | .stage2_c, |
| ... | ... | @@ -65,11 +65,8 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *con |
| 65 | 65 | .stage2_sparc64, |
| 66 | 66 | .stage2_spirv64, |
| 67 | 67 | .stage2_powerpc, |
| 68 | => |backend| { | |
| 69 | const Backend = importBackend(backend); | |
| 70 | return if (@hasDecl(Backend, "legalizeFeatures")) Backend.legalizeFeatures(target) else comptime &.initEmpty(); | |
| 71 | }, | |
| 72 | } | |
| 68 | => |backend| importBackend(backend).legalizeFeatures(target), | |
| 69 | }; | |
| 73 | 70 | } |
| 74 | 71 | |
| 75 | 72 | pub fn generateFunction( |
src/codegen/c.zig+6-2| ... | ... | @@ -20,6 +20,10 @@ const Alignment = InternPool.Alignment; |
| 20 | 20 | const BigIntLimb = std.math.big.Limb; |
| 21 | 21 | const BigInt = std.math.big.int; |
| 22 | 22 | |
| 23 | pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 24 | return comptime &.initEmpty(); | |
| 25 | } | |
| 26 | ||
| 23 | 27 | pub const CType = @import("c/Type.zig"); |
| 24 | 28 | |
| 25 | 29 | pub const CValue = union(enum) { |
| ... | ... | @@ -4179,7 +4183,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 4179 | 4183 | try v.elem(f, w); |
| 4180 | 4184 | try w.writeAll(", "); |
| 4181 | 4185 | try f.writeCValue(w, rhs, .FunctionArgument); |
| 4182 | try v.elem(f, w); | |
| 4186 | if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); | |
| 4183 | 4187 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); |
| 4184 | 4188 | try w.writeAll(");\n"); |
| 4185 | 4189 | try v.end(f, inst, w); |
| ... | ... | @@ -6536,7 +6540,7 @@ fn airBinBuiltinCall( |
| 6536 | 6540 | try v.elem(f, writer); |
| 6537 | 6541 | try writer.writeAll(", "); |
| 6538 | 6542 | try f.writeCValue(writer, rhs, .FunctionArgument); |
| 6539 | try v.elem(f, writer); | |
| 6543 | if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, writer); | |
| 6540 | 6544 | try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info); |
| 6541 | 6545 | try writer.writeAll(");\n"); |
| 6542 | 6546 | try v.end(f, inst, writer); |
src/codegen/llvm.zig+23-7| ... | ... | @@ -36,6 +36,10 @@ const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; |
| 36 | 36 | |
| 37 | 37 | const Error = error{ OutOfMemory, CodegenFail }; |
| 38 | 38 | |
| 39 | pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 40 | return comptime &.initEmpty(); | |
| 41 | } | |
| 42 | ||
| 39 | 43 | fn subArchName(features: std.Target.Cpu.Feature.Set, arch: anytype, mappings: anytype) ?[]const u8 { |
| 40 | 44 | inline for (mappings) |mapping| { |
| 41 | 45 | if (arch.featureSetHas(features, mapping[0])) return mapping[1]; |
| ... | ... | @@ -8923,6 +8927,8 @@ pub const FuncGen = struct { |
| 8923 | 8927 | const rhs = try self.resolveInst(extra.rhs); |
| 8924 | 8928 | |
| 8925 | 8929 | const lhs_ty = self.typeOf(extra.lhs); |
| 8930 | if (lhs_ty.isVector(zcu) and !self.typeOf(extra.rhs).isVector(zcu)) | |
| 8931 | return self.ng.todo("implement vector shifts with scalar rhs", .{}); | |
| 8926 | 8932 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); |
| 8927 | 8933 | |
| 8928 | 8934 | const dest_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -8992,6 +8998,8 @@ pub const FuncGen = struct { |
| 8992 | 8998 | const rhs = try self.resolveInst(bin_op.rhs); |
| 8993 | 8999 | |
| 8994 | 9000 | const lhs_ty = self.typeOf(bin_op.lhs); |
| 9001 | if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 9002 | return self.ng.todo("implement vector shifts with scalar rhs", .{}); | |
| 8995 | 9003 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); |
| 8996 | 9004 | |
| 8997 | 9005 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); |
| ... | ... | @@ -9003,14 +9011,17 @@ pub const FuncGen = struct { |
| 9003 | 9011 | |
| 9004 | 9012 | fn airShl(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9005 | 9013 | const o = self.ng.object; |
| 9014 | const zcu = o.pt.zcu; | |
| 9006 | 9015 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 9007 | 9016 | |
| 9008 | 9017 | const lhs = try self.resolveInst(bin_op.lhs); |
| 9009 | 9018 | const rhs = try self.resolveInst(bin_op.rhs); |
| 9010 | 9019 | |
| 9011 | const lhs_type = self.typeOf(bin_op.lhs); | |
| 9020 | const lhs_ty = self.typeOf(bin_op.lhs); | |
| 9021 | if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 9022 | return self.ng.todo("implement vector shifts with scalar rhs", .{}); | |
| 9012 | 9023 | |
| 9013 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_type), ""); | |
| 9024 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); | |
| 9014 | 9025 | return self.wip.bin(.shl, lhs, casted_rhs, ""); |
| 9015 | 9026 | } |
| 9016 | 9027 | |
| ... | ... | @@ -9029,6 +9040,8 @@ pub const FuncGen = struct { |
| 9029 | 9040 | const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder); |
| 9030 | 9041 | |
| 9031 | 9042 | const rhs_ty = self.typeOf(bin_op.rhs); |
| 9043 | if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) | |
| 9044 | return self.ng.todo("implement vector shifts with scalar rhs", .{}); | |
| 9032 | 9045 | const rhs_info = rhs_ty.intInfo(zcu); |
| 9033 | 9046 | assert(rhs_info.signedness == .unsigned); |
| 9034 | 9047 | const llvm_rhs_ty = try o.lowerType(rhs_ty); |
| ... | ... | @@ -9101,6 +9114,8 @@ pub const FuncGen = struct { |
| 9101 | 9114 | const rhs = try self.resolveInst(bin_op.rhs); |
| 9102 | 9115 | |
| 9103 | 9116 | const lhs_ty = self.typeOf(bin_op.lhs); |
| 9117 | if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 9118 | return self.ng.todo("implement vector shifts with scalar rhs", .{}); | |
| 9104 | 9119 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); |
| 9105 | 9120 | |
| 9106 | 9121 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); |
| ... | ... | @@ -9255,8 +9270,6 @@ pub const FuncGen = struct { |
| 9255 | 9270 | const operand_ty = self.typeOf(ty_op.operand); |
| 9256 | 9271 | const dest_ty = self.typeOfIndex(inst); |
| 9257 | 9272 | const target = zcu.getTarget(); |
| 9258 | const dest_bits = dest_ty.floatBits(target); | |
| 9259 | const src_bits = operand_ty.floatBits(target); | |
| 9260 | 9273 | |
| 9261 | 9274 | if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { |
| 9262 | 9275 | return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty), ""); |
| ... | ... | @@ -9264,6 +9277,8 @@ pub const FuncGen = struct { |
| 9264 | 9277 | const operand_llvm_ty = try o.lowerType(operand_ty); |
| 9265 | 9278 | const dest_llvm_ty = try o.lowerType(dest_ty); |
| 9266 | 9279 | |
| 9280 | const dest_bits = dest_ty.floatBits(target); | |
| 9281 | const src_bits = operand_ty.floatBits(target); | |
| 9267 | 9282 | const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{ |
| 9268 | 9283 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), |
| 9269 | 9284 | }); |
| ... | ... | @@ -9348,11 +9363,12 @@ pub const FuncGen = struct { |
| 9348 | 9363 | return self.wip.conv(.unsigned, operand, llvm_dest_ty, ""); |
| 9349 | 9364 | } |
| 9350 | 9365 | |
| 9351 | if (operand_ty.zigTypeTag(zcu) == .int and inst_ty.isPtrAtRuntime(zcu)) { | |
| 9366 | const operand_scalar_ty = operand_ty.scalarType(zcu); | |
| 9367 | const inst_scalar_ty = inst_ty.scalarType(zcu); | |
| 9368 | if (operand_scalar_ty.zigTypeTag(zcu) == .int and inst_scalar_ty.isPtrAtRuntime(zcu)) { | |
| 9352 | 9369 | return self.wip.cast(.inttoptr, operand, llvm_dest_ty, ""); |
| 9353 | 9370 | } |
| 9354 | ||
| 9355 | if (operand_ty.isPtrAtRuntime(zcu) and inst_ty.zigTypeTag(zcu) == .int) { | |
| 9371 | if (operand_scalar_ty.isPtrAtRuntime(zcu) and inst_scalar_ty.zigTypeTag(zcu) == .int) { | |
| 9356 | 9372 | return self.wip.cast(.ptrtoint, operand, llvm_dest_ty, ""); |
| 9357 | 9373 | } |
| 9358 | 9374 |
src/codegen/spirv.zig+12| ... | ... | @@ -28,6 +28,10 @@ const SpvAssembler = @import("spirv/Assembler.zig"); |
| 28 | 28 | |
| 29 | 29 | const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef); |
| 30 | 30 | |
| 31 | pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 32 | return comptime &.initEmpty(); | |
| 33 | } | |
| 34 | ||
| 31 | 35 | pub const zig_call_abi_ver = 3; |
| 32 | 36 | pub const big_int_bits = 32; |
| 33 | 37 | |
| ... | ... | @@ -3380,6 +3384,10 @@ const NavGen = struct { |
| 3380 | 3384 | const zcu = self.pt.zcu; |
| 3381 | 3385 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3382 | 3386 | |
| 3387 | if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) { | |
| 3388 | return self.fail("vector shift with scalar rhs", .{}); | |
| 3389 | } | |
| 3390 | ||
| 3383 | 3391 | const base = try self.temporary(bin_op.lhs); |
| 3384 | 3392 | const shift = try self.temporary(bin_op.rhs); |
| 3385 | 3393 | |
| ... | ... | @@ -3866,6 +3874,10 @@ const NavGen = struct { |
| 3866 | 3874 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 3867 | 3875 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3868 | 3876 | |
| 3877 | if (self.typeOf(extra.lhs).isVector(zcu) and !self.typeOf(extra.rhs).isVector(zcu)) { | |
| 3878 | return self.fail("vector shift with scalar rhs", .{}); | |
| 3879 | } | |
| 3880 | ||
| 3869 | 3881 | const base = try self.temporary(extra.lhs); |
| 3870 | 3882 | const shift = try self.temporary(extra.rhs); |
| 3871 | 3883 |
src/target.zig-4| ... | ... | @@ -850,9 +850,5 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt |
| 850 | 850 | .stage2_llvm => false, |
| 851 | 851 | else => true, |
| 852 | 852 | }, |
| 853 | .all_vector_instructions => switch (backend) { | |
| 854 | .stage2_x86_64 => true, | |
| 855 | else => false, | |
| 856 | }, | |
| 857 | 853 | }; |
| 858 | 854 | } |