stage2: add ZIR support for BoolNot
This commit is contained in:
@@ -2566,6 +2566,7 @@ fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In
|
||||
.condbr => return self.analyzeInstCondBr(scope, old_inst.cast(zir.Inst.CondBr).?),
|
||||
.isnull => return self.analyzeInstIsNull(scope, old_inst.cast(zir.Inst.IsNull).?),
|
||||
.isnonnull => return self.analyzeInstIsNonNull(scope, old_inst.cast(zir.Inst.IsNonNull).?),
|
||||
.boolnot => return self.analyzeInstBoolNot(scope, old_inst.cast(zir.Inst.BoolNot).?),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3243,6 +3244,17 @@ fn analyzeInstCmp(self: *Module, scope: *Scope, inst: *zir.Inst.Cmp) InnerError!
|
||||
return self.fail(scope, inst.base.src, "TODO implement more cmp analysis", .{});
|
||||
}
|
||||
|
||||
fn analyzeInstBoolNot(self: *Module, scope: *Scope, inst: *zir.Inst.BoolNot) InnerError!*Inst {
|
||||
const uncasted_operand = try self.resolveInst(scope, inst.positionals.operand);
|
||||
const bool_type = Type.initTag(.bool);
|
||||
const operand = try self.coerce(scope, bool_type, uncasted_operand);
|
||||
if (try self.resolveDefinedValue(scope, operand)) |val| {
|
||||
return self.constBool(scope, inst.base.src, !val.toBool());
|
||||
}
|
||||
const b = try self.requireRuntimeBlock(scope, inst.base.src);
|
||||
return self.addNewInstArgs(b, inst.base.src, bool_type, Inst.Not, .{ .operand = operand });
|
||||
}
|
||||
|
||||
fn analyzeInstIsNull(self: *Module, scope: *Scope, inst: *zir.Inst.IsNull) InnerError!*Inst {
|
||||
const operand = try self.resolveInst(scope, inst.positionals.operand);
|
||||
return self.analyzeIsNull(scope, inst.base.src, operand, true);
|
||||
|
||||
@@ -407,6 +407,13 @@ const Function = struct {
|
||||
.retvoid => return self.genRetVoid(inst.cast(ir.Inst.RetVoid).?, arch),
|
||||
.sub => return self.genSub(inst.cast(ir.Inst.Sub).?, arch),
|
||||
.unreach => return MCValue{ .unreach = {} },
|
||||
.not => return self.genNot(inst.cast(ir.Inst.Not).?, arch),
|
||||
}
|
||||
}
|
||||
|
||||
fn genNot(self: *Function, inst: *ir.Inst.Not, comptime arch: std.Target.Cpu.Arch) !MCValue {
|
||||
switch (arch) {
|
||||
else => return self.fail(inst.base.src, "TODO implement NOT for {}", .{self.target.cpu.arch}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ pub const Inst = struct {
|
||||
retvoid,
|
||||
sub,
|
||||
unreach,
|
||||
not,
|
||||
};
|
||||
|
||||
pub fn cast(base: *Inst, comptime T: type) ?*T {
|
||||
@@ -194,6 +195,15 @@ pub const Inst = struct {
|
||||
false_death_count: u32 = 0,
|
||||
};
|
||||
|
||||
pub const Not = struct {
|
||||
pub const base_tag = Tag.not;
|
||||
|
||||
base: Inst,
|
||||
args: struct {
|
||||
operand: *Inst,
|
||||
},
|
||||
};
|
||||
|
||||
pub const Constant = struct {
|
||||
pub const base_tag = Tag.constant;
|
||||
base: Inst,
|
||||
|
||||
@@ -56,6 +56,7 @@ pub const Inst = struct {
|
||||
declval,
|
||||
/// Same as declval but the parameter is a `*Module.Decl` rather than a name.
|
||||
declval_in_module,
|
||||
boolnot,
|
||||
/// String Literal. Makes an anonymous Decl and then takes a pointer to it.
|
||||
str,
|
||||
int,
|
||||
@@ -115,6 +116,7 @@ pub const Inst = struct {
|
||||
.cmp,
|
||||
.isnull,
|
||||
.isnonnull,
|
||||
.boolnot,
|
||||
=> false,
|
||||
|
||||
.condbr,
|
||||
@@ -143,6 +145,7 @@ pub const Inst = struct {
|
||||
.declval_in_module => DeclValInModule,
|
||||
.compileerror => CompileError,
|
||||
.@"const" => Const,
|
||||
.boolnot => BoolNot,
|
||||
.str => Str,
|
||||
.int => Int,
|
||||
.inttype => IntType,
|
||||
@@ -299,6 +302,16 @@ pub const Inst = struct {
|
||||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const BoolNot = struct {
|
||||
pub const base_tag = Tag.boolnot;
|
||||
base: Inst,
|
||||
|
||||
positionals: struct {
|
||||
operand: *Inst,
|
||||
},
|
||||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const Str = struct {
|
||||
pub const base_tag = Tag.str;
|
||||
base: Inst,
|
||||
@@ -762,6 +775,7 @@ const Writer = struct {
|
||||
.declval_in_module => return self.writeInstToStreamGeneric(stream, .declval_in_module, inst),
|
||||
.compileerror => return self.writeInstToStreamGeneric(stream, .compileerror, inst),
|
||||
.@"const" => return self.writeInstToStreamGeneric(stream, .@"const", inst),
|
||||
.boolnot => return self.writeInstToStreamGeneric(stream, .boolnot, inst),
|
||||
.str => return self.writeInstToStreamGeneric(stream, .str, inst),
|
||||
.int => return self.writeInstToStreamGeneric(stream, .int, inst),
|
||||
.inttype => return self.writeInstToStreamGeneric(stream, .inttype, inst),
|
||||
@@ -1658,6 +1672,22 @@ const EmitZIR = struct {
|
||||
};
|
||||
for (body.instructions) |inst| {
|
||||
const new_inst = switch (inst.tag) {
|
||||
.not => blk: {
|
||||
const old_inst = inst.cast(ir.Inst.Not).?;
|
||||
assert(inst.ty.zigTypeTag() == .Bool);
|
||||
const new_inst = try self.arena.allocator.create(Inst.BoolNot);
|
||||
new_inst.* = .{
|
||||
.base = .{
|
||||
.src = inst.src,
|
||||
.tag = Inst.BoolNot.base_tag,
|
||||
},
|
||||
.positionals = .{
|
||||
.operand = try self.resolveInst(new_body, old_inst.args.operand),
|
||||
},
|
||||
.kw_args = .{},
|
||||
};
|
||||
break :blk &new_inst.base;
|
||||
},
|
||||
.add => blk: {
|
||||
const old_inst = inst.cast(ir.Inst.Add).?;
|
||||
const new_inst = try self.arena.allocator.create(Inst.Add);
|
||||
|
||||
Reference in New Issue
Block a user