diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 44 | ||||
| -rw-r--r-- | src/value.zig | 32 |
2 files changed, 63 insertions, 13 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index fbf25be288..2cc9b82410 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -758,8 +758,8 @@ fn analyzeBodyInner( .is_non_null => try sema.zirIsNonNull(block, inst), .is_non_null_ptr => try sema.zirIsNonNullPtr(block, inst), .merge_error_sets => try sema.zirMergeErrorSets(block, inst), - .negate => try sema.zirNegate(block, inst, .sub), - .negate_wrap => try sema.zirNegate(block, inst, .subwrap), + .negate => try sema.zirNegate(block, inst), + .negate_wrap => try sema.zirNegateWrap(block, inst), .optional_payload_safe => try sema.zirOptionalPayload(block, inst, true), .optional_payload_safe_ptr => try sema.zirOptionalPayloadPtr(block, inst, true), .optional_payload_unsafe => try sema.zirOptionalPayload(block, inst, false), @@ -9328,15 +9328,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai return sema.fail(block, lhs_src, "TODO runtime array_mul", .{}); } -fn zirNegate( - sema: *Sema, - block: *Block, - inst: Zir.Inst.Index, - tag_override: Zir.Inst.Tag, -) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - +fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const lhs_src = src; @@ -9346,16 +9338,42 @@ fn zirNegate( const rhs_ty = sema.typeOf(rhs); const rhs_scalar_ty = rhs_ty.scalarType(); - if (tag_override == .sub and rhs_scalar_ty.isUnsignedInt()) { + if (rhs_scalar_ty.isUnsignedInt()) { return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)}); } + if (rhs_scalar_ty.isAnyFloat()) { + // We handle comptime negation here to ensure negative zero is represented in the bits. + if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| { + if (rhs_val.isUndef()) return sema.addConstUndef(rhs_ty); + const target = sema.mod.getTarget(); + return sema.addConstant(rhs_ty, try rhs_val.floatNeg(rhs_ty, sema.arena, target)); + } + } + + const lhs = if (rhs_ty.zigTypeTag() == .Vector) + try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero)) + else + sema.resolveInst(.zero); + + return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src); +} + +fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { + const inst_data = sema.code.instructions.items(.data)[inst].un_node; + const src = inst_data.src(); + const lhs_src = src; + const rhs_src = src; // TODO better source location + + const rhs = sema.resolveInst(inst_data.operand); + const rhs_ty = sema.typeOf(rhs); + const lhs = if (rhs_ty.zigTypeTag() == .Vector) try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero)) else sema.resolveInst(.zero); - return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src); + return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src); } fn zirArithmetic( diff --git a/src/value.zig b/src/value.zig index e8ccada8ed..1e70ad0c54 100644 --- a/src/value.zig +++ b/src/value.zig @@ -4155,6 +4155,38 @@ pub const Value = extern union { } } + pub fn floatNeg( + val: Value, + float_type: Type, + arena: Allocator, + target: Target, + ) !Value { + if (float_type.zigTypeTag() == .Vector) { + const result_data = try arena.alloc(Value, float_type.vectorLen()); + for (result_data) |*scalar, i| { + scalar.* = try floatNegScalar(val.indexVectorlike(i), float_type.scalarType(), arena, target); + } + return Value.Tag.aggregate.create(arena, result_data); + } + return floatNegScalar(val, float_type, arena, target); + } + + pub fn floatNegScalar( + val: Value, + float_type: Type, + arena: Allocator, + target: Target, + ) !Value { + switch (float_type.floatBits(target)) { + 16 => return Value.Tag.float_16.create(arena, -val.toFloat(f16)), + 32 => return Value.Tag.float_32.create(arena, -val.toFloat(f32)), + 64 => return Value.Tag.float_64.create(arena, -val.toFloat(f64)), + 80 => return Value.Tag.float_80.create(arena, -val.toFloat(f80)), + 128 => return Value.Tag.float_128.create(arena, -val.toFloat(f128)), + else => unreachable, + } + } + pub fn floatDiv( lhs: Value, rhs: Value, |
