stage2: fix if expressions on error unions

AstGen had the then-else logic backwards for if expressions
on error unions. This commit fixes it.

Turns out AstGen only really needs `is_non_null` and `is_non_err`,
and does not need the `is_null` or `is_err` variants. So I removed the
`is_null{,_ptr}` and `is_err{,_ptr}` ZIR instructions (-4) and
added `is_non_err`, `is_non_err_ptr` ZIR instructions (+2) for
a total of (-2) ZIR instructions, giving us a tiny bit more headroom
within the 256 tag limit. This required swapping the order of
then/else blocks in a handful of cases, but ultimately means the
ZIR will be in the same as source order, which is convenient
when debugging.

AIR code on the other hand, gains the `is_non_err` and `is_non_err_ptr`
instructions.

Sema: fix logic in zirErrUnionCode and zirErrUnionCodePtr returning the
wrong result type.
This commit is contained in:
Andrew Kelley
2021-07-07 19:50:56 -07:00
parent 5816997ae7
commit 5c8bd443d9
7 changed files with 119 additions and 104 deletions

View File

@@ -859,6 +859,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.is_non_null_ptr => return self.genIsNonNullPtr(inst.castTag(.is_non_null_ptr).?),
.is_null => return self.genIsNull(inst.castTag(.is_null).?),
.is_null_ptr => return self.genIsNullPtr(inst.castTag(.is_null_ptr).?),
.is_non_err => return self.genIsNonErr(inst.castTag(.is_non_err).?),
.is_non_err_ptr => return self.genIsNonErrPtr(inst.castTag(.is_non_err_ptr).?),
.is_err => return self.genIsErr(inst.castTag(.is_err).?),
.is_err_ptr => return self.genIsErrPtr(inst.castTag(.is_err_ptr).?),
.load => return self.genLoad(inst.castTag(.load).?),
@@ -2972,6 +2974,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return self.fail(inst.base.src, "TODO load the operand and call genIsErr", .{});
}
fn genIsNonErr(self: *Self, inst: *ir.Inst.UnOp) !MCValue {
switch (arch) {
else => return self.fail(inst.base.src, "TODO implement is_non_err for {}", .{self.target.cpu.arch}),
}
}
fn genIsNonErrPtr(self: *Self, inst: *ir.Inst.UnOp) !MCValue {
return self.fail(inst.base.src, "TODO load the operand and call genIsNonErr", .{});
}
fn genLoop(self: *Self, inst: *ir.Inst.Loop) !MCValue {
// A loop is a setup to be able to jump back to the beginning.
const start_index = self.code.items.len;