mirror of
https://github.com/ziglang/zig.git
synced 2026-01-02 19:43:29 +00:00
stage2: add floatCast to zir and ir
This commit is contained in:
parent
7b52dbbf83
commit
7e7d1df4da
@ -2352,6 +2352,7 @@ fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In
|
||||
.fntype => return self.analyzeInstFnType(scope, old_inst.castTag(.fntype).?),
|
||||
.intcast => return self.analyzeInstIntCast(scope, old_inst.castTag(.intcast).?),
|
||||
.bitcast => return self.analyzeInstBitCast(scope, old_inst.castTag(.bitcast).?),
|
||||
.floatcast => return self.analyzeInstFloatCast(scope, old_inst.castTag(.floatcast).?),
|
||||
.elemptr => return self.analyzeInstElemPtr(scope, old_inst.castTag(.elemptr).?),
|
||||
.add => return self.analyzeInstAdd(scope, old_inst.castTag(.add).?),
|
||||
.sub => return self.analyzeInstSub(scope, old_inst.castTag(.sub).?),
|
||||
@ -2796,16 +2797,16 @@ fn analyzeInstFieldPtr(self: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPt
|
||||
}
|
||||
}
|
||||
|
||||
fn analyzeInstIntCast(self: *Module, scope: *Scope, intcast: *zir.Inst.IntCast) InnerError!*Inst {
|
||||
const dest_type = try self.resolveType(scope, intcast.positionals.dest_type);
|
||||
const new_inst = try self.resolveInst(scope, intcast.positionals.value);
|
||||
fn analyzeInstIntCast(self: *Module, scope: *Scope, inst: *zir.Inst.IntCast) InnerError!*Inst {
|
||||
const dest_type = try self.resolveType(scope, inst.positionals.dest_type);
|
||||
const operand = try self.resolveInst(scope, inst.positionals.operand);
|
||||
|
||||
const dest_is_comptime_int = switch (dest_type.zigTypeTag()) {
|
||||
.ComptimeInt => true,
|
||||
.Int => false,
|
||||
else => return self.fail(
|
||||
scope,
|
||||
intcast.positionals.dest_type.src,
|
||||
inst.positionals.dest_type.src,
|
||||
"expected integer type, found '{}'",
|
||||
.{
|
||||
dest_type,
|
||||
@ -2813,21 +2814,23 @@ fn analyzeInstIntCast(self: *Module, scope: *Scope, intcast: *zir.Inst.IntCast)
|
||||
),
|
||||
};
|
||||
|
||||
switch (new_inst.ty.zigTypeTag()) {
|
||||
switch (operand.ty.zigTypeTag()) {
|
||||
.ComptimeInt, .Int => {},
|
||||
else => return self.fail(
|
||||
scope,
|
||||
intcast.positionals.value.src,
|
||||
inst.positionals.operand.src,
|
||||
"expected integer type, found '{}'",
|
||||
.{new_inst.ty},
|
||||
.{operand.ty},
|
||||
),
|
||||
}
|
||||
|
||||
if (dest_is_comptime_int or new_inst.value() != null) {
|
||||
return self.coerce(scope, dest_type, new_inst);
|
||||
if (operand.value() != null) {
|
||||
return self.coerce(scope, dest_type, operand);
|
||||
} else if (dest_is_comptime_int) {
|
||||
return self.fail(scope, inst.base.src, "unable to cast runtime value to 'comptime_int'", .{});
|
||||
}
|
||||
|
||||
return self.fail(scope, intcast.base.src, "TODO implement analyze widen or shorten int", .{});
|
||||
return self.fail(scope, inst.base.src, "TODO implement analyze widen or shorten int", .{});
|
||||
}
|
||||
|
||||
fn analyzeInstBitCast(self: *Module, scope: *Scope, inst: *zir.Inst.BitCast) InnerError!*Inst {
|
||||
@ -2836,6 +2839,42 @@ fn analyzeInstBitCast(self: *Module, scope: *Scope, inst: *zir.Inst.BitCast) Inn
|
||||
return self.bitcast(scope, dest_type, operand);
|
||||
}
|
||||
|
||||
fn analyzeInstFloatCast(self: *Module, scope: *Scope, inst: *zir.Inst.FloatCast) InnerError!*Inst {
|
||||
const dest_type = try self.resolveType(scope, inst.positionals.dest_type);
|
||||
const operand = try self.resolveInst(scope, inst.positionals.operand);
|
||||
|
||||
const dest_is_comptime_float = switch (dest_type.zigTypeTag()) {
|
||||
.ComptimeFloat => true,
|
||||
.Float => false,
|
||||
else => return self.fail(
|
||||
scope,
|
||||
inst.positionals.dest_type.src,
|
||||
"expected float type, found '{}'",
|
||||
.{
|
||||
dest_type,
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
switch (operand.ty.zigTypeTag()) {
|
||||
.ComptimeFloat, .Float, .ComptimeInt => {},
|
||||
else => return self.fail(
|
||||
scope,
|
||||
inst.positionals.operand.src,
|
||||
"expected float type, found '{}'",
|
||||
.{operand.ty},
|
||||
),
|
||||
}
|
||||
|
||||
if (operand.value() != null) {
|
||||
return self.coerce(scope, dest_type, operand);
|
||||
} else if (dest_is_comptime_float) {
|
||||
return self.fail(scope, inst.base.src, "unable to cast runtime value to 'comptime_float'", .{});
|
||||
}
|
||||
|
||||
return self.fail(scope, inst.base.src, "TODO implement analyze widen or shorten float", .{});
|
||||
}
|
||||
|
||||
fn analyzeInstElemPtr(self: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) InnerError!*Inst {
|
||||
const array_ptr = try self.resolveInst(scope, inst.positionals.array_ptr);
|
||||
const uncasted_index = try self.resolveInst(scope, inst.positionals.index);
|
||||
@ -3411,11 +3450,12 @@ fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {
|
||||
|
||||
const src_info = inst.ty.intInfo(self.target());
|
||||
const dst_info = dest_type.intInfo(self.target());
|
||||
if (src_info.signed == dst_info.signed and dst_info.bits >= src_info.bits) {
|
||||
if ((src_info.signed == dst_info.signed and dst_info.bits >= src_info.bits) or
|
||||
// small enough unsigned ints can get casted to large enough signed ints
|
||||
(src_info.signed and !dst_info.signed and dst_info.bits > src_info.bits))
|
||||
{
|
||||
const b = try self.requireRuntimeBlock(scope, inst.src);
|
||||
return self.addNewInstArgs(b, inst.src, dest_type, Inst.WidenOrShorten, .{ .operand = inst });
|
||||
} else {
|
||||
return self.fail(scope, inst.src, "TODO implement more int widening {} to {}", .{ inst.ty, dest_type });
|
||||
return self.addUnOp(b, inst.src, dest_type, .intcast, inst);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3427,7 +3467,7 @@ fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {
|
||||
const dst_bits = dest_type.floatBits(self.target());
|
||||
if (dst_bits >= src_bits) {
|
||||
const b = try self.requireRuntimeBlock(scope, inst.src);
|
||||
return self.addNewInstArgs(b, inst.src, dest_type, Inst.WidenOrShorten, .{ .operand = inst });
|
||||
return self.addUnOp(b, inst.src, dest_type, .floatcast, inst);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -459,16 +459,26 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
.sub => return self.genSub(inst.castTag(.sub).?),
|
||||
.unreach => return MCValue{ .unreach = {} },
|
||||
.not => return self.genNot(inst.castTag(.not).?),
|
||||
.widenorshorten => return self.genWidenOrShorten(isnt.castTag(.widenorshorten).?),
|
||||
.floatcast => return self.genFloatCast(inst.castTag(.floatcast).?),
|
||||
.intcast => return self.genIntCast(inst.castTag(.intcast).?),
|
||||
}
|
||||
}
|
||||
|
||||
fn genWidenOrShorten(self: *Self, inst: *ir.Inst.WidenOrShorten) !MCValue {
|
||||
fn genFloatCast(self: *Self, inst: *ir.Inst.UnOp) !MCValue {
|
||||
// No side effects, so if it's unreferenced, do nothing.
|
||||
if (inst.base.isUnused())
|
||||
return MCValue.dead;
|
||||
switch (arch) {
|
||||
else => return self.fail(inst.base.src, "TODO implement widen or shorten for {}", .{self.target.cpu.arch}),
|
||||
else => return self.fail(inst.base.src, "TODO implement floatCast for {}", .{self.target.cpu.arch}),
|
||||
}
|
||||
}
|
||||
|
||||
fn genIntCast(self: *Self, inst: *ir.Inst.UnOp) !MCValue {
|
||||
// No side effects, so if it's unreferenced, do nothing.
|
||||
if (inst.base.isUnused())
|
||||
return MCValue.dead;
|
||||
switch (arch) {
|
||||
else => return self.fail(inst.base.src, "TODO implement intCast for {}", .{self.target.cpu.arch}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +71,8 @@ pub const Inst = struct {
|
||||
sub,
|
||||
unreach,
|
||||
not,
|
||||
widenorshorten,
|
||||
floatcast,
|
||||
intcast,
|
||||
|
||||
/// There is one-to-one correspondence between tag and type for now,
|
||||
/// but this will not always be the case. For example, binary operations
|
||||
@ -90,6 +91,8 @@ pub const Inst = struct {
|
||||
.isnonnull,
|
||||
.isnull,
|
||||
.ptrtoint,
|
||||
.floatcast,
|
||||
.intcast,
|
||||
=> UnOp,
|
||||
|
||||
.add,
|
||||
@ -109,7 +112,6 @@ pub const Inst = struct {
|
||||
.call => Call,
|
||||
.condbr => CondBr,
|
||||
.constant => Constant,
|
||||
.widenorshorten => WidenOrShorten,
|
||||
};
|
||||
}
|
||||
|
||||
@ -376,15 +378,6 @@ pub const Inst = struct {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
pub const WidenOrShorten = struct {
|
||||
pub const base_tag = Tag.widenorshorten;
|
||||
|
||||
base: Inst,
|
||||
args: struct {
|
||||
operand: *Inst,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
pub const Body = struct {
|
||||
|
||||
@ -80,7 +80,6 @@ pub const Value = extern union {
|
||||
elem_ptr,
|
||||
bytes,
|
||||
repeated, // the value is a value repeated some number of times
|
||||
float,
|
||||
float_16,
|
||||
float_32,
|
||||
float_64,
|
||||
@ -221,7 +220,7 @@ pub const Value = extern union {
|
||||
.float_16 => return self.copyPayloadShallow(allocator, Payload.Float_16),
|
||||
.float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32),
|
||||
.float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64),
|
||||
.float_128, .float => return self.copyPayloadShallow(allocator, Payload.Float_128),
|
||||
.float_128 => return self.copyPayloadShallow(allocator, Payload.Float_128),
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,7 +311,7 @@ pub const Value = extern union {
|
||||
.float_16 => return out_stream.print("{}", .{val.cast(Payload.Float_16).?.val}),
|
||||
.float_32 => return out_stream.print("{}", .{val.cast(Payload.Float_32).?.val}),
|
||||
.float_64 => return out_stream.print("{}", .{val.cast(Payload.Float_64).?.val}),
|
||||
.float_128, .float => return out_stream.print("{}", .{val.cast(Payload.Float_128).?.val}),
|
||||
.float_128 => return out_stream.print("{}", .{val.cast(Payload.Float_128).?.val}),
|
||||
};
|
||||
}
|
||||
|
||||
@ -393,7 +392,6 @@ pub const Value = extern union {
|
||||
.elem_ptr,
|
||||
.bytes,
|
||||
.repeated,
|
||||
.float,
|
||||
.float_16,
|
||||
.float_32,
|
||||
.float_64,
|
||||
@ -453,7 +451,6 @@ pub const Value = extern union {
|
||||
.bytes,
|
||||
.undef,
|
||||
.repeated,
|
||||
.float,
|
||||
.float_16,
|
||||
.float_32,
|
||||
.float_64,
|
||||
@ -525,7 +522,6 @@ pub const Value = extern union {
|
||||
.bytes,
|
||||
.undef,
|
||||
.repeated,
|
||||
.float,
|
||||
.float_16,
|
||||
.float_32,
|
||||
.float_64,
|
||||
@ -560,7 +556,7 @@ pub const Value = extern union {
|
||||
.float_16 => self.cast(Payload.Float_16).?.val,
|
||||
.float_32 => self.cast(Payload.Float_32).?.val,
|
||||
.float_64 => self.cast(Payload.Float_64).?.val,
|
||||
.float_128, .float => self.cast(Payload.Float_128).?.val,
|
||||
.float_128 => self.cast(Payload.Float_128).?.val,
|
||||
|
||||
.zero, .the_one_possible_value => 0,
|
||||
.int_u64 => @intToFloat(f128, self.cast(Payload.Int_u64).?.int),
|
||||
@ -624,7 +620,6 @@ pub const Value = extern union {
|
||||
.bytes,
|
||||
.undef,
|
||||
.repeated,
|
||||
.float,
|
||||
.float_16,
|
||||
.float_32,
|
||||
.float_64,
|
||||
@ -701,7 +696,6 @@ pub const Value = extern union {
|
||||
.elem_ptr,
|
||||
.bytes,
|
||||
.repeated,
|
||||
.float,
|
||||
.float_16,
|
||||
.float_32,
|
||||
.float_64,
|
||||
@ -830,8 +824,8 @@ pub const Value = extern union {
|
||||
.float_16 => @rem(self.cast(Payload.Float_16).?.val, 1) != 0,
|
||||
.float_32 => @rem(self.cast(Payload.Float_32).?.val, 1) != 0,
|
||||
.float_64 => @rem(self.cast(Payload.Float_64).?.val, 1) != 0,
|
||||
// .float_128, .float => @rem(self.cast(Payload.Float_128).?.val, 1) != 0,
|
||||
.float_128, .float => @panic("TODO lld: error: undefined symbol: fmodl"),
|
||||
// .float_128 => @rem(self.cast(Payload.Float_128).?.val, 1) != 0,
|
||||
.float_128 => @panic("TODO lld: error: undefined symbol: fmodl"),
|
||||
};
|
||||
}
|
||||
|
||||
@ -902,7 +896,7 @@ pub const Value = extern union {
|
||||
.float_16 => std.math.order(lhs.cast(Payload.Float_16).?.val, 0),
|
||||
.float_32 => std.math.order(lhs.cast(Payload.Float_32).?.val, 0),
|
||||
.float_64 => std.math.order(lhs.cast(Payload.Float_64).?.val, 0),
|
||||
.float_128, .float => std.math.order(lhs.cast(Payload.Float_128).?.val, 0),
|
||||
.float_128 => std.math.order(lhs.cast(Payload.Float_128).?.val, 0),
|
||||
};
|
||||
}
|
||||
|
||||
@ -923,7 +917,7 @@ pub const Value = extern union {
|
||||
.float_16 => return std.math.order(lhs.cast(Payload.Float_16).?.val, rhs.cast(Payload.Float_16).?.val),
|
||||
.float_32 => return std.math.order(lhs.cast(Payload.Float_32).?.val, rhs.cast(Payload.Float_32).?.val),
|
||||
.float_64 => return std.math.order(lhs.cast(Payload.Float_64).?.val, rhs.cast(Payload.Float_64).?.val),
|
||||
.float_128, .float => return std.math.order(lhs.cast(Payload.Float_128).?.val, rhs.cast(Payload.Float_128).?.val),
|
||||
.float_128 => return std.math.order(lhs.cast(Payload.Float_128).?.val, rhs.cast(Payload.Float_128).?.val),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
@ -1012,7 +1006,6 @@ pub const Value = extern union {
|
||||
.bytes,
|
||||
.undef,
|
||||
.repeated,
|
||||
.float,
|
||||
.float_16,
|
||||
.float_32,
|
||||
.float_64,
|
||||
@ -1088,7 +1081,6 @@ pub const Value = extern union {
|
||||
.elem_ptr,
|
||||
.ref_val,
|
||||
.decl_ref,
|
||||
.float,
|
||||
.float_16,
|
||||
.float_32,
|
||||
.float_64,
|
||||
@ -1179,7 +1171,6 @@ pub const Value = extern union {
|
||||
.elem_ptr,
|
||||
.bytes,
|
||||
.repeated,
|
||||
.float,
|
||||
.float_16,
|
||||
.float_32,
|
||||
.float_64,
|
||||
@ -1196,7 +1187,6 @@ pub const Value = extern union {
|
||||
return switch (self.tag()) {
|
||||
.undef => unreachable,
|
||||
|
||||
.float,
|
||||
.float_16,
|
||||
.float_32,
|
||||
.float_64,
|
||||
|
||||
@ -76,6 +76,7 @@ pub const Inst = struct {
|
||||
primitive,
|
||||
intcast,
|
||||
bitcast,
|
||||
floatcast,
|
||||
elemptr,
|
||||
add,
|
||||
sub,
|
||||
@ -137,6 +138,7 @@ pub const Inst = struct {
|
||||
.fntype => FnType,
|
||||
.intcast => IntCast,
|
||||
.bitcast => BitCast,
|
||||
.floatcast => FloatCast,
|
||||
.elemptr => ElemPtr,
|
||||
.condbr => CondBr,
|
||||
};
|
||||
@ -169,6 +171,7 @@ pub const Inst = struct {
|
||||
.primitive,
|
||||
.intcast,
|
||||
.bitcast,
|
||||
.floatcast,
|
||||
.elemptr,
|
||||
.add,
|
||||
.sub,
|
||||
@ -556,6 +559,18 @@ pub const Inst = struct {
|
||||
};
|
||||
};
|
||||
|
||||
pub const FloatCast = struct {
|
||||
pub const base_tag = Tag.floatcast;
|
||||
pub const builtin_name = "@floatCast";
|
||||
base: Inst,
|
||||
|
||||
positionals: struct {
|
||||
dest_type: *Inst,
|
||||
operand: *Inst,
|
||||
},
|
||||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const IntCast = struct {
|
||||
pub const base_tag = Tag.intcast;
|
||||
pub const builtin_name = "@intCast";
|
||||
@ -563,7 +578,7 @@ pub const Inst = struct {
|
||||
|
||||
positionals: struct {
|
||||
dest_type: *Inst,
|
||||
value: *Inst,
|
||||
operand: *Inst,
|
||||
},
|
||||
kw_args: struct {},
|
||||
};
|
||||
@ -1620,6 +1635,28 @@ const EmitZIR = struct {
|
||||
return &new_inst.base;
|
||||
}
|
||||
|
||||
fn emitCast(
|
||||
self: *EmitZIR,
|
||||
src: usize,
|
||||
new_body: ZirBody,
|
||||
old_inst: *ir.Inst.UnOp,
|
||||
comptime I: type,
|
||||
) Allocator.Error!*Inst {
|
||||
const new_inst = try self.arena.allocator.create(I);
|
||||
new_inst.* = .{
|
||||
.base = .{
|
||||
.src = src,
|
||||
.tag = I.base_tag,
|
||||
},
|
||||
.positionals = .{
|
||||
.dest_type = (try self.emitType(src, old_inst.base.ty)).inst,
|
||||
.operand = try self.resolveInst(new_body, old_inst.operand),
|
||||
},
|
||||
.kw_args = .{},
|
||||
};
|
||||
return &new_inst.base;
|
||||
}
|
||||
|
||||
fn emitBody(
|
||||
self: *EmitZIR,
|
||||
body: ir.Body,
|
||||
@ -1654,22 +1691,9 @@ const EmitZIR = struct {
|
||||
.cmp_gt => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_gt).?, .cmp_gt),
|
||||
.cmp_neq => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_neq).?, .cmp_neq),
|
||||
|
||||
.bitcast => blk: {
|
||||
const old_inst = inst.castTag(.bitcast).?;
|
||||
const new_inst = try self.arena.allocator.create(Inst.BitCast);
|
||||
new_inst.* = .{
|
||||
.base = .{
|
||||
.src = inst.src,
|
||||
.tag = Inst.BitCast.base_tag,
|
||||
},
|
||||
.positionals = .{
|
||||
.dest_type = (try self.emitType(inst.src, inst.ty)).inst,
|
||||
.operand = try self.resolveInst(new_body, old_inst.operand),
|
||||
},
|
||||
.kw_args = .{},
|
||||
};
|
||||
break :blk &new_inst.base;
|
||||
},
|
||||
.bitcast => try self.emitCast(inst.src, new_body, inst.castTag(.bitcast).?, Inst.BitCast),
|
||||
.intcast => try self.emitCast(inst.src, new_body, inst.castTag(.intcast).?, Inst.IntCast),
|
||||
.floatcast => try self.emitCast(inst.src, new_body, inst.castTag(.floatcast).?, Inst.FloatCast),
|
||||
|
||||
.block => blk: {
|
||||
const old_inst = inst.castTag(.block).?;
|
||||
@ -1822,10 +1846,6 @@ const EmitZIR = struct {
|
||||
};
|
||||
break :blk &new_inst.base;
|
||||
},
|
||||
.widenorshorten => blk: {
|
||||
const old_inst = inst.cast(ir.Inst.WidenOrShorten).?;
|
||||
break :blk try self.resolveInst(new_body, old_inst.args.operand);
|
||||
},
|
||||
};
|
||||
try instructions.append(new_inst);
|
||||
try inst_table.put(inst, new_inst);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user