| ... | ... | @@ -1088,19 +1088,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) InnerError!CallWValu |
| 1088 | 1088 | } |
| 1089 | 1089 | |
| 1090 | 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 | 1091 | // Check if we store the result as a pointer to the stack rather than |
| 1096 | 1092 | // by value |
| 1097 | | if (result.return_value != .none) { |
| 1093 | if (isByRef(ret_ty)) { |
| 1098 | 1094 | if (self.initial_stack_value == .none) try self.initializeStack(); |
| 1099 | | const offset = std.math.cast(u32, ret_ty.abiSize(self.target)) catch { |
| 1100 | | return self.fail("Return type '{}' too big for stack frame", .{ret_ty}); |
| 1101 | | }; |
| 1102 | | |
| 1103 | | try self.moveStack(offset, result.return_value.local); |
| 1095 | result.return_value = try self.allocStack(ret_ty); |
| 1104 | 1096 | |
| 1105 | 1097 | // We want to make sure the return value's stack value doesn't get overwritten, |
| 1106 | 1098 | // so set initial stack value to current's position instead. |
| ... | ... | @@ -1165,10 +1157,16 @@ fn allocStack(self: *Self, ty: Type) !WValue { |
| 1165 | 1157 | assert(ty.hasCodeGenBits()); |
| 1166 | 1158 | |
| 1167 | 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 | 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 | 1170 | // allocate a local using wasm's pointer size |
| 1173 | 1171 | const local = try self.allocLocal(Type.@"usize"); |
| 1174 | 1172 | try self.moveStack(abi_size, local.local); |
| ... | ... | @@ -1337,6 +1335,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1337 | 1335 | .ret => self.airRet(inst), |
| 1338 | 1336 | .ret_ptr => self.airRetPtr(inst), |
| 1339 | 1337 | .ret_load => self.airRetLoad(inst), |
| 1338 | .slice => self.airSlice(inst), |
| 1340 | 1339 | .slice_len => self.airSliceLen(inst), |
| 1341 | 1340 | .slice_elem_val => self.airSliceElemVal(inst), |
| 1342 | 1341 | .slice_elem_ptr => self.airSliceElemPtr(inst), |
| ... | ... | @@ -1994,6 +1993,11 @@ fn emitUndefined(self: *Self, ty: Type) InnerError!void { |
| 1994 | 1993 | const result = try self.allocStack(ty); |
| 1995 | 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 | 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 | 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 | 2696 | fn airSliceLen(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2677 | 2697 | if (self.liveness.isUnused(inst)) return WValue.none; |
| 2678 | 2698 | |