From 722d4a11bbba4052558f6f69b7e710d1206f3355 Mon Sep 17 00:00:00 2001 From: John Schmidt Date: Fri, 4 Feb 2022 20:21:15 +0100 Subject: stage2: implement @sqrt for f{16,32,64} Support for f128, comptime_float, and c_longdouble require improvements to compiler_rt and will implemented in a later PR. Some of the code in this commit could be made more generic, for instance `llvm.airSqrt` could probably be `llvm.airUnaryMath`, but let's cross that bridge when we get to it. --- src/value.zig | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src/value.zig') diff --git a/src/value.zig b/src/value.zig index cc6827b0cc..4bb0a58aed 100644 --- a/src/value.zig +++ b/src/value.zig @@ -3265,6 +3265,28 @@ pub const Value = extern union { } } + pub fn sqrt(val: Value, float_type: Type, arena: Allocator) !Value { + switch (float_type.tag()) { + .f16 => { + const f = val.toFloat(f16); + return Value.Tag.float_16.create(arena, @sqrt(f)); + }, + .f32 => { + const f = val.toFloat(f32); + return Value.Tag.float_32.create(arena, @sqrt(f)); + }, + .f64 => { + const f = val.toFloat(f64); + return Value.Tag.float_64.create(arena, @sqrt(f)); + }, + + // TODO: implement @sqrt for these types + .f128, .comptime_float, .c_longdouble => unreachable, + + else => unreachable, + } + } + /// This type is not copyable since it may contain pointers to its inner data. pub const Payload = struct { tag: Tag, -- cgit v1.2.3 From a028488384c599aa997ba04bbd5ed98f2172630c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 7 Feb 2022 16:48:37 -0700 Subject: Sema: clean up zirUnaryMath * pass air_tag instead of zir_tag * also pass eval function so that the branch only happens once and the body of zirUnaryMath is simplified * Value.sqrt: update to handle f80 and f128 in the normalized way that includes handling c_longdouble. Semi-related change: fix incorrect sqrt builtin name for f80 in stage1. --- src/Sema.zig | 81 +++++++++++++++----------------------------------- src/stage1/codegen.cpp | 2 +- src/value.zig | 28 +++++++++++------ 3 files changed, 44 insertions(+), 67 deletions(-) (limited to 'src/value.zig') diff --git a/src/Sema.zig b/src/Sema.zig index b1772502bf..72dfb4420b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -745,19 +745,19 @@ fn analyzeBodyInner( .clz => try sema.zirClzCtz(block, inst, .clz, Value.clz), .ctz => try sema.zirClzCtz(block, inst, .ctz, Value.ctz), - .sqrt => try sema.zirUnaryMath(block, inst, .sqrt), - .sin => try sema.zirUnaryMath(block, inst, .sin), - .cos => try sema.zirUnaryMath(block, inst, .cos), - .exp => try sema.zirUnaryMath(block, inst, .exp), - .exp2 => try sema.zirUnaryMath(block, inst, .exp2), - .log => try sema.zirUnaryMath(block, inst, .log), - .log2 => try sema.zirUnaryMath(block, inst, .log2), - .log10 => try sema.zirUnaryMath(block, inst, .log10), - .fabs => try sema.zirUnaryMath(block, inst, .fabs), - .floor => try sema.zirUnaryMath(block, inst, .floor), - .ceil => try sema.zirUnaryMath(block, inst, .ceil), - .trunc => try sema.zirUnaryMath(block, inst, .trunc), - .round => try sema.zirUnaryMath(block, inst, .round), + .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt), + .sin => @panic("TODO"), + .cos => @panic("TODO"), + .exp => @panic("TODO"), + .exp2 => @panic("TODO"), + .log => @panic("TODO"), + .log2 => @panic("TODO"), + .log10 => @panic("TODO"), + .fabs => @panic("TODO"), + .floor => @panic("TODO"), + .ceil => @panic("TODO"), + .trunc => @panic("TODO"), + .round => @panic("TODO"), .error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent), .error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon), @@ -11014,60 +11014,27 @@ fn zirUnaryMath( sema: *Sema, block: *Block, inst: Zir.Inst.Index, - zir_tag: Zir.Inst.Tag, + air_tag: Air.Inst.Tag, + eval: fn (Value, Type, Allocator, std.Target) Allocator.Error!Value, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[inst].un_node; - const src = inst_data.src(); const operand = sema.resolveInst(inst_data.operand); + const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand_ty = sema.typeOf(operand); - const operand_zig_ty_tag = operand_ty.zigTypeTag(); + try sema.checkFloatType(block, operand_src, operand_ty); - const is_float = operand_zig_ty_tag == .Float or operand_zig_ty_tag == .ComptimeFloat; - if (!is_float) { - return sema.fail(block, src, "expected float type, found '{s}'", .{@tagName(operand_zig_ty_tag)}); + if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| { + if (operand_val.isUndef()) return sema.addConstUndef(operand_ty); + const target = sema.mod.getTarget(); + const result_val = try eval(operand_val, operand_ty, sema.arena, target); + return sema.addConstant(operand_ty, result_val); } - switch (zir_tag) { - .sqrt => { - switch (operand_ty.tag()) { - .f128, - .comptime_float, - .c_longdouble, - => |t| return sema.fail(block, src, "TODO implement @sqrt for type '{s}'", .{@tagName(t)}), - else => {}, - } - - const maybe_operand_val = try sema.resolveMaybeUndefVal(block, src, operand); - if (maybe_operand_val) |val| { - if (val.isUndef()) - return sema.addConstUndef(operand_ty); - const result_val = try val.sqrt(operand_ty, sema.arena); - return sema.addConstant(operand_ty, result_val); - } - - try sema.requireRuntimeBlock(block, src); - return block.addUnOp(.sqrt, operand); - }, - - .sin, - .cos, - .exp, - .exp2, - .log, - .log2, - .log10, - .fabs, - .floor, - .ceil, - .trunc, - .round, - => return sema.fail(block, src, "TODO: implement zirUnaryMath for ZIR tag '{s}'", .{@tagName(zir_tag)}), - - else => unreachable, - } + try sema.requireRuntimeBlock(block, operand_src); + return block.addUnOp(air_tag, operand); } fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 02f84beeab..c06f71e834 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -6996,7 +6996,7 @@ static LLVMValueRef ir_render_soft_f80_float_op(CodeGen *g, Stage1Air *executabl const char *func_name; switch (instruction->fn_id) { case BuiltinFnIdSqrt: - func_name = "__sqrt"; + func_name = "__sqrtx"; break; case BuiltinFnIdSin: func_name = "__sinx"; diff --git a/src/value.zig b/src/value.zig index 4bb0a58aed..23a04f2e5a 100644 --- a/src/value.zig +++ b/src/value.zig @@ -3265,24 +3265,34 @@ pub const Value = extern union { } } - pub fn sqrt(val: Value, float_type: Type, arena: Allocator) !Value { - switch (float_type.tag()) { - .f16 => { + pub fn sqrt(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value { + switch (float_type.floatBits(target)) { + 16 => { const f = val.toFloat(f16); return Value.Tag.float_16.create(arena, @sqrt(f)); }, - .f32 => { + 32 => { const f = val.toFloat(f32); return Value.Tag.float_32.create(arena, @sqrt(f)); }, - .f64 => { + 64 => { const f = val.toFloat(f64); return Value.Tag.float_64.create(arena, @sqrt(f)); }, - - // TODO: implement @sqrt for these types - .f128, .comptime_float, .c_longdouble => unreachable, - + 80 => { + if (true) { + @panic("TODO implement compiler_rt __sqrtx"); + } + const f = val.toFloat(f80); + return Value.Tag.float_80.create(arena, @sqrt(f)); + }, + 128 => { + if (true) { + @panic("TODO implement compiler_rt sqrtq"); + } + const f = val.toFloat(f128); + return Value.Tag.float_128.create(arena, @sqrt(f)); + }, else => unreachable, } } -- cgit v1.2.3