| 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,6 +42,7 @@ pub const Feature = enum { |
| 42 | scalarize_shl_sat, | 42 | scalarize_shl_sat, |
| 43 | scalarize_xor, | 43 | scalarize_xor, |
| 44 | scalarize_not, | 44 | scalarize_not, |
| 45 | scalarize_bitcast, | ||
| 45 | scalarize_clz, | 46 | scalarize_clz, |
| 46 | scalarize_ctz, | 47 | scalarize_ctz, |
| 47 | scalarize_popcount, | 48 | scalarize_popcount, |
| ... | @@ -76,7 +77,7 @@ pub const Feature = enum { | ... | @@ -76,7 +77,7 @@ pub const Feature = enum { |
| 76 | scalarize_mul_add, | 77 | scalarize_mul_add, |
| 77 | 78 | ||
| 78 | /// Legalize (shift lhs, (splat rhs)) -> (shift lhs, rhs) | 79 | /// Legalize (shift lhs, (splat rhs)) -> (shift lhs, rhs) |
| 79 | remove_shift_vector_rhs_splat, | 80 | unsplat_shift_rhs, |
| 80 | /// Legalize reduce of a one element vector to a bitcast | 81 | /// Legalize reduce of a one element vector to a bitcast |
| 81 | reduce_one_elem_to_bitcast, | 82 | reduce_one_elem_to_bitcast, |
| 82 | 83 | ||
| ... | @@ -121,6 +122,7 @@ pub const Feature = enum { | ... | @@ -121,6 +122,7 @@ pub const Feature = enum { |
| 121 | .shl_sat => .scalarize_shl_sat, | 122 | .shl_sat => .scalarize_shl_sat, |
| 122 | .xor => .scalarize_xor, | 123 | .xor => .scalarize_xor, |
| 123 | .not => .scalarize_not, | 124 | .not => .scalarize_not, |
| 125 | .bitcast => .scalarize_bitcast, | ||
| 124 | .clz => .scalarize_clz, | 126 | .clz => .scalarize_clz, |
| 125 | .ctz => .scalarize_ctz, | 127 | .ctz => .scalarize_ctz, |
| 126 | .popcount => .scalarize_popcount, | 128 | .popcount => .scalarize_popcount, |
| ... | @@ -259,9 +261,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { | ... | @@ -259,9 +261,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { |
| 259 | => |air_tag| done: { | 261 | => |air_tag| done: { |
| 260 | const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op; | 262 | const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 261 | if (!l.typeOf(bin_op.rhs).isVector(zcu)) break :done; | 263 | if (!l.typeOf(bin_op.rhs).isVector(zcu)) break :done; |
| 262 | if (l.features.contains(comptime .scalarize(air_tag))) { | 264 | if (l.features.contains(.unsplat_shift_rhs)) { |
| 263 | continue :inst try l.scalarize(inst, .bin_op); | ||
| 264 | } else if (l.features.contains(.remove_shift_vector_rhs_splat)) { | ||
| 265 | if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) { | 265 | if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) { |
| 266 | else => {}, | 266 | else => {}, |
| 267 | .aggregate => |aggregate| switch (aggregate.storage) { | 267 | .aggregate => |aggregate| switch (aggregate.storage) { |
| ... | @@ -282,6 +282,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { | ... | @@ -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 | inline .not, | 287 | inline .not, |
| 287 | .clz, | 288 | .clz, |
| ... | @@ -302,8 +303,14 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { | ... | @@ -302,8 +303,14 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { |
| 302 | const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op; | 303 | const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 303 | if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op); | 304 | if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op); |
| 304 | }, | 305 | }, |
| 305 | .bitcast, | 306 | inline .bitcast, |
| 306 | => {}, | 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 | .block, | 314 | .block, |
| 308 | .loop, | 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,16 +10165,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10165 | try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src); | 10165 | try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src); |
| 10166 | try sema.validateRuntimeValue(block, ptr_src, operand); | 10166 | try sema.validateRuntimeValue(block, ptr_src, operand); |
| 10167 | try sema.checkLogicalPtrOperation(block, ptr_src, ptr_ty); | 10167 | try sema.checkLogicalPtrOperation(block, ptr_src, ptr_ty); |
| 10168 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | 10168 | return block.addBitCast(dest_ty, operand); |
| 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); | ||
| 10178 | } | 10169 | } |
| 10179 | 10170 | ||
| 10180 | fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,17 +10631,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 10640 | if (dst_bits >= src_bits) { | 10631 | if (dst_bits >= src_bits) { |
| 10641 | return sema.coerce(block, dest_ty, operand, operand_src); | 10632 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 10642 | } | 10633 | } |
| 10643 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | 10634 | return block.addTyOp(.fptrunc, dest_ty, operand); |
| 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); | ||
| 10654 | } | 10635 | } |
| 10655 | 10636 | ||
| 10656 | fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,16 +20703,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 20722 | .storage = .{ .elems = new_elems }, | 20703 | .storage = .{ .elems = new_elems }, |
| 20723 | } })); | 20704 | } })); |
| 20724 | } | 20705 | } |
| 20725 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | 20706 | return block.addBitCast(dest_ty, operand); |
| 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); | ||
| 20735 | } | 20707 | } |
| 20736 | 20708 | ||
| 20737 | fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,42 +22299,23 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 22327 | .storage = .{ .repeated_elem = (try pt.intValue(dest_scalar_ty, 0)).toIntern() }, | 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)) { | 22302 | const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand); |
| 22331 | 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()) { |
| 22332 | if (block.wantSafety()) { | 22304 | const back = try block.addTyOp(.float_from_int, operand_ty, result); |
| 22333 | 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); |
| 22334 | const diff = try block.addBinOp(if (block.float_mode == .optimized) .sub_optimized else .sub, operand, back); | 22306 | const ok = if (is_vector) ok: { |
| 22335 | 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); |
| 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); | 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); |
| 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); | 22309 | const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg); |
| 22338 | const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg); | 22310 | break :ok try block.addReduce(ok, .And); |
| 22339 | break :ok try block.addReduce(ok, .And); | 22311 | } else ok: { |
| 22340 | } 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())); |
| 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())); | 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())); |
| 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())); | 22314 | break :ok try block.addBinOp(.bool_and, ok_pos, ok_neg); |
| 22343 | break :ok try block.addBinOp(.bool_and, ok_pos, ok_neg); | 22315 | }; |
| 22344 | }; | 22316 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); |
| 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; | ||
| 22364 | } | 22317 | } |
| 22365 | return block.addAggregateInit(dest_ty, new_elems); | 22318 | return result; |
| 22366 | } | 22319 | } |
| 22367 | 22320 | ||
| 22368 | fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,7 +22330,6 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 22377 | const operand_ty = sema.typeOf(operand); | 22330 | const operand_ty = sema.typeOf(operand); |
| 22378 | 22331 | ||
| 22379 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); | 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 | const dest_scalar_ty = dest_ty.scalarType(zcu); | 22334 | const dest_scalar_ty = dest_ty.scalarType(zcu); |
| 22383 | const operand_scalar_ty = operand_ty.scalarType(zcu); | 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,17 +22345,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 22393 | } | 22345 | } |
| 22394 | 22346 | ||
| 22395 | try sema.requireRuntimeBlock(block, src, operand_src); | 22347 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 22396 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | 22348 | return block.addTyOp(.float_from_int, dest_ty, operand); |
| 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); | ||
| 22407 | } | 22349 | } |
| 22408 | 22350 | ||
| 22409 | fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,69 +22415,34 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 22473 | } | 22415 | } |
| 22474 | try sema.requireRuntimeBlock(block, src, operand_src); | 22416 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 22475 | try sema.checkLogicalPtrOperation(block, src, ptr_ty); | 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 | if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) { | 22418 | if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) { |
| 22509 | for (0..len) |i| { | 22419 | if (!ptr_ty.isAllowzeroPtr(zcu)) { |
| 22510 | const idx_ref = try pt.intRef(.usize, i); | 22420 | const is_non_zero = if (is_vector) all_non_zero: { |
| 22511 | const elem_coerced = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref); | 22421 | const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); |
| 22512 | if (!ptr_ty.isAllowzeroPtr(zcu)) { | 22422 | const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq); |
| 22513 | const is_non_zero = try block.addBinOp(.cmp_neq, elem_coerced, .zero_usize); | 22423 | break :all_non_zero try block.addReduce(is_non_zero, .And); |
| 22514 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | 22424 | } else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize); |
| 22515 | } | 22425 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); |
| 22516 | if (ptr_align.compare(.gt, .@"1")) { | 22426 | } |
| 22517 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; | 22427 | if (ptr_align.compare(.gt, .@"1")) { |
| 22518 | const align_mask = Air.internedToRef((try pt.intValue( | 22428 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; |
| 22519 | .usize, | 22429 | const align_mask = Air.internedToRef((try sema.splat(operand_ty, try pt.intValue( |
| 22520 | if (elem_ty.fnPtrMaskOrNull(zcu)) |mask| | 22430 | .usize, |
| 22521 | align_bytes_minus_1 & mask | 22431 | if (elem_ty.fnPtrMaskOrNull(zcu)) |mask| |
| 22522 | else | 22432 | align_bytes_minus_1 & mask |
| 22523 | align_bytes_minus_1, | 22433 | else |
| 22524 | )).toIntern()); | 22434 | align_bytes_minus_1, |
| 22525 | const remainder = try block.addBinOp(.bit_and, elem_coerced, align_mask); | 22435 | ))).toIntern()); |
| 22526 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); | 22436 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_mask); |
| 22527 | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); | 22437 | const is_aligned = if (is_vector) all_aligned: { |
| 22528 | } | 22438 | const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); |
| 22529 | } | 22439 | const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq); |
| 22530 | } | 22440 | break :all_aligned try block.addReduce(is_aligned, .And); |
| 22531 | 22441 | } else try block.addBinOp(.cmp_eq, remainder, .zero_usize); | |
| 22532 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); | 22442 | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); |
| 22533 | for (new_elems, 0..) |*new_elem, i| { | 22443 | } |
| 22534 | const idx_ref = try pt.intRef(.usize, i); | 22444 | } |
| 22535 | const old_elem = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref); | 22445 | return block.addBitCast(dest_ty, operand_coerced); |
| 22536 | new_elem.* = try block.addBitCast(ptr_ty, old_elem); | ||
| 22537 | } | ||
| 22538 | return block.addAggregateInit(dest_ty, new_elems); | ||
| 22539 | } | 22446 | } |
| 22540 | 22447 | ||
| 22541 | fn ptrFromIntVal( | 22448 | fn ptrFromIntVal( |
src/Zcu.zig-9| ... | @@ -3840,15 +3840,6 @@ pub const Feature = enum { | ... | @@ -3840,15 +3840,6 @@ pub const Feature = enum { |
| 3840 | safety_checked_instructions, | 3840 | safety_checked_instructions, |
| 3841 | /// If the backend supports running from another thread. | 3841 | /// If the backend supports running from another thread. |
| 3842 | separate_thread, | 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 | pub fn backendSupportsFeature(zcu: *const Zcu, comptime feature: Feature) bool { | 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,6 +40,10 @@ const gp = abi.RegisterClass.gp; |
| 40 | 40 | ||
| 41 | const InnerError = CodeGenError || error{OutOfRegisters}; | 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 | gpa: Allocator, | 47 | gpa: Allocator, |
| 44 | pt: Zcu.PerThread, | 48 | pt: Zcu.PerThread, |
| 45 | air: Air, | 49 | air: Air, |
| ... | @@ -2261,12 +2265,13 @@ fn shiftExact( | ... | @@ -2261,12 +2265,13 @@ fn shiftExact( |
| 2261 | rhs_ty: Type, | 2265 | rhs_ty: Type, |
| 2262 | maybe_inst: ?Air.Inst.Index, | 2266 | maybe_inst: ?Air.Inst.Index, |
| 2263 | ) InnerError!MCValue { | 2267 | ) InnerError!MCValue { |
| 2264 | _ = rhs_ty; | ||
| 2265 | |||
| 2266 | const pt = self.pt; | 2268 | const pt = self.pt; |
| 2267 | const zcu = pt.zcu; | 2269 | const zcu = pt.zcu; |
| 2268 | switch (lhs_ty.zigTypeTag(zcu)) { | 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 | .int => { | 2275 | .int => { |
| 2271 | const int_info = lhs_ty.intInfo(zcu); | 2276 | const int_info = lhs_ty.intInfo(zcu); |
| 2272 | if (int_info.bits <= 64) { | 2277 | if (int_info.bits <= 64) { |
| ... | @@ -2317,7 +2322,10 @@ fn shiftNormal( | ... | @@ -2317,7 +2322,10 @@ fn shiftNormal( |
| 2317 | const pt = self.pt; | 2322 | const pt = self.pt; |
| 2318 | const zcu = pt.zcu; | 2323 | const zcu = pt.zcu; |
| 2319 | switch (lhs_ty.zigTypeTag(zcu)) { | 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 | .int => { | 2329 | .int => { |
| 2322 | const int_info = lhs_ty.intInfo(zcu); | 2330 | const int_info = lhs_ty.intInfo(zcu); |
| 2323 | if (int_info.bits <= 64) { | 2331 | if (int_info.bits <= 64) { |
| ... | @@ -2874,7 +2882,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2874,7 +2882,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 2874 | const overflow_bit_offset = @as(u32, @intCast(tuple_ty.structFieldOffset(1, zcu))); | 2882 | const overflow_bit_offset = @as(u32, @intCast(tuple_ty.structFieldOffset(1, zcu))); |
| 2875 | 2883 | ||
| 2876 | switch (lhs_ty.zigTypeTag(zcu)) { | 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 | .int => { | 2889 | .int => { |
| 2879 | const int_info = lhs_ty.intInfo(zcu); | 2890 | const int_info = lhs_ty.intInfo(zcu); |
| 2880 | if (int_info.bits <= 64) { | 2891 | if (int_info.bits <= 64) { |
| ... | @@ -2993,8 +3004,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2993,8 +3004,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 2993 | } | 3004 | } |
| 2994 | 3005 | ||
| 2995 | fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!void { | 3006 | fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 3007 | const zcu = self.pt.zcu; | ||
| 2996 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 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 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 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,6 +41,10 @@ const gp = abi.RegisterClass.gp; |
| 41 | 41 | ||
| 42 | const InnerError = CodeGenError || error{OutOfRegisters}; | 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 | gpa: Allocator, | 48 | gpa: Allocator, |
| 45 | pt: Zcu.PerThread, | 49 | pt: Zcu.PerThread, |
| 46 | air: Air, | 50 | air: Air, |
| ... | @@ -1857,7 +1861,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1857,7 +1861,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1857 | const overflow_bit_offset: u32 = @intCast(tuple_ty.structFieldOffset(1, zcu)); | 1861 | const overflow_bit_offset: u32 = @intCast(tuple_ty.structFieldOffset(1, zcu)); |
| 1858 | 1862 | ||
| 1859 | switch (lhs_ty.zigTypeTag(zcu)) { | 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 | .int => { | 1868 | .int => { |
| 1862 | const int_info = lhs_ty.intInfo(zcu); | 1869 | const int_info = lhs_ty.intInfo(zcu); |
| 1863 | if (int_info.bits <= 32) { | 1870 | if (int_info.bits <= 32) { |
| ... | @@ -1978,8 +1985,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1978,8 +1985,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1978 | } | 1985 | } |
| 1979 | 1986 | ||
| 1980 | fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { | 1987 | fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1988 | const zcu = self.pt.zcu; | ||
| 1981 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 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 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1996 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1984 | } | 1997 | } |
| 1985 | 1998 | ||
| ... | @@ -3788,7 +3801,10 @@ fn shiftExact( | ... | @@ -3788,7 +3801,10 @@ fn shiftExact( |
| 3788 | const pt = self.pt; | 3801 | const pt = self.pt; |
| 3789 | const zcu = pt.zcu; | 3802 | const zcu = pt.zcu; |
| 3790 | switch (lhs_ty.zigTypeTag(zcu)) { | 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 | .int => { | 3808 | .int => { |
| 3793 | const int_info = lhs_ty.intInfo(zcu); | 3809 | const int_info = lhs_ty.intInfo(zcu); |
| 3794 | if (int_info.bits <= 32) { | 3810 | if (int_info.bits <= 32) { |
| ... | @@ -3828,7 +3844,10 @@ fn shiftNormal( | ... | @@ -3828,7 +3844,10 @@ fn shiftNormal( |
| 3828 | const pt = self.pt; | 3844 | const pt = self.pt; |
| 3829 | const zcu = pt.zcu; | 3845 | const zcu = pt.zcu; |
| 3830 | switch (lhs_ty.zigTypeTag(zcu)) { | 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 | .int => { | 3851 | .int => { |
| 3833 | const int_info = lhs_ty.intInfo(zcu); | 3852 | const int_info = lhs_ty.intInfo(zcu); |
| 3834 | if (int_info.bits <= 32) { | 3853 | if (int_info.bits <= 32) { |
src/arch/powerpc/CodeGen.zig+4| ... | @@ -10,6 +10,10 @@ const Zcu = @import("../../Zcu.zig"); | ... | @@ -10,6 +10,10 @@ const Zcu = @import("../../Zcu.zig"); |
| 10 | const assert = std.debug.assert; | 10 | const assert = std.debug.assert; |
| 11 | const log = std.log.scoped(.codegen); | 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 | pub fn generate( | 17 | pub fn generate( |
| 14 | bin_file: *link.File, | 18 | bin_file: *link.File, |
| 15 | pt: Zcu.PerThread, | 19 | pt: Zcu.PerThread, |
src/arch/riscv64/CodeGen.zig+19-2| ... | @@ -51,6 +51,10 @@ const Instruction = encoding.Instruction; | ... | @@ -51,6 +51,10 @@ const Instruction = encoding.Instruction; |
| 51 | 51 | ||
| 52 | const InnerError = CodeGenError || error{OutOfRegisters}; | 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 | pt: Zcu.PerThread, | 58 | pt: Zcu.PerThread, |
| 55 | air: Air, | 59 | air: Air, |
| 56 | liveness: Air.Liveness, | 60 | liveness: Air.Liveness, |
| ... | @@ -2764,6 +2768,7 @@ fn genBinOp( | ... | @@ -2764,6 +2768,7 @@ fn genBinOp( |
| 2764 | .shl, | 2768 | .shl, |
| 2765 | .shl_exact, | 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 | if (bit_size > 64) return func.fail("TODO: genBinOp shift > 64 bits, {}", .{bit_size}); | 2772 | if (bit_size > 64) return func.fail("TODO: genBinOp shift > 64 bits, {}", .{bit_size}); |
| 2768 | try func.truncateRegister(rhs_ty, rhs_reg); | 2773 | try func.truncateRegister(rhs_ty, rhs_reg); |
| 2769 | 2774 | ||
| ... | @@ -3248,8 +3253,14 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3248,8 +3253,14 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3248 | } | 3253 | } |
| 3249 | 3254 | ||
| 3250 | fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void { | 3255 | fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3256 | const zcu = func.pt.zcu; | ||
| 3251 | const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 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 | return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 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,8 +3277,14 @@ fn airMulSat(func: *Func, inst: Air.Inst.Index) !void { |
| 3266 | } | 3277 | } |
| 3267 | 3278 | ||
| 3268 | fn airShlSat(func: *Func, inst: Air.Inst.Index) !void { | 3279 | fn airShlSat(func: *Func, inst: Air.Inst.Index) !void { |
| 3280 | const zcu = func.pt.zcu; | ||
| 3269 | const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 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 | return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 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,6 +41,10 @@ const Self = @This(); |
| 41 | 41 | ||
| 42 | const InnerError = CodeGenError || error{OutOfRegisters}; | 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 | const RegisterView = enum(u1) { | 48 | const RegisterView = enum(u1) { |
| 45 | caller, | 49 | caller, |
| 46 | callee, | 50 | callee, |
| ... | @@ -2270,8 +2274,14 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2270,8 +2274,14 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 2270 | } | 2274 | } |
| 2271 | 2275 | ||
| 2272 | fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { | 2276 | fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2277 | const zcu = self.pt.zcu; | ||
| 2273 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 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 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 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,7 +2297,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2287 | const rhs_ty = self.typeOf(extra.rhs); | 2297 | const rhs_ty = self.typeOf(extra.rhs); |
| 2288 | 2298 | ||
| 2289 | switch (lhs_ty.zigTypeTag(zcu)) { | 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 | .int => { | 2304 | .int => { |
| 2292 | const int_info = lhs_ty.intInfo(zcu); | 2305 | const int_info = lhs_ty.intInfo(zcu); |
| 2293 | if (int_info.bits <= 64) { | 2306 | if (int_info.bits <= 64) { |
| ... | @@ -3002,7 +3015,10 @@ fn binOp( | ... | @@ -3002,7 +3015,10 @@ fn binOp( |
| 3002 | 3015 | ||
| 3003 | // Truncate if necessary | 3016 | // Truncate if necessary |
| 3004 | switch (lhs_ty.zigTypeTag(zcu)) { | 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 | .int => { | 3022 | .int => { |
| 3007 | const int_info = lhs_ty.intInfo(zcu); | 3023 | const int_info = lhs_ty.intInfo(zcu); |
| 3008 | if (int_info.bits <= 64) { | 3024 | if (int_info.bits <= 64) { |
| ... | @@ -3024,7 +3040,10 @@ fn binOp( | ... | @@ -3024,7 +3040,10 @@ fn binOp( |
| 3024 | .shr_exact, | 3040 | .shr_exact, |
| 3025 | => { | 3041 | => { |
| 3026 | switch (lhs_ty.zigTypeTag(zcu)) { | 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 | .int => { | 3047 | .int => { |
| 3029 | const int_info = lhs_ty.intInfo(zcu); | 3048 | const int_info = lhs_ty.intInfo(zcu); |
| 3030 | if (int_info.bits <= 64) { | 3049 | if (int_info.bits <= 64) { |
src/arch/wasm/CodeGen.zig+26-5| ... | @@ -31,6 +31,10 @@ const libcFloatSuffix = target_util.libcFloatSuffix; | ... | @@ -31,6 +31,10 @@ const libcFloatSuffix = target_util.libcFloatSuffix; |
| 31 | const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev; | 31 | const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev; |
| 32 | const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; | 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 | /// Reference to the function declaration the code | 38 | /// Reference to the function declaration the code |
| 35 | /// section belongs to | 39 | /// section belongs to |
| 36 | owner_nav: InternPool.Nav.Index, | 40 | owner_nav: InternPool.Nav.Index, |
| ... | @@ -2638,6 +2642,10 @@ fn airBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | ... | @@ -2638,6 +2642,10 @@ fn airBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 2638 | // For big integers we can ignore this as we will call into compiler-rt which handles this. | 2642 | // For big integers we can ignore this as we will call into compiler-rt which handles this. |
| 2639 | const result = switch (op) { | 2643 | const result = switch (op) { |
| 2640 | .shr, .shl => result: { | 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 | const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(zcu))) orelse { | 2649 | const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(zcu))) orelse { |
| 2642 | return cg.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)}); | 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,8 +3063,12 @@ fn airWrapBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 3055 | const lhs_ty = cg.typeOf(bin_op.lhs); | 3063 | const lhs_ty = cg.typeOf(bin_op.lhs); |
| 3056 | const rhs_ty = cg.typeOf(bin_op.rhs); | 3064 | const rhs_ty = cg.typeOf(bin_op.rhs); |
| 3057 | 3065 | ||
| 3058 | if (lhs_ty.zigTypeTag(zcu) == .vector or rhs_ty.zigTypeTag(zcu) == .vector) { | 3066 | if (lhs_ty.isVector(zcu)) { |
| 3059 | return cg.fail("TODO: Implement wrapping arithmetic for vectors", .{}); | 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 | // For certain operations, such as shifting, the types are different. | 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,13 +6079,17 @@ fn airShlWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6067 | const ty = cg.typeOf(extra.lhs); | 6079 | const ty = cg.typeOf(extra.lhs); |
| 6068 | const rhs_ty = cg.typeOf(extra.rhs); | 6080 | const rhs_ty = cg.typeOf(extra.rhs); |
| 6069 | 6081 | ||
| 6070 | if (ty.zigTypeTag(zcu) == .vector) { | 6082 | if (ty.isVector(zcu)) { |
| 6071 | return cg.fail("TODO: Implement overflow arithmetic for vectors", .{}); | 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 | const int_info = ty.intInfo(zcu); | 6090 | const int_info = ty.intInfo(zcu); |
| 6075 | const wasm_bits = toWasmBits(int_info.bits) orelse { | 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 | // Ensure rhs is coerced to lhs as they must have the same WebAssembly types | 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,6 +7010,11 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6994 | 7010 | ||
| 6995 | const pt = cg.pt; | 7011 | const pt = cg.pt; |
| 6996 | const zcu = pt.zcu; | 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 | const ty = cg.typeOfIndex(inst); | 7018 | const ty = cg.typeOfIndex(inst); |
| 6998 | const int_info = ty.intInfo(zcu); | 7019 | const int_info = ty.intInfo(zcu); |
| 6999 | const is_signed = int_info.signedness == .signed; | 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,7 +32,7 @@ const FrameIndex = bits.FrameIndex; |
| 32 | 32 | ||
| 33 | const InnerError = codegen.CodeGenError || error{OutOfRegisters}; | 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 | @setEvalBranchQuota(1_200); | 36 | @setEvalBranchQuota(1_200); |
| 37 | return switch (target.ofmt == .coff) { | 37 | return switch (target.ofmt == .coff) { |
| 38 | inline false, true => |use_old| comptime &.init(.{ | 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,7 +86,7 @@ pub inline fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Fe |
| 86 | .scalarize_float_from_int = use_old, | 86 | .scalarize_float_from_int = use_old, |
| 87 | .scalarize_mul_add = use_old, | 87 | .scalarize_mul_add = use_old, |
| 88 | 88 | ||
| 89 | .remove_shift_vector_rhs_splat = false, | 89 | .unsplat_shift_rhs = false, |
| 90 | .reduce_one_elem_to_bitcast = true, | 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,7 +52,7 @@ fn importBackend(comptime backend: std.builtin.CompilerBackend) type { |
| 52 | pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *const Air.Legalize.Features { | 52 | pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *const Air.Legalize.Features { |
| 53 | const zcu = pt.zcu; | 53 | const zcu = pt.zcu; |
| 54 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; | 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 | else => unreachable, | 56 | else => unreachable, |
| 57 | inline .stage2_llvm, | 57 | inline .stage2_llvm, |
| 58 | .stage2_c, | 58 | .stage2_c, |
| ... | @@ -65,11 +65,8 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *con | ... | @@ -65,11 +65,8 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *con |
| 65 | .stage2_sparc64, | 65 | .stage2_sparc64, |
| 66 | .stage2_spirv64, | 66 | .stage2_spirv64, |
| 67 | .stage2_powerpc, | 67 | .stage2_powerpc, |
| 68 | => |backend| { | 68 | => |backend| importBackend(backend).legalizeFeatures(target), |
| 69 | const Backend = importBackend(backend); | 69 | }; |
| 70 | return if (@hasDecl(Backend, "legalizeFeatures")) Backend.legalizeFeatures(target) else comptime &.initEmpty(); | ||
| 71 | }, | ||
| 72 | } | ||
| 73 | } | 70 | } |
| 74 | 71 | ||
| 75 | pub fn generateFunction( | 72 | pub fn generateFunction( |
src/codegen/c.zig+6-2| ... | @@ -20,6 +20,10 @@ const Alignment = InternPool.Alignment; | ... | @@ -20,6 +20,10 @@ const Alignment = InternPool.Alignment; |
| 20 | const BigIntLimb = std.math.big.Limb; | 20 | const BigIntLimb = std.math.big.Limb; |
| 21 | const BigInt = std.math.big.int; | 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 | pub const CType = @import("c/Type.zig"); | 27 | pub const CType = @import("c/Type.zig"); |
| 24 | 28 | ||
| 25 | pub const CValue = union(enum) { | 29 | pub const CValue = union(enum) { |
| ... | @@ -4179,7 +4183,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: | ... | @@ -4179,7 +4183,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 4179 | try v.elem(f, w); | 4183 | try v.elem(f, w); |
| 4180 | try w.writeAll(", "); | 4184 | try w.writeAll(", "); |
| 4181 | try f.writeCValue(w, rhs, .FunctionArgument); | 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 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); | 4187 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); |
| 4184 | try w.writeAll(");\n"); | 4188 | try w.writeAll(");\n"); |
| 4185 | try v.end(f, inst, w); | 4189 | try v.end(f, inst, w); |
| ... | @@ -6536,7 +6540,7 @@ fn airBinBuiltinCall( | ... | @@ -6536,7 +6540,7 @@ fn airBinBuiltinCall( |
| 6536 | try v.elem(f, writer); | 6540 | try v.elem(f, writer); |
| 6537 | try writer.writeAll(", "); | 6541 | try writer.writeAll(", "); |
| 6538 | try f.writeCValue(writer, rhs, .FunctionArgument); | 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 | try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info); | 6544 | try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info); |
| 6541 | try writer.writeAll(");\n"); | 6545 | try writer.writeAll(");\n"); |
| 6542 | try v.end(f, inst, writer); | 6546 | try v.end(f, inst, writer); |
src/codegen/llvm.zig+23-7| ... | @@ -36,6 +36,10 @@ const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; | ... | @@ -36,6 +36,10 @@ const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; |
| 36 | 36 | ||
| 37 | const Error = error{ OutOfMemory, CodegenFail }; | 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 | fn subArchName(features: std.Target.Cpu.Feature.Set, arch: anytype, mappings: anytype) ?[]const u8 { | 43 | fn subArchName(features: std.Target.Cpu.Feature.Set, arch: anytype, mappings: anytype) ?[]const u8 { |
| 40 | inline for (mappings) |mapping| { | 44 | inline for (mappings) |mapping| { |
| 41 | if (arch.featureSetHas(features, mapping[0])) return mapping[1]; | 45 | if (arch.featureSetHas(features, mapping[0])) return mapping[1]; |
| ... | @@ -8923,6 +8927,8 @@ pub const FuncGen = struct { | ... | @@ -8923,6 +8927,8 @@ pub const FuncGen = struct { |
| 8923 | const rhs = try self.resolveInst(extra.rhs); | 8927 | const rhs = try self.resolveInst(extra.rhs); |
| 8924 | 8928 | ||
| 8925 | const lhs_ty = self.typeOf(extra.lhs); | 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 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); | 8932 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); |
| 8927 | 8933 | ||
| 8928 | const dest_ty = self.typeOfIndex(inst); | 8934 | const dest_ty = self.typeOfIndex(inst); |
| ... | @@ -8992,6 +8998,8 @@ pub const FuncGen = struct { | ... | @@ -8992,6 +8998,8 @@ pub const FuncGen = struct { |
| 8992 | const rhs = try self.resolveInst(bin_op.rhs); | 8998 | const rhs = try self.resolveInst(bin_op.rhs); |
| 8993 | 8999 | ||
| 8994 | const lhs_ty = self.typeOf(bin_op.lhs); | 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 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); | 9003 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); |
| 8996 | 9004 | ||
| 8997 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); | 9005 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); |
| ... | @@ -9003,14 +9011,17 @@ pub const FuncGen = struct { | ... | @@ -9003,14 +9011,17 @@ pub const FuncGen = struct { |
| 9003 | 9011 | ||
| 9004 | fn airShl(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { | 9012 | fn airShl(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9005 | const o = self.ng.object; | 9013 | const o = self.ng.object; |
| 9014 | const zcu = o.pt.zcu; | ||
| 9006 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 9015 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 9007 | 9016 | ||
| 9008 | const lhs = try self.resolveInst(bin_op.lhs); | 9017 | const lhs = try self.resolveInst(bin_op.lhs); |
| 9009 | const rhs = try self.resolveInst(bin_op.rhs); | 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 | return self.wip.bin(.shl, lhs, casted_rhs, ""); | 9025 | return self.wip.bin(.shl, lhs, casted_rhs, ""); |
| 9015 | } | 9026 | } |
| 9016 | 9027 | ||
| ... | @@ -9029,6 +9040,8 @@ pub const FuncGen = struct { | ... | @@ -9029,6 +9040,8 @@ pub const FuncGen = struct { |
| 9029 | const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder); | 9040 | const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder); |
| 9030 | 9041 | ||
| 9031 | const rhs_ty = self.typeOf(bin_op.rhs); | 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 | const rhs_info = rhs_ty.intInfo(zcu); | 9045 | const rhs_info = rhs_ty.intInfo(zcu); |
| 9033 | assert(rhs_info.signedness == .unsigned); | 9046 | assert(rhs_info.signedness == .unsigned); |
| 9034 | const llvm_rhs_ty = try o.lowerType(rhs_ty); | 9047 | const llvm_rhs_ty = try o.lowerType(rhs_ty); |
| ... | @@ -9101,6 +9114,8 @@ pub const FuncGen = struct { | ... | @@ -9101,6 +9114,8 @@ pub const FuncGen = struct { |
| 9101 | const rhs = try self.resolveInst(bin_op.rhs); | 9114 | const rhs = try self.resolveInst(bin_op.rhs); |
| 9102 | 9115 | ||
| 9103 | const lhs_ty = self.typeOf(bin_op.lhs); | 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 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); | 9119 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); |
| 9105 | 9120 | ||
| 9106 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); | 9121 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); |
| ... | @@ -9255,8 +9270,6 @@ pub const FuncGen = struct { | ... | @@ -9255,8 +9270,6 @@ pub const FuncGen = struct { |
| 9255 | const operand_ty = self.typeOf(ty_op.operand); | 9270 | const operand_ty = self.typeOf(ty_op.operand); |
| 9256 | const dest_ty = self.typeOfIndex(inst); | 9271 | const dest_ty = self.typeOfIndex(inst); |
| 9257 | const target = zcu.getTarget(); | 9272 | const target = zcu.getTarget(); |
| 9258 | const dest_bits = dest_ty.floatBits(target); | ||
| 9259 | const src_bits = operand_ty.floatBits(target); | ||
| 9260 | 9273 | ||
| 9261 | if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { | 9274 | if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { |
| 9262 | return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty), ""); | 9275 | return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty), ""); |
| ... | @@ -9264,6 +9277,8 @@ pub const FuncGen = struct { | ... | @@ -9264,6 +9277,8 @@ pub const FuncGen = struct { |
| 9264 | const operand_llvm_ty = try o.lowerType(operand_ty); | 9277 | const operand_llvm_ty = try o.lowerType(operand_ty); |
| 9265 | const dest_llvm_ty = try o.lowerType(dest_ty); | 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 | const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{ | 9282 | const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{ |
| 9268 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), | 9283 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), |
| 9269 | }); | 9284 | }); |
| ... | @@ -9348,11 +9363,12 @@ pub const FuncGen = struct { | ... | @@ -9348,11 +9363,12 @@ pub const FuncGen = struct { |
| 9348 | return self.wip.conv(.unsigned, operand, llvm_dest_ty, ""); | 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 | return self.wip.cast(.inttoptr, operand, llvm_dest_ty, ""); | 9369 | return self.wip.cast(.inttoptr, operand, llvm_dest_ty, ""); |
| 9353 | } | 9370 | } |
| 9354 | 9371 | if (operand_scalar_ty.isPtrAtRuntime(zcu) and inst_scalar_ty.zigTypeTag(zcu) == .int) { | |
| 9355 | if (operand_ty.isPtrAtRuntime(zcu) and inst_ty.zigTypeTag(zcu) == .int) { | ||
| 9356 | return self.wip.cast(.ptrtoint, operand, llvm_dest_ty, ""); | 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,6 +28,10 @@ const SpvAssembler = @import("spirv/Assembler.zig"); |
| 28 | 28 | ||
| 29 | const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef); | 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 | pub const zig_call_abi_ver = 3; | 35 | pub const zig_call_abi_ver = 3; |
| 32 | pub const big_int_bits = 32; | 36 | pub const big_int_bits = 32; |
| 33 | 37 | ||
| ... | @@ -3380,6 +3384,10 @@ const NavGen = struct { | ... | @@ -3380,6 +3384,10 @@ const NavGen = struct { |
| 3380 | const zcu = self.pt.zcu; | 3384 | const zcu = self.pt.zcu; |
| 3381 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 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 | const base = try self.temporary(bin_op.lhs); | 3391 | const base = try self.temporary(bin_op.lhs); |
| 3384 | const shift = try self.temporary(bin_op.rhs); | 3392 | const shift = try self.temporary(bin_op.rhs); |
| 3385 | 3393 | ||
| ... | @@ -3866,6 +3874,10 @@ const NavGen = struct { | ... | @@ -3866,6 +3874,10 @@ const NavGen = struct { |
| 3866 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 3874 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 3867 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 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 | const base = try self.temporary(extra.lhs); | 3881 | const base = try self.temporary(extra.lhs); |
| 3870 | const shift = try self.temporary(extra.rhs); | 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,9 +850,5 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt |
| 850 | .stage2_llvm => false, | 850 | .stage2_llvm => false, |
| 851 | else => true, | 851 | else => true, |
| 852 | }, | 852 | }, |
| 853 | .all_vector_instructions => switch (backend) { | ||
| 854 | .stage2_x86_64 => true, | ||
| 855 | else => false, | ||
| 856 | }, | ||
| 857 | }; | 853 | }; |
| 858 | } | 854 | } |