| author | |
| committer | |
| log | 9f744f19e7036df9a410f780f3394f6669b8079e |
| tree | 055ef5f9727b51bde13f86805c67b3a4608b8c68 |
| parent | d7a89f98765381b4be2ce7626addad07ecfa7208 |
| parent | 6dc35efe4958a0569c4d8576bca84d62264b1d1d |
| signature |
stage2 wasm: Add division and bitwise/boolean ops &, |, ^, and, or6 files changed, 126 insertions(+), 1 deletions(-)
src/Sema.zig+2-1| ... | ... | @@ -3846,6 +3846,7 @@ fn analyzeArithmetic( |
| 3846 | 3846 | .subwrap => .subwrap, |
| 3847 | 3847 | .mul => .mul, |
| 3848 | 3848 | .mulwrap => .mulwrap, |
| 3849 | .div => .div, | |
| 3849 | 3850 | else => return sema.mod.fail(&block.base, src, "TODO implement arithmetic for operand '{s}''", .{@tagName(zir_tag)}), |
| 3850 | 3851 | }; |
| 3851 | 3852 | |
| ... | ... | @@ -4161,7 +4162,7 @@ fn zirBoolBr( |
| 4161 | 4162 | _ = try rhs_block.addBr(src, block_inst, rhs_result); |
| 4162 | 4163 | |
| 4163 | 4164 | const tzir_then_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, then_block.instructions.items) }; |
| 4164 | const tzir_else_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, rhs_block.instructions.items) }; | |
| 4165 | const tzir_else_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, else_block.instructions.items) }; | |
| 4165 | 4166 | _ = try child_block.addCondBr(src, lhs, tzir_then_body, tzir_else_body); |
| 4166 | 4167 | |
| 4167 | 4168 | block_inst.body = .{ |
src/codegen.zig+10| ... | ... | @@ -855,6 +855,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 855 | 855 | .not => return self.genNot(inst.castTag(.not).?), |
| 856 | 856 | .mul => return self.genMul(inst.castTag(.mul).?), |
| 857 | 857 | .mulwrap => return self.genMulWrap(inst.castTag(.mulwrap).?), |
| 858 | .div => return self.genDiv(inst.castTag(.div).?), | |
| 858 | 859 | .ptrtoint => return self.genPtrToInt(inst.castTag(.ptrtoint).?), |
| 859 | 860 | .ref => return self.genRef(inst.castTag(.ref).?), |
| 860 | 861 | .ret => return self.genRet(inst.castTag(.ret).?), |
| ... | ... | @@ -1092,6 +1093,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1092 | 1093 | } |
| 1093 | 1094 | } |
| 1094 | 1095 | |
| 1096 | fn genDiv(self: *Self, inst: *ir.Inst.BinOp) !MCValue { | |
| 1097 | // No side effects, so if it's unreferenced, do nothing. | |
| 1098 | if (inst.base.isUnused()) | |
| 1099 | return MCValue.dead; | |
| 1100 | switch (arch) { | |
| 1101 | else => return self.fail(inst.base.src, "TODO implement div for {}", .{self.target.cpu.arch}), | |
| 1102 | } | |
| 1103 | } | |
| 1104 | ||
| 1095 | 1105 | fn genBitAnd(self: *Self, inst: *ir.Inst.BinOp) !MCValue { |
| 1096 | 1106 | // No side effects, so if it's unreferenced, do nothing. |
| 1097 | 1107 | if (inst.base.isUnused()) |
src/codegen/c.zig+3| ... | ... | @@ -632,6 +632,9 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi |
| 632 | 632 | .mul => try genBinOp(o, inst.castTag(.sub).?, " * "), |
| 633 | 633 | // TODO make this do wrapping multiplication for signed ints |
| 634 | 634 | .mulwrap => try genBinOp(o, inst.castTag(.sub).?, " * "), |
| 635 | // TODO use a different strategy for div that communicates to the optimizer | |
| 636 | // that wrapping is UB. | |
| 637 | .div => try genBinOp(o, inst.castTag(.div).?, " / "), | |
| 635 | 638 | |
| 636 | 639 | .constant => unreachable, // excluded from function bodies |
| 637 | 640 | .alloc => try genAlloc(o, inst.castTag(.alloc).?), |
src/codegen/wasm.zig+7| ... | ... | @@ -657,6 +657,10 @@ pub const Context = struct { |
| 657 | 657 | .breakpoint => self.genBreakpoint(inst.castTag(.breakpoint).?), |
| 658 | 658 | .br => self.genBr(inst.castTag(.br).?), |
| 659 | 659 | .call => self.genCall(inst.castTag(.call).?), |
| 660 | .bit_or => self.genBinOp(inst.castTag(.bit_or).?, .@"or"), | |
| 661 | .bit_and => self.genBinOp(inst.castTag(.bit_and).?, .@"and"), | |
| 662 | .bool_or => self.genBinOp(inst.castTag(.bool_or).?, .@"or"), | |
| 663 | .bool_and => self.genBinOp(inst.castTag(.bool_and).?, .@"and"), | |
| 660 | 664 | .cmp_eq => self.genCmp(inst.castTag(.cmp_eq).?, .eq), |
| 661 | 665 | .cmp_gte => self.genCmp(inst.castTag(.cmp_gte).?, .gte), |
| 662 | 666 | .cmp_gt => self.genCmp(inst.castTag(.cmp_gt).?, .gt), |
| ... | ... | @@ -669,6 +673,8 @@ pub const Context = struct { |
| 669 | 673 | .load => self.genLoad(inst.castTag(.load).?), |
| 670 | 674 | .loop => self.genLoop(inst.castTag(.loop).?), |
| 671 | 675 | .mul => self.genBinOp(inst.castTag(.mul).?, .mul), |
| 676 | .div => self.genBinOp(inst.castTag(.div).?, .div), | |
| 677 | .xor => self.genBinOp(inst.castTag(.xor).?, .xor), | |
| 672 | 678 | .not => self.genNot(inst.castTag(.not).?), |
| 673 | 679 | .ret => self.genRet(inst.castTag(.ret).?), |
| 674 | 680 | .retvoid => WValue.none, |
| ... | ... | @@ -764,6 +770,7 @@ pub const Context = struct { |
| 764 | 770 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 765 | 771 | .op = op, |
| 766 | 772 | .valtype1 = try self.typeToValtype(inst.base.src, inst.base.ty), |
| 773 | .signedness = if (inst.base.ty.isSignedInt()) .signed else .unsigned, | |
| 767 | 774 | }); |
| 768 | 775 | try self.code.append(wasm.opcode(opcode)); |
| 769 | 776 | return .none; |
src/ir.zig+4| ... | ... | @@ -115,6 +115,7 @@ pub const Inst = struct { |
| 115 | 115 | unreach, |
| 116 | 116 | mul, |
| 117 | 117 | mulwrap, |
| 118 | div, | |
| 118 | 119 | not, |
| 119 | 120 | floatcast, |
| 120 | 121 | intcast, |
| ... | ... | @@ -181,6 +182,7 @@ pub const Inst = struct { |
| 181 | 182 | .subwrap, |
| 182 | 183 | .mul, |
| 183 | 184 | .mulwrap, |
| 185 | .div, | |
| 184 | 186 | .cmp_lt, |
| 185 | 187 | .cmp_lte, |
| 186 | 188 | .cmp_eq, |
| ... | ... | @@ -752,6 +754,7 @@ const DumpTzir = struct { |
| 752 | 754 | .subwrap, |
| 753 | 755 | .mul, |
| 754 | 756 | .mulwrap, |
| 757 | .div, | |
| 755 | 758 | .cmp_lt, |
| 756 | 759 | .cmp_lte, |
| 757 | 760 | .cmp_eq, |
| ... | ... | @@ -891,6 +894,7 @@ const DumpTzir = struct { |
| 891 | 894 | .subwrap, |
| 892 | 895 | .mul, |
| 893 | 896 | .mulwrap, |
| 897 | .div, | |
| 894 | 898 | .cmp_lt, |
| 895 | 899 | .cmp_lte, |
| 896 | 900 | .cmp_eq, |
test/stage2/wasm.zig+100| ... | ... | @@ -153,6 +153,106 @@ pub fn addCases(ctx: *TestContext) !void { |
| 153 | 153 | \\ return x * y; |
| 154 | 154 | \\} |
| 155 | 155 | , "350\n"); |
| 156 | ||
| 157 | case.addCompareOutput( | |
| 158 | \\export fn _start() u32 { | |
| 159 | \\ var i: u32 = 352; | |
| 160 | \\ i /= 7; // i = 50 | |
| 161 | \\ var result: u32 = foo(i, 7); | |
| 162 | \\ return result; | |
| 163 | \\} | |
| 164 | \\fn foo(x: u32, y: u32) u32 { | |
| 165 | \\ return x / y; | |
| 166 | \\} | |
| 167 | , "7\n"); | |
| 168 | ||
| 169 | case.addCompareOutput( | |
| 170 | \\export fn _start() u32 { | |
| 171 | \\ var i: u32 = 5; | |
| 172 | \\ i &= 6; | |
| 173 | \\ return i; | |
| 174 | \\} | |
| 175 | , "4\n"); | |
| 176 | ||
| 177 | case.addCompareOutput( | |
| 178 | \\export fn _start() u32 { | |
| 179 | \\ var i: u32 = 5; | |
| 180 | \\ i |= 6; | |
| 181 | \\ return i; | |
| 182 | \\} | |
| 183 | , "7\n"); | |
| 184 | ||
| 185 | case.addCompareOutput( | |
| 186 | \\export fn _start() u32 { | |
| 187 | \\ var i: u32 = 5; | |
| 188 | \\ i ^= 6; | |
| 189 | \\ return i; | |
| 190 | \\} | |
| 191 | , "3\n"); | |
| 192 | ||
| 193 | case.addCompareOutput( | |
| 194 | \\export fn _start() bool { | |
| 195 | \\ var b: bool = false; | |
| 196 | \\ b = b or false; | |
| 197 | \\ return b; | |
| 198 | \\} | |
| 199 | , "0\n"); | |
| 200 | ||
| 201 | case.addCompareOutput( | |
| 202 | \\export fn _start() bool { | |
| 203 | \\ var b: bool = true; | |
| 204 | \\ b = b or false; | |
| 205 | \\ return b; | |
| 206 | \\} | |
| 207 | , "1\n"); | |
| 208 | ||
| 209 | case.addCompareOutput( | |
| 210 | \\export fn _start() bool { | |
| 211 | \\ var b: bool = false; | |
| 212 | \\ b = b or true; | |
| 213 | \\ return b; | |
| 214 | \\} | |
| 215 | , "1\n"); | |
| 216 | ||
| 217 | case.addCompareOutput( | |
| 218 | \\export fn _start() bool { | |
| 219 | \\ var b: bool = true; | |
| 220 | \\ b = b or true; | |
| 221 | \\ return b; | |
| 222 | \\} | |
| 223 | , "1\n"); | |
| 224 | ||
| 225 | case.addCompareOutput( | |
| 226 | \\export fn _start() bool { | |
| 227 | \\ var b: bool = false; | |
| 228 | \\ b = b and false; | |
| 229 | \\ return b; | |
| 230 | \\} | |
| 231 | , "0\n"); | |
| 232 | ||
| 233 | case.addCompareOutput( | |
| 234 | \\export fn _start() bool { | |
| 235 | \\ var b: bool = true; | |
| 236 | \\ b = b and false; | |
| 237 | \\ return b; | |
| 238 | \\} | |
| 239 | , "0\n"); | |
| 240 | ||
| 241 | case.addCompareOutput( | |
| 242 | \\export fn _start() bool { | |
| 243 | \\ var b: bool = false; | |
| 244 | \\ b = b and true; | |
| 245 | \\ return b; | |
| 246 | \\} | |
| 247 | , "0\n"); | |
| 248 | ||
| 249 | case.addCompareOutput( | |
| 250 | \\export fn _start() bool { | |
| 251 | \\ var b: bool = true; | |
| 252 | \\ b = b and true; | |
| 253 | \\ return b; | |
| 254 | \\} | |
| 255 | , "1\n"); | |
| 156 | 256 | } |
| 157 | 257 | |
| 158 | 258 | { |