| 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,6 +3846,7 @@ fn analyzeArithmetic( |
| 3846 | .subwrap => .subwrap, | 3846 | .subwrap => .subwrap, |
| 3847 | .mul => .mul, | 3847 | .mul => .mul, |
| 3848 | .mulwrap => .mulwrap, | 3848 | .mulwrap => .mulwrap, |
| 3849 | .div => .div, | ||
| 3849 | else => return sema.mod.fail(&block.base, src, "TODO implement arithmetic for operand '{s}''", .{@tagName(zir_tag)}), | 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,7 +4162,7 @@ fn zirBoolBr( |
| 4161 | _ = try rhs_block.addBr(src, block_inst, rhs_result); | 4162 | _ = try rhs_block.addBr(src, block_inst, rhs_result); |
| 4162 | 4163 | ||
| 4163 | const tzir_then_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, then_block.instructions.items) }; | 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 | _ = try child_block.addCondBr(src, lhs, tzir_then_body, tzir_else_body); | 4166 | _ = try child_block.addCondBr(src, lhs, tzir_then_body, tzir_else_body); |
| 4166 | 4167 | ||
| 4167 | block_inst.body = .{ | 4168 | block_inst.body = .{ |
src/codegen.zig+10| ... | @@ -855,6 +855,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -855,6 +855,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 855 | .not => return self.genNot(inst.castTag(.not).?), | 855 | .not => return self.genNot(inst.castTag(.not).?), |
| 856 | .mul => return self.genMul(inst.castTag(.mul).?), | 856 | .mul => return self.genMul(inst.castTag(.mul).?), |
| 857 | .mulwrap => return self.genMulWrap(inst.castTag(.mulwrap).?), | 857 | .mulwrap => return self.genMulWrap(inst.castTag(.mulwrap).?), |
| 858 | .div => return self.genDiv(inst.castTag(.div).?), | ||
| 858 | .ptrtoint => return self.genPtrToInt(inst.castTag(.ptrtoint).?), | 859 | .ptrtoint => return self.genPtrToInt(inst.castTag(.ptrtoint).?), |
| 859 | .ref => return self.genRef(inst.castTag(.ref).?), | 860 | .ref => return self.genRef(inst.castTag(.ref).?), |
| 860 | .ret => return self.genRet(inst.castTag(.ret).?), | 861 | .ret => return self.genRet(inst.castTag(.ret).?), |
| ... | @@ -1092,6 +1093,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -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 | fn genBitAnd(self: *Self, inst: *ir.Inst.BinOp) !MCValue { | 1105 | fn genBitAnd(self: *Self, inst: *ir.Inst.BinOp) !MCValue { |
| 1096 | // No side effects, so if it's unreferenced, do nothing. | 1106 | // No side effects, so if it's unreferenced, do nothing. |
| 1097 | if (inst.base.isUnused()) | 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,6 +632,9 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi |
| 632 | .mul => try genBinOp(o, inst.castTag(.sub).?, " * "), | 632 | .mul => try genBinOp(o, inst.castTag(.sub).?, " * "), |
| 633 | // TODO make this do wrapping multiplication for signed ints | 633 | // TODO make this do wrapping multiplication for signed ints |
| 634 | .mulwrap => try genBinOp(o, inst.castTag(.sub).?, " * "), | 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 | .constant => unreachable, // excluded from function bodies | 639 | .constant => unreachable, // excluded from function bodies |
| 637 | .alloc => try genAlloc(o, inst.castTag(.alloc).?), | 640 | .alloc => try genAlloc(o, inst.castTag(.alloc).?), |
src/codegen/wasm.zig+7| ... | @@ -657,6 +657,10 @@ pub const Context = struct { | ... | @@ -657,6 +657,10 @@ pub const Context = struct { |
| 657 | .breakpoint => self.genBreakpoint(inst.castTag(.breakpoint).?), | 657 | .breakpoint => self.genBreakpoint(inst.castTag(.breakpoint).?), |
| 658 | .br => self.genBr(inst.castTag(.br).?), | 658 | .br => self.genBr(inst.castTag(.br).?), |
| 659 | .call => self.genCall(inst.castTag(.call).?), | 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 | .cmp_eq => self.genCmp(inst.castTag(.cmp_eq).?, .eq), | 664 | .cmp_eq => self.genCmp(inst.castTag(.cmp_eq).?, .eq), |
| 661 | .cmp_gte => self.genCmp(inst.castTag(.cmp_gte).?, .gte), | 665 | .cmp_gte => self.genCmp(inst.castTag(.cmp_gte).?, .gte), |
| 662 | .cmp_gt => self.genCmp(inst.castTag(.cmp_gt).?, .gt), | 666 | .cmp_gt => self.genCmp(inst.castTag(.cmp_gt).?, .gt), |
| ... | @@ -669,6 +673,8 @@ pub const Context = struct { | ... | @@ -669,6 +673,8 @@ pub const Context = struct { |
| 669 | .load => self.genLoad(inst.castTag(.load).?), | 673 | .load => self.genLoad(inst.castTag(.load).?), |
| 670 | .loop => self.genLoop(inst.castTag(.loop).?), | 674 | .loop => self.genLoop(inst.castTag(.loop).?), |
| 671 | .mul => self.genBinOp(inst.castTag(.mul).?, .mul), | 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 | .not => self.genNot(inst.castTag(.not).?), | 678 | .not => self.genNot(inst.castTag(.not).?), |
| 673 | .ret => self.genRet(inst.castTag(.ret).?), | 679 | .ret => self.genRet(inst.castTag(.ret).?), |
| 674 | .retvoid => WValue.none, | 680 | .retvoid => WValue.none, |
| ... | @@ -764,6 +770,7 @@ pub const Context = struct { | ... | @@ -764,6 +770,7 @@ pub const Context = struct { |
| 764 | const opcode: wasm.Opcode = buildOpcode(.{ | 770 | const opcode: wasm.Opcode = buildOpcode(.{ |
| 765 | .op = op, | 771 | .op = op, |
| 766 | .valtype1 = try self.typeToValtype(inst.base.src, inst.base.ty), | 772 | .valtype1 = try self.typeToValtype(inst.base.src, inst.base.ty), |
| 773 | .signedness = if (inst.base.ty.isSignedInt()) .signed else .unsigned, | ||
| 767 | }); | 774 | }); |
| 768 | try self.code.append(wasm.opcode(opcode)); | 775 | try self.code.append(wasm.opcode(opcode)); |
| 769 | return .none; | 776 | return .none; |
src/ir.zig+4| ... | @@ -115,6 +115,7 @@ pub const Inst = struct { | ... | @@ -115,6 +115,7 @@ pub const Inst = struct { |
| 115 | unreach, | 115 | unreach, |
| 116 | mul, | 116 | mul, |
| 117 | mulwrap, | 117 | mulwrap, |
| 118 | div, | ||
| 118 | not, | 119 | not, |
| 119 | floatcast, | 120 | floatcast, |
| 120 | intcast, | 121 | intcast, |
| ... | @@ -181,6 +182,7 @@ pub const Inst = struct { | ... | @@ -181,6 +182,7 @@ pub const Inst = struct { |
| 181 | .subwrap, | 182 | .subwrap, |
| 182 | .mul, | 183 | .mul, |
| 183 | .mulwrap, | 184 | .mulwrap, |
| 185 | .div, | ||
| 184 | .cmp_lt, | 186 | .cmp_lt, |
| 185 | .cmp_lte, | 187 | .cmp_lte, |
| 186 | .cmp_eq, | 188 | .cmp_eq, |
| ... | @@ -752,6 +754,7 @@ const DumpTzir = struct { | ... | @@ -752,6 +754,7 @@ const DumpTzir = struct { |
| 752 | .subwrap, | 754 | .subwrap, |
| 753 | .mul, | 755 | .mul, |
| 754 | .mulwrap, | 756 | .mulwrap, |
| 757 | .div, | ||
| 755 | .cmp_lt, | 758 | .cmp_lt, |
| 756 | .cmp_lte, | 759 | .cmp_lte, |
| 757 | .cmp_eq, | 760 | .cmp_eq, |
| ... | @@ -891,6 +894,7 @@ const DumpTzir = struct { | ... | @@ -891,6 +894,7 @@ const DumpTzir = struct { |
| 891 | .subwrap, | 894 | .subwrap, |
| 892 | .mul, | 895 | .mul, |
| 893 | .mulwrap, | 896 | .mulwrap, |
| 897 | .div, | ||
| 894 | .cmp_lt, | 898 | .cmp_lt, |
| 895 | .cmp_lte, | 899 | .cmp_lte, |
| 896 | .cmp_eq, | 900 | .cmp_eq, |
test/stage2/wasm.zig+100| ... | @@ -153,6 +153,106 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -153,6 +153,106 @@ pub fn addCases(ctx: *TestContext) !void { |
| 153 | \\ return x * y; | 153 | \\ return x * y; |
| 154 | \\} | 154 | \\} |
| 155 | , "350\n"); | 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 | { |