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