| author | |
| committer | |
| log | 4f5e065d6ec10cb27589995bf5d6390647f783f2 |
| tree | f00a00cdbdd3b0ffa807b5f52e63fff345584d63 |
| parent | 14cef9dd3d8074b0dc2ee48a0905300ce6317aed |
4 files changed, 59 insertions(+), 0 deletions(-)
src-self-hosted/Module.zig+12| ... | ... | @@ -2566,6 +2566,7 @@ fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In |
| 2566 | 2566 | .condbr => return self.analyzeInstCondBr(scope, old_inst.cast(zir.Inst.CondBr).?), |
| 2567 | 2567 | .isnull => return self.analyzeInstIsNull(scope, old_inst.cast(zir.Inst.IsNull).?), |
| 2568 | 2568 | .isnonnull => return self.analyzeInstIsNonNull(scope, old_inst.cast(zir.Inst.IsNonNull).?), |
| 2569 | .boolnot => return self.analyzeInstBoolNot(scope, old_inst.cast(zir.Inst.BoolNot).?), | |
| 2569 | 2570 | } |
| 2570 | 2571 | } |
| 2571 | 2572 | |
| ... | ... | @@ -3243,6 +3244,17 @@ fn analyzeInstCmp(self: *Module, scope: *Scope, inst: *zir.Inst.Cmp) InnerError! |
| 3243 | 3244 | return self.fail(scope, inst.base.src, "TODO implement more cmp analysis", .{}); |
| 3244 | 3245 | } |
| 3245 | 3246 | |
| 3247 | fn analyzeInstBoolNot(self: *Module, scope: *Scope, inst: *zir.Inst.BoolNot) InnerError!*Inst { | |
| 3248 | const uncasted_operand = try self.resolveInst(scope, inst.positionals.operand); | |
| 3249 | const bool_type = Type.initTag(.bool); | |
| 3250 | const operand = try self.coerce(scope, bool_type, uncasted_operand); | |
| 3251 | if (try self.resolveDefinedValue(scope, operand)) |val| { | |
| 3252 | return self.constBool(scope, inst.base.src, !val.toBool()); | |
| 3253 | } | |
| 3254 | const b = try self.requireRuntimeBlock(scope, inst.base.src); | |
| 3255 | return self.addNewInstArgs(b, inst.base.src, bool_type, Inst.Not, .{ .operand = operand }); | |
| 3256 | } | |
| 3257 | ||
| 3246 | 3258 | fn analyzeInstIsNull(self: *Module, scope: *Scope, inst: *zir.Inst.IsNull) InnerError!*Inst { |
| 3247 | 3259 | const operand = try self.resolveInst(scope, inst.positionals.operand); |
| 3248 | 3260 | return self.analyzeIsNull(scope, inst.base.src, operand, true); |
src-self-hosted/codegen.zig+7| ... | ... | @@ -407,6 +407,13 @@ const Function = struct { |
| 407 | 407 | .retvoid => return self.genRetVoid(inst.cast(ir.Inst.RetVoid).?, arch), |
| 408 | 408 | .sub => return self.genSub(inst.cast(ir.Inst.Sub).?, arch), |
| 409 | 409 | .unreach => return MCValue{ .unreach = {} }, |
| 410 | .not => return self.genNot(inst.cast(ir.Inst.Not).?, arch), | |
| 411 | } | |
| 412 | } | |
| 413 | ||
| 414 | fn genNot(self: *Function, inst: *ir.Inst.Not, comptime arch: std.Target.Cpu.Arch) !MCValue { | |
| 415 | switch (arch) { | |
| 416 | else => return self.fail(inst.base.src, "TODO implement NOT for {}", .{self.target.cpu.arch}), | |
| 410 | 417 | } |
| 411 | 418 | } |
| 412 | 419 |
src-self-hosted/ir.zig+10| ... | ... | @@ -60,6 +60,7 @@ pub const Inst = struct { |
| 60 | 60 | retvoid, |
| 61 | 61 | sub, |
| 62 | 62 | unreach, |
| 63 | not, | |
| 63 | 64 | }; |
| 64 | 65 | |
| 65 | 66 | pub fn cast(base: *Inst, comptime T: type) ?*T { |
| ... | ... | @@ -194,6 +195,15 @@ pub const Inst = struct { |
| 194 | 195 | false_death_count: u32 = 0, |
| 195 | 196 | }; |
| 196 | 197 | |
| 198 | pub const Not = struct { | |
| 199 | pub const base_tag = Tag.not; | |
| 200 | ||
| 201 | base: Inst, | |
| 202 | args: struct { | |
| 203 | operand: *Inst, | |
| 204 | }, | |
| 205 | }; | |
| 206 | ||
| 197 | 207 | pub const Constant = struct { |
| 198 | 208 | pub const base_tag = Tag.constant; |
| 199 | 209 | base: Inst, |
src-self-hosted/zir.zig+30| ... | ... | @@ -56,6 +56,7 @@ pub const Inst = struct { |
| 56 | 56 | declval, |
| 57 | 57 | /// Same as declval but the parameter is a `*Module.Decl` rather than a name. |
| 58 | 58 | declval_in_module, |
| 59 | boolnot, | |
| 59 | 60 | /// String Literal. Makes an anonymous Decl and then takes a pointer to it. |
| 60 | 61 | str, |
| 61 | 62 | int, |
| ... | ... | @@ -115,6 +116,7 @@ pub const Inst = struct { |
| 115 | 116 | .cmp, |
| 116 | 117 | .isnull, |
| 117 | 118 | .isnonnull, |
| 119 | .boolnot, | |
| 118 | 120 | => false, |
| 119 | 121 | |
| 120 | 122 | .condbr, |
| ... | ... | @@ -143,6 +145,7 @@ pub const Inst = struct { |
| 143 | 145 | .declval_in_module => DeclValInModule, |
| 144 | 146 | .compileerror => CompileError, |
| 145 | 147 | .@"const" => Const, |
| 148 | .boolnot => BoolNot, | |
| 146 | 149 | .str => Str, |
| 147 | 150 | .int => Int, |
| 148 | 151 | .inttype => IntType, |
| ... | ... | @@ -299,6 +302,16 @@ pub const Inst = struct { |
| 299 | 302 | kw_args: struct {}, |
| 300 | 303 | }; |
| 301 | 304 | |
| 305 | pub const BoolNot = struct { | |
| 306 | pub const base_tag = Tag.boolnot; | |
| 307 | base: Inst, | |
| 308 | ||
| 309 | positionals: struct { | |
| 310 | operand: *Inst, | |
| 311 | }, | |
| 312 | kw_args: struct {}, | |
| 313 | }; | |
| 314 | ||
| 302 | 315 | pub const Str = struct { |
| 303 | 316 | pub const base_tag = Tag.str; |
| 304 | 317 | base: Inst, |
| ... | ... | @@ -762,6 +775,7 @@ const Writer = struct { |
| 762 | 775 | .declval_in_module => return self.writeInstToStreamGeneric(stream, .declval_in_module, inst), |
| 763 | 776 | .compileerror => return self.writeInstToStreamGeneric(stream, .compileerror, inst), |
| 764 | 777 | .@"const" => return self.writeInstToStreamGeneric(stream, .@"const", inst), |
| 778 | .boolnot => return self.writeInstToStreamGeneric(stream, .boolnot, inst), | |
| 765 | 779 | .str => return self.writeInstToStreamGeneric(stream, .str, inst), |
| 766 | 780 | .int => return self.writeInstToStreamGeneric(stream, .int, inst), |
| 767 | 781 | .inttype => return self.writeInstToStreamGeneric(stream, .inttype, inst), |
| ... | ... | @@ -1658,6 +1672,22 @@ const EmitZIR = struct { |
| 1658 | 1672 | }; |
| 1659 | 1673 | for (body.instructions) |inst| { |
| 1660 | 1674 | const new_inst = switch (inst.tag) { |
| 1675 | .not => blk: { | |
| 1676 | const old_inst = inst.cast(ir.Inst.Not).?; | |
| 1677 | assert(inst.ty.zigTypeTag() == .Bool); | |
| 1678 | const new_inst = try self.arena.allocator.create(Inst.BoolNot); | |
| 1679 | new_inst.* = .{ | |
| 1680 | .base = .{ | |
| 1681 | .src = inst.src, | |
| 1682 | .tag = Inst.BoolNot.base_tag, | |
| 1683 | }, | |
| 1684 | .positionals = .{ | |
| 1685 | .operand = try self.resolveInst(new_body, old_inst.args.operand), | |
| 1686 | }, | |
| 1687 | .kw_args = .{}, | |
| 1688 | }; | |
| 1689 | break :blk &new_inst.base; | |
| 1690 | }, | |
| 1661 | 1691 | .add => blk: { |
| 1662 | 1692 | const old_inst = inst.cast(ir.Inst.Add).?; |
| 1663 | 1693 | const new_inst = try self.arena.allocator.create(Inst.Add); |