| ... | @@ -1088,19 +1088,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) InnerError!CallWValu | ... | @@ -1088,19 +1088,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) InnerError!CallWValu |
| 1088 | } | 1088 | } |
| 1089 | | 1089 | |
| 1090 | const ret_ty = fn_ty.fnReturnType(); | 1090 | const ret_ty = fn_ty.fnReturnType(); |
| 1091 | if (isByRef(ret_ty)) { | | |
| 1092 | result.return_value = try self.allocLocal(Type.initTag(.i32)); | | |
| 1093 | } | | |
| 1094 | | | |
| 1095 | // Check if we store the result as a pointer to the stack rather than | 1091 | // Check if we store the result as a pointer to the stack rather than |
| 1096 | // by value | 1092 | // by value |
| 1097 | if (result.return_value != .none) { | 1093 | if (isByRef(ret_ty)) { |
| 1098 | if (self.initial_stack_value == .none) try self.initializeStack(); | 1094 | if (self.initial_stack_value == .none) try self.initializeStack(); |
| 1099 | const offset = std.math.cast(u32, ret_ty.abiSize(self.target)) catch { | 1095 | result.return_value = try self.allocStack(ret_ty); |
| 1100 | return self.fail("Return type '{}' too big for stack frame", .{ret_ty}); | | |
| 1101 | }; | | |
| 1102 | | | |
| 1103 | try self.moveStack(offset, result.return_value.local); | | |
| 1104 | | 1096 | |
| 1105 | // We want to make sure the return value's stack value doesn't get overwritten, | 1097 | // We want to make sure the return value's stack value doesn't get overwritten, |
| 1106 | // so set initial stack value to current's position instead. | 1098 | // so set initial stack value to current's position instead. |
| ... | @@ -1165,10 +1157,16 @@ fn allocStack(self: *Self, ty: Type) !WValue { | ... | @@ -1165,10 +1157,16 @@ fn allocStack(self: *Self, ty: Type) !WValue { |
| 1165 | assert(ty.hasCodeGenBits()); | 1157 | assert(ty.hasCodeGenBits()); |
| 1166 | | 1158 | |
| 1167 | // calculate needed stack space | 1159 | // calculate needed stack space |
| 1168 | const abi_size = std.math.cast(u32, ty.abiSize(self.target)) catch { | 1160 | var abi_size = std.math.cast(u32, ty.abiSize(self.target)) catch { |
| 1169 | return self.fail("Given type '{}' too big to fit into stack frame", .{ty}); | 1161 | return self.fail("Given type '{}' too big to fit into stack frame", .{ty}); |
| 1170 | }; | 1162 | }; |
| 1171 | | 1163 | |
| | 1164 | // We store slices as a struct with a pointer field and a length field |
| | 1165 | // both being 'usize' size. |
| | 1166 | if (ty.isSlice()) { |
| | 1167 | abi_size = self.ptrSize() * 2; |
| | 1168 | } |
| | 1169 | |
| 1172 | // allocate a local using wasm's pointer size | 1170 | // allocate a local using wasm's pointer size |
| 1173 | const local = try self.allocLocal(Type.@"usize"); | 1171 | const local = try self.allocLocal(Type.@"usize"); |
| 1174 | try self.moveStack(abi_size, local.local); | 1172 | try self.moveStack(abi_size, local.local); |
| ... | @@ -1337,6 +1335,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1337,6 +1335,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1337 | .ret => self.airRet(inst), | 1335 | .ret => self.airRet(inst), |
| 1338 | .ret_ptr => self.airRetPtr(inst), | 1336 | .ret_ptr => self.airRetPtr(inst), |
| 1339 | .ret_load => self.airRetLoad(inst), | 1337 | .ret_load => self.airRetLoad(inst), |
| | 1338 | .slice => self.airSlice(inst), |
| 1340 | .slice_len => self.airSliceLen(inst), | 1339 | .slice_len => self.airSliceLen(inst), |
| 1341 | .slice_elem_val => self.airSliceElemVal(inst), | 1340 | .slice_elem_val => self.airSliceElemVal(inst), |
| 1342 | .slice_elem_ptr => self.airSliceElemPtr(inst), | 1341 | .slice_elem_ptr => self.airSliceElemPtr(inst), |
| ... | @@ -1994,6 +1993,11 @@ fn emitUndefined(self: *Self, ty: Type) InnerError!void { | ... | @@ -1994,6 +1993,11 @@ fn emitUndefined(self: *Self, ty: Type) InnerError!void { |
| 1994 | const result = try self.allocStack(ty); | 1993 | const result = try self.allocStack(ty); |
| 1995 | try self.addLabel(.local_get, result.local); | 1994 | try self.addLabel(.local_get, result.local); |
| 1996 | }, | 1995 | }, |
| | 1996 | .Pointer => switch (self.ptrSize()) { |
| | 1997 | 4 => try self.addImm32(@bitCast(i32, @as(u32, 0xaaaaaaaa))), |
| | 1998 | 8 => try self.addImm64(0xaaaaaaaaaaaaaaaa), |
| | 1999 | else => unreachable, |
| | 2000 | }, |
| 1997 | else => return self.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty}), | 2001 | else => return self.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty}), |
| 1998 | } | 2002 | } |
| 1999 | } | 2003 | } |
| ... | @@ -2673,6 +2677,22 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2673,6 +2677,22 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2673 | return result; | 2677 | return result; |
| 2674 | } | 2678 | } |
| 2675 | | 2679 | |
| | 2680 | fn airSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| | 2681 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| | 2682 | |
| | 2683 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| | 2684 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| | 2685 | const lhs = self.resolveInst(bin_op.lhs); |
| | 2686 | const rhs = self.resolveInst(bin_op.rhs); |
| | 2687 | const slice_ty = self.air.typeOfIndex(inst); |
| | 2688 | |
| | 2689 | const slice = try self.allocStack(slice_ty); |
| | 2690 | try self.store(slice, lhs, Type.usize, 0); |
| | 2691 | try self.store(slice, rhs, Type.usize, self.ptrSize()); |
| | 2692 | |
| | 2693 | return slice; |
| | 2694 | } |
| | 2695 | |
| 2676 | fn airSliceLen(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2696 | fn airSliceLen(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2677 | if (self.liveness.isUnused(inst)) return WValue.none; | 2697 | if (self.liveness.isUnused(inst)) return WValue.none; |
| 2678 | | 2698 | |