| 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,6 +2566,7 @@ fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In |
| 2566 | .condbr => return self.analyzeInstCondBr(scope, old_inst.cast(zir.Inst.CondBr).?), | 2566 | .condbr => return self.analyzeInstCondBr(scope, old_inst.cast(zir.Inst.CondBr).?), |
| 2567 | .isnull => return self.analyzeInstIsNull(scope, old_inst.cast(zir.Inst.IsNull).?), | 2567 | .isnull => return self.analyzeInstIsNull(scope, old_inst.cast(zir.Inst.IsNull).?), |
| 2568 | .isnonnull => return self.analyzeInstIsNonNull(scope, old_inst.cast(zir.Inst.IsNonNull).?), | 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,6 +3244,17 @@ fn analyzeInstCmp(self: *Module, scope: *Scope, inst: *zir.Inst.Cmp) InnerError! |
| 3243 | return self.fail(scope, inst.base.src, "TODO implement more cmp analysis", .{}); | 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 | fn analyzeInstIsNull(self: *Module, scope: *Scope, inst: *zir.Inst.IsNull) InnerError!*Inst { | 3258 | fn analyzeInstIsNull(self: *Module, scope: *Scope, inst: *zir.Inst.IsNull) InnerError!*Inst { |
| 3247 | const operand = try self.resolveInst(scope, inst.positionals.operand); | 3259 | const operand = try self.resolveInst(scope, inst.positionals.operand); |
| 3248 | return self.analyzeIsNull(scope, inst.base.src, operand, true); | 3260 | return self.analyzeIsNull(scope, inst.base.src, operand, true); |
src-self-hosted/codegen.zig+7| ... | @@ -407,6 +407,13 @@ const Function = struct { | ... | @@ -407,6 +407,13 @@ const Function = struct { |
| 407 | .retvoid => return self.genRetVoid(inst.cast(ir.Inst.RetVoid).?, arch), | 407 | .retvoid => return self.genRetVoid(inst.cast(ir.Inst.RetVoid).?, arch), |
| 408 | .sub => return self.genSub(inst.cast(ir.Inst.Sub).?, arch), | 408 | .sub => return self.genSub(inst.cast(ir.Inst.Sub).?, arch), |
| 409 | .unreach => return MCValue{ .unreach = {} }, | 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,6 +60,7 @@ pub const Inst = struct { |
| 60 | retvoid, | 60 | retvoid, |
| 61 | sub, | 61 | sub, |
| 62 | unreach, | 62 | unreach, |
| 63 | not, | ||
| 63 | }; | 64 | }; |
| 64 | 65 | ||
| 65 | pub fn cast(base: *Inst, comptime T: type) ?*T { | 66 | pub fn cast(base: *Inst, comptime T: type) ?*T { |
| ... | @@ -194,6 +195,15 @@ pub const Inst = struct { | ... | @@ -194,6 +195,15 @@ pub const Inst = struct { |
| 194 | false_death_count: u32 = 0, | 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 | pub const Constant = struct { | 207 | pub const Constant = struct { |
| 198 | pub const base_tag = Tag.constant; | 208 | pub const base_tag = Tag.constant; |
| 199 | base: Inst, | 209 | base: Inst, |
src-self-hosted/zir.zig+30| ... | @@ -56,6 +56,7 @@ pub const Inst = struct { | ... | @@ -56,6 +56,7 @@ pub const Inst = struct { |
| 56 | declval, | 56 | declval, |
| 57 | /// Same as declval but the parameter is a `*Module.Decl` rather than a name. | 57 | /// Same as declval but the parameter is a `*Module.Decl` rather than a name. |
| 58 | declval_in_module, | 58 | declval_in_module, |
| 59 | boolnot, | ||
| 59 | /// String Literal. Makes an anonymous Decl and then takes a pointer to it. | 60 | /// String Literal. Makes an anonymous Decl and then takes a pointer to it. |
| 60 | str, | 61 | str, |
| 61 | int, | 62 | int, |
| ... | @@ -115,6 +116,7 @@ pub const Inst = struct { | ... | @@ -115,6 +116,7 @@ pub const Inst = struct { |
| 115 | .cmp, | 116 | .cmp, |
| 116 | .isnull, | 117 | .isnull, |
| 117 | .isnonnull, | 118 | .isnonnull, |
| 119 | .boolnot, | ||
| 118 | => false, | 120 | => false, |
| 119 | 121 | ||
| 120 | .condbr, | 122 | .condbr, |
| ... | @@ -143,6 +145,7 @@ pub const Inst = struct { | ... | @@ -143,6 +145,7 @@ pub const Inst = struct { |
| 143 | .declval_in_module => DeclValInModule, | 145 | .declval_in_module => DeclValInModule, |
| 144 | .compileerror => CompileError, | 146 | .compileerror => CompileError, |
| 145 | .@"const" => Const, | 147 | .@"const" => Const, |
| 148 | .boolnot => BoolNot, | ||
| 146 | .str => Str, | 149 | .str => Str, |
| 147 | .int => Int, | 150 | .int => Int, |
| 148 | .inttype => IntType, | 151 | .inttype => IntType, |
| ... | @@ -299,6 +302,16 @@ pub const Inst = struct { | ... | @@ -299,6 +302,16 @@ pub const Inst = struct { |
| 299 | kw_args: struct {}, | 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 | pub const Str = struct { | 315 | pub const Str = struct { |
| 303 | pub const base_tag = Tag.str; | 316 | pub const base_tag = Tag.str; |
| 304 | base: Inst, | 317 | base: Inst, |
| ... | @@ -762,6 +775,7 @@ const Writer = struct { | ... | @@ -762,6 +775,7 @@ const Writer = struct { |
| 762 | .declval_in_module => return self.writeInstToStreamGeneric(stream, .declval_in_module, inst), | 775 | .declval_in_module => return self.writeInstToStreamGeneric(stream, .declval_in_module, inst), |
| 763 | .compileerror => return self.writeInstToStreamGeneric(stream, .compileerror, inst), | 776 | .compileerror => return self.writeInstToStreamGeneric(stream, .compileerror, inst), |
| 764 | .@"const" => return self.writeInstToStreamGeneric(stream, .@"const", inst), | 777 | .@"const" => return self.writeInstToStreamGeneric(stream, .@"const", inst), |
| 778 | .boolnot => return self.writeInstToStreamGeneric(stream, .boolnot, inst), | ||
| 765 | .str => return self.writeInstToStreamGeneric(stream, .str, inst), | 779 | .str => return self.writeInstToStreamGeneric(stream, .str, inst), |
| 766 | .int => return self.writeInstToStreamGeneric(stream, .int, inst), | 780 | .int => return self.writeInstToStreamGeneric(stream, .int, inst), |
| 767 | .inttype => return self.writeInstToStreamGeneric(stream, .inttype, inst), | 781 | .inttype => return self.writeInstToStreamGeneric(stream, .inttype, inst), |
| ... | @@ -1658,6 +1672,22 @@ const EmitZIR = struct { | ... | @@ -1658,6 +1672,22 @@ const EmitZIR = struct { |
| 1658 | }; | 1672 | }; |
| 1659 | for (body.instructions) |inst| { | 1673 | for (body.instructions) |inst| { |
| 1660 | const new_inst = switch (inst.tag) { | 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 | .add => blk: { | 1691 | .add => blk: { |
| 1662 | const old_inst = inst.cast(ir.Inst.Add).?; | 1692 | const old_inst = inst.cast(ir.Inst.Add).?; |
| 1663 | const new_inst = try self.arena.allocator.create(Inst.Add); | 1693 | const new_inst = try self.arena.allocator.create(Inst.Add); |