Commit a028488384

Andrew Kelley <andrew@ziglang.org>
2022-02-08 00:48:37
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.
1 parent 722d4a1
Changed files (3)
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";
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 {
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,
         }
     }