diff options
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 16 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 20 | ||||
| -rw-r--r-- | src/codegen/llvm/bindings.zig | 3 |
3 files changed, 36 insertions, 3 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 54c0dfb3c7..15eb917fda 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1755,6 +1755,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .mul_sat => try airSatOp(f, inst, "muls_"), .shl_sat => try airSatOp(f, inst, "shls_"), + .neg => try airNeg(f, inst), + .sqrt, .sin, .cos, @@ -4098,6 +4100,20 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { return local; } +fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue { + if (f.liveness.isUnused(inst)) return CValue.none; + + const un_op = f.air.instructions.items(.data)[inst].un_op; + const writer = f.object.writer(); + const inst_ty = f.air.typeOfIndex(inst); + const operand = try f.resolveInst(un_op); + const local = try f.allocLocal(inst_ty, .Const); + try writer.writeAll("-"); + try f.writeCValue(writer, operand); + try writer.writeAll(";\n"); + return local; +} + fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; const pl_op = f.air.instructions.items(.data)[inst].pl_op; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index c62860c88d..529cd206ac 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4022,6 +4022,7 @@ pub const FuncGen = struct { .ceil => try self.airUnaryOp(inst, .ceil), .round => try self.airUnaryOp(inst, .round), .trunc_float => try self.airUnaryOp(inst, .trunc), + .neg => try self.airUnaryOp(inst, .neg), .cmp_eq => try self.airCmp(inst, .eq), .cmp_gt => try self.airCmp(inst, .gt), @@ -6548,13 +6549,14 @@ pub const FuncGen = struct { fabs, floor, fma, + fmax, + fmin, + fmod, log, log10, log2, - fmax, - fmin, mul, - fmod, + neg, round, sin, sqrt, @@ -6587,6 +6589,7 @@ pub const FuncGen = struct { var fn_name_buf: [64]u8 = undefined; const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) { // Some operations are dedicated LLVM instructions, not available as intrinsics + .neg => return self.builder.buildFNeg(params[0], ""), .add => return self.builder.buildFAdd(params[0], params[1], ""), .sub => return self.builder.buildFSub(params[0], params[1], ""), .mul => return self.builder.buildFMul(params[0], params[1], ""), @@ -6598,6 +6601,17 @@ pub const FuncGen = struct { } else b: { const float_bits = scalar_ty.floatBits(target); break :b switch (op) { + .neg => { + // In this case we can generate a softfloat negation by XORing the + // bits with a constant. + const int_llvm_ty = self.dg.context.intType(float_bits); + const one = int_llvm_ty.constInt(1, .False); + const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False); + const sign_mask = one.constShl(shift_amt); + const bitcasted_operand = self.builder.buildBitCast(params[0], int_llvm_ty, ""); + const result = self.builder.buildXor(bitcasted_operand, sign_mask, ""); + return self.builder.buildBitCast(result, llvm_ty, ""); + }, .add, .sub, .div, .mul => FloatOpStrat{ .libc = std.fmt.bufPrintZ(&fn_name_buf, "__{s}{s}f3", .{ @tagName(op), compilerRtFloatAbbrev(float_bits), diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 671014ba3b..8aa8e5c6f2 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -549,6 +549,9 @@ pub const Builder = opaque { pub const buildFSub = LLVMBuildFSub; extern fn LLVMBuildFSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; + pub const buildFNeg = LLVMBuildFNeg; + extern fn LLVMBuildFNeg(*const Builder, V: *const Value, Name: [*:0]const u8) *const Value; + pub const buildSub = LLVMBuildSub; extern fn LLVMBuildSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; |
