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.
This commit is contained in:
Andrew Kelley 2022-02-07 16:48:37 -07:00
parent 722d4a11bb
commit a028488384
3 changed files with 44 additions and 67 deletions

View File

@ -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 {

View File

@ -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";

View File

@ -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,
}
}