cbe: add error comparison support

This commit is contained in:
jacob gw 2021-03-01 11:25:50 -05:00 committed by Veikka Tuominen
parent 0a7be71bc2
commit 6467ef6d3b
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
4 changed files with 41 additions and 22 deletions

View File

@ -2237,6 +2237,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
// No side effects, so if it's unreferenced, do nothing.
if (inst.base.isUnused())
return MCValue{ .dead = {} };
if (inst.lhs.ty.zigTypeTag() == .ErrorSet or inst.rhs.ty.zigTypeTag() == .ErrorSet)
return self.fail(inst.base.src, "TODO implement cmp for errors", .{});
switch (arch) {
.x86_64 => {
try self.code.ensureCapacity(self.code.items.len + 8);

View File

@ -1663,6 +1663,7 @@ pub const Type = extern union {
.Int,
.Float,
.ErrorSet,
.ErrorUnion,
.Enum,
.Frame,
.AnyFrame,
@ -1687,7 +1688,6 @@ pub const Type = extern union {
},
.Pointer, .Array => ty = ty.elemType(),
.ErrorUnion => @panic("TODO fn isValidVarType"),
.Fn => @panic("TODO fn isValidVarType"),
.Struct => @panic("TODO struct isValidVarType"),
.Union => @panic("TODO union isValidVarType"),

View File

@ -2326,7 +2326,8 @@ fn zirCmp(
return mod.constBool(scope, inst.base.src, std.mem.eql(u8, lval.castTag(.@"error").?.data.name, rval.castTag(.@"error").?.data.name) == (op == .eq));
}
}
return mod.fail(scope, inst.base.src, "TODO implement equality comparison between runtime errors", .{});
const b = try mod.requireRuntimeBlock(scope, inst.base.src);
return mod.addBinOp(b, inst.base.src, Type.initTag(.bool), if (op == .eq) .cmp_eq else .cmp_neq, lhs, rhs);
} else if (lhs.ty.isNumeric() and rhs.ty.isNumeric()) {
// This operation allows any combination of integer and float types, regardless of the
// signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for

View File

@ -244,30 +244,46 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, "");
}
//{
// var case = ctx.exeFromCompiledC("optionals", .{});
// // Simple while loop
// case.addCompareOutput(
// \\export fn main() c_int {
// \\ var count: c_int = 0;
// \\ var opt_ptr: ?*c_int = &count;
// \\ while (opt_ptr) |_| : (count += 1) {
// \\ if (count == 4) opt_ptr = null;
// \\ }
// \\ return count - 5;
// \\}
// , "");
// // Same with non pointer optionals
// case.addCompareOutput(
// \\export fn main() c_int {
// \\ var count: c_int = 0;
// \\ var opt_ptr: ?c_int = count;
// \\ while (opt_ptr) |_| : (count += 1) {
// \\ if (count == 4) opt_ptr = null;
// \\ }
// \\ return count - 5;
// \\}
// , "");
//}
{
var case = ctx.exeFromCompiledC("optionals", .{});
// Simple while loop
var case = ctx.exeFromCompiledC("errors", .{});
case.addCompareOutput(
\\export fn main() c_int {
\\ var count: c_int = 0;
\\ var opt_ptr: ?*c_int = &count;
\\ while (opt_ptr) |_| : (count += 1) {
\\ if (count == 4) opt_ptr = null;
\\ }
\\ return count - 5;
\\ var e1 = error.Foo;
\\ var e2 = error.Bar;
\\ assert(e1 != e2);
\\ assert(e1 == error.Foo);
\\ assert(e2 == error.Bar);
\\ return 0;
\\}
, "");
// Same with non pointer optionals
case.addCompareOutput(
\\export fn main() c_int {
\\ var count: c_int = 0;
\\ var opt_ptr: ?c_int = count;
\\ while (opt_ptr) |_| : (count += 1) {
\\ if (count == 4) opt_ptr = null;
\\ }
\\ return count - 5;
\\fn assert(b: bool) void {
\\ if (!b) unreachable;
\\}
, "");
}