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 {...@@ -619,7 +619,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue {
619 .code = &value_bytes,619 .code = &value_bytes,
620 .symbol_index = try self.bin_file.createLocalSymbol(self.decl, ty),620 .symbol_index = try self.bin_file.createLocalSymbol(self.decl, ty),
621 };621 };
622 const result = decl_gen.genTypedValue(ty, val, value_bytes.writer()) catch |err| {622 const result = decl_gen.genTypedValue(ty, val) catch |err| {
623 // When a codegen error occured, take ownership of the error message623 // When a codegen error occured, take ownership of the error message
624 if (err == error.CodegenFail) {624 if (err == error.CodegenFail) {
625 self.err_msg = decl_gen.err_msg;625 self.err_msg = decl_gen.err_msg;
...@@ -907,14 +907,15 @@ pub const DeclGen = struct {...@@ -907,14 +907,15 @@ pub const DeclGen = struct {
907 break :init_val payload.data.init;907 break :init_val payload.data.init;
908 } else decl.val;908 } else decl.val;
909 if (init_val.tag() != .unreachable_value) {909 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);
911 }911 }
912 return Result{ .appended = {} };912 return Result{ .appended = {} };
913 }913 }
914 }914 }
915915
916 /// Generates the wasm bytecode for the declaration belonging to `Context`916 /// 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();
918 if (val.isUndef()) {919 if (val.isUndef()) {
919 try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target())));920 try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target())));
920 return Result{ .appended = {} };921 return Result{ .appended = {} };
...@@ -926,7 +927,7 @@ pub const DeclGen = struct {...@@ -926,7 +927,7 @@ pub const DeclGen = struct {
926 .function => val.castTag(.function).?.data.owner_decl,927 .function => val.castTag(.function).?.data.owner_decl,
927 else => unreachable,928 else => unreachable,
928 };929 };
929 return try self.lowerDeclRef(ty, val, fn_decl, writer);930 return try self.lowerDeclRef(ty, val, fn_decl);
930 },931 },
931 .Optional => {932 .Optional => {
932 var opt_buf: Type.Payload.ElemType = undefined;933 var opt_buf: Type.Payload.ElemType = undefined;
...@@ -942,9 +943,9 @@ pub const DeclGen = struct {...@@ -942,9 +943,9 @@ pub const DeclGen = struct {
942943
943 if (ty.isPtrLikeOptional()) {944 if (ty.isPtrLikeOptional()) {
944 if (val.castTag(.opt_payload)) |payload| {945 if (val.castTag(.opt_payload)) |payload| {
945 return self.genTypedValue(payload_type, payload.data, writer);946 return self.genTypedValue(payload_type, payload.data);
946 } else if (!val.isNull()) {947 } else if (!val.isNull()) {
947 return self.genTypedValue(payload_type, val, writer);948 return self.genTypedValue(payload_type, val);
948 } else {949 } else {
949 try writer.writeByteNTimes(0, abi_size);950 try writer.writeByteNTimes(0, abi_size);
950 return Result{ .appended = {} };951 return Result{ .appended = {} };
...@@ -956,7 +957,6 @@ pub const DeclGen = struct {...@@ -956,7 +957,6 @@ pub const DeclGen = struct {
956 switch (try self.genTypedValue(957 switch (try self.genTypedValue(
957 payload_type,958 payload_type,
958 if (val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef),959 if (val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef),
959 writer,
960 )) {960 )) {
961 .appended => {},961 .appended => {},
962 .externally_managed => |payload| try writer.writeAll(payload),962 .externally_managed => |payload| try writer.writeAll(payload),
...@@ -972,7 +972,7 @@ pub const DeclGen = struct {...@@ -972,7 +972,7 @@ pub const DeclGen = struct {
972 const elem_vals = val.castTag(.array).?.data;972 const elem_vals = val.castTag(.array).?.data;
973 const elem_ty = ty.childType();973 const elem_ty = ty.childType();
974 for (elem_vals) |elem_val| {974 for (elem_vals) |elem_val| {
975 switch (try self.genTypedValue(elem_ty, elem_val, writer)) {975 switch (try self.genTypedValue(elem_ty, elem_val)) {
976 .appended => {},976 .appended => {},
977 .externally_managed => |data| try writer.writeAll(data),977 .externally_managed => |data| try writer.writeAll(data),
978 }978 }
...@@ -987,20 +987,20 @@ pub const DeclGen = struct {...@@ -987,20 +987,20 @@ pub const DeclGen = struct {
987987
988 var index: u32 = 0;988 var index: u32 = 0;
989 while (index < len) : (index += 1) {989 while (index < len) : (index += 1) {
990 switch (try self.genTypedValue(elem_ty, array, writer)) {990 switch (try self.genTypedValue(elem_ty, array)) {
991 .externally_managed => |data| try writer.writeAll(data),991 .externally_managed => |data| try writer.writeAll(data),
992 .appended => {},992 .appended => {},
993 }993 }
994 }994 }
995 if (sentinel) |sentinel_value| {995 if (sentinel) |sentinel_value| {
996 return self.genTypedValue(elem_ty, sentinel_value, writer);996 return self.genTypedValue(elem_ty, sentinel_value);
997 }997 }
998 return Result{ .appended = {} };998 return Result{ .appended = {} };
999 },999 },
1000 .empty_array_sentinel => {1000 .empty_array_sentinel => {
1001 const elem_ty = ty.childType();1001 const elem_ty = ty.childType();
1002 const sent_val = ty.sentinel().?;1002 const sent_val = ty.sentinel().?;
1003 return self.genTypedValue(elem_ty, sent_val, writer);1003 return self.genTypedValue(elem_ty, sent_val);
1004 },1004 },
1005 else => unreachable,1005 else => unreachable,
1006 },1006 },
...@@ -1037,25 +1037,37 @@ pub const DeclGen = struct {...@@ -1037,25 +1037,37 @@ pub const DeclGen = struct {
1037 const int_val = val.enumToInt(ty, &int_buffer);1037 const int_val = val.enumToInt(ty, &int_buffer);
1038 var buf: Type.Payload.Bits = undefined;1038 var buf: Type.Payload.Bits = undefined;
1039 const int_ty = ty.intTagType(&buf);1039 const int_ty = ty.intTagType(&buf);
1040 return self.genTypedValue(int_ty, int_val, writer);1040 return self.genTypedValue(int_ty, int_val);
1041 },1041 },
1042 .Bool => {1042 .Bool => {
1043 try writer.writeByte(@boolToInt(val.toBool()));1043 try writer.writeByte(@boolToInt(val.toBool()));
1044 return Result{ .appended = {} };1044 return Result{ .appended = {} };
1045 },1045 },
1046 .Struct => {1046 .Struct => {
1047 const struct_ty = ty.castTag(.@"struct").?.data;1047 const struct_obj = ty.castTag(.@"struct").?.data;
1048 if (struct_ty.layout == .Packed) {1048 if (struct_obj.layout == .Packed) {
1049 return self.fail("TODO: Packed structs for wasm", .{});1049 return self.fail("TODO: Packed structs for wasm", .{});
1050 }1050 }
1051
1052 const struct_begin = self.code.items.len;
1051 const field_vals = val.castTag(.@"struct").?.data;1053 const field_vals = val.castTag(.@"struct").?.data;
1052 for (field_vals) |field_val, index| {1054 for (field_vals) |field_val, index| {
1053 const field_ty = ty.structFieldType(index);1055 const field_ty = ty.structFieldType(index);
1054 if (!field_ty.hasRuntimeBits()) continue;1056 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)) {
1056 .appended => {},1059 .appended => {},
1057 .externally_managed => |payload| try writer.writeAll(payload),1060 .externally_managed => |payload| try writer.writeAll(payload),
1058 }1061 }
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 }
1059 }1071 }
1060 return Result{ .appended = {} };1072 return Result{ .appended = {} };
1061 },1073 },
...@@ -1064,12 +1076,12 @@ pub const DeclGen = struct {...@@ -1064,12 +1076,12 @@ pub const DeclGen = struct {
1064 const layout = ty.unionGetLayout(self.target());1076 const layout = ty.unionGetLayout(self.target());
10651077
1066 if (layout.payload_size == 0) {1078 if (layout.payload_size == 0) {
1067 return self.genTypedValue(ty.unionTagType().?, union_val.tag, writer);1079 return self.genTypedValue(ty.unionTagType().?, union_val.tag);
1068 }1080 }
10691081
1070 // Check if we should store the tag first, in which case, do so now:1082 // Check if we should store the tag first, in which case, do so now:
1071 if (layout.tag_align >= layout.payload_align) {1083 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)) {
1073 .appended => {},1085 .appended => {},
1074 .externally_managed => |payload| try writer.writeAll(payload),1086 .externally_managed => |payload| try writer.writeAll(payload),
1075 }1087 }
...@@ -1082,7 +1094,7 @@ pub const DeclGen = struct {...@@ -1082,7 +1094,7 @@ pub const DeclGen = struct {
1082 if (!field_ty.hasRuntimeBits()) {1094 if (!field_ty.hasRuntimeBits()) {
1083 try writer.writeByteNTimes(0xaa, @intCast(usize, layout.payload_size));1095 try writer.writeByteNTimes(0xaa, @intCast(usize, layout.payload_size));
1084 } else {1096 } else {
1085 switch (try self.genTypedValue(field_ty, union_val.val, writer)) {1097 switch (try self.genTypedValue(field_ty, union_val.val)) {
1086 .appended => {},1098 .appended => {},
1087 .externally_managed => |payload| try writer.writeAll(payload),1099 .externally_managed => |payload| try writer.writeAll(payload),
1088 }1100 }
...@@ -1098,26 +1110,26 @@ pub const DeclGen = struct {...@@ -1098,26 +1110,26 @@ pub const DeclGen = struct {
1098 if (layout.tag_size == 0) {1110 if (layout.tag_size == 0) {
1099 return Result{ .appended = {} };1111 return Result{ .appended = {} };
1100 }1112 }
1101 return self.genTypedValue(union_ty.tag_ty, union_val.tag, writer);1113 return self.genTypedValue(union_ty.tag_ty, union_val.tag);
1102 },1114 },
1103 .Pointer => switch (val.tag()) {1115 .Pointer => switch (val.tag()) {
1104 .variable => {1116 .variable => {
1105 const decl = val.castTag(.variable).?.data.owner_decl;1117 const decl = val.castTag(.variable).?.data.owner_decl;
1106 return self.lowerDeclRef(ty, val, decl, writer);1118 return self.lowerDeclRef(ty, val, decl);
1107 },1119 },
1108 .decl_ref => {1120 .decl_ref => {
1109 const decl = val.castTag(.decl_ref).?.data;1121 const decl = val.castTag(.decl_ref).?.data;
1110 return self.lowerDeclRef(ty, val, decl, writer);1122 return self.lowerDeclRef(ty, val, decl);
1111 },1123 },
1112 .slice => {1124 .slice => {
1113 const slice = val.castTag(.slice).?.data;1125 const slice = val.castTag(.slice).?.data;
1114 var buf: Type.SlicePtrFieldTypeBuffer = undefined;1126 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1115 const ptr_ty = ty.slicePtrFieldType(&buf);1127 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)) {
1117 .externally_managed => |data| try writer.writeAll(data),1129 .externally_managed => |data| try writer.writeAll(data),
1118 .appended => {},1130 .appended => {},
1119 }1131 }
1120 switch (try self.genTypedValue(Type.usize, slice.len, writer)) {1132 switch (try self.genTypedValue(Type.usize, slice.len)) {
1121 .externally_managed => |data| try writer.writeAll(data),1133 .externally_managed => |data| try writer.writeAll(data),
1122 .appended => {},1134 .appended => {},
1123 }1135 }
...@@ -1135,14 +1147,14 @@ pub const DeclGen = struct {...@@ -1135,14 +1147,14 @@ pub const DeclGen = struct {
1135 const is_pl = val.errorUnionIsPayload();1147 const is_pl = val.errorUnionIsPayload();
11361148
1137 const err_val = if (!is_pl) val else Value.initTag(.zero);1149 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)) {
1139 .externally_managed => |data| try writer.writeAll(data),1151 .externally_managed => |data| try writer.writeAll(data),
1140 .appended => {},1152 .appended => {},
1141 }1153 }
11421154
1143 if (payload_ty.hasRuntimeBits()) {1155 if (payload_ty.hasRuntimeBits()) {
1144 const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);1156 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)) {
1146 .externally_managed => |data| try writer.writeAll(data),1158 .externally_managed => |data| try writer.writeAll(data),
1147 .appended => {},1159 .appended => {},
1148 }1160 }
...@@ -1167,11 +1179,12 @@ pub const DeclGen = struct {...@@ -1167,11 +1179,12 @@ pub const DeclGen = struct {
1167 }1179 }
1168 }1180 }
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();
1171 if (ty.isSlice()) {1184 if (ty.isSlice()) {
1172 var buf: Type.SlicePtrFieldTypeBuffer = undefined;1185 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1173 const slice_ty = ty.slicePtrFieldType(&buf);1186 const slice_ty = ty.slicePtrFieldType(&buf);
1174 switch (try self.genTypedValue(slice_ty, val, writer)) {1187 switch (try self.genTypedValue(slice_ty, val)) {
1175 .appended => {},1188 .appended => {},
1176 .externally_managed => |payload| try writer.writeAll(payload),1189 .externally_managed => |payload| try writer.writeAll(payload),
1177 }1190 }
...@@ -1179,7 +1192,7 @@ pub const DeclGen = struct {...@@ -1179,7 +1192,7 @@ pub const DeclGen = struct {
1179 .base = .{ .tag = .int_u64 },1192 .base = .{ .tag = .int_u64 },
1180 .data = val.sliceLen(),1193 .data = val.sliceLen(),
1181 };1194 };
1182 return self.genTypedValue(Type.usize, Value.initPayload(&slice_len.base), writer);1195 return self.genTypedValue(Type.usize, Value.initPayload(&slice_len.base));
1183 }1196 }
11841197
1185 decl.markAlive();1198 decl.markAlive();