| author | |
| committer | |
| log | afdcfb005ea32849f30e2abd7361ce1f33d0ee74 |
| tree | ee60a029d0fd028bc17e65e84a0fe36877a7c1fb |
| parent | 3f4676901a8c02d9d7069b284aa848d685c3975c |
Made most `Value` functions require a `Type`. If the provided type is a
vector, then automatically vectorize the operation and return with
another vector. The Sema side can then automatically become vectorized
with minimal changes. There are already a few manually vectorized
instructions, but we can simplify those later.2 files changed, 1006 insertions(+), 278 deletions(-)
src/Sema.zig+278-235| ... | ... | @@ -2105,7 +2105,7 @@ fn zirEnumDecl( |
| 2105 | 2105 | }); |
| 2106 | 2106 | } else if (any_values) { |
| 2107 | 2107 | const tag_val = if (last_tag_val) |val| |
| 2108 | try val.intAdd(Value.one, sema.arena) | |
| 2108 | try val.intAdd(Value.one, enum_obj.tag_ty, sema.arena) | |
| 2109 | 2109 | else |
| 2110 | 2110 | Value.zero; |
| 2111 | 2111 | last_tag_val = tag_val; |
| ... | ... | @@ -8192,14 +8192,22 @@ fn zirShl( |
| 8192 | 8192 | defer tracy.end(); |
| 8193 | 8193 | |
| 8194 | 8194 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 8195 | const src = inst_data.src(); | |
| 8195 | 8196 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 8196 | 8197 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 8197 | 8198 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 8198 | 8199 | const lhs = sema.resolveInst(extra.lhs); |
| 8199 | 8200 | const rhs = sema.resolveInst(extra.rhs); |
| 8201 | const lhs_ty = sema.typeOf(lhs); | |
| 8202 | const rhs_ty = sema.typeOf(rhs); | |
| 8203 | const target = sema.mod.getTarget(); | |
| 8204 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | |
| 8205 | ||
| 8206 | const scalar_ty = lhs_ty.scalarType(); | |
| 8207 | const scalar_rhs_ty = rhs_ty.scalarType(); | |
| 8200 | 8208 | |
| 8201 | 8209 | // TODO coerce rhs if air_tag is not shl_sat |
| 8202 | const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, sema.typeOf(rhs)); | |
| 8210 | const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, scalar_rhs_ty); | |
| 8203 | 8211 | |
| 8204 | 8212 | const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs); |
| 8205 | 8213 | const maybe_rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs); |
| ... | ... | @@ -8213,35 +8221,31 @@ fn zirShl( |
| 8213 | 8221 | } |
| 8214 | 8222 | } |
| 8215 | 8223 | |
| 8216 | const lhs_ty = sema.typeOf(lhs); | |
| 8217 | const rhs_ty = sema.typeOf(rhs); | |
| 8218 | const target = sema.mod.getTarget(); | |
| 8219 | ||
| 8220 | 8224 | const runtime_src = if (maybe_lhs_val) |lhs_val| rs: { |
| 8221 | 8225 | if (lhs_val.isUndef()) return sema.addConstUndef(lhs_ty); |
| 8222 | 8226 | const rhs_val = maybe_rhs_val orelse break :rs rhs_src; |
| 8223 | 8227 | |
| 8224 | 8228 | const val = switch (air_tag) { |
| 8225 | 8229 | .shl_exact => val: { |
| 8226 | const shifted = try lhs_val.shl(rhs_val, sema.arena); | |
| 8227 | if (lhs_ty.zigTypeTag() == .ComptimeInt) { | |
| 8230 | const shifted = try lhs_val.shl(rhs_val, lhs_ty, sema.arena); | |
| 8231 | if (scalar_ty.zigTypeTag() == .ComptimeInt) { | |
| 8228 | 8232 | break :val shifted; |
| 8229 | 8233 | } |
| 8230 | const int_info = lhs_ty.intInfo(target); | |
| 8231 | const truncated = try shifted.intTrunc(sema.arena, int_info.signedness, int_info.bits); | |
| 8232 | if (truncated.compareHetero(.eq, shifted)) { | |
| 8234 | const int_info = scalar_ty.intInfo(target); | |
| 8235 | const truncated = try shifted.intTrunc(lhs_ty, sema.arena, int_info.signedness, int_info.bits); | |
| 8236 | if (truncated.compare(.eq, shifted, lhs_ty)) { | |
| 8233 | 8237 | break :val shifted; |
| 8234 | 8238 | } |
| 8235 | 8239 | return sema.addConstUndef(lhs_ty); |
| 8236 | 8240 | }, |
| 8237 | 8241 | |
| 8238 | .shl_sat => if (lhs_ty.zigTypeTag() == .ComptimeInt) | |
| 8239 | try lhs_val.shl(rhs_val, sema.arena) | |
| 8242 | .shl_sat => if (scalar_ty.zigTypeTag() == .ComptimeInt) | |
| 8243 | try lhs_val.shl(rhs_val, lhs_ty, sema.arena) | |
| 8240 | 8244 | else |
| 8241 | 8245 | try lhs_val.shlSat(rhs_val, lhs_ty, sema.arena, target), |
| 8242 | 8246 | |
| 8243 | .shl => if (lhs_ty.zigTypeTag() == .ComptimeInt) | |
| 8244 | try lhs_val.shl(rhs_val, sema.arena) | |
| 8247 | .shl => if (scalar_ty.zigTypeTag() == .ComptimeInt) | |
| 8248 | try lhs_val.shl(rhs_val, lhs_ty, sema.arena) | |
| 8245 | 8249 | else |
| 8246 | 8250 | try lhs_val.shlTrunc(rhs_val, lhs_ty, sema.arena, target), |
| 8247 | 8251 | |
| ... | ... | @@ -8256,7 +8260,7 @@ fn zirShl( |
| 8256 | 8260 | const new_rhs = if (air_tag == .shl_sat) rhs: { |
| 8257 | 8261 | // Limit the RHS type for saturating shl to be an integer as small as the LHS. |
| 8258 | 8262 | if (rhs_is_comptime_int or |
| 8259 | rhs_ty.intInfo(target).bits > lhs_ty.intInfo(target).bits) | |
| 8263 | scalar_rhs_ty.intInfo(target).bits > scalar_ty.intInfo(target).bits) | |
| 8260 | 8264 | { |
| 8261 | 8265 | const max_int = try sema.addConstant( |
| 8262 | 8266 | lhs_ty, |
| ... | ... | @@ -8283,15 +8287,18 @@ fn zirShr( |
| 8283 | 8287 | defer tracy.end(); |
| 8284 | 8288 | |
| 8285 | 8289 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 8290 | const src = inst_data.src(); | |
| 8286 | 8291 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 8287 | 8292 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 8288 | 8293 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 8289 | 8294 | const lhs = sema.resolveInst(extra.lhs); |
| 8290 | 8295 | const rhs = sema.resolveInst(extra.rhs); |
| 8296 | const lhs_ty = sema.typeOf(lhs); | |
| 8297 | const rhs_ty = sema.typeOf(rhs); | |
| 8298 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | |
| 8291 | 8299 | |
| 8292 | 8300 | const runtime_src = if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| rs: { |
| 8293 | 8301 | if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| { |
| 8294 | const lhs_ty = sema.typeOf(lhs); | |
| 8295 | 8302 | if (lhs_val.isUndef() or rhs_val.isUndef()) { |
| 8296 | 8303 | return sema.addConstUndef(lhs_ty); |
| 8297 | 8304 | } |
| ... | ... | @@ -8301,13 +8308,12 @@ fn zirShr( |
| 8301 | 8308 | } |
| 8302 | 8309 | if (air_tag == .shr_exact) { |
| 8303 | 8310 | // Detect if any ones would be shifted out. |
| 8304 | const bits = @intCast(u16, rhs_val.toUnsignedInt()); | |
| 8305 | const truncated = try lhs_val.intTrunc(sema.arena, .unsigned, bits); | |
| 8311 | const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val); | |
| 8306 | 8312 | if (!truncated.compareWithZero(.eq)) { |
| 8307 | 8313 | return sema.addConstUndef(lhs_ty); |
| 8308 | 8314 | } |
| 8309 | 8315 | } |
| 8310 | const val = try lhs_val.shr(rhs_val, sema.arena); | |
| 8316 | const val = try lhs_val.shr(rhs_val, lhs_ty, sema.arena); | |
| 8311 | 8317 | return sema.addConstant(lhs_ty, val); |
| 8312 | 8318 | } else { |
| 8313 | 8319 | // Even if lhs is not comptime known, we can still deduce certain things based |
| ... | ... | @@ -8342,32 +8348,15 @@ fn zirBitwise( |
| 8342 | 8348 | const rhs = sema.resolveInst(extra.rhs); |
| 8343 | 8349 | const lhs_ty = sema.typeOf(lhs); |
| 8344 | 8350 | const rhs_ty = sema.typeOf(rhs); |
| 8351 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | |
| 8345 | 8352 | |
| 8346 | 8353 | const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; |
| 8347 | 8354 | const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } }); |
| 8348 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | |
| 8349 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | |
| 8350 | ||
| 8351 | const scalar_type = if (resolved_type.zigTypeTag() == .Vector) | |
| 8352 | resolved_type.elemType() | |
| 8353 | else | |
| 8354 | resolved_type; | |
| 8355 | ||
| 8355 | const scalar_type = resolved_type.scalarType(); | |
| 8356 | 8356 | const scalar_tag = scalar_type.zigTypeTag(); |
| 8357 | 8357 | |
| 8358 | if (lhs_ty.zigTypeTag() == .Vector and rhs_ty.zigTypeTag() == .Vector) { | |
| 8359 | if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) { | |
| 8360 | return sema.fail(block, src, "vector length mismatch: {d} and {d}", .{ | |
| 8361 | lhs_ty.arrayLen(), | |
| 8362 | rhs_ty.arrayLen(), | |
| 8363 | }); | |
| 8364 | } | |
| 8365 | } else if (lhs_ty.zigTypeTag() == .Vector or rhs_ty.zigTypeTag() == .Vector) { | |
| 8366 | return sema.fail(block, src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{ | |
| 8367 | lhs_ty, | |
| 8368 | rhs_ty, | |
| 8369 | }); | |
| 8370 | } | |
| 8358 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); | |
| 8359 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); | |
| 8371 | 8360 | |
| 8372 | 8361 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; |
| 8373 | 8362 | |
| ... | ... | @@ -8377,16 +8366,13 @@ fn zirBitwise( |
| 8377 | 8366 | |
| 8378 | 8367 | if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| { |
| 8379 | 8368 | if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| { |
| 8380 | if (resolved_type.zigTypeTag() == .Vector) { | |
| 8381 | return sema.fail(block, src, "TODO implement zirBitwise for vectors at comptime", .{}); | |
| 8382 | } | |
| 8383 | 8369 | const result_val = switch (air_tag) { |
| 8384 | .bit_and => try lhs_val.bitwiseAnd(rhs_val, sema.arena), | |
| 8385 | .bit_or => try lhs_val.bitwiseOr(rhs_val, sema.arena), | |
| 8386 | .xor => try lhs_val.bitwiseXor(rhs_val, sema.arena), | |
| 8370 | .bit_and => try lhs_val.bitwiseAnd(rhs_val, resolved_type, sema.arena), | |
| 8371 | .bit_or => try lhs_val.bitwiseOr(rhs_val, resolved_type, sema.arena), | |
| 8372 | .xor => try lhs_val.bitwiseXor(rhs_val, resolved_type, sema.arena), | |
| 8387 | 8373 | else => unreachable, |
| 8388 | 8374 | }; |
| 8389 | return sema.addConstant(scalar_type, result_val); | |
| 8375 | return sema.addConstant(resolved_type, result_val); | |
| 8390 | 8376 | } |
| 8391 | 8377 | } |
| 8392 | 8378 | |
| ... | ... | @@ -8413,9 +8399,9 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 8413 | 8399 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { |
| 8414 | 8400 | const target = sema.mod.getTarget(); |
| 8415 | 8401 | if (val.isUndef()) { |
| 8416 | return sema.addConstUndef(scalar_type); | |
| 8402 | return sema.addConstUndef(operand_type); | |
| 8417 | 8403 | } else if (operand_type.zigTypeTag() == .Vector) { |
| 8418 | const vec_len = try sema.usizeCast(block, operand_src, operand_type.arrayLen()); | |
| 8404 | const vec_len = try sema.usizeCast(block, operand_src, operand_type.vectorLen()); | |
| 8419 | 8405 | var elem_val_buf: Value.ElemValueBuffer = undefined; |
| 8420 | 8406 | const elems = try sema.arena.alloc(Value, vec_len); |
| 8421 | 8407 | for (elems) |*elem, i| { |
| ... | ... | @@ -8427,8 +8413,8 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 8427 | 8413 | try Value.Tag.aggregate.create(sema.arena, elems), |
| 8428 | 8414 | ); |
| 8429 | 8415 | } else { |
| 8430 | const result_val = try val.bitwiseNot(scalar_type, sema.arena, target); | |
| 8431 | return sema.addConstant(scalar_type, result_val); | |
| 8416 | const result_val = try val.bitwiseNot(operand_type, sema.arena, target); | |
| 8417 | return sema.addConstant(operand_type, result_val); | |
| 8432 | 8418 | } |
| 8433 | 8419 | } |
| 8434 | 8420 | |
| ... | ... | @@ -8780,8 +8766,19 @@ fn zirNegate( |
| 8780 | 8766 | const src = inst_data.src(); |
| 8781 | 8767 | const lhs_src = src; |
| 8782 | 8768 | const rhs_src = src; // TODO better source location |
| 8783 | const lhs = sema.resolveInst(.zero); | |
| 8769 | ||
| 8784 | 8770 | const rhs = sema.resolveInst(inst_data.operand); |
| 8771 | const rhs_ty = sema.typeOf(rhs); | |
| 8772 | const rhs_scalar_ty = rhs_ty.scalarType(); | |
| 8773 | ||
| 8774 | if (tag_override == .sub and rhs_scalar_ty.isUnsignedInt()) { | |
| 8775 | return sema.fail(block, src, "negation of type '{}'", .{rhs_ty}); | |
| 8776 | } | |
| 8777 | ||
| 8778 | const lhs = if (rhs_ty.zigTypeTag() == .Vector) | |
| 8779 | try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero)) | |
| 8780 | else | |
| 8781 | sema.resolveInst(.zero); | |
| 8785 | 8782 | |
| 8786 | 8783 | return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src); |
| 8787 | 8784 | } |
| ... | ... | @@ -8999,18 +8996,8 @@ fn analyzeArithmetic( |
| 8999 | 8996 | const rhs_ty = sema.typeOf(rhs); |
| 9000 | 8997 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); |
| 9001 | 8998 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); |
| 9002 | if (lhs_zig_ty_tag == .Vector and rhs_zig_ty_tag == .Vector) { | |
| 9003 | if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) { | |
| 9004 | return sema.fail(block, src, "vector length mismatch: {d} and {d}", .{ | |
| 9005 | lhs_ty.arrayLen(), rhs_ty.arrayLen(), | |
| 9006 | }); | |
| 9007 | } | |
| 9008 | return sema.fail(block, src, "TODO implement support for vectors in Sema.analyzeArithmetic", .{}); | |
| 9009 | } else if (lhs_zig_ty_tag == .Vector or rhs_zig_ty_tag == .Vector) { | |
| 9010 | return sema.fail(block, src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{ | |
| 9011 | lhs_ty, rhs_ty, | |
| 9012 | }); | |
| 9013 | } | |
| 8999 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | |
| 9000 | ||
| 9014 | 9001 | if (lhs_zig_ty_tag == .Pointer) switch (lhs_ty.ptrSize()) { |
| 9015 | 9002 | .One, .Slice => {}, |
| 9016 | 9003 | .Many, .C => { |
| ... | ... | @@ -9033,15 +9020,13 @@ fn analyzeArithmetic( |
| 9033 | 9020 | const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ |
| 9034 | 9021 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 9035 | 9022 | }); |
| 9023 | ||
| 9036 | 9024 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| 9037 | 9025 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| 9038 | 9026 | |
| 9039 | const scalar_type = if (resolved_type.zigTypeTag() == .Vector) | |
| 9040 | resolved_type.elemType() | |
| 9041 | else | |
| 9042 | resolved_type; | |
| 9043 | ||
| 9044 | const scalar_tag = scalar_type.zigTypeTag(); | |
| 9027 | const lhs_scalar_ty = lhs_ty.scalarType(); | |
| 9028 | const rhs_scalar_ty = rhs_ty.scalarType(); | |
| 9029 | const scalar_tag = resolved_type.scalarType().zigTypeTag(); | |
| 9045 | 9030 | |
| 9046 | 9031 | const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; |
| 9047 | 9032 | const is_float = scalar_tag == .Float or scalar_tag == .ComptimeFloat; |
| ... | ... | @@ -9075,7 +9060,7 @@ fn analyzeArithmetic( |
| 9075 | 9060 | if (is_int) { |
| 9076 | 9061 | return sema.failWithUseOfUndef(block, rhs_src); |
| 9077 | 9062 | } else { |
| 9078 | return sema.addConstUndef(scalar_type); | |
| 9063 | return sema.addConstUndef(resolved_type); | |
| 9079 | 9064 | } |
| 9080 | 9065 | } |
| 9081 | 9066 | if (rhs_val.compareWithZero(.eq)) { |
| ... | ... | @@ -9087,19 +9072,19 @@ fn analyzeArithmetic( |
| 9087 | 9072 | if (is_int) { |
| 9088 | 9073 | return sema.failWithUseOfUndef(block, lhs_src); |
| 9089 | 9074 | } else { |
| 9090 | return sema.addConstUndef(scalar_type); | |
| 9075 | return sema.addConstUndef(resolved_type); | |
| 9091 | 9076 | } |
| 9092 | 9077 | } |
| 9093 | 9078 | if (maybe_rhs_val) |rhs_val| { |
| 9094 | 9079 | if (is_int) { |
| 9095 | 9080 | return sema.addConstant( |
| 9096 | scalar_type, | |
| 9097 | try lhs_val.intAdd(rhs_val, sema.arena), | |
| 9081 | resolved_type, | |
| 9082 | try lhs_val.intAdd(rhs_val, resolved_type, sema.arena), | |
| 9098 | 9083 | ); |
| 9099 | 9084 | } else { |
| 9100 | 9085 | return sema.addConstant( |
| 9101 | scalar_type, | |
| 9102 | try lhs_val.floatAdd(rhs_val, scalar_type, sema.arena, target), | |
| 9086 | resolved_type, | |
| 9087 | try lhs_val.floatAdd(rhs_val, resolved_type, sema.arena, target), | |
| 9103 | 9088 | ); |
| 9104 | 9089 | } |
| 9105 | 9090 | } else break :rs .{ .src = rhs_src, .air_tag = .add }; |
| ... | ... | @@ -9116,15 +9101,15 @@ fn analyzeArithmetic( |
| 9116 | 9101 | } |
| 9117 | 9102 | if (maybe_rhs_val) |rhs_val| { |
| 9118 | 9103 | if (rhs_val.isUndef()) { |
| 9119 | return sema.addConstUndef(scalar_type); | |
| 9104 | return sema.addConstUndef(resolved_type); | |
| 9120 | 9105 | } |
| 9121 | 9106 | if (rhs_val.compareWithZero(.eq)) { |
| 9122 | 9107 | return casted_lhs; |
| 9123 | 9108 | } |
| 9124 | 9109 | if (maybe_lhs_val) |lhs_val| { |
| 9125 | 9110 | return sema.addConstant( |
| 9126 | scalar_type, | |
| 9127 | try lhs_val.numberAddWrap(rhs_val, scalar_type, sema.arena, target), | |
| 9111 | resolved_type, | |
| 9112 | try lhs_val.numberAddWrap(rhs_val, resolved_type, sema.arena, target), | |
| 9128 | 9113 | ); |
| 9129 | 9114 | } else break :rs .{ .src = lhs_src, .air_tag = .addwrap }; |
| 9130 | 9115 | } else break :rs .{ .src = rhs_src, .air_tag = .addwrap }; |
| ... | ... | @@ -9140,18 +9125,18 @@ fn analyzeArithmetic( |
| 9140 | 9125 | } |
| 9141 | 9126 | if (maybe_rhs_val) |rhs_val| { |
| 9142 | 9127 | if (rhs_val.isUndef()) { |
| 9143 | return sema.addConstUndef(scalar_type); | |
| 9128 | return sema.addConstUndef(resolved_type); | |
| 9144 | 9129 | } |
| 9145 | 9130 | if (rhs_val.compareWithZero(.eq)) { |
| 9146 | 9131 | return casted_lhs; |
| 9147 | 9132 | } |
| 9148 | 9133 | if (maybe_lhs_val) |lhs_val| { |
| 9149 | 9134 | const val = if (scalar_tag == .ComptimeInt) |
| 9150 | try lhs_val.intAdd(rhs_val, sema.arena) | |
| 9135 | try lhs_val.intAdd(rhs_val, resolved_type, sema.arena) | |
| 9151 | 9136 | else |
| 9152 | try lhs_val.intAddSat(rhs_val, scalar_type, sema.arena, target); | |
| 9137 | try lhs_val.intAddSat(rhs_val, resolved_type, sema.arena, target); | |
| 9153 | 9138 | |
| 9154 | return sema.addConstant(scalar_type, val); | |
| 9139 | return sema.addConstant(resolved_type, val); | |
| 9155 | 9140 | } else break :rs .{ .src = lhs_src, .air_tag = .add_sat }; |
| 9156 | 9141 | } else break :rs .{ .src = rhs_src, .air_tag = .add_sat }; |
| 9157 | 9142 | }, |
| ... | ... | @@ -9168,7 +9153,7 @@ fn analyzeArithmetic( |
| 9168 | 9153 | if (is_int) { |
| 9169 | 9154 | return sema.failWithUseOfUndef(block, rhs_src); |
| 9170 | 9155 | } else { |
| 9171 | return sema.addConstUndef(scalar_type); | |
| 9156 | return sema.addConstUndef(resolved_type); | |
| 9172 | 9157 | } |
| 9173 | 9158 | } |
| 9174 | 9159 | if (rhs_val.compareWithZero(.eq)) { |
| ... | ... | @@ -9180,19 +9165,19 @@ fn analyzeArithmetic( |
| 9180 | 9165 | if (is_int) { |
| 9181 | 9166 | return sema.failWithUseOfUndef(block, lhs_src); |
| 9182 | 9167 | } else { |
| 9183 | return sema.addConstUndef(scalar_type); | |
| 9168 | return sema.addConstUndef(resolved_type); | |
| 9184 | 9169 | } |
| 9185 | 9170 | } |
| 9186 | 9171 | if (maybe_rhs_val) |rhs_val| { |
| 9187 | 9172 | if (is_int) { |
| 9188 | 9173 | return sema.addConstant( |
| 9189 | scalar_type, | |
| 9190 | try lhs_val.intSub(rhs_val, sema.arena), | |
| 9174 | resolved_type, | |
| 9175 | try lhs_val.intSub(rhs_val, resolved_type, sema.arena), | |
| 9191 | 9176 | ); |
| 9192 | 9177 | } else { |
| 9193 | 9178 | return sema.addConstant( |
| 9194 | scalar_type, | |
| 9195 | try lhs_val.floatSub(rhs_val, scalar_type, sema.arena, target), | |
| 9179 | resolved_type, | |
| 9180 | try lhs_val.floatSub(rhs_val, resolved_type, sema.arena, target), | |
| 9196 | 9181 | ); |
| 9197 | 9182 | } |
| 9198 | 9183 | } else break :rs .{ .src = rhs_src, .air_tag = .sub }; |
| ... | ... | @@ -9204,7 +9189,7 @@ fn analyzeArithmetic( |
| 9204 | 9189 | // If either of the operands are undefined, the result is undefined. |
| 9205 | 9190 | if (maybe_rhs_val) |rhs_val| { |
| 9206 | 9191 | if (rhs_val.isUndef()) { |
| 9207 | return sema.addConstUndef(scalar_type); | |
| 9192 | return sema.addConstUndef(resolved_type); | |
| 9208 | 9193 | } |
| 9209 | 9194 | if (rhs_val.compareWithZero(.eq)) { |
| 9210 | 9195 | return casted_lhs; |
| ... | ... | @@ -9212,12 +9197,12 @@ fn analyzeArithmetic( |
| 9212 | 9197 | } |
| 9213 | 9198 | if (maybe_lhs_val) |lhs_val| { |
| 9214 | 9199 | if (lhs_val.isUndef()) { |
| 9215 | return sema.addConstUndef(scalar_type); | |
| 9200 | return sema.addConstUndef(resolved_type); | |
| 9216 | 9201 | } |
| 9217 | 9202 | if (maybe_rhs_val) |rhs_val| { |
| 9218 | 9203 | return sema.addConstant( |
| 9219 | scalar_type, | |
| 9220 | try lhs_val.numberSubWrap(rhs_val, scalar_type, sema.arena, target), | |
| 9204 | resolved_type, | |
| 9205 | try lhs_val.numberSubWrap(rhs_val, resolved_type, sema.arena, target), | |
| 9221 | 9206 | ); |
| 9222 | 9207 | } else break :rs .{ .src = rhs_src, .air_tag = .subwrap }; |
| 9223 | 9208 | } else break :rs .{ .src = lhs_src, .air_tag = .subwrap }; |
| ... | ... | @@ -9228,7 +9213,7 @@ fn analyzeArithmetic( |
| 9228 | 9213 | // If either of the operands are undefined, result is undefined. |
| 9229 | 9214 | if (maybe_rhs_val) |rhs_val| { |
| 9230 | 9215 | if (rhs_val.isUndef()) { |
| 9231 | return sema.addConstUndef(scalar_type); | |
| 9216 | return sema.addConstUndef(resolved_type); | |
| 9232 | 9217 | } |
| 9233 | 9218 | if (rhs_val.compareWithZero(.eq)) { |
| 9234 | 9219 | return casted_lhs; |
| ... | ... | @@ -9236,15 +9221,15 @@ fn analyzeArithmetic( |
| 9236 | 9221 | } |
| 9237 | 9222 | if (maybe_lhs_val) |lhs_val| { |
| 9238 | 9223 | if (lhs_val.isUndef()) { |
| 9239 | return sema.addConstUndef(scalar_type); | |
| 9224 | return sema.addConstUndef(resolved_type); | |
| 9240 | 9225 | } |
| 9241 | 9226 | if (maybe_rhs_val) |rhs_val| { |
| 9242 | 9227 | const val = if (scalar_tag == .ComptimeInt) |
| 9243 | try lhs_val.intSub(rhs_val, sema.arena) | |
| 9228 | try lhs_val.intSub(rhs_val, resolved_type, sema.arena) | |
| 9244 | 9229 | else |
| 9245 | try lhs_val.intSubSat(rhs_val, scalar_type, sema.arena, target); | |
| 9230 | try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, target); | |
| 9246 | 9231 | |
| 9247 | return sema.addConstant(scalar_type, val); | |
| 9232 | return sema.addConstant(resolved_type, val); | |
| 9248 | 9233 | } else break :rs .{ .src = rhs_src, .air_tag = .sub_sat }; |
| 9249 | 9234 | } else break :rs .{ .src = lhs_src, .air_tag = .sub_sat }; |
| 9250 | 9235 | }, |
| ... | ... | @@ -9274,7 +9259,7 @@ fn analyzeArithmetic( |
| 9274 | 9259 | if (maybe_lhs_val) |lhs_val| { |
| 9275 | 9260 | if (!lhs_val.isUndef()) { |
| 9276 | 9261 | if (lhs_val.compareWithZero(.eq)) { |
| 9277 | return sema.addConstant(scalar_type, Value.zero); | |
| 9262 | return sema.addConstant(resolved_type, Value.zero); | |
| 9278 | 9263 | } |
| 9279 | 9264 | } |
| 9280 | 9265 | } |
| ... | ... | @@ -9288,27 +9273,27 @@ fn analyzeArithmetic( |
| 9288 | 9273 | } |
| 9289 | 9274 | if (maybe_lhs_val) |lhs_val| { |
| 9290 | 9275 | if (lhs_val.isUndef()) { |
| 9291 | if (lhs_ty.isSignedInt() and rhs_ty.isSignedInt()) { | |
| 9276 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { | |
| 9292 | 9277 | if (maybe_rhs_val) |rhs_val| { |
| 9293 | if (rhs_val.compare(.neq, Value.negative_one, scalar_type)) { | |
| 9294 | return sema.addConstUndef(scalar_type); | |
| 9278 | if (rhs_val.compare(.neq, Value.negative_one, rhs_ty)) { | |
| 9279 | return sema.addConstUndef(resolved_type); | |
| 9295 | 9280 | } |
| 9296 | 9281 | } |
| 9297 | 9282 | return sema.failWithUseOfUndef(block, rhs_src); |
| 9298 | 9283 | } |
| 9299 | return sema.addConstUndef(scalar_type); | |
| 9284 | return sema.addConstUndef(resolved_type); | |
| 9300 | 9285 | } |
| 9301 | 9286 | |
| 9302 | 9287 | if (maybe_rhs_val) |rhs_val| { |
| 9303 | 9288 | if (is_int) { |
| 9304 | 9289 | return sema.addConstant( |
| 9305 | scalar_type, | |
| 9306 | try lhs_val.intDiv(rhs_val, sema.arena), | |
| 9290 | resolved_type, | |
| 9291 | try lhs_val.intDiv(rhs_val, resolved_type, sema.arena), | |
| 9307 | 9292 | ); |
| 9308 | 9293 | } else { |
| 9309 | 9294 | return sema.addConstant( |
| 9310 | scalar_type, | |
| 9311 | try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target), | |
| 9295 | resolved_type, | |
| 9296 | try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target), | |
| 9312 | 9297 | ); |
| 9313 | 9298 | } |
| 9314 | 9299 | } else { |
| ... | ... | @@ -9349,7 +9334,7 @@ fn analyzeArithmetic( |
| 9349 | 9334 | if (maybe_lhs_val) |lhs_val| { |
| 9350 | 9335 | if (!lhs_val.isUndef()) { |
| 9351 | 9336 | if (lhs_val.compareWithZero(.eq)) { |
| 9352 | return sema.addConstant(scalar_type, Value.zero); | |
| 9337 | return sema.addConstant(resolved_type, Value.zero); | |
| 9353 | 9338 | } |
| 9354 | 9339 | } |
| 9355 | 9340 | } |
| ... | ... | @@ -9363,27 +9348,27 @@ fn analyzeArithmetic( |
| 9363 | 9348 | } |
| 9364 | 9349 | if (maybe_lhs_val) |lhs_val| { |
| 9365 | 9350 | if (lhs_val.isUndef()) { |
| 9366 | if (lhs_ty.isSignedInt() and rhs_ty.isSignedInt()) { | |
| 9351 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { | |
| 9367 | 9352 | if (maybe_rhs_val) |rhs_val| { |
| 9368 | if (rhs_val.compare(.neq, Value.negative_one, scalar_type)) { | |
| 9369 | return sema.addConstUndef(scalar_type); | |
| 9353 | if (rhs_val.compare(.neq, Value.negative_one, rhs_ty)) { | |
| 9354 | return sema.addConstUndef(resolved_type); | |
| 9370 | 9355 | } |
| 9371 | 9356 | } |
| 9372 | 9357 | return sema.failWithUseOfUndef(block, rhs_src); |
| 9373 | 9358 | } |
| 9374 | return sema.addConstUndef(scalar_type); | |
| 9359 | return sema.addConstUndef(resolved_type); | |
| 9375 | 9360 | } |
| 9376 | 9361 | |
| 9377 | 9362 | if (maybe_rhs_val) |rhs_val| { |
| 9378 | 9363 | if (is_int) { |
| 9379 | 9364 | return sema.addConstant( |
| 9380 | scalar_type, | |
| 9381 | try lhs_val.intDiv(rhs_val, sema.arena), | |
| 9365 | resolved_type, | |
| 9366 | try lhs_val.intDiv(rhs_val, resolved_type, sema.arena), | |
| 9382 | 9367 | ); |
| 9383 | 9368 | } else { |
| 9384 | 9369 | return sema.addConstant( |
| 9385 | scalar_type, | |
| 9386 | try lhs_val.floatDivTrunc(rhs_val, scalar_type, sema.arena, target), | |
| 9370 | resolved_type, | |
| 9371 | try lhs_val.floatDivTrunc(rhs_val, resolved_type, sema.arena, target), | |
| 9387 | 9372 | ); |
| 9388 | 9373 | } |
| 9389 | 9374 | } else break :rs .{ .src = rhs_src, .air_tag = .div_trunc }; |
| ... | ... | @@ -9412,7 +9397,7 @@ fn analyzeArithmetic( |
| 9412 | 9397 | if (maybe_lhs_val) |lhs_val| { |
| 9413 | 9398 | if (!lhs_val.isUndef()) { |
| 9414 | 9399 | if (lhs_val.compareWithZero(.eq)) { |
| 9415 | return sema.addConstant(scalar_type, Value.zero); | |
| 9400 | return sema.addConstant(resolved_type, Value.zero); | |
| 9416 | 9401 | } |
| 9417 | 9402 | } |
| 9418 | 9403 | } |
| ... | ... | @@ -9426,27 +9411,27 @@ fn analyzeArithmetic( |
| 9426 | 9411 | } |
| 9427 | 9412 | if (maybe_lhs_val) |lhs_val| { |
| 9428 | 9413 | if (lhs_val.isUndef()) { |
| 9429 | if (lhs_ty.isSignedInt() and rhs_ty.isSignedInt()) { | |
| 9414 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { | |
| 9430 | 9415 | if (maybe_rhs_val) |rhs_val| { |
| 9431 | if (rhs_val.compare(.neq, Value.negative_one, scalar_type)) { | |
| 9432 | return sema.addConstUndef(scalar_type); | |
| 9416 | if (rhs_val.compare(.neq, Value.negative_one, rhs_ty)) { | |
| 9417 | return sema.addConstUndef(resolved_type); | |
| 9433 | 9418 | } |
| 9434 | 9419 | } |
| 9435 | 9420 | return sema.failWithUseOfUndef(block, rhs_src); |
| 9436 | 9421 | } |
| 9437 | return sema.addConstUndef(scalar_type); | |
| 9422 | return sema.addConstUndef(resolved_type); | |
| 9438 | 9423 | } |
| 9439 | 9424 | |
| 9440 | 9425 | if (maybe_rhs_val) |rhs_val| { |
| 9441 | 9426 | if (is_int) { |
| 9442 | 9427 | return sema.addConstant( |
| 9443 | scalar_type, | |
| 9444 | try lhs_val.intDivFloor(rhs_val, sema.arena), | |
| 9428 | resolved_type, | |
| 9429 | try lhs_val.intDivFloor(rhs_val, resolved_type, sema.arena), | |
| 9445 | 9430 | ); |
| 9446 | 9431 | } else { |
| 9447 | 9432 | return sema.addConstant( |
| 9448 | scalar_type, | |
| 9449 | try lhs_val.floatDivFloor(rhs_val, scalar_type, sema.arena, target), | |
| 9433 | resolved_type, | |
| 9434 | try lhs_val.floatDivFloor(rhs_val, resolved_type, sema.arena, target), | |
| 9450 | 9435 | ); |
| 9451 | 9436 | } |
| 9452 | 9437 | } else break :rs .{ .src = rhs_src, .air_tag = .div_floor }; |
| ... | ... | @@ -9474,7 +9459,7 @@ fn analyzeArithmetic( |
| 9474 | 9459 | return sema.failWithUseOfUndef(block, rhs_src); |
| 9475 | 9460 | } else { |
| 9476 | 9461 | if (lhs_val.compareWithZero(.eq)) { |
| 9477 | return sema.addConstant(scalar_type, Value.zero); | |
| 9462 | return sema.addConstant(resolved_type, Value.zero); | |
| 9478 | 9463 | } |
| 9479 | 9464 | } |
| 9480 | 9465 | } |
| ... | ... | @@ -9491,14 +9476,14 @@ fn analyzeArithmetic( |
| 9491 | 9476 | if (is_int) { |
| 9492 | 9477 | // TODO: emit compile error if there is a remainder |
| 9493 | 9478 | return sema.addConstant( |
| 9494 | scalar_type, | |
| 9495 | try lhs_val.intDiv(rhs_val, sema.arena), | |
| 9479 | resolved_type, | |
| 9480 | try lhs_val.intDiv(rhs_val, resolved_type, sema.arena), | |
| 9496 | 9481 | ); |
| 9497 | 9482 | } else { |
| 9498 | 9483 | // TODO: emit compile error if there is a remainder |
| 9499 | 9484 | return sema.addConstant( |
| 9500 | scalar_type, | |
| 9501 | try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target), | |
| 9485 | resolved_type, | |
| 9486 | try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target), | |
| 9502 | 9487 | ); |
| 9503 | 9488 | } |
| 9504 | 9489 | } else break :rs .{ .src = rhs_src, .air_tag = .div_exact }; |
| ... | ... | @@ -9516,9 +9501,9 @@ fn analyzeArithmetic( |
| 9516 | 9501 | if (maybe_lhs_val) |lhs_val| { |
| 9517 | 9502 | if (!lhs_val.isUndef()) { |
| 9518 | 9503 | if (lhs_val.compareWithZero(.eq)) { |
| 9519 | return sema.addConstant(scalar_type, Value.zero); | |
| 9504 | return sema.addConstant(resolved_type, Value.zero); | |
| 9520 | 9505 | } |
| 9521 | if (lhs_val.compare(.eq, Value.one, scalar_type)) { | |
| 9506 | if (lhs_val.compare(.eq, Value.one, lhs_ty)) { | |
| 9522 | 9507 | return casted_rhs; |
| 9523 | 9508 | } |
| 9524 | 9509 | } |
| ... | ... | @@ -9528,13 +9513,13 @@ fn analyzeArithmetic( |
| 9528 | 9513 | if (is_int) { |
| 9529 | 9514 | return sema.failWithUseOfUndef(block, rhs_src); |
| 9530 | 9515 | } else { |
| 9531 | return sema.addConstUndef(scalar_type); | |
| 9516 | return sema.addConstUndef(resolved_type); | |
| 9532 | 9517 | } |
| 9533 | 9518 | } |
| 9534 | 9519 | if (rhs_val.compareWithZero(.eq)) { |
| 9535 | return sema.addConstant(scalar_type, Value.zero); | |
| 9520 | return sema.addConstant(resolved_type, Value.zero); | |
| 9536 | 9521 | } |
| 9537 | if (rhs_val.compare(.eq, Value.one, scalar_type)) { | |
| 9522 | if (rhs_val.compare(.eq, Value.one, rhs_ty)) { | |
| 9538 | 9523 | return casted_lhs; |
| 9539 | 9524 | } |
| 9540 | 9525 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -9542,18 +9527,18 @@ fn analyzeArithmetic( |
| 9542 | 9527 | if (is_int) { |
| 9543 | 9528 | return sema.failWithUseOfUndef(block, lhs_src); |
| 9544 | 9529 | } else { |
| 9545 | return sema.addConstUndef(scalar_type); | |
| 9530 | return sema.addConstUndef(resolved_type); | |
| 9546 | 9531 | } |
| 9547 | 9532 | } |
| 9548 | 9533 | if (is_int) { |
| 9549 | 9534 | return sema.addConstant( |
| 9550 | scalar_type, | |
| 9551 | try lhs_val.intMul(rhs_val, sema.arena), | |
| 9535 | resolved_type, | |
| 9536 | try lhs_val.intMul(rhs_val, resolved_type, sema.arena), | |
| 9552 | 9537 | ); |
| 9553 | 9538 | } else { |
| 9554 | 9539 | return sema.addConstant( |
| 9555 | scalar_type, | |
| 9556 | try lhs_val.floatMul(rhs_val, scalar_type, sema.arena, target), | |
| 9540 | resolved_type, | |
| 9541 | try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, target), | |
| 9557 | 9542 | ); |
| 9558 | 9543 | } |
| 9559 | 9544 | } else break :rs .{ .src = lhs_src, .air_tag = .mul }; |
| ... | ... | @@ -9567,30 +9552,30 @@ fn analyzeArithmetic( |
| 9567 | 9552 | if (maybe_lhs_val) |lhs_val| { |
| 9568 | 9553 | if (!lhs_val.isUndef()) { |
| 9569 | 9554 | if (lhs_val.compareWithZero(.eq)) { |
| 9570 | return sema.addConstant(scalar_type, Value.zero); | |
| 9555 | return sema.addConstant(resolved_type, Value.zero); | |
| 9571 | 9556 | } |
| 9572 | if (lhs_val.compare(.eq, Value.one, scalar_type)) { | |
| 9557 | if (lhs_val.compare(.eq, Value.one, lhs_ty)) { | |
| 9573 | 9558 | return casted_rhs; |
| 9574 | 9559 | } |
| 9575 | 9560 | } |
| 9576 | 9561 | } |
| 9577 | 9562 | if (maybe_rhs_val) |rhs_val| { |
| 9578 | 9563 | if (rhs_val.isUndef()) { |
| 9579 | return sema.addConstUndef(scalar_type); | |
| 9564 | return sema.addConstUndef(resolved_type); | |
| 9580 | 9565 | } |
| 9581 | 9566 | if (rhs_val.compareWithZero(.eq)) { |
| 9582 | return sema.addConstant(scalar_type, Value.zero); | |
| 9567 | return sema.addConstant(resolved_type, Value.zero); | |
| 9583 | 9568 | } |
| 9584 | if (rhs_val.compare(.eq, Value.one, scalar_type)) { | |
| 9569 | if (rhs_val.compare(.eq, Value.one, rhs_ty)) { | |
| 9585 | 9570 | return casted_lhs; |
| 9586 | 9571 | } |
| 9587 | 9572 | if (maybe_lhs_val) |lhs_val| { |
| 9588 | 9573 | if (lhs_val.isUndef()) { |
| 9589 | return sema.addConstUndef(scalar_type); | |
| 9574 | return sema.addConstUndef(resolved_type); | |
| 9590 | 9575 | } |
| 9591 | 9576 | return sema.addConstant( |
| 9592 | scalar_type, | |
| 9593 | try lhs_val.numberMulWrap(rhs_val, scalar_type, sema.arena, target), | |
| 9577 | resolved_type, | |
| 9578 | try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, target), | |
| 9594 | 9579 | ); |
| 9595 | 9580 | } else break :rs .{ .src = lhs_src, .air_tag = .mulwrap }; |
| 9596 | 9581 | } else break :rs .{ .src = rhs_src, .air_tag = .mulwrap }; |
| ... | ... | @@ -9603,34 +9588,34 @@ fn analyzeArithmetic( |
| 9603 | 9588 | if (maybe_lhs_val) |lhs_val| { |
| 9604 | 9589 | if (!lhs_val.isUndef()) { |
| 9605 | 9590 | if (lhs_val.compareWithZero(.eq)) { |
| 9606 | return sema.addConstant(scalar_type, Value.zero); | |
| 9591 | return sema.addConstant(resolved_type, Value.zero); | |
| 9607 | 9592 | } |
| 9608 | if (lhs_val.compare(.eq, Value.one, scalar_type)) { | |
| 9593 | if (lhs_val.compare(.eq, Value.one, lhs_ty)) { | |
| 9609 | 9594 | return casted_rhs; |
| 9610 | 9595 | } |
| 9611 | 9596 | } |
| 9612 | 9597 | } |
| 9613 | 9598 | if (maybe_rhs_val) |rhs_val| { |
| 9614 | 9599 | if (rhs_val.isUndef()) { |
| 9615 | return sema.addConstUndef(scalar_type); | |
| 9600 | return sema.addConstUndef(resolved_type); | |
| 9616 | 9601 | } |
| 9617 | 9602 | if (rhs_val.compareWithZero(.eq)) { |
| 9618 | return sema.addConstant(scalar_type, Value.zero); | |
| 9603 | return sema.addConstant(resolved_type, Value.zero); | |
| 9619 | 9604 | } |
| 9620 | if (rhs_val.compare(.eq, Value.one, scalar_type)) { | |
| 9605 | if (rhs_val.compare(.eq, Value.one, rhs_ty)) { | |
| 9621 | 9606 | return casted_lhs; |
| 9622 | 9607 | } |
| 9623 | 9608 | if (maybe_lhs_val) |lhs_val| { |
| 9624 | 9609 | if (lhs_val.isUndef()) { |
| 9625 | return sema.addConstUndef(scalar_type); | |
| 9610 | return sema.addConstUndef(resolved_type); | |
| 9626 | 9611 | } |
| 9627 | 9612 | |
| 9628 | 9613 | const val = if (scalar_tag == .ComptimeInt) |
| 9629 | try lhs_val.intMul(rhs_val, sema.arena) | |
| 9614 | try lhs_val.intMul(rhs_val, resolved_type, sema.arena) | |
| 9630 | 9615 | else |
| 9631 | try lhs_val.intMulSat(rhs_val, scalar_type, sema.arena, target); | |
| 9616 | try lhs_val.intMulSat(rhs_val, resolved_type, sema.arena, target); | |
| 9632 | 9617 | |
| 9633 | return sema.addConstant(scalar_type, val); | |
| 9618 | return sema.addConstant(resolved_type, val); | |
| 9634 | 9619 | } else break :rs .{ .src = lhs_src, .air_tag = .mul_sat }; |
| 9635 | 9620 | } else break :rs .{ .src = rhs_src, .air_tag = .mul_sat }; |
| 9636 | 9621 | }, |
| ... | ... | @@ -9654,9 +9639,9 @@ fn analyzeArithmetic( |
| 9654 | 9639 | return sema.failWithUseOfUndef(block, lhs_src); |
| 9655 | 9640 | } |
| 9656 | 9641 | if (lhs_val.compareWithZero(.eq)) { |
| 9657 | return sema.addConstant(scalar_type, Value.zero); | |
| 9642 | return sema.addConstant(resolved_type, Value.zero); | |
| 9658 | 9643 | } |
| 9659 | } else if (lhs_ty.isSignedInt()) { | |
| 9644 | } else if (lhs_scalar_ty.isSignedInt()) { | |
| 9660 | 9645 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); |
| 9661 | 9646 | } |
| 9662 | 9647 | if (maybe_rhs_val) |rhs_val| { |
| ... | ... | @@ -9667,7 +9652,7 @@ fn analyzeArithmetic( |
| 9667 | 9652 | return sema.failWithDivideByZero(block, rhs_src); |
| 9668 | 9653 | } |
| 9669 | 9654 | if (maybe_lhs_val) |lhs_val| { |
| 9670 | const rem_result = try lhs_val.intRem(rhs_val, sema.arena); | |
| 9655 | const rem_result = try lhs_val.intRem(rhs_val, resolved_type, sema.arena); | |
| 9671 | 9656 | // If this answer could possibly be different by doing `intMod`, |
| 9672 | 9657 | // we must emit a compile error. Otherwise, it's OK. |
| 9673 | 9658 | if (rhs_val.compareWithZero(.lt) != lhs_val.compareWithZero(.lt) and |
| ... | ... | @@ -9681,12 +9666,12 @@ fn analyzeArithmetic( |
| 9681 | 9666 | } |
| 9682 | 9667 | if (lhs_val.compareWithZero(.lt)) { |
| 9683 | 9668 | // Negative |
| 9684 | return sema.addConstant(scalar_type, Value.zero); | |
| 9669 | return sema.addConstant(resolved_type, Value.zero); | |
| 9685 | 9670 | } |
| 9686 | return sema.addConstant(scalar_type, rem_result); | |
| 9671 | return sema.addConstant(resolved_type, rem_result); | |
| 9687 | 9672 | } |
| 9688 | 9673 | break :rs .{ .src = lhs_src, .air_tag = .rem }; |
| 9689 | } else if (rhs_ty.isSignedInt()) { | |
| 9674 | } else if (rhs_scalar_ty.isSignedInt()) { | |
| 9690 | 9675 | return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty); |
| 9691 | 9676 | } else { |
| 9692 | 9677 | break :rs .{ .src = rhs_src, .air_tag = .rem }; |
| ... | ... | @@ -9708,8 +9693,8 @@ fn analyzeArithmetic( |
| 9708 | 9693 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); |
| 9709 | 9694 | } |
| 9710 | 9695 | return sema.addConstant( |
| 9711 | scalar_type, | |
| 9712 | try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target), | |
| 9696 | resolved_type, | |
| 9697 | try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target), | |
| 9713 | 9698 | ); |
| 9714 | 9699 | } else { |
| 9715 | 9700 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); |
| ... | ... | @@ -9745,8 +9730,8 @@ fn analyzeArithmetic( |
| 9745 | 9730 | } |
| 9746 | 9731 | if (maybe_lhs_val) |lhs_val| { |
| 9747 | 9732 | return sema.addConstant( |
| 9748 | scalar_type, | |
| 9749 | try lhs_val.intRem(rhs_val, sema.arena), | |
| 9733 | resolved_type, | |
| 9734 | try lhs_val.intRem(rhs_val, resolved_type, sema.arena), | |
| 9750 | 9735 | ); |
| 9751 | 9736 | } |
| 9752 | 9737 | break :rs .{ .src = lhs_src, .air_tag = .rem }; |
| ... | ... | @@ -9765,12 +9750,12 @@ fn analyzeArithmetic( |
| 9765 | 9750 | } |
| 9766 | 9751 | if (maybe_lhs_val) |lhs_val| { |
| 9767 | 9752 | if (lhs_val.isUndef()) { |
| 9768 | return sema.addConstUndef(scalar_type); | |
| 9753 | return sema.addConstUndef(resolved_type); | |
| 9769 | 9754 | } |
| 9770 | 9755 | if (maybe_rhs_val) |rhs_val| { |
| 9771 | 9756 | return sema.addConstant( |
| 9772 | scalar_type, | |
| 9773 | try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target), | |
| 9757 | resolved_type, | |
| 9758 | try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target), | |
| 9774 | 9759 | ); |
| 9775 | 9760 | } else break :rs .{ .src = rhs_src, .air_tag = .rem }; |
| 9776 | 9761 | } else break :rs .{ .src = lhs_src, .air_tag = .rem }; |
| ... | ... | @@ -9802,8 +9787,8 @@ fn analyzeArithmetic( |
| 9802 | 9787 | } |
| 9803 | 9788 | if (maybe_lhs_val) |lhs_val| { |
| 9804 | 9789 | return sema.addConstant( |
| 9805 | scalar_type, | |
| 9806 | try lhs_val.intMod(rhs_val, sema.arena), | |
| 9790 | resolved_type, | |
| 9791 | try lhs_val.intMod(rhs_val, resolved_type, sema.arena), | |
| 9807 | 9792 | ); |
| 9808 | 9793 | } |
| 9809 | 9794 | break :rs .{ .src = lhs_src, .air_tag = .mod }; |
| ... | ... | @@ -9822,12 +9807,12 @@ fn analyzeArithmetic( |
| 9822 | 9807 | } |
| 9823 | 9808 | if (maybe_lhs_val) |lhs_val| { |
| 9824 | 9809 | if (lhs_val.isUndef()) { |
| 9825 | return sema.addConstUndef(scalar_type); | |
| 9810 | return sema.addConstUndef(resolved_type); | |
| 9826 | 9811 | } |
| 9827 | 9812 | if (maybe_rhs_val) |rhs_val| { |
| 9828 | 9813 | return sema.addConstant( |
| 9829 | scalar_type, | |
| 9830 | try lhs_val.floatMod(rhs_val, scalar_type, sema.arena, target), | |
| 9814 | resolved_type, | |
| 9815 | try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target), | |
| 9831 | 9816 | ); |
| 9832 | 9817 | } else break :rs .{ .src = rhs_src, .air_tag = .mod }; |
| 9833 | 9818 | } else break :rs .{ .src = lhs_src, .air_tag = .mod }; |
| ... | ... | @@ -10178,6 +10163,11 @@ fn analyzeCmp( |
| 10178 | 10163 | ) CompileError!Air.Inst.Ref { |
| 10179 | 10164 | const lhs_ty = sema.typeOf(lhs); |
| 10180 | 10165 | const rhs_ty = sema.typeOf(rhs); |
| 10166 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | |
| 10167 | ||
| 10168 | if (lhs_ty.zigTypeTag() == .Vector and rhs_ty.zigTypeTag() == .Vector) { | |
| 10169 | return sema.cmpVector(block, src, lhs, rhs, op, lhs_src, rhs_src); | |
| 10170 | } | |
| 10181 | 10171 | if (lhs_ty.isNumeric() and rhs_ty.isNumeric()) { |
| 10182 | 10172 | // This operation allows any combination of integer and float types, regardless of the |
| 10183 | 10173 | // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for |
| ... | ... | @@ -10212,6 +10202,12 @@ fn cmpSelf( |
| 10212 | 10202 | if (try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs)) |rhs_val| { |
| 10213 | 10203 | if (rhs_val.isUndef()) return sema.addConstUndef(Type.bool); |
| 10214 | 10204 | |
| 10205 | if (resolved_type.zigTypeTag() == .Vector) { | |
| 10206 | const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.@"bool"); | |
| 10207 | const cmp_val = try lhs_val.compareVector(op, rhs_val, resolved_type, sema.arena); | |
| 10208 | return sema.addConstant(result_ty, cmp_val); | |
| 10209 | } | |
| 10210 | ||
| 10215 | 10211 | if (lhs_val.compare(op, rhs_val, resolved_type)) { |
| 10216 | 10212 | return Air.Inst.Ref.bool_true; |
| 10217 | 10213 | } else { |
| ... | ... | @@ -10237,16 +10233,12 @@ fn cmpSelf( |
| 10237 | 10233 | } |
| 10238 | 10234 | }; |
| 10239 | 10235 | try sema.requireRuntimeBlock(block, runtime_src); |
| 10240 | ||
| 10241 | const tag: Air.Inst.Tag = switch (op) { | |
| 10242 | .lt => .cmp_lt, | |
| 10243 | .lte => .cmp_lte, | |
| 10244 | .eq => .cmp_eq, | |
| 10245 | .gte => .cmp_gte, | |
| 10246 | .gt => .cmp_gt, | |
| 10247 | .neq => .cmp_neq, | |
| 10248 | }; | |
| 10249 | // TODO handle vectors | |
| 10236 | if (resolved_type.zigTypeTag() == .Vector) { | |
| 10237 | const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.@"bool"); | |
| 10238 | const result_ty_ref = try sema.addType(result_ty); | |
| 10239 | return block.addCmpVector(casted_lhs, casted_rhs, op, result_ty_ref); | |
| 10240 | } | |
| 10241 | const tag = Air.Inst.Tag.fromCmpOp(op); | |
| 10250 | 10242 | return block.addBinOp(tag, casted_lhs, casted_rhs); |
| 10251 | 10243 | } |
| 10252 | 10244 | |
| ... | ... | @@ -11367,7 +11359,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi |
| 11367 | 11359 | const elem_ty = operand.elemType2(); |
| 11368 | 11360 | const log2_elem_ty = try sema.log2IntType(block, elem_ty, src); |
| 11369 | 11361 | return Type.Tag.vector.create(sema.arena, .{ |
| 11370 | .len = operand.arrayLen(), | |
| 11362 | .len = operand.vectorLen(), | |
| 11371 | 11363 | .elem_type = log2_elem_ty, |
| 11372 | 11364 | }); |
| 11373 | 11365 | }, |
| ... | ... | @@ -13298,7 +13290,7 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 13298 | 13290 | |
| 13299 | 13291 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { |
| 13300 | 13292 | const target = sema.mod.getTarget(); |
| 13301 | const result_val = val.floatToInt(sema.arena, dest_ty, target) catch |err| switch (err) { | |
| 13293 | const result_val = val.floatToInt(sema.arena, operand_ty, dest_ty, target) catch |err| switch (err) { | |
| 13302 | 13294 | error.FloatCannotFit => { |
| 13303 | 13295 | return sema.fail(block, operand_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty }); |
| 13304 | 13296 | }, |
| ... | ... | @@ -13325,7 +13317,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 13325 | 13317 | |
| 13326 | 13318 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { |
| 13327 | 13319 | const target = sema.mod.getTarget(); |
| 13328 | const result_val = try val.intToFloat(sema.arena, dest_ty, target); | |
| 13320 | const result_val = try val.intToFloat(sema.arena, operand_ty, dest_ty, target); | |
| 13329 | 13321 | return sema.addConstant(dest_ty, result_val); |
| 13330 | 13322 | } |
| 13331 | 13323 | |
| ... | ... | @@ -13535,14 +13527,14 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13535 | 13527 | if (!is_vector) { |
| 13536 | 13528 | return sema.addConstant( |
| 13537 | 13529 | dest_ty, |
| 13538 | try val.intTrunc(sema.arena, dest_info.signedness, dest_info.bits), | |
| 13530 | try val.intTrunc(operand_ty, sema.arena, dest_info.signedness, dest_info.bits), | |
| 13539 | 13531 | ); |
| 13540 | 13532 | } |
| 13541 | 13533 | var elem_buf: Value.ElemValueBuffer = undefined; |
| 13542 | 13534 | const elems = try sema.arena.alloc(Value, operand_ty.vectorLen()); |
| 13543 | 13535 | for (elems) |*elem, i| { |
| 13544 | 13536 | const elem_val = val.elemValueBuffer(i, &elem_buf); |
| 13545 | elem.* = try elem_val.intTrunc(sema.arena, dest_info.signedness, dest_info.bits); | |
| 13537 | elem.* = try elem_val.intTrunc(operand_scalar_ty, sema.arena, dest_info.signedness, dest_info.bits); | |
| 13546 | 13538 | } |
| 13547 | 13539 | return sema.addConstant( |
| 13548 | 13540 | dest_ty, |
| ... | ... | @@ -14097,13 +14089,40 @@ fn checkSimdBinOp( |
| 14097 | 14089 | ) CompileError!SimdBinOp { |
| 14098 | 14090 | const lhs_ty = sema.typeOf(uncasted_lhs); |
| 14099 | 14091 | const rhs_ty = sema.typeOf(uncasted_rhs); |
| 14100 | const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(); | |
| 14101 | const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); | |
| 14102 | 14092 | |
| 14103 | var vec_len: ?usize = null; | |
| 14093 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | |
| 14094 | var vec_len: ?usize = if (lhs_ty.zigTypeTag() == .Vector) lhs_ty.vectorLen() else null; | |
| 14095 | const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{ | |
| 14096 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, | |
| 14097 | }); | |
| 14098 | const lhs = try sema.coerce(block, result_ty, uncasted_lhs, lhs_src); | |
| 14099 | const rhs = try sema.coerce(block, result_ty, uncasted_rhs, rhs_src); | |
| 14100 | ||
| 14101 | return SimdBinOp{ | |
| 14102 | .len = vec_len, | |
| 14103 | .lhs = lhs, | |
| 14104 | .rhs = rhs, | |
| 14105 | .lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs), | |
| 14106 | .rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs), | |
| 14107 | .result_ty = result_ty, | |
| 14108 | .scalar_ty = result_ty.scalarType(), | |
| 14109 | }; | |
| 14110 | } | |
| 14111 | ||
| 14112 | fn checkVectorizableBinaryOperands( | |
| 14113 | sema: *Sema, | |
| 14114 | block: *Block, | |
| 14115 | src: LazySrcLoc, | |
| 14116 | lhs_ty: Type, | |
| 14117 | rhs_ty: Type, | |
| 14118 | lhs_src: LazySrcLoc, | |
| 14119 | rhs_src: LazySrcLoc, | |
| 14120 | ) CompileError!void { | |
| 14121 | const lhs_zig_ty_tag = lhs_ty.zigTypeTag(); | |
| 14122 | const rhs_zig_ty_tag = rhs_ty.zigTypeTag(); | |
| 14104 | 14123 | if (lhs_zig_ty_tag == .Vector and rhs_zig_ty_tag == .Vector) { |
| 14105 | const lhs_len = lhs_ty.arrayLen(); | |
| 14106 | const rhs_len = rhs_ty.arrayLen(); | |
| 14124 | const lhs_len = lhs_ty.vectorLen(); | |
| 14125 | const rhs_len = rhs_ty.vectorLen(); | |
| 14107 | 14126 | if (lhs_len != rhs_len) { |
| 14108 | 14127 | const msg = msg: { |
| 14109 | 14128 | const msg = try sema.errMsg(block, src, "vector length mismatch", .{}); |
| ... | ... | @@ -14114,7 +14133,6 @@ fn checkSimdBinOp( |
| 14114 | 14133 | }; |
| 14115 | 14134 | return sema.failWithOwnedErrorMsg(block, msg); |
| 14116 | 14135 | } |
| 14117 | vec_len = try sema.usizeCast(block, lhs_src, lhs_len); | |
| 14118 | 14136 | } else if (lhs_zig_ty_tag == .Vector or rhs_zig_ty_tag == .Vector) { |
| 14119 | 14137 | const msg = msg: { |
| 14120 | 14138 | const msg = try sema.errMsg(block, src, "mixed scalar and vector operands: {} and {}", .{ |
| ... | ... | @@ -14132,21 +14150,6 @@ fn checkSimdBinOp( |
| 14132 | 14150 | }; |
| 14133 | 14151 | return sema.failWithOwnedErrorMsg(block, msg); |
| 14134 | 14152 | } |
| 14135 | const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{ | |
| 14136 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, | |
| 14137 | }); | |
| 14138 | const lhs = try sema.coerce(block, result_ty, uncasted_lhs, lhs_src); | |
| 14139 | const rhs = try sema.coerce(block, result_ty, uncasted_rhs, rhs_src); | |
| 14140 | ||
| 14141 | return SimdBinOp{ | |
| 14142 | .len = vec_len, | |
| 14143 | .lhs = lhs, | |
| 14144 | .rhs = rhs, | |
| 14145 | .lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs), | |
| 14146 | .rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs), | |
| 14147 | .result_ty = result_ty, | |
| 14148 | .scalar_ty = result_ty.scalarType(), | |
| 14149 | }; | |
| 14150 | 14153 | } |
| 14151 | 14154 | |
| 14152 | 14155 | fn resolveExportOptions( |
| ... | ... | @@ -14376,9 +14379,9 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 14376 | 14379 | while (i < vec_len) : (i += 1) { |
| 14377 | 14380 | const elem_val = operand_val.elemValueBuffer(i, &elem_buf); |
| 14378 | 14381 | switch (operation) { |
| 14379 | .And => accum = try accum.bitwiseAnd(elem_val, sema.arena), | |
| 14380 | .Or => accum = try accum.bitwiseOr(elem_val, sema.arena), | |
| 14381 | .Xor => accum = try accum.bitwiseXor(elem_val, sema.arena), | |
| 14382 | .And => accum = try accum.bitwiseAnd(elem_val, scalar_ty, sema.arena), | |
| 14383 | .Or => accum = try accum.bitwiseOr(elem_val, scalar_ty, sema.arena), | |
| 14384 | .Xor => accum = try accum.bitwiseXor(elem_val, scalar_ty, sema.arena), | |
| 14382 | 14385 | .Min => accum = accum.numberMin(elem_val), |
| 14383 | 14386 | .Max => accum = accum.numberMax(elem_val), |
| 14384 | 14387 | .Add => accum = try accum.numberAddWrap(elem_val, scalar_ty, sema.arena, target), |
| ... | ... | @@ -14697,10 +14700,10 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 14697 | 14700 | .Xchg => operand_val, |
| 14698 | 14701 | .Add => try stored_val.numberAddWrap(operand_val, operand_ty, sema.arena, target), |
| 14699 | 14702 | .Sub => try stored_val.numberSubWrap(operand_val, operand_ty, sema.arena, target), |
| 14700 | .And => try stored_val.bitwiseAnd (operand_val, sema.arena), | |
| 14703 | .And => try stored_val.bitwiseAnd (operand_val, operand_ty, sema.arena), | |
| 14701 | 14704 | .Nand => try stored_val.bitwiseNand (operand_val, operand_ty, sema.arena, target), |
| 14702 | .Or => try stored_val.bitwiseOr (operand_val, sema.arena), | |
| 14703 | .Xor => try stored_val.bitwiseXor (operand_val, sema.arena), | |
| 14705 | .Or => try stored_val.bitwiseOr (operand_val, operand_ty, sema.arena), | |
| 14706 | .Xor => try stored_val.bitwiseXor (operand_val, operand_ty, sema.arena), | |
| 14704 | 14707 | .Max => stored_val.numberMax (operand_val), |
| 14705 | 14708 | .Min => stored_val.numberMin (operand_val), |
| 14706 | 14709 | // zig fmt: on |
| ... | ... | @@ -17523,7 +17526,7 @@ fn coerce( |
| 17523 | 17526 | if (val.floatHasFraction()) { |
| 17524 | 17527 | return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val.fmtValue(inst_ty), dest_ty }); |
| 17525 | 17528 | } |
| 17526 | const result_val = val.floatToInt(sema.arena, dest_ty, target) catch |err| switch (err) { | |
| 17529 | const result_val = val.floatToInt(sema.arena, inst_ty, dest_ty, target) catch |err| switch (err) { | |
| 17527 | 17530 | error.FloatCannotFit => { |
| 17528 | 17531 | return sema.fail(block, inst_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty }); |
| 17529 | 17532 | }, |
| ... | ... | @@ -17586,7 +17589,7 @@ fn coerce( |
| 17586 | 17589 | }, |
| 17587 | 17590 | .Int, .ComptimeInt => int: { |
| 17588 | 17591 | const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse break :int; |
| 17589 | const result_val = try val.intToFloat(sema.arena, dest_ty, target); | |
| 17592 | const result_val = try val.intToFloat(sema.arena, inst_ty, dest_ty, target); | |
| 17590 | 17593 | // TODO implement this compile error |
| 17591 | 17594 | //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty); |
| 17592 | 17595 | //if (!int_again_val.eql(val, inst_ty)) { |
| ... | ... | @@ -17823,8 +17826,21 @@ fn coerceInMemoryAllowed( |
| 17823 | 17826 | return .ok; |
| 17824 | 17827 | } |
| 17825 | 17828 | |
| 17829 | // Vectors | |
| 17830 | if (dest_tag == .Vector and src_tag == .Vector) vectors: { | |
| 17831 | const dest_len = dest_ty.vectorLen(); | |
| 17832 | const src_len = src_ty.vectorLen(); | |
| 17833 | if (dest_len != src_len) break :vectors; | |
| 17834 | ||
| 17835 | const dest_elem_ty = dest_ty.scalarType(); | |
| 17836 | const src_elem_ty = src_ty.scalarType(); | |
| 17837 | const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src); | |
| 17838 | if (child == .no_match) break :vectors; | |
| 17839 | ||
| 17840 | return .ok; | |
| 17841 | } | |
| 17842 | ||
| 17826 | 17843 | // TODO: non-pointer-like optionals |
| 17827 | // TODO: vectors | |
| 17828 | 17844 | |
| 17829 | 17845 | return .no_match; |
| 17830 | 17846 | } |
| ... | ... | @@ -19697,19 +19713,6 @@ fn cmpNumeric( |
| 19697 | 19713 | const lhs_ty_tag = lhs_ty.zigTypeTag(); |
| 19698 | 19714 | const rhs_ty_tag = rhs_ty.zigTypeTag(); |
| 19699 | 19715 | |
| 19700 | if (lhs_ty_tag == .Vector and rhs_ty_tag == .Vector) { | |
| 19701 | if (lhs_ty.vectorLen() != rhs_ty.vectorLen()) { | |
| 19702 | return sema.fail(block, src, "vector length mismatch: {d} and {d}", .{ | |
| 19703 | lhs_ty.vectorLen(), rhs_ty.vectorLen(), | |
| 19704 | }); | |
| 19705 | } | |
| 19706 | return sema.fail(block, src, "TODO implement support for vectors in cmpNumeric", .{}); | |
| 19707 | } else if (lhs_ty_tag == .Vector or rhs_ty_tag == .Vector) { | |
| 19708 | return sema.fail(block, src, "mixed scalar and vector operands to comparison operator: '{}' and '{}'", .{ | |
| 19709 | lhs_ty, rhs_ty, | |
| 19710 | }); | |
| 19711 | } | |
| 19712 | ||
| 19713 | 19716 | const runtime_src: LazySrcLoc = src: { |
| 19714 | 19717 | if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| { |
| 19715 | 19718 | if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| { |
| ... | ... | @@ -19895,6 +19898,46 @@ fn cmpNumeric( |
| 19895 | 19898 | return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs); |
| 19896 | 19899 | } |
| 19897 | 19900 | |
| 19901 | /// Asserts that lhs and rhs types are both vectors. | |
| 19902 | fn cmpVector( | |
| 19903 | sema: *Sema, | |
| 19904 | block: *Block, | |
| 19905 | src: LazySrcLoc, | |
| 19906 | lhs: Air.Inst.Ref, | |
| 19907 | rhs: Air.Inst.Ref, | |
| 19908 | op: std.math.CompareOperator, | |
| 19909 | lhs_src: LazySrcLoc, | |
| 19910 | rhs_src: LazySrcLoc, | |
| 19911 | ) CompileError!Air.Inst.Ref { | |
| 19912 | const lhs_ty = sema.typeOf(lhs); | |
| 19913 | const rhs_ty = sema.typeOf(rhs); | |
| 19914 | assert(lhs_ty.zigTypeTag() == .Vector); | |
| 19915 | assert(rhs_ty.zigTypeTag() == .Vector); | |
| 19916 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); | |
| 19917 | ||
| 19918 | const result_ty = try Type.vector(sema.arena, lhs_ty.vectorLen(), Type.@"bool"); | |
| 19919 | ||
| 19920 | const runtime_src: LazySrcLoc = src: { | |
| 19921 | if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| { | |
| 19922 | if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| { | |
| 19923 | if (lhs_val.isUndef() or rhs_val.isUndef()) { | |
| 19924 | return sema.addConstUndef(result_ty); | |
| 19925 | } | |
| 19926 | const cmp_val = try lhs_val.compareVector(op, rhs_val, lhs_ty, sema.arena); | |
| 19927 | return sema.addConstant(result_ty, cmp_val); | |
| 19928 | } else { | |
| 19929 | break :src rhs_src; | |
| 19930 | } | |
| 19931 | } else { | |
| 19932 | break :src lhs_src; | |
| 19933 | } | |
| 19934 | }; | |
| 19935 | ||
| 19936 | try sema.requireRuntimeBlock(block, runtime_src); | |
| 19937 | const result_ty_inst = try sema.addType(result_ty); | |
| 19938 | return block.addCmpVector(lhs, rhs, op, result_ty_inst); | |
| 19939 | } | |
| 19940 | ||
| 19898 | 19941 | fn wrapOptional( |
| 19899 | 19942 | sema: *Sema, |
| 19900 | 19943 | block: *Block, |
| ... | ... | @@ -21201,7 +21244,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 21201 | 21244 | map.putAssumeCapacityContext(copied_val, {}, .{ .ty = int_tag_ty }); |
| 21202 | 21245 | } else { |
| 21203 | 21246 | const val = if (last_tag_val) |val| |
| 21204 | try val.intAdd(Value.one, sema.arena) | |
| 21247 | try val.intAdd(Value.one, int_tag_ty, sema.arena) | |
| 21205 | 21248 | else |
| 21206 | 21249 | Value.zero; |
| 21207 | 21250 | last_tag_val = val; |
src/value.zig+728-43| ... | ... | @@ -1846,8 +1846,23 @@ pub const Value = extern union { |
| 1846 | 1846 | return order(lhs, rhs).compare(op); |
| 1847 | 1847 | } |
| 1848 | 1848 | |
| 1849 | /// Asserts the value is comparable. Both operands have type `ty`. | |
| 1849 | /// Asserts the values are comparable. Both operands have type `ty`. | |
| 1850 | /// Vector results will be reduced with AND. | |
| 1850 | 1851 | pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type) bool { |
| 1852 | if (ty.zigTypeTag() == .Vector) { | |
| 1853 | var i: usize = 0; | |
| 1854 | while (i < ty.vectorLen()) : (i += 1) { | |
| 1855 | if (!compareScalar(lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType())) { | |
| 1856 | return false; | |
| 1857 | } | |
| 1858 | } | |
| 1859 | return true; | |
| 1860 | } | |
| 1861 | return compareScalar(lhs, op, rhs, ty); | |
| 1862 | } | |
| 1863 | ||
| 1864 | /// Asserts the values are comparable. Both operands have type `ty`. | |
| 1865 | pub fn compareScalar(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type) bool { | |
| 1851 | 1866 | return switch (op) { |
| 1852 | 1867 | .eq => lhs.eql(rhs, ty), |
| 1853 | 1868 | .neq => !lhs.eql(rhs, ty), |
| ... | ... | @@ -1855,18 +1870,25 @@ pub const Value = extern union { |
| 1855 | 1870 | }; |
| 1856 | 1871 | } |
| 1857 | 1872 | |
| 1873 | /// Asserts the values are comparable vectors of type `ty`. | |
| 1874 | pub fn compareVector(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 1875 | assert(ty.zigTypeTag() == .Vector); | |
| 1876 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 1877 | for (result_data) |*scalar, i| { | |
| 1878 | const res_bool = compareScalar(lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType()); | |
| 1879 | scalar.* = if (res_bool) Value.@"true" else Value.@"false"; | |
| 1880 | } | |
| 1881 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 1882 | } | |
| 1883 | ||
| 1858 | 1884 | /// Asserts the value is comparable. |
| 1859 | /// For vectors this is only valid with op == .eq. | |
| 1885 | /// Vector results will be reduced with AND. | |
| 1860 | 1886 | pub fn compareWithZero(lhs: Value, op: std.math.CompareOperator) bool { |
| 1861 | 1887 | switch (lhs.tag()) { |
| 1862 | .repeated => { | |
| 1863 | assert(op == .eq); | |
| 1864 | return lhs.castTag(.repeated).?.data.compareWithZero(.eq); | |
| 1865 | }, | |
| 1888 | .repeated => return lhs.castTag(.repeated).?.data.compareWithZero(op), | |
| 1866 | 1889 | .aggregate => { |
| 1867 | assert(op == .eq); | |
| 1868 | 1890 | for (lhs.castTag(.aggregate).?.data) |elem_val| { |
| 1869 | if (!elem_val.compareWithZero(.eq)) return false; | |
| 1891 | if (!elem_val.compareWithZero(op)) return false; | |
| 1870 | 1892 | } |
| 1871 | 1893 | return true; |
| 1872 | 1894 | }, |
| ... | ... | @@ -2404,6 +2426,27 @@ pub const Value = extern union { |
| 2404 | 2426 | }; |
| 2405 | 2427 | } |
| 2406 | 2428 | |
| 2429 | /// Index into a vector-like `Value`. Asserts `index` is a valid index for `val`. | |
| 2430 | /// Some scalar values are considered vector-like to avoid needing to allocate | |
| 2431 | /// a new `repeated` each time a constant is used. | |
| 2432 | pub fn indexVectorlike(val: Value, index: usize) Value { | |
| 2433 | return switch (val.tag()) { | |
| 2434 | .aggregate => val.castTag(.aggregate).?.data[index], | |
| 2435 | ||
| 2436 | .repeated => val.castTag(.repeated).?.data, | |
| 2437 | // These values will implicitly be treated as `repeated`. | |
| 2438 | .zero, | |
| 2439 | .one, | |
| 2440 | .bool_false, | |
| 2441 | .bool_true, | |
| 2442 | .int_i64, | |
| 2443 | .int_u64, | |
| 2444 | => val, | |
| 2445 | ||
| 2446 | else => unreachable, | |
| 2447 | }; | |
| 2448 | } | |
| 2449 | ||
| 2407 | 2450 | /// Asserts the value is a single-item pointer to an array, or an array, |
| 2408 | 2451 | /// or an unknown-length pointer, and returns the element value at the index. |
| 2409 | 2452 | pub fn elemValue(val: Value, arena: Allocator, index: usize) !Value { |
| ... | ... | @@ -2646,25 +2689,38 @@ pub const Value = extern union { |
| 2646 | 2689 | }; |
| 2647 | 2690 | } |
| 2648 | 2691 | |
| 2649 | pub fn intToFloat(val: Value, arena: Allocator, dest_ty: Type, target: Target) !Value { | |
| 2692 | pub fn intToFloat(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target) !Value { | |
| 2693 | if (int_ty.zigTypeTag() == .Vector) { | |
| 2694 | const result_data = try arena.alloc(Value, int_ty.vectorLen()); | |
| 2695 | for (result_data) |*scalar, i| { | |
| 2696 | scalar.* = try intToFloatScalar(val.indexVectorlike(i), arena, int_ty.scalarType(), float_ty.scalarType(), target); | |
| 2697 | } | |
| 2698 | return Value.Tag.aggregate.create(arena, result_data); | |
| 2699 | } | |
| 2700 | return intToFloatScalar(val, arena, int_ty, float_ty, target); | |
| 2701 | } | |
| 2702 | ||
| 2703 | pub fn intToFloatScalar(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target) !Value { | |
| 2704 | assert(int_ty.isNumeric() and !int_ty.isAnyFloat()); | |
| 2705 | assert(float_ty.isAnyFloat()); | |
| 2650 | 2706 | switch (val.tag()) { |
| 2651 | 2707 | .undef, .zero, .one => return val, |
| 2652 | 2708 | .the_only_possible_value => return Value.initTag(.zero), // for i0, u0 |
| 2653 | 2709 | .int_u64 => { |
| 2654 | return intToFloatInner(val.castTag(.int_u64).?.data, arena, dest_ty, target); | |
| 2710 | return intToFloatInner(val.castTag(.int_u64).?.data, arena, float_ty, target); | |
| 2655 | 2711 | }, |
| 2656 | 2712 | .int_i64 => { |
| 2657 | return intToFloatInner(val.castTag(.int_i64).?.data, arena, dest_ty, target); | |
| 2713 | return intToFloatInner(val.castTag(.int_i64).?.data, arena, float_ty, target); | |
| 2658 | 2714 | }, |
| 2659 | 2715 | .int_big_positive => { |
| 2660 | 2716 | const limbs = val.castTag(.int_big_positive).?.data; |
| 2661 | 2717 | const float = bigIntToFloat(limbs, true); |
| 2662 | return floatToValue(float, arena, dest_ty, target); | |
| 2718 | return floatToValue(float, arena, float_ty, target); | |
| 2663 | 2719 | }, |
| 2664 | 2720 | .int_big_negative => { |
| 2665 | 2721 | const limbs = val.castTag(.int_big_negative).?.data; |
| 2666 | 2722 | const float = bigIntToFloat(limbs, false); |
| 2667 | return floatToValue(float, arena, dest_ty, target); | |
| 2723 | return floatToValue(float, arena, float_ty, target); | |
| 2668 | 2724 | }, |
| 2669 | 2725 | else => unreachable, |
| 2670 | 2726 | } |
| ... | ... | @@ -2694,7 +2750,20 @@ pub const Value = extern union { |
| 2694 | 2750 | } |
| 2695 | 2751 | } |
| 2696 | 2752 | |
| 2697 | pub fn floatToInt(val: Value, arena: Allocator, dest_ty: Type, target: Target) error{ FloatCannotFit, OutOfMemory }!Value { | |
| 2753 | pub fn floatToInt(val: Value, arena: Allocator, float_ty: Type, int_ty: Type, target: Target) error{ FloatCannotFit, OutOfMemory }!Value { | |
| 2754 | if (float_ty.zigTypeTag() == .Vector) { | |
| 2755 | const result_data = try arena.alloc(Value, float_ty.vectorLen()); | |
| 2756 | for (result_data) |*scalar, i| { | |
| 2757 | scalar.* = try floatToIntScalar(val.indexVectorlike(i), arena, float_ty.scalarType(), int_ty.scalarType(), target); | |
| 2758 | } | |
| 2759 | return Value.Tag.aggregate.create(arena, result_data); | |
| 2760 | } | |
| 2761 | return floatToIntScalar(val, arena, float_ty, int_ty, target); | |
| 2762 | } | |
| 2763 | ||
| 2764 | pub fn floatToIntScalar(val: Value, arena: Allocator, float_ty: Type, int_ty: Type, target: Target) error{ FloatCannotFit, OutOfMemory }!Value { | |
| 2765 | assert(float_ty.isAnyFloat()); | |
| 2766 | assert(int_ty.isInt()); | |
| 2698 | 2767 | const Limb = std.math.big.Limb; |
| 2699 | 2768 | |
| 2700 | 2769 | var value = val.toFloat(f64); // TODO: f128 ? |
| ... | ... | @@ -2724,7 +2793,7 @@ pub const Value = extern union { |
| 2724 | 2793 | else |
| 2725 | 2794 | try Value.Tag.int_big_positive.create(arena, result_limbs); |
| 2726 | 2795 | |
| 2727 | if (result.intFitsInType(dest_ty, target)) { | |
| 2796 | if (result.intFitsInType(int_ty, target)) { | |
| 2728 | 2797 | return result; |
| 2729 | 2798 | } else { |
| 2730 | 2799 | return error.FloatCannotFit; |
| ... | ... | @@ -2771,18 +2840,36 @@ pub const Value = extern union { |
| 2771 | 2840 | }; |
| 2772 | 2841 | } |
| 2773 | 2842 | |
| 2774 | /// Supports both floats and ints; handles undefined. | |
| 2843 | /// Supports both (vectors of) floats and ints; handles undefined scalars. | |
| 2775 | 2844 | pub fn numberAddWrap( |
| 2776 | 2845 | lhs: Value, |
| 2777 | 2846 | rhs: Value, |
| 2778 | 2847 | ty: Type, |
| 2779 | 2848 | arena: Allocator, |
| 2780 | 2849 | target: Target, |
| 2850 | ) !Value { | |
| 2851 | if (ty.zigTypeTag() == .Vector) { | |
| 2852 | const result_data = try arena.alloc(Value, ty.vectorLen()); | |
| 2853 | for (result_data) |*scalar, i| { | |
| 2854 | scalar.* = try numberAddWrapScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); | |
| 2855 | } | |
| 2856 | return Value.Tag.aggregate.create(arena, result_data); | |
| 2857 | } | |
| 2858 | return numberAddWrapScalar(lhs, rhs, ty, arena, target); | |
| 2859 | } | |
| 2860 | ||
| 2861 | /// Supports both floats and ints; handles undefined. | |
| 2862 | pub fn numberAddWrapScalar( | |
| 2863 | lhs: Value, | |
| 2864 | rhs: Value, | |
| 2865 | ty: Type, | |
| 2866 | arena: Allocator, | |
| 2867 | target: Target, | |
| 2781 | 2868 | ) !Value { |
| 2782 | 2869 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 2783 | 2870 | |
| 2784 | 2871 | if (ty.zigTypeTag() == .ComptimeInt) { |
| 2785 | return intAdd(lhs, rhs, arena); | |
| 2872 | return intAdd(lhs, rhs, ty, arena); | |
| 2786 | 2873 | } |
| 2787 | 2874 | |
| 2788 | 2875 | if (ty.isAnyFloat()) { |
| ... | ... | @@ -2809,13 +2896,31 @@ pub const Value = extern union { |
| 2809 | 2896 | } |
| 2810 | 2897 | } |
| 2811 | 2898 | |
| 2812 | /// Supports integers only; asserts neither operand is undefined. | |
| 2899 | /// Supports (vectors of) integers only; asserts neither operand is undefined. | |
| 2813 | 2900 | pub fn intAddSat( |
| 2814 | 2901 | lhs: Value, |
| 2815 | 2902 | rhs: Value, |
| 2816 | 2903 | ty: Type, |
| 2817 | 2904 | arena: Allocator, |
| 2818 | 2905 | target: Target, |
| 2906 | ) !Value { | |
| 2907 | if (ty.zigTypeTag() == .Vector) { | |
| 2908 | const result_data = try arena.alloc(Value, ty.vectorLen()); | |
| 2909 | for (result_data) |*scalar, i| { | |
| 2910 | scalar.* = try intAddSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); | |
| 2911 | } | |
| 2912 | return Value.Tag.aggregate.create(arena, result_data); | |
| 2913 | } | |
| 2914 | return intAddSatScalar(lhs, rhs, ty, arena, target); | |
| 2915 | } | |
| 2916 | ||
| 2917 | /// Supports integers only; asserts neither operand is undefined. | |
| 2918 | pub fn intAddSatScalar( | |
| 2919 | lhs: Value, | |
| 2920 | rhs: Value, | |
| 2921 | ty: Type, | |
| 2922 | arena: Allocator, | |
| 2923 | target: Target, | |
| 2819 | 2924 | ) !Value { |
| 2820 | 2925 | assert(!lhs.isUndef()); |
| 2821 | 2926 | assert(!rhs.isUndef()); |
| ... | ... | @@ -2861,18 +2966,36 @@ pub const Value = extern union { |
| 2861 | 2966 | }; |
| 2862 | 2967 | } |
| 2863 | 2968 | |
| 2864 | /// Supports both floats and ints; handles undefined. | |
| 2969 | /// Supports both (vectors of) floats and ints; handles undefined scalars. | |
| 2865 | 2970 | pub fn numberSubWrap( |
| 2866 | 2971 | lhs: Value, |
| 2867 | 2972 | rhs: Value, |
| 2868 | 2973 | ty: Type, |
| 2869 | 2974 | arena: Allocator, |
| 2870 | 2975 | target: Target, |
| 2976 | ) !Value { | |
| 2977 | if (ty.zigTypeTag() == .Vector) { | |
| 2978 | const result_data = try arena.alloc(Value, ty.vectorLen()); | |
| 2979 | for (result_data) |*scalar, i| { | |
| 2980 | scalar.* = try numberSubWrapScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); | |
| 2981 | } | |
| 2982 | return Value.Tag.aggregate.create(arena, result_data); | |
| 2983 | } | |
| 2984 | return numberSubWrapScalar(lhs, rhs, ty, arena, target); | |
| 2985 | } | |
| 2986 | ||
| 2987 | /// Supports both floats and ints; handles undefined. | |
| 2988 | pub fn numberSubWrapScalar( | |
| 2989 | lhs: Value, | |
| 2990 | rhs: Value, | |
| 2991 | ty: Type, | |
| 2992 | arena: Allocator, | |
| 2993 | target: Target, | |
| 2871 | 2994 | ) !Value { |
| 2872 | 2995 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 2873 | 2996 | |
| 2874 | 2997 | if (ty.zigTypeTag() == .ComptimeInt) { |
| 2875 | return intSub(lhs, rhs, arena); | |
| 2998 | return intSub(lhs, rhs, ty, arena); | |
| 2876 | 2999 | } |
| 2877 | 3000 | |
| 2878 | 3001 | if (ty.isAnyFloat()) { |
| ... | ... | @@ -2883,13 +3006,31 @@ pub const Value = extern union { |
| 2883 | 3006 | return overflow_result.wrapped_result; |
| 2884 | 3007 | } |
| 2885 | 3008 | |
| 2886 | /// Supports integers only; asserts neither operand is undefined. | |
| 3009 | /// Supports (vectors of) integers only; asserts neither operand is undefined. | |
| 2887 | 3010 | pub fn intSubSat( |
| 2888 | 3011 | lhs: Value, |
| 2889 | 3012 | rhs: Value, |
| 2890 | 3013 | ty: Type, |
| 2891 | 3014 | arena: Allocator, |
| 2892 | 3015 | target: Target, |
| 3016 | ) !Value { | |
| 3017 | if (ty.zigTypeTag() == .Vector) { | |
| 3018 | const result_data = try arena.alloc(Value, ty.vectorLen()); | |
| 3019 | for (result_data) |*scalar, i| { | |
| 3020 | scalar.* = try intSubSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); | |
| 3021 | } | |
| 3022 | return Value.Tag.aggregate.create(arena, result_data); | |
| 3023 | } | |
| 3024 | return intSubSatScalar(lhs, rhs, ty, arena, target); | |
| 3025 | } | |
| 3026 | ||
| 3027 | /// Supports integers only; asserts neither operand is undefined. | |
| 3028 | pub fn intSubSatScalar( | |
| 3029 | lhs: Value, | |
| 3030 | rhs: Value, | |
| 3031 | ty: Type, | |
| 3032 | arena: Allocator, | |
| 3033 | target: Target, | |
| 2893 | 3034 | ) !Value { |
| 2894 | 3035 | assert(!lhs.isUndef()); |
| 2895 | 3036 | assert(!rhs.isUndef()); |
| ... | ... | @@ -2944,18 +3085,36 @@ pub const Value = extern union { |
| 2944 | 3085 | }; |
| 2945 | 3086 | } |
| 2946 | 3087 | |
| 2947 | /// Supports both floats and ints; handles undefined. | |
| 3088 | /// Supports both (vectors of) floats and ints; handles undefined scalars. | |
| 2948 | 3089 | pub fn numberMulWrap( |
| 2949 | 3090 | lhs: Value, |
| 2950 | 3091 | rhs: Value, |
| 2951 | 3092 | ty: Type, |
| 2952 | 3093 | arena: Allocator, |
| 2953 | 3094 | target: Target, |
| 3095 | ) !Value { | |
| 3096 | if (ty.zigTypeTag() == .Vector) { | |
| 3097 | const result_data = try arena.alloc(Value, ty.vectorLen()); | |
| 3098 | for (result_data) |*scalar, i| { | |
| 3099 | scalar.* = try numberMulWrapScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); | |
| 3100 | } | |
| 3101 | return Value.Tag.aggregate.create(arena, result_data); | |
| 3102 | } | |
| 3103 | return numberMulWrapScalar(lhs, rhs, ty, arena, target); | |
| 3104 | } | |
| 3105 | ||
| 3106 | /// Supports both floats and ints; handles undefined. | |
| 3107 | pub fn numberMulWrapScalar( | |
| 3108 | lhs: Value, | |
| 3109 | rhs: Value, | |
| 3110 | ty: Type, | |
| 3111 | arena: Allocator, | |
| 3112 | target: Target, | |
| 2954 | 3113 | ) !Value { |
| 2955 | 3114 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 2956 | 3115 | |
| 2957 | 3116 | if (ty.zigTypeTag() == .ComptimeInt) { |
| 2958 | return intMul(lhs, rhs, arena); | |
| 3117 | return intMul(lhs, rhs, ty, arena); | |
| 2959 | 3118 | } |
| 2960 | 3119 | |
| 2961 | 3120 | if (ty.isAnyFloat()) { |
| ... | ... | @@ -2966,13 +3125,31 @@ pub const Value = extern union { |
| 2966 | 3125 | return overflow_result.wrapped_result; |
| 2967 | 3126 | } |
| 2968 | 3127 | |
| 2969 | /// Supports integers only; asserts neither operand is undefined. | |
| 3128 | /// Supports (vectors of) integers only; asserts neither operand is undefined. | |
| 2970 | 3129 | pub fn intMulSat( |
| 2971 | 3130 | lhs: Value, |
| 2972 | 3131 | rhs: Value, |
| 2973 | 3132 | ty: Type, |
| 2974 | 3133 | arena: Allocator, |
| 2975 | 3134 | target: Target, |
| 3135 | ) !Value { | |
| 3136 | if (ty.zigTypeTag() == .Vector) { | |
| 3137 | const result_data = try arena.alloc(Value, ty.vectorLen()); | |
| 3138 | for (result_data) |*scalar, i| { | |
| 3139 | scalar.* = try intMulSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); | |
| 3140 | } | |
| 3141 | return Value.Tag.aggregate.create(arena, result_data); | |
| 3142 | } | |
| 3143 | return intMulSatScalar(lhs, rhs, ty, arena, target); | |
| 3144 | } | |
| 3145 | ||
| 3146 | /// Supports (vectors of) integers only; asserts neither operand is undefined. | |
| 3147 | pub fn intMulSatScalar( | |
| 3148 | lhs: Value, | |
| 3149 | rhs: Value, | |
| 3150 | ty: Type, | |
| 3151 | arena: Allocator, | |
| 3152 | target: Target, | |
| 2976 | 3153 | ) !Value { |
| 2977 | 3154 | assert(!lhs.isUndef()); |
| 2978 | 3155 | assert(!rhs.isUndef()); |
| ... | ... | @@ -3025,8 +3202,20 @@ pub const Value = extern union { |
| 3025 | 3202 | }; |
| 3026 | 3203 | } |
| 3027 | 3204 | |
| 3028 | /// operands must be integers; handles undefined. | |
| 3205 | /// operands must be (vectors of) integers; handles undefined scalars. | |
| 3029 | 3206 | pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, target: Target) !Value { |
| 3207 | if (ty.zigTypeTag() == .Vector) { | |
| 3208 | const result_data = try arena.alloc(Value, ty.vectorLen()); | |
| 3209 | for (result_data) |*scalar, i| { | |
| 3210 | scalar.* = try bitwiseNotScalar(val.indexVectorlike(i), ty.scalarType(), arena, target); | |
| 3211 | } | |
| 3212 | return Value.Tag.aggregate.create(arena, result_data); | |
| 3213 | } | |
| 3214 | return bitwiseNotScalar(val, ty, arena, target); | |
| 3215 | } | |
| 3216 | ||
| 3217 | /// operands must be integers; handles undefined. | |
| 3218 | pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, target: Target) !Value { | |
| 3030 | 3219 | if (val.isUndef()) return Value.initTag(.undef); |
| 3031 | 3220 | |
| 3032 | 3221 | const info = ty.intInfo(target); |
| ... | ... | @@ -3050,8 +3239,20 @@ pub const Value = extern union { |
| 3050 | 3239 | return fromBigInt(arena, result_bigint.toConst()); |
| 3051 | 3240 | } |
| 3052 | 3241 | |
| 3242 | /// operands must be (vectors of) integers; handles undefined scalars. | |
| 3243 | pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3244 | if (ty.zigTypeTag() == .Vector) { | |
| 3245 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3246 | for (result_data) |*scalar, i| { | |
| 3247 | scalar.* = try bitwiseAndScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3248 | } | |
| 3249 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3250 | } | |
| 3251 | return bitwiseAndScalar(lhs, rhs, allocator); | |
| 3252 | } | |
| 3253 | ||
| 3053 | 3254 | /// operands must be integers; handles undefined. |
| 3054 | pub fn bitwiseAnd(lhs: Value, rhs: Value, arena: Allocator) !Value { | |
| 3255 | pub fn bitwiseAndScalar(lhs: Value, rhs: Value, arena: Allocator) !Value { | |
| 3055 | 3256 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 3056 | 3257 | |
| 3057 | 3258 | // TODO is this a performance issue? maybe we should try the operation without |
| ... | ... | @@ -3070,22 +3271,46 @@ pub const Value = extern union { |
| 3070 | 3271 | return fromBigInt(arena, result_bigint.toConst()); |
| 3071 | 3272 | } |
| 3072 | 3273 | |
| 3073 | /// operands must be integers; handles undefined. | |
| 3274 | /// operands must be (vectors of) integers; handles undefined scalars. | |
| 3074 | 3275 | pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, target: Target) !Value { |
| 3276 | if (ty.zigTypeTag() == .Vector) { | |
| 3277 | const result_data = try arena.alloc(Value, ty.vectorLen()); | |
| 3278 | for (result_data) |*scalar, i| { | |
| 3279 | scalar.* = try bitwiseNandScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); | |
| 3280 | } | |
| 3281 | return Value.Tag.aggregate.create(arena, result_data); | |
| 3282 | } | |
| 3283 | return bitwiseNandScalar(lhs, rhs, ty, arena, target); | |
| 3284 | } | |
| 3285 | ||
| 3286 | /// operands must be integers; handles undefined. | |
| 3287 | pub fn bitwiseNandScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, target: Target) !Value { | |
| 3075 | 3288 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 3076 | 3289 | |
| 3077 | const anded = try bitwiseAnd(lhs, rhs, arena); | |
| 3290 | const anded = try bitwiseAnd(lhs, rhs, ty, arena); | |
| 3078 | 3291 | |
| 3079 | 3292 | const all_ones = if (ty.isSignedInt()) |
| 3080 | 3293 | try Value.Tag.int_i64.create(arena, -1) |
| 3081 | 3294 | else |
| 3082 | 3295 | try ty.maxInt(arena, target); |
| 3083 | 3296 | |
| 3084 | return bitwiseXor(anded, all_ones, arena); | |
| 3297 | return bitwiseXor(anded, all_ones, ty, arena); | |
| 3298 | } | |
| 3299 | ||
| 3300 | /// operands must be (vectors of) integers; handles undefined scalars. | |
| 3301 | pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3302 | if (ty.zigTypeTag() == .Vector) { | |
| 3303 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3304 | for (result_data) |*scalar, i| { | |
| 3305 | scalar.* = try bitwiseOrScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3306 | } | |
| 3307 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3308 | } | |
| 3309 | return bitwiseOrScalar(lhs, rhs, allocator); | |
| 3085 | 3310 | } |
| 3086 | 3311 | |
| 3087 | 3312 | /// operands must be integers; handles undefined. |
| 3088 | pub fn bitwiseOr(lhs: Value, rhs: Value, arena: Allocator) !Value { | |
| 3313 | pub fn bitwiseOrScalar(lhs: Value, rhs: Value, arena: Allocator) !Value { | |
| 3089 | 3314 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 3090 | 3315 | |
| 3091 | 3316 | // TODO is this a performance issue? maybe we should try the operation without |
| ... | ... | @@ -3103,8 +3328,20 @@ pub const Value = extern union { |
| 3103 | 3328 | return fromBigInt(arena, result_bigint.toConst()); |
| 3104 | 3329 | } |
| 3105 | 3330 | |
| 3331 | /// operands must be (vectors of) integers; handles undefined scalars. | |
| 3332 | pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3333 | if (ty.zigTypeTag() == .Vector) { | |
| 3334 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3335 | for (result_data) |*scalar, i| { | |
| 3336 | scalar.* = try bitwiseXorScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3337 | } | |
| 3338 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3339 | } | |
| 3340 | return bitwiseXorScalar(lhs, rhs, allocator); | |
| 3341 | } | |
| 3342 | ||
| 3106 | 3343 | /// operands must be integers; handles undefined. |
| 3107 | pub fn bitwiseXor(lhs: Value, rhs: Value, arena: Allocator) !Value { | |
| 3344 | pub fn bitwiseXorScalar(lhs: Value, rhs: Value, arena: Allocator) !Value { | |
| 3108 | 3345 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 3109 | 3346 | |
| 3110 | 3347 | // TODO is this a performance issue? maybe we should try the operation without |
| ... | ... | @@ -3123,7 +3360,18 @@ pub const Value = extern union { |
| 3123 | 3360 | return fromBigInt(arena, result_bigint.toConst()); |
| 3124 | 3361 | } |
| 3125 | 3362 | |
| 3126 | pub fn intAdd(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3363 | pub fn intAdd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3364 | if (ty.zigTypeTag() == .Vector) { | |
| 3365 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3366 | for (result_data) |*scalar, i| { | |
| 3367 | scalar.* = try intAddScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3368 | } | |
| 3369 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3370 | } | |
| 3371 | return intAddScalar(lhs, rhs, allocator); | |
| 3372 | } | |
| 3373 | ||
| 3374 | pub fn intAddScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3127 | 3375 | // TODO is this a performance issue? maybe we should try the operation without |
| 3128 | 3376 | // resorting to BigInt first. |
| 3129 | 3377 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -3139,7 +3387,18 @@ pub const Value = extern union { |
| 3139 | 3387 | return fromBigInt(allocator, result_bigint.toConst()); |
| 3140 | 3388 | } |
| 3141 | 3389 | |
| 3142 | pub fn intSub(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3390 | pub fn intSub(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3391 | if (ty.zigTypeTag() == .Vector) { | |
| 3392 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3393 | for (result_data) |*scalar, i| { | |
| 3394 | scalar.* = try intSubScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3395 | } | |
| 3396 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3397 | } | |
| 3398 | return intSubScalar(lhs, rhs, allocator); | |
| 3399 | } | |
| 3400 | ||
| 3401 | pub fn intSubScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3143 | 3402 | // TODO is this a performance issue? maybe we should try the operation without |
| 3144 | 3403 | // resorting to BigInt first. |
| 3145 | 3404 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -3155,7 +3414,18 @@ pub const Value = extern union { |
| 3155 | 3414 | return fromBigInt(allocator, result_bigint.toConst()); |
| 3156 | 3415 | } |
| 3157 | 3416 | |
| 3158 | pub fn intDiv(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3417 | pub fn intDiv(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3418 | if (ty.zigTypeTag() == .Vector) { | |
| 3419 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3420 | for (result_data) |*scalar, i| { | |
| 3421 | scalar.* = try intDivScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3422 | } | |
| 3423 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3424 | } | |
| 3425 | return intDivScalar(lhs, rhs, allocator); | |
| 3426 | } | |
| 3427 | ||
| 3428 | pub fn intDivScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3159 | 3429 | // TODO is this a performance issue? maybe we should try the operation without |
| 3160 | 3430 | // resorting to BigInt first. |
| 3161 | 3431 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -3180,7 +3450,18 @@ pub const Value = extern union { |
| 3180 | 3450 | return fromBigInt(allocator, result_q.toConst()); |
| 3181 | 3451 | } |
| 3182 | 3452 | |
| 3183 | pub fn intDivFloor(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3453 | pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3454 | if (ty.zigTypeTag() == .Vector) { | |
| 3455 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3456 | for (result_data) |*scalar, i| { | |
| 3457 | scalar.* = try intDivFloorScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3458 | } | |
| 3459 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3460 | } | |
| 3461 | return intDivFloorScalar(lhs, rhs, allocator); | |
| 3462 | } | |
| 3463 | ||
| 3464 | pub fn intDivFloorScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3184 | 3465 | // TODO is this a performance issue? maybe we should try the operation without |
| 3185 | 3466 | // resorting to BigInt first. |
| 3186 | 3467 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -3205,7 +3486,18 @@ pub const Value = extern union { |
| 3205 | 3486 | return fromBigInt(allocator, result_q.toConst()); |
| 3206 | 3487 | } |
| 3207 | 3488 | |
| 3208 | pub fn intRem(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3489 | pub fn intRem(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3490 | if (ty.zigTypeTag() == .Vector) { | |
| 3491 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3492 | for (result_data) |*scalar, i| { | |
| 3493 | scalar.* = try intRemScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3494 | } | |
| 3495 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3496 | } | |
| 3497 | return intRemScalar(lhs, rhs, allocator); | |
| 3498 | } | |
| 3499 | ||
| 3500 | pub fn intRemScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3209 | 3501 | // TODO is this a performance issue? maybe we should try the operation without |
| 3210 | 3502 | // resorting to BigInt first. |
| 3211 | 3503 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -3232,7 +3524,18 @@ pub const Value = extern union { |
| 3232 | 3524 | return fromBigInt(allocator, result_r.toConst()); |
| 3233 | 3525 | } |
| 3234 | 3526 | |
| 3235 | pub fn intMod(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3527 | pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3528 | if (ty.zigTypeTag() == .Vector) { | |
| 3529 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3530 | for (result_data) |*scalar, i| { | |
| 3531 | scalar.* = try intModScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3532 | } | |
| 3533 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3534 | } | |
| 3535 | return intModScalar(lhs, rhs, allocator); | |
| 3536 | } | |
| 3537 | ||
| 3538 | pub fn intModScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3236 | 3539 | // TODO is this a performance issue? maybe we should try the operation without |
| 3237 | 3540 | // resorting to BigInt first. |
| 3238 | 3541 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -3270,6 +3573,17 @@ pub const Value = extern union { |
| 3270 | 3573 | } |
| 3271 | 3574 | |
| 3272 | 3575 | pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value { |
| 3576 | if (float_type.zigTypeTag() == .Vector) { | |
| 3577 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 3578 | for (result_data) |*scalar, i| { | |
| 3579 | scalar.* = try floatRemScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 3580 | } | |
| 3581 | return Value.Tag.aggregate.create(arena, result_data); | |
| 3582 | } | |
| 3583 | return floatRemScalar(lhs, rhs, float_type, arena, target); | |
| 3584 | } | |
| 3585 | ||
| 3586 | pub fn floatRemScalar(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value { | |
| 3273 | 3587 | switch (float_type.floatBits(target)) { |
| 3274 | 3588 | 16 => { |
| 3275 | 3589 | const lhs_val = lhs.toFloat(f16); |
| ... | ... | @@ -3304,6 +3618,17 @@ pub const Value = extern union { |
| 3304 | 3618 | } |
| 3305 | 3619 | |
| 3306 | 3620 | pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value { |
| 3621 | if (float_type.zigTypeTag() == .Vector) { | |
| 3622 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 3623 | for (result_data) |*scalar, i| { | |
| 3624 | scalar.* = try floatModScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 3625 | } | |
| 3626 | return Value.Tag.aggregate.create(arena, result_data); | |
| 3627 | } | |
| 3628 | return floatModScalar(lhs, rhs, float_type, arena, target); | |
| 3629 | } | |
| 3630 | ||
| 3631 | pub fn floatModScalar(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value { | |
| 3307 | 3632 | switch (float_type.floatBits(target)) { |
| 3308 | 3633 | 16 => { |
| 3309 | 3634 | const lhs_val = lhs.toFloat(f16); |
| ... | ... | @@ -3337,7 +3662,18 @@ pub const Value = extern union { |
| 3337 | 3662 | } |
| 3338 | 3663 | } |
| 3339 | 3664 | |
| 3340 | pub fn intMul(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3665 | pub fn intMul(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3666 | if (ty.zigTypeTag() == .Vector) { | |
| 3667 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3668 | for (result_data) |*scalar, i| { | |
| 3669 | scalar.* = try intMulScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3670 | } | |
| 3671 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3672 | } | |
| 3673 | return intMulScalar(lhs, rhs, allocator); | |
| 3674 | } | |
| 3675 | ||
| 3676 | pub fn intMulScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3341 | 3677 | // TODO is this a performance issue? maybe we should try the operation without |
| 3342 | 3678 | // resorting to BigInt first. |
| 3343 | 3679 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -3358,7 +3694,30 @@ pub const Value = extern union { |
| 3358 | 3694 | return fromBigInt(allocator, result_bigint.toConst()); |
| 3359 | 3695 | } |
| 3360 | 3696 | |
| 3361 | pub fn intTrunc(val: Value, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16) !Value { | |
| 3697 | pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16) !Value { | |
| 3698 | if (ty.zigTypeTag() == .Vector) { | |
| 3699 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3700 | for (result_data) |*scalar, i| { | |
| 3701 | scalar.* = try intTruncScalar(val.indexVectorlike(i), allocator, signedness, bits); | |
| 3702 | } | |
| 3703 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3704 | } | |
| 3705 | return intTruncScalar(val, allocator, signedness, bits); | |
| 3706 | } | |
| 3707 | ||
| 3708 | /// This variant may vectorize on `bits`. Asserts that `bits` is a (vector of) `u16`. | |
| 3709 | pub fn intTruncBitsAsValue(val: Value, ty: Type, allocator: Allocator, signedness: std.builtin.Signedness, bits: Value) !Value { | |
| 3710 | if (ty.zigTypeTag() == .Vector) { | |
| 3711 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3712 | for (result_data) |*scalar, i| { | |
| 3713 | scalar.* = try intTruncScalar(val.indexVectorlike(i), allocator, signedness, @intCast(u16, bits.indexVectorlike(i).toUnsignedInt())); | |
| 3714 | } | |
| 3715 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3716 | } | |
| 3717 | return intTruncScalar(val, allocator, signedness, @intCast(u16, bits.toUnsignedInt())); | |
| 3718 | } | |
| 3719 | ||
| 3720 | pub fn intTruncScalar(val: Value, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16) !Value { | |
| 3362 | 3721 | if (bits == 0) return Value.zero; |
| 3363 | 3722 | |
| 3364 | 3723 | var val_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -3374,7 +3733,18 @@ pub const Value = extern union { |
| 3374 | 3733 | return fromBigInt(allocator, result_bigint.toConst()); |
| 3375 | 3734 | } |
| 3376 | 3735 | |
| 3377 | pub fn shl(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3736 | pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3737 | if (ty.zigTypeTag() == .Vector) { | |
| 3738 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3739 | for (result_data) |*scalar, i| { | |
| 3740 | scalar.* = try shlScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3741 | } | |
| 3742 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3743 | } | |
| 3744 | return shlScalar(lhs, rhs, allocator); | |
| 3745 | } | |
| 3746 | ||
| 3747 | pub fn shlScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3378 | 3748 | // TODO is this a performance issue? maybe we should try the operation without |
| 3379 | 3749 | // resorting to BigInt first. |
| 3380 | 3750 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -3430,6 +3800,23 @@ pub const Value = extern union { |
| 3430 | 3800 | ty: Type, |
| 3431 | 3801 | arena: Allocator, |
| 3432 | 3802 | target: Target, |
| 3803 | ) !Value { | |
| 3804 | if (ty.zigTypeTag() == .Vector) { | |
| 3805 | const result_data = try arena.alloc(Value, ty.vectorLen()); | |
| 3806 | for (result_data) |*scalar, i| { | |
| 3807 | scalar.* = try shlSatScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); | |
| 3808 | } | |
| 3809 | return Value.Tag.aggregate.create(arena, result_data); | |
| 3810 | } | |
| 3811 | return shlSatScalar(lhs, rhs, ty, arena, target); | |
| 3812 | } | |
| 3813 | ||
| 3814 | pub fn shlSatScalar( | |
| 3815 | lhs: Value, | |
| 3816 | rhs: Value, | |
| 3817 | ty: Type, | |
| 3818 | arena: Allocator, | |
| 3819 | target: Target, | |
| 3433 | 3820 | ) !Value { |
| 3434 | 3821 | // TODO is this a performance issue? maybe we should try the operation without |
| 3435 | 3822 | // resorting to BigInt first. |
| ... | ... | @@ -3458,13 +3845,41 @@ pub const Value = extern union { |
| 3458 | 3845 | arena: Allocator, |
| 3459 | 3846 | target: Target, |
| 3460 | 3847 | ) !Value { |
| 3461 | const shifted = try lhs.shl(rhs, arena); | |
| 3848 | if (ty.zigTypeTag() == .Vector) { | |
| 3849 | const result_data = try arena.alloc(Value, ty.vectorLen()); | |
| 3850 | for (result_data) |*scalar, i| { | |
| 3851 | scalar.* = try shlTruncScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); | |
| 3852 | } | |
| 3853 | return Value.Tag.aggregate.create(arena, result_data); | |
| 3854 | } | |
| 3855 | return shlTruncScalar(lhs, rhs, ty, arena, target); | |
| 3856 | } | |
| 3857 | ||
| 3858 | pub fn shlTruncScalar( | |
| 3859 | lhs: Value, | |
| 3860 | rhs: Value, | |
| 3861 | ty: Type, | |
| 3862 | arena: Allocator, | |
| 3863 | target: Target, | |
| 3864 | ) !Value { | |
| 3865 | const shifted = try lhs.shl(rhs, ty, arena); | |
| 3462 | 3866 | const int_info = ty.intInfo(target); |
| 3463 | const truncated = try shifted.intTrunc(arena, int_info.signedness, int_info.bits); | |
| 3867 | const truncated = try shifted.intTrunc(ty, arena, int_info.signedness, int_info.bits); | |
| 3464 | 3868 | return truncated; |
| 3465 | 3869 | } |
| 3466 | 3870 | |
| 3467 | pub fn shr(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3871 | pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator) !Value { | |
| 3872 | if (ty.zigTypeTag() == .Vector) { | |
| 3873 | const result_data = try allocator.alloc(Value, ty.vectorLen()); | |
| 3874 | for (result_data) |*scalar, i| { | |
| 3875 | scalar.* = try shrScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator); | |
| 3876 | } | |
| 3877 | return Value.Tag.aggregate.create(allocator, result_data); | |
| 3878 | } | |
| 3879 | return shrScalar(lhs, rhs, allocator); | |
| 3880 | } | |
| 3881 | ||
| 3882 | pub fn shrScalar(lhs: Value, rhs: Value, allocator: Allocator) !Value { | |
| 3468 | 3883 | // TODO is this a performance issue? maybe we should try the operation without |
| 3469 | 3884 | // resorting to BigInt first. |
| 3470 | 3885 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -3497,6 +3912,23 @@ pub const Value = extern union { |
| 3497 | 3912 | float_type: Type, |
| 3498 | 3913 | arena: Allocator, |
| 3499 | 3914 | target: Target, |
| 3915 | ) !Value { | |
| 3916 | if (float_type.zigTypeTag() == .Vector) { | |
| 3917 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 3918 | for (result_data) |*scalar, i| { | |
| 3919 | scalar.* = try floatAddScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 3920 | } | |
| 3921 | return Value.Tag.aggregate.create(arena, result_data); | |
| 3922 | } | |
| 3923 | return floatAddScalar(lhs, rhs, float_type, arena, target); | |
| 3924 | } | |
| 3925 | ||
| 3926 | pub fn floatAddScalar( | |
| 3927 | lhs: Value, | |
| 3928 | rhs: Value, | |
| 3929 | float_type: Type, | |
| 3930 | arena: Allocator, | |
| 3931 | target: Target, | |
| 3500 | 3932 | ) !Value { |
| 3501 | 3933 | switch (float_type.floatBits(target)) { |
| 3502 | 3934 | 16 => { |
| ... | ... | @@ -3534,6 +3966,23 @@ pub const Value = extern union { |
| 3534 | 3966 | float_type: Type, |
| 3535 | 3967 | arena: Allocator, |
| 3536 | 3968 | target: Target, |
| 3969 | ) !Value { | |
| 3970 | if (float_type.zigTypeTag() == .Vector) { | |
| 3971 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 3972 | for (result_data) |*scalar, i| { | |
| 3973 | scalar.* = try floatSubScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 3974 | } | |
| 3975 | return Value.Tag.aggregate.create(arena, result_data); | |
| 3976 | } | |
| 3977 | return floatSubScalar(lhs, rhs, float_type, arena, target); | |
| 3978 | } | |
| 3979 | ||
| 3980 | pub fn floatSubScalar( | |
| 3981 | lhs: Value, | |
| 3982 | rhs: Value, | |
| 3983 | float_type: Type, | |
| 3984 | arena: Allocator, | |
| 3985 | target: Target, | |
| 3537 | 3986 | ) !Value { |
| 3538 | 3987 | switch (float_type.floatBits(target)) { |
| 3539 | 3988 | 16 => { |
| ... | ... | @@ -3571,6 +4020,23 @@ pub const Value = extern union { |
| 3571 | 4020 | float_type: Type, |
| 3572 | 4021 | arena: Allocator, |
| 3573 | 4022 | target: Target, |
| 4023 | ) !Value { | |
| 4024 | if (float_type.zigTypeTag() == .Vector) { | |
| 4025 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4026 | for (result_data) |*scalar, i| { | |
| 4027 | scalar.* = try floatDivScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4028 | } | |
| 4029 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4030 | } | |
| 4031 | return floatDivScalar(lhs, rhs, float_type, arena, target); | |
| 4032 | } | |
| 4033 | ||
| 4034 | pub fn floatDivScalar( | |
| 4035 | lhs: Value, | |
| 4036 | rhs: Value, | |
| 4037 | float_type: Type, | |
| 4038 | arena: Allocator, | |
| 4039 | target: Target, | |
| 3574 | 4040 | ) !Value { |
| 3575 | 4041 | switch (float_type.floatBits(target)) { |
| 3576 | 4042 | 16 => { |
| ... | ... | @@ -3611,6 +4077,23 @@ pub const Value = extern union { |
| 3611 | 4077 | float_type: Type, |
| 3612 | 4078 | arena: Allocator, |
| 3613 | 4079 | target: Target, |
| 4080 | ) !Value { | |
| 4081 | if (float_type.zigTypeTag() == .Vector) { | |
| 4082 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4083 | for (result_data) |*scalar, i| { | |
| 4084 | scalar.* = try floatDivFloorScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4085 | } | |
| 4086 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4087 | } | |
| 4088 | return floatDivFloorScalar(lhs, rhs, float_type, arena, target); | |
| 4089 | } | |
| 4090 | ||
| 4091 | pub fn floatDivFloorScalar( | |
| 4092 | lhs: Value, | |
| 4093 | rhs: Value, | |
| 4094 | float_type: Type, | |
| 4095 | arena: Allocator, | |
| 4096 | target: Target, | |
| 3614 | 4097 | ) !Value { |
| 3615 | 4098 | switch (float_type.floatBits(target)) { |
| 3616 | 4099 | 16 => { |
| ... | ... | @@ -3651,6 +4134,23 @@ pub const Value = extern union { |
| 3651 | 4134 | float_type: Type, |
| 3652 | 4135 | arena: Allocator, |
| 3653 | 4136 | target: Target, |
| 4137 | ) !Value { | |
| 4138 | if (float_type.zigTypeTag() == .Vector) { | |
| 4139 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4140 | for (result_data) |*scalar, i| { | |
| 4141 | scalar.* = try floatDivTruncScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4142 | } | |
| 4143 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4144 | } | |
| 4145 | return floatDivTruncScalar(lhs, rhs, float_type, arena, target); | |
| 4146 | } | |
| 4147 | ||
| 4148 | pub fn floatDivTruncScalar( | |
| 4149 | lhs: Value, | |
| 4150 | rhs: Value, | |
| 4151 | float_type: Type, | |
| 4152 | arena: Allocator, | |
| 4153 | target: Target, | |
| 3654 | 4154 | ) !Value { |
| 3655 | 4155 | switch (float_type.floatBits(target)) { |
| 3656 | 4156 | 16 => { |
| ... | ... | @@ -3691,6 +4191,23 @@ pub const Value = extern union { |
| 3691 | 4191 | float_type: Type, |
| 3692 | 4192 | arena: Allocator, |
| 3693 | 4193 | target: Target, |
| 4194 | ) !Value { | |
| 4195 | if (float_type.zigTypeTag() == .Vector) { | |
| 4196 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4197 | for (result_data) |*scalar, i| { | |
| 4198 | scalar.* = try floatMulScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4199 | } | |
| 4200 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4201 | } | |
| 4202 | return floatMulScalar(lhs, rhs, float_type, arena, target); | |
| 4203 | } | |
| 4204 | ||
| 4205 | pub fn floatMulScalar( | |
| 4206 | lhs: Value, | |
| 4207 | rhs: Value, | |
| 4208 | float_type: Type, | |
| 4209 | arena: Allocator, | |
| 4210 | target: Target, | |
| 3694 | 4211 | ) !Value { |
| 3695 | 4212 | switch (float_type.floatBits(target)) { |
| 3696 | 4213 | 16 => { |
| ... | ... | @@ -3726,6 +4243,17 @@ pub const Value = extern union { |
| 3726 | 4243 | } |
| 3727 | 4244 | |
| 3728 | 4245 | pub fn sqrt(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4246 | if (float_type.zigTypeTag() == .Vector) { | |
| 4247 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4248 | for (result_data) |*scalar, i| { | |
| 4249 | scalar.* = try sqrtScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4250 | } | |
| 4251 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4252 | } | |
| 4253 | return sqrtScalar(val, float_type, arena, target); | |
| 4254 | } | |
| 4255 | ||
| 4256 | pub fn sqrtScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 3729 | 4257 | switch (float_type.floatBits(target)) { |
| 3730 | 4258 | 16 => { |
| 3731 | 4259 | const f = val.toFloat(f16); |
| ... | ... | @@ -3758,6 +4286,17 @@ pub const Value = extern union { |
| 3758 | 4286 | } |
| 3759 | 4287 | |
| 3760 | 4288 | pub fn sin(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4289 | if (float_type.zigTypeTag() == .Vector) { | |
| 4290 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4291 | for (result_data) |*scalar, i| { | |
| 4292 | scalar.* = try sinScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4293 | } | |
| 4294 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4295 | } | |
| 4296 | return sinScalar(val, float_type, arena, target); | |
| 4297 | } | |
| 4298 | ||
| 4299 | pub fn sinScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 3761 | 4300 | switch (float_type.floatBits(target)) { |
| 3762 | 4301 | 16 => { |
| 3763 | 4302 | const f = val.toFloat(f16); |
| ... | ... | @@ -3790,6 +4329,17 @@ pub const Value = extern union { |
| 3790 | 4329 | } |
| 3791 | 4330 | |
| 3792 | 4331 | pub fn cos(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4332 | if (float_type.zigTypeTag() == .Vector) { | |
| 4333 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4334 | for (result_data) |*scalar, i| { | |
| 4335 | scalar.* = try cosScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4336 | } | |
| 4337 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4338 | } | |
| 4339 | return cosScalar(val, float_type, arena, target); | |
| 4340 | } | |
| 4341 | ||
| 4342 | pub fn cosScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 3793 | 4343 | switch (float_type.floatBits(target)) { |
| 3794 | 4344 | 16 => { |
| 3795 | 4345 | const f = val.toFloat(f16); |
| ... | ... | @@ -3822,6 +4372,17 @@ pub const Value = extern union { |
| 3822 | 4372 | } |
| 3823 | 4373 | |
| 3824 | 4374 | pub fn exp(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4375 | if (float_type.zigTypeTag() == .Vector) { | |
| 4376 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4377 | for (result_data) |*scalar, i| { | |
| 4378 | scalar.* = try expScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4379 | } | |
| 4380 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4381 | } | |
| 4382 | return expScalar(val, float_type, arena, target); | |
| 4383 | } | |
| 4384 | ||
| 4385 | pub fn expScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 3825 | 4386 | switch (float_type.floatBits(target)) { |
| 3826 | 4387 | 16 => { |
| 3827 | 4388 | const f = val.toFloat(f16); |
| ... | ... | @@ -3854,6 +4415,17 @@ pub const Value = extern union { |
| 3854 | 4415 | } |
| 3855 | 4416 | |
| 3856 | 4417 | pub fn exp2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4418 | if (float_type.zigTypeTag() == .Vector) { | |
| 4419 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4420 | for (result_data) |*scalar, i| { | |
| 4421 | scalar.* = try exp2Scalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4422 | } | |
| 4423 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4424 | } | |
| 4425 | return exp2Scalar(val, float_type, arena, target); | |
| 4426 | } | |
| 4427 | ||
| 4428 | pub fn exp2Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 3857 | 4429 | switch (float_type.floatBits(target)) { |
| 3858 | 4430 | 16 => { |
| 3859 | 4431 | const f = val.toFloat(f16); |
| ... | ... | @@ -3886,6 +4458,17 @@ pub const Value = extern union { |
| 3886 | 4458 | } |
| 3887 | 4459 | |
| 3888 | 4460 | pub fn log(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4461 | if (float_type.zigTypeTag() == .Vector) { | |
| 4462 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4463 | for (result_data) |*scalar, i| { | |
| 4464 | scalar.* = try logScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4465 | } | |
| 4466 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4467 | } | |
| 4468 | return logScalar(val, float_type, arena, target); | |
| 4469 | } | |
| 4470 | ||
| 4471 | pub fn logScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 3889 | 4472 | switch (float_type.floatBits(target)) { |
| 3890 | 4473 | 16 => { |
| 3891 | 4474 | const f = val.toFloat(f16); |
| ... | ... | @@ -3918,6 +4501,17 @@ pub const Value = extern union { |
| 3918 | 4501 | } |
| 3919 | 4502 | |
| 3920 | 4503 | pub fn log2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4504 | if (float_type.zigTypeTag() == .Vector) { | |
| 4505 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4506 | for (result_data) |*scalar, i| { | |
| 4507 | scalar.* = try log2Scalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4508 | } | |
| 4509 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4510 | } | |
| 4511 | return log2Scalar(val, float_type, arena, target); | |
| 4512 | } | |
| 4513 | ||
| 4514 | pub fn log2Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 3921 | 4515 | switch (float_type.floatBits(target)) { |
| 3922 | 4516 | 16 => { |
| 3923 | 4517 | const f = val.toFloat(f16); |
| ... | ... | @@ -3950,6 +4544,17 @@ pub const Value = extern union { |
| 3950 | 4544 | } |
| 3951 | 4545 | |
| 3952 | 4546 | pub fn log10(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4547 | if (float_type.zigTypeTag() == .Vector) { | |
| 4548 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4549 | for (result_data) |*scalar, i| { | |
| 4550 | scalar.* = try log10Scalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4551 | } | |
| 4552 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4553 | } | |
| 4554 | return log10Scalar(val, float_type, arena, target); | |
| 4555 | } | |
| 4556 | ||
| 4557 | pub fn log10Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 3953 | 4558 | switch (float_type.floatBits(target)) { |
| 3954 | 4559 | 16 => { |
| 3955 | 4560 | const f = val.toFloat(f16); |
| ... | ... | @@ -3982,6 +4587,17 @@ pub const Value = extern union { |
| 3982 | 4587 | } |
| 3983 | 4588 | |
| 3984 | 4589 | pub fn fabs(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4590 | if (float_type.zigTypeTag() == .Vector) { | |
| 4591 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4592 | for (result_data) |*scalar, i| { | |
| 4593 | scalar.* = try fabsScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4594 | } | |
| 4595 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4596 | } | |
| 4597 | return fabsScalar(val, float_type, arena, target); | |
| 4598 | } | |
| 4599 | ||
| 4600 | pub fn fabsScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 3985 | 4601 | switch (float_type.floatBits(target)) { |
| 3986 | 4602 | 16 => { |
| 3987 | 4603 | const f = val.toFloat(f16); |
| ... | ... | @@ -4011,6 +4627,17 @@ pub const Value = extern union { |
| 4011 | 4627 | } |
| 4012 | 4628 | |
| 4013 | 4629 | pub fn floor(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4630 | if (float_type.zigTypeTag() == .Vector) { | |
| 4631 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4632 | for (result_data) |*scalar, i| { | |
| 4633 | scalar.* = try floorScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4634 | } | |
| 4635 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4636 | } | |
| 4637 | return floorScalar(val, float_type, arena, target); | |
| 4638 | } | |
| 4639 | ||
| 4640 | pub fn floorScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 4014 | 4641 | switch (float_type.floatBits(target)) { |
| 4015 | 4642 | 16 => { |
| 4016 | 4643 | const f = val.toFloat(f16); |
| ... | ... | @@ -4040,6 +4667,17 @@ pub const Value = extern union { |
| 4040 | 4667 | } |
| 4041 | 4668 | |
| 4042 | 4669 | pub fn ceil(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4670 | if (float_type.zigTypeTag() == .Vector) { | |
| 4671 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4672 | for (result_data) |*scalar, i| { | |
| 4673 | scalar.* = try ceilScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4674 | } | |
| 4675 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4676 | } | |
| 4677 | return ceilScalar(val, float_type, arena, target); | |
| 4678 | } | |
| 4679 | ||
| 4680 | pub fn ceilScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 4043 | 4681 | switch (float_type.floatBits(target)) { |
| 4044 | 4682 | 16 => { |
| 4045 | 4683 | const f = val.toFloat(f16); |
| ... | ... | @@ -4069,6 +4707,17 @@ pub const Value = extern union { |
| 4069 | 4707 | } |
| 4070 | 4708 | |
| 4071 | 4709 | pub fn round(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4710 | if (float_type.zigTypeTag() == .Vector) { | |
| 4711 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4712 | for (result_data) |*scalar, i| { | |
| 4713 | scalar.* = try roundScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4714 | } | |
| 4715 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4716 | } | |
| 4717 | return roundScalar(val, float_type, arena, target); | |
| 4718 | } | |
| 4719 | ||
| 4720 | pub fn roundScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 4072 | 4721 | switch (float_type.floatBits(target)) { |
| 4073 | 4722 | 16 => { |
| 4074 | 4723 | const f = val.toFloat(f16); |
| ... | ... | @@ -4098,6 +4747,17 @@ pub const Value = extern union { |
| 4098 | 4747 | } |
| 4099 | 4748 | |
| 4100 | 4749 | pub fn trunc(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { |
| 4750 | if (float_type.zigTypeTag() == .Vector) { | |
| 4751 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4752 | for (result_data) |*scalar, i| { | |
| 4753 | scalar.* = try truncScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); | |
| 4754 | } | |
| 4755 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4756 | } | |
| 4757 | return truncScalar(val, float_type, arena, target); | |
| 4758 | } | |
| 4759 | ||
| 4760 | pub fn truncScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { | |
| 4101 | 4761 | switch (float_type.floatBits(target)) { |
| 4102 | 4762 | 16 => { |
| 4103 | 4763 | const f = val.toFloat(f16); |
| ... | ... | @@ -4133,6 +4793,31 @@ pub const Value = extern union { |
| 4133 | 4793 | addend: Value, |
| 4134 | 4794 | arena: Allocator, |
| 4135 | 4795 | target: Target, |
| 4796 | ) Allocator.Error!Value { | |
| 4797 | if (float_type.zigTypeTag() == .Vector) { | |
| 4798 | const result_data = try arena.alloc(Value, float_type.vectorLen()); | |
| 4799 | for (result_data) |*scalar, i| { | |
| 4800 | scalar.* = try mulAddScalar( | |
| 4801 | float_type.scalarType(), | |
| 4802 | mulend1.indexVectorlike(i), | |
| 4803 | mulend2.indexVectorlike(i), | |
| 4804 | addend.indexVectorlike(i), | |
| 4805 | arena, | |
| 4806 | target, | |
| 4807 | ); | |
| 4808 | } | |
| 4809 | return Value.Tag.aggregate.create(arena, result_data); | |
| 4810 | } | |
| 4811 | return mulAddScalar(float_type, mulend1, mulend2, addend, arena, target); | |
| 4812 | } | |
| 4813 | ||
| 4814 | pub fn mulAddScalar( | |
| 4815 | float_type: Type, | |
| 4816 | mulend1: Value, | |
| 4817 | mulend2: Value, | |
| 4818 | addend: Value, | |
| 4819 | arena: Allocator, | |
| 4820 | target: Target, | |
| 4136 | 4821 | ) Allocator.Error!Value { |
| 4137 | 4822 | switch (float_type.floatBits(target)) { |
| 4138 | 4823 | 16 => { |