| ... | ... | @@ -792,43 +792,45 @@ pub const Context = struct { |
| 792 | 792 | fn genInst(self: *Context, inst: Air.Inst.Index) !WValue { |
| 793 | 793 | const air_tags = self.air.instructions.items(.tag); |
| 794 | 794 | return switch (air_tags[inst]) { |
| 795 | | .add => self.genBinOp(inst, .add), |
| 796 | | .alloc => self.genAlloc(inst), |
| 797 | | .arg => self.genArg(inst), |
| 798 | | .bit_and => self.genBinOp(inst, .@"and"), |
| 799 | | .bitcast => self.genBitcast(inst), |
| 800 | | .bit_or => self.genBinOp(inst, .@"or"), |
| 801 | | .block => self.genBlock(inst), |
| 802 | | .bool_and => self.genBinOp(inst, .@"and"), |
| 803 | | .bool_or => self.genBinOp(inst, .@"or"), |
| 804 | | .breakpoint => self.genBreakpoint(inst), |
| 805 | | .br => self.genBr(inst), |
| 806 | | .call => self.genCall(inst), |
| 807 | | .cmp_eq => self.genCmp(inst, .eq), |
| 808 | | .cmp_gte => self.genCmp(inst, .gte), |
| 809 | | .cmp_gt => self.genCmp(inst, .gt), |
| 810 | | .cmp_lte => self.genCmp(inst, .lte), |
| 811 | | .cmp_lt => self.genCmp(inst, .lt), |
| 812 | | .cmp_neq => self.genCmp(inst, .neq), |
| 813 | | .cond_br => self.genCondBr(inst), |
| 795 | .add => self.airBinOp(inst, .add), |
| 796 | .sub => self.airBinOp(inst, .sub), |
| 797 | .mul => self.airBinOp(inst, .mul), |
| 798 | .div => self.airBinOp(inst, .div), |
| 799 | .bit_and => self.airBinOp(inst, .@"and"), |
| 800 | .bit_or => self.airBinOp(inst, .@"or"), |
| 801 | .bool_and => self.airBinOp(inst, .@"and"), |
| 802 | .bool_or => self.airBinOp(inst, .@"or"), |
| 803 | .xor => self.airBinOp(inst, .xor), |
| 804 | |
| 805 | .cmp_eq => self.airCmp(inst, .eq), |
| 806 | .cmp_gte => self.airCmp(inst, .gte), |
| 807 | .cmp_gt => self.airCmp(inst, .gt), |
| 808 | .cmp_lte => self.airCmp(inst, .lte), |
| 809 | .cmp_lt => self.airCmp(inst, .lt), |
| 810 | .cmp_neq => self.airCmp(inst, .neq), |
| 811 | |
| 812 | .alloc => self.airAlloc(inst), |
| 813 | .arg => self.airArg(inst), |
| 814 | .bitcast => self.airBitcast(inst), |
| 815 | .block => self.airBlock(inst), |
| 816 | .breakpoint => self.airBreakpoint(inst), |
| 817 | .br => self.airBr(inst), |
| 818 | .call => self.airCall(inst), |
| 819 | .cond_br => self.airCondBr(inst), |
| 814 | 820 | .constant => unreachable, |
| 815 | 821 | .dbg_stmt => WValue.none, |
| 816 | | .div => self.genBinOp(inst, .div), |
| 817 | | .is_err => self.genIsErr(inst, .i32_ne), |
| 818 | | .is_non_err => self.genIsErr(inst, .i32_eq), |
| 819 | | .load => self.genLoad(inst), |
| 820 | | .loop => self.genLoop(inst), |
| 821 | | .mul => self.genBinOp(inst, .mul), |
| 822 | | .not => self.genNot(inst), |
| 823 | | .ret => self.genRet(inst), |
| 824 | | .store => self.genStore(inst), |
| 825 | | .struct_field_ptr => self.genStructFieldPtr(inst), |
| 826 | | .sub => self.genBinOp(inst, .sub), |
| 827 | | .switch_br => self.genSwitchBr(inst), |
| 828 | | .unreach => self.genUnreachable(inst), |
| 829 | | .unwrap_errunion_payload => self.genUnwrapErrUnionPayload(inst), |
| 830 | | .wrap_errunion_payload => self.genWrapErrUnionPayload(inst), |
| 831 | | .xor => self.genBinOp(inst, .xor), |
| 822 | .is_err => self.airIsErr(inst, .i32_ne), |
| 823 | .is_non_err => self.airIsErr(inst, .i32_eq), |
| 824 | .load => self.airLoad(inst), |
| 825 | .loop => self.airLoop(inst), |
| 826 | .not => self.airNot(inst), |
| 827 | .ret => self.airRet(inst), |
| 828 | .store => self.airStore(inst), |
| 829 | .struct_field_ptr => self.airStructFieldPtr(inst), |
| 830 | .switch_br => self.airSwitchBr(inst), |
| 831 | .unreach => self.airUnreachable(inst), |
| 832 | .unwrap_errunion_payload => self.airUnwrapErrUnionPayload(inst), |
| 833 | .wrap_errunion_payload => self.airWrapErrUnionPayload(inst), |
| 832 | 834 | else => |tag| self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}), |
| 833 | 835 | }; |
| 834 | 836 | } |
| ... | ... | @@ -840,7 +842,7 @@ pub const Context = struct { |
| 840 | 842 | } |
| 841 | 843 | } |
| 842 | 844 | |
| 843 | | fn genRet(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 845 | fn airRet(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 844 | 846 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 845 | 847 | const operand = self.resolveInst(un_op); |
| 846 | 848 | try self.emitWValue(operand); |
| ... | ... | @@ -848,7 +850,7 @@ pub const Context = struct { |
| 848 | 850 | return .none; |
| 849 | 851 | } |
| 850 | 852 | |
| 851 | | fn genCall(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 853 | fn airCall(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 852 | 854 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 853 | 855 | const extra = self.air.extraData(Air.Call, pl_op.payload); |
| 854 | 856 | const args = self.air.extra[extra.end..][0..extra.data.args_len]; |
| ... | ... | @@ -882,12 +884,12 @@ pub const Context = struct { |
| 882 | 884 | return .none; |
| 883 | 885 | } |
| 884 | 886 | |
| 885 | | fn genAlloc(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 887 | fn airAlloc(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 886 | 888 | const elem_type = self.air.typeOfIndex(inst).elemType(); |
| 887 | 889 | return self.allocLocal(elem_type); |
| 888 | 890 | } |
| 889 | 891 | |
| 890 | | fn genStore(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 892 | fn airStore(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 891 | 893 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 892 | 894 | const writer = self.code.writer(); |
| 893 | 895 | |
| ... | ... | @@ -926,19 +928,19 @@ pub const Context = struct { |
| 926 | 928 | return .none; |
| 927 | 929 | } |
| 928 | 930 | |
| 929 | | fn genLoad(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 931 | fn airLoad(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 930 | 932 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 931 | 933 | return self.resolveInst(ty_op.operand); |
| 932 | 934 | } |
| 933 | 935 | |
| 934 | | fn genArg(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 936 | fn airArg(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 935 | 937 | _ = inst; |
| 936 | 938 | // arguments share the index with locals |
| 937 | 939 | defer self.local_index += 1; |
| 938 | 940 | return WValue{ .local = self.local_index }; |
| 939 | 941 | } |
| 940 | 942 | |
| 941 | | fn genBinOp(self: *Context, inst: Air.Inst.Index, op: Op) InnerError!WValue { |
| 943 | fn airBinOp(self: *Context, inst: Air.Inst.Index, op: Op) InnerError!WValue { |
| 942 | 944 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 943 | 945 | const lhs = self.resolveInst(bin_op.lhs); |
| 944 | 946 | const rhs = self.resolveInst(bin_op.rhs); |
| ... | ... | @@ -1074,7 +1076,7 @@ pub const Context = struct { |
| 1074 | 1076 | } |
| 1075 | 1077 | } |
| 1076 | 1078 | |
| 1077 | | fn genBlock(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1079 | fn airBlock(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1078 | 1080 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1079 | 1081 | const block_ty = try self.genBlockType(self.air.getRefType(ty_pl.ty)); |
| 1080 | 1082 | const extra = self.air.extraData(Air.Block, ty_pl.payload); |
| ... | ... | @@ -1108,7 +1110,7 @@ pub const Context = struct { |
| 1108 | 1110 | self.block_depth -= 1; |
| 1109 | 1111 | } |
| 1110 | 1112 | |
| 1111 | | fn genLoop(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1113 | fn airLoop(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1112 | 1114 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1113 | 1115 | const loop = self.air.extraData(Air.Block, ty_pl.payload); |
| 1114 | 1116 | const body = self.air.extra[loop.end..][0..loop.data.body_len]; |
| ... | ... | @@ -1127,7 +1129,7 @@ pub const Context = struct { |
| 1127 | 1129 | return .none; |
| 1128 | 1130 | } |
| 1129 | 1131 | |
| 1130 | | fn genCondBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1132 | fn airCondBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1131 | 1133 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 1132 | 1134 | const condition = self.resolveInst(pl_op.operand); |
| 1133 | 1135 | const extra = self.air.extraData(Air.CondBr, pl_op.payload); |
| ... | ... | @@ -1166,7 +1168,7 @@ pub const Context = struct { |
| 1166 | 1168 | return .none; |
| 1167 | 1169 | } |
| 1168 | 1170 | |
| 1169 | | fn genCmp(self: *Context, inst: Air.Inst.Index, op: std.math.CompareOperator) InnerError!WValue { |
| 1171 | fn airCmp(self: *Context, inst: Air.Inst.Index, op: std.math.CompareOperator) InnerError!WValue { |
| 1170 | 1172 | // save offset, so potential conditions can insert blocks in front of |
| 1171 | 1173 | // the comparison that we can later jump back to |
| 1172 | 1174 | const offset = self.code.items.len; |
| ... | ... | @@ -1202,7 +1204,7 @@ pub const Context = struct { |
| 1202 | 1204 | return WValue{ .code_offset = offset }; |
| 1203 | 1205 | } |
| 1204 | 1206 | |
| 1205 | | fn genBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1207 | fn airBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1206 | 1208 | const br = self.air.instructions.items(.data)[inst].br; |
| 1207 | 1209 | |
| 1208 | 1210 | // if operand has codegen bits we should break with a value |
| ... | ... | @@ -1220,7 +1222,7 @@ pub const Context = struct { |
| 1220 | 1222 | return .none; |
| 1221 | 1223 | } |
| 1222 | 1224 | |
| 1223 | | fn genNot(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1225 | fn airNot(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1224 | 1226 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1225 | 1227 | const offset = self.code.items.len; |
| 1226 | 1228 | |
| ... | ... | @@ -1238,7 +1240,7 @@ pub const Context = struct { |
| 1238 | 1240 | return WValue{ .code_offset = offset }; |
| 1239 | 1241 | } |
| 1240 | 1242 | |
| 1241 | | fn genBreakpoint(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1243 | fn airBreakpoint(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1242 | 1244 | _ = self; |
| 1243 | 1245 | _ = inst; |
| 1244 | 1246 | // unsupported by wasm itself. Can be implemented once we support DWARF |
| ... | ... | @@ -1246,18 +1248,18 @@ pub const Context = struct { |
| 1246 | 1248 | return .none; |
| 1247 | 1249 | } |
| 1248 | 1250 | |
| 1249 | | fn genUnreachable(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1251 | fn airUnreachable(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1250 | 1252 | _ = inst; |
| 1251 | 1253 | try self.code.append(wasm.opcode(.@"unreachable")); |
| 1252 | 1254 | return .none; |
| 1253 | 1255 | } |
| 1254 | 1256 | |
| 1255 | | fn genBitcast(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1257 | fn airBitcast(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1256 | 1258 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1257 | 1259 | return self.resolveInst(ty_op.operand); |
| 1258 | 1260 | } |
| 1259 | 1261 | |
| 1260 | | fn genStructFieldPtr(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1262 | fn airStructFieldPtr(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1261 | 1263 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1262 | 1264 | const extra = self.air.extraData(Air.StructField, ty_pl.payload); |
| 1263 | 1265 | const struct_ptr = self.resolveInst(extra.data.struct_ptr); |
| ... | ... | @@ -1265,7 +1267,7 @@ pub const Context = struct { |
| 1265 | 1267 | return WValue{ .local = struct_ptr.multi_value.index + @intCast(u32, extra.data.field_index) }; |
| 1266 | 1268 | } |
| 1267 | 1269 | |
| 1268 | | fn genSwitchBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1270 | fn airSwitchBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1269 | 1271 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 1270 | 1272 | const extra = self.air.extraData(Air.SwitchBr, pl_op.payload); |
| 1271 | 1273 | const cases = self.air.extra[extra.end..][0..extra.data.cases_len]; |
| ... | ... | @@ -1319,7 +1321,7 @@ pub const Context = struct { |
| 1319 | 1321 | return .none; |
| 1320 | 1322 | } |
| 1321 | 1323 | |
| 1322 | | fn genIsErr(self: *Context, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!WValue { |
| 1324 | fn airIsErr(self: *Context, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!WValue { |
| 1323 | 1325 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 1324 | 1326 | const operand = self.resolveInst(un_op); |
| 1325 | 1327 | const offset = self.code.items.len; |
| ... | ... | @@ -1336,7 +1338,7 @@ pub const Context = struct { |
| 1336 | 1338 | return WValue{ .code_offset = offset }; |
| 1337 | 1339 | } |
| 1338 | 1340 | |
| 1339 | | fn genUnwrapErrUnionPayload(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1341 | fn airUnwrapErrUnionPayload(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1340 | 1342 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1341 | 1343 | const operand = self.resolveInst(ty_op.operand); |
| 1342 | 1344 | // The index of multi_value contains the error code. To get the initial index of the payload we get |
| ... | ... | @@ -1346,7 +1348,7 @@ pub const Context = struct { |
| 1346 | 1348 | return WValue{ .local = operand.multi_value.index + 1 }; |
| 1347 | 1349 | } |
| 1348 | 1350 | |
| 1349 | | fn genWrapErrUnionPayload(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1351 | fn airWrapErrUnionPayload(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
| 1350 | 1352 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1351 | 1353 | return self.resolveInst(ty_op.operand); |
| 1352 | 1354 | } |