Commit 7e7d1df4da
Changed files (5)
src-self-hosted
src-self-hosted/codegen.zig
@@ -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}),
}
}
src-self-hosted/ir.zig
@@ -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 {
src-self-hosted/Module.zig
@@ -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);
}
}
src-self-hosted/value.zig
@@ -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,
src-self-hosted/zir.zig
@@ -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);