authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-02 11:18:41+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-02 13:43:46+01:00
logc157b1987865892fa1acfe88208e3567048fc892
treec106ed6fc95572f6614e54c7232d73c50bc23f0d
parent15ff891f044102ba6515cb07f40805452420ea24

wasm32: fix struct padding


1 files changed, 41 insertions(+), 28 deletions(-)

src/arch/wasm/CodeGen.zig+41-28
......@@ -619,7 +619,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue {
619619 .code = &value_bytes,
620620 .symbol_index = try self.bin_file.createLocalSymbol(self.decl, ty),
621621 };
622 const result = decl_gen.genTypedValue(ty, val, value_bytes.writer()) catch |err| {
622 const result = decl_gen.genTypedValue(ty, val) catch |err| {
623623 // When a codegen error occured, take ownership of the error message
624624 if (err == error.CodegenFail) {
625625 self.err_msg = decl_gen.err_msg;
......@@ -907,14 +907,15 @@ pub const DeclGen = struct {
907907 break :init_val payload.data.init;
908908 } else decl.val;
909909 if (init_val.tag() != .unreachable_value) {
910 return self.genTypedValue(decl.ty, init_val, self.code.writer());
910 return self.genTypedValue(decl.ty, init_val);
911911 }
912912 return Result{ .appended = {} };
913913 }
914914 }
915915
916916 /// Generates the wasm bytecode for the declaration belonging to `Context`
917 fn genTypedValue(self: *DeclGen, ty: Type, val: Value, writer: anytype) InnerError!Result {
917 fn genTypedValue(self: *DeclGen, ty: Type, val: Value) InnerError!Result {
918 const writer = self.code.writer();
918919 if (val.isUndef()) {
919920 try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target())));
920921 return Result{ .appended = {} };
......@@ -926,7 +927,7 @@ pub const DeclGen = struct {
926927 .function => val.castTag(.function).?.data.owner_decl,
927928 else => unreachable,
928929 };
929 return try self.lowerDeclRef(ty, val, fn_decl, writer);
930 return try self.lowerDeclRef(ty, val, fn_decl);
930931 },
931932 .Optional => {
932933 var opt_buf: Type.Payload.ElemType = undefined;
......@@ -942,9 +943,9 @@ pub const DeclGen = struct {
942943
943944 if (ty.isPtrLikeOptional()) {
944945 if (val.castTag(.opt_payload)) |payload| {
945 return self.genTypedValue(payload_type, payload.data, writer);
946 return self.genTypedValue(payload_type, payload.data);
946947 } else if (!val.isNull()) {
947 return self.genTypedValue(payload_type, val, writer);
948 return self.genTypedValue(payload_type, val);
948949 } else {
949950 try writer.writeByteNTimes(0, abi_size);
950951 return Result{ .appended = {} };
......@@ -956,7 +957,6 @@ pub const DeclGen = struct {
956957 switch (try self.genTypedValue(
957958 payload_type,
958959 if (val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef),
959 writer,
960960 )) {
961961 .appended => {},
962962 .externally_managed => |payload| try writer.writeAll(payload),
......@@ -972,7 +972,7 @@ pub const DeclGen = struct {
972972 const elem_vals = val.castTag(.array).?.data;
973973 const elem_ty = ty.childType();
974974 for (elem_vals) |elem_val| {
975 switch (try self.genTypedValue(elem_ty, elem_val, writer)) {
975 switch (try self.genTypedValue(elem_ty, elem_val)) {
976976 .appended => {},
977977 .externally_managed => |data| try writer.writeAll(data),
978978 }
......@@ -987,20 +987,20 @@ pub const DeclGen = struct {
987987
988988 var index: u32 = 0;
989989 while (index < len) : (index += 1) {
990 switch (try self.genTypedValue(elem_ty, array, writer)) {
990 switch (try self.genTypedValue(elem_ty, array)) {
991991 .externally_managed => |data| try writer.writeAll(data),
992992 .appended => {},
993993 }
994994 }
995995 if (sentinel) |sentinel_value| {
996 return self.genTypedValue(elem_ty, sentinel_value, writer);
996 return self.genTypedValue(elem_ty, sentinel_value);
997997 }
998998 return Result{ .appended = {} };
999999 },
10001000 .empty_array_sentinel => {
10011001 const elem_ty = ty.childType();
10021002 const sent_val = ty.sentinel().?;
1003 return self.genTypedValue(elem_ty, sent_val, writer);
1003 return self.genTypedValue(elem_ty, sent_val);
10041004 },
10051005 else => unreachable,
10061006 },
......@@ -1037,25 +1037,37 @@ pub const DeclGen = struct {
10371037 const int_val = val.enumToInt(ty, &int_buffer);
10381038 var buf: Type.Payload.Bits = undefined;
10391039 const int_ty = ty.intTagType(&buf);
1040 return self.genTypedValue(int_ty, int_val, writer);
1040 return self.genTypedValue(int_ty, int_val);
10411041 },
10421042 .Bool => {
10431043 try writer.writeByte(@boolToInt(val.toBool()));
10441044 return Result{ .appended = {} };
10451045 },
10461046 .Struct => {
1047 const struct_ty = ty.castTag(.@"struct").?.data;
1048 if (struct_ty.layout == .Packed) {
1047 const struct_obj = ty.castTag(.@"struct").?.data;
1048 if (struct_obj.layout == .Packed) {
10491049 return self.fail("TODO: Packed structs for wasm", .{});
10501050 }
1051
1052 const struct_begin = self.code.items.len;
10511053 const field_vals = val.castTag(.@"struct").?.data;
10521054 for (field_vals) |field_val, index| {
10531055 const field_ty = ty.structFieldType(index);
10541056 if (!field_ty.hasRuntimeBits()) continue;
1055 switch (try self.genTypedValue(field_ty, field_val, writer)) {
1057
1058 switch (try self.genTypedValue(field_ty, field_val)) {
10561059 .appended => {},
10571060 .externally_managed => |payload| try writer.writeAll(payload),
10581061 }
1062 const unpadded_field_len = self.code.items.len - struct_begin;
1063
1064 // Pad struct members if required
1065 const padded_field_end = ty.structFieldOffset(index + 1, self.target());
1066 const padding = try std.math.cast(usize, padded_field_end - unpadded_field_len);
1067
1068 if (padding > 0) {
1069 try writer.writeByteNTimes(0, padding);
1070 }
10591071 }
10601072 return Result{ .appended = {} };
10611073 },
......@@ -1064,12 +1076,12 @@ pub const DeclGen = struct {
10641076 const layout = ty.unionGetLayout(self.target());
10651077
10661078 if (layout.payload_size == 0) {
1067 return self.genTypedValue(ty.unionTagType().?, union_val.tag, writer);
1079 return self.genTypedValue(ty.unionTagType().?, union_val.tag);
10681080 }
10691081
10701082 // Check if we should store the tag first, in which case, do so now:
10711083 if (layout.tag_align >= layout.payload_align) {
1072 switch (try self.genTypedValue(ty.unionTagType().?, union_val.tag, writer)) {
1084 switch (try self.genTypedValue(ty.unionTagType().?, union_val.tag)) {
10731085 .appended => {},
10741086 .externally_managed => |payload| try writer.writeAll(payload),
10751087 }
......@@ -1082,7 +1094,7 @@ pub const DeclGen = struct {
10821094 if (!field_ty.hasRuntimeBits()) {
10831095 try writer.writeByteNTimes(0xaa, @intCast(usize, layout.payload_size));
10841096 } else {
1085 switch (try self.genTypedValue(field_ty, union_val.val, writer)) {
1097 switch (try self.genTypedValue(field_ty, union_val.val)) {
10861098 .appended => {},
10871099 .externally_managed => |payload| try writer.writeAll(payload),
10881100 }
......@@ -1098,26 +1110,26 @@ pub const DeclGen = struct {
10981110 if (layout.tag_size == 0) {
10991111 return Result{ .appended = {} };
11001112 }
1101 return self.genTypedValue(union_ty.tag_ty, union_val.tag, writer);
1113 return self.genTypedValue(union_ty.tag_ty, union_val.tag);
11021114 },
11031115 .Pointer => switch (val.tag()) {
11041116 .variable => {
11051117 const decl = val.castTag(.variable).?.data.owner_decl;
1106 return self.lowerDeclRef(ty, val, decl, writer);
1118 return self.lowerDeclRef(ty, val, decl);
11071119 },
11081120 .decl_ref => {
11091121 const decl = val.castTag(.decl_ref).?.data;
1110 return self.lowerDeclRef(ty, val, decl, writer);
1122 return self.lowerDeclRef(ty, val, decl);
11111123 },
11121124 .slice => {
11131125 const slice = val.castTag(.slice).?.data;
11141126 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
11151127 const ptr_ty = ty.slicePtrFieldType(&buf);
1116 switch (try self.genTypedValue(ptr_ty, slice.ptr, writer)) {
1128 switch (try self.genTypedValue(ptr_ty, slice.ptr)) {
11171129 .externally_managed => |data| try writer.writeAll(data),
11181130 .appended => {},
11191131 }
1120 switch (try self.genTypedValue(Type.usize, slice.len, writer)) {
1132 switch (try self.genTypedValue(Type.usize, slice.len)) {
11211133 .externally_managed => |data| try writer.writeAll(data),
11221134 .appended => {},
11231135 }
......@@ -1135,14 +1147,14 @@ pub const DeclGen = struct {
11351147 const is_pl = val.errorUnionIsPayload();
11361148
11371149 const err_val = if (!is_pl) val else Value.initTag(.zero);
1138 switch (try self.genTypedValue(error_ty, err_val, writer)) {
1150 switch (try self.genTypedValue(error_ty, err_val)) {
11391151 .externally_managed => |data| try writer.writeAll(data),
11401152 .appended => {},
11411153 }
11421154
11431155 if (payload_ty.hasRuntimeBits()) {
11441156 const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);
1145 switch (try self.genTypedValue(payload_ty, pl_val, writer)) {
1157 switch (try self.genTypedValue(payload_ty, pl_val)) {
11461158 .externally_managed => |data| try writer.writeAll(data),
11471159 .appended => {},
11481160 }
......@@ -1167,11 +1179,12 @@ pub const DeclGen = struct {
11671179 }
11681180 }
11691181
1170 fn lowerDeclRef(self: *DeclGen, ty: Type, val: Value, decl: *Module.Decl, writer: anytype) InnerError!Result {
1182 fn lowerDeclRef(self: *DeclGen, ty: Type, val: Value, decl: *Module.Decl) InnerError!Result {
1183 const writer = self.code.writer();
11711184 if (ty.isSlice()) {
11721185 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
11731186 const slice_ty = ty.slicePtrFieldType(&buf);
1174 switch (try self.genTypedValue(slice_ty, val, writer)) {
1187 switch (try self.genTypedValue(slice_ty, val)) {
11751188 .appended => {},
11761189 .externally_managed => |payload| try writer.writeAll(payload),
11771190 }
......@@ -1179,7 +1192,7 @@ pub const DeclGen = struct {
11791192 .base = .{ .tag = .int_u64 },
11801193 .data = val.sliceLen(),
11811194 };
1182 return self.genTypedValue(Type.usize, Value.initPayload(&slice_len.base), writer);
1195 return self.genTypedValue(Type.usize, Value.initPayload(&slice_len.base));
11831196 }
11841197
11851198 decl.markAlive();