| ... | ... | @@ -619,7 +619,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue { |
| 619 | 619 | .code = &value_bytes, |
| 620 | 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 | 623 | // When a codegen error occured, take ownership of the error message |
| 624 | 624 | if (err == error.CodegenFail) { |
| 625 | 625 | self.err_msg = decl_gen.err_msg; |
| ... | ... | @@ -907,14 +907,15 @@ pub const DeclGen = struct { |
| 907 | 907 | break :init_val payload.data.init; |
| 908 | 908 | } else decl.val; |
| 909 | 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 | 912 | return Result{ .appended = {} }; |
| 913 | 913 | } |
| 914 | 914 | } |
| 915 | 915 | |
| 916 | 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 | 919 | if (val.isUndef()) { |
| 919 | 920 | try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target()))); |
| 920 | 921 | return Result{ .appended = {} }; |
| ... | ... | @@ -926,7 +927,7 @@ pub const DeclGen = struct { |
| 926 | 927 | .function => val.castTag(.function).?.data.owner_decl, |
| 927 | 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 | 932 | .Optional => { |
| 932 | 933 | var opt_buf: Type.Payload.ElemType = undefined; |
| ... | ... | @@ -942,9 +943,9 @@ pub const DeclGen = struct { |
| 942 | 943 | |
| 943 | 944 | if (ty.isPtrLikeOptional()) { |
| 944 | 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 | 947 | } else if (!val.isNull()) { |
| 947 | | return self.genTypedValue(payload_type, val, writer); |
| 948 | return self.genTypedValue(payload_type, val); |
| 948 | 949 | } else { |
| 949 | 950 | try writer.writeByteNTimes(0, abi_size); |
| 950 | 951 | return Result{ .appended = {} }; |
| ... | ... | @@ -956,7 +957,6 @@ pub const DeclGen = struct { |
| 956 | 957 | switch (try self.genTypedValue( |
| 957 | 958 | payload_type, |
| 958 | 959 | if (val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef), |
| 959 | | writer, |
| 960 | 960 | )) { |
| 961 | 961 | .appended => {}, |
| 962 | 962 | .externally_managed => |payload| try writer.writeAll(payload), |
| ... | ... | @@ -972,7 +972,7 @@ pub const DeclGen = struct { |
| 972 | 972 | const elem_vals = val.castTag(.array).?.data; |
| 973 | 973 | const elem_ty = ty.childType(); |
| 974 | 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 | 976 | .appended => {}, |
| 977 | 977 | .externally_managed => |data| try writer.writeAll(data), |
| 978 | 978 | } |
| ... | ... | @@ -987,20 +987,20 @@ pub const DeclGen = struct { |
| 987 | 987 | |
| 988 | 988 | var index: u32 = 0; |
| 989 | 989 | while (index < len) : (index += 1) { |
| 990 | | switch (try self.genTypedValue(elem_ty, array, writer)) { |
| 990 | switch (try self.genTypedValue(elem_ty, array)) { |
| 991 | 991 | .externally_managed => |data| try writer.writeAll(data), |
| 992 | 992 | .appended => {}, |
| 993 | 993 | } |
| 994 | 994 | } |
| 995 | 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 | 998 | return Result{ .appended = {} }; |
| 999 | 999 | }, |
| 1000 | 1000 | .empty_array_sentinel => { |
| 1001 | 1001 | const elem_ty = ty.childType(); |
| 1002 | 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 | 1005 | else => unreachable, |
| 1006 | 1006 | }, |
| ... | ... | @@ -1037,25 +1037,37 @@ pub const DeclGen = struct { |
| 1037 | 1037 | const int_val = val.enumToInt(ty, &int_buffer); |
| 1038 | 1038 | var buf: Type.Payload.Bits = undefined; |
| 1039 | 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 | 1042 | .Bool => { |
| 1043 | 1043 | try writer.writeByte(@boolToInt(val.toBool())); |
| 1044 | 1044 | return Result{ .appended = {} }; |
| 1045 | 1045 | }, |
| 1046 | 1046 | .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) { |
| 1049 | 1049 | return self.fail("TODO: Packed structs for wasm", .{}); |
| 1050 | 1050 | } |
| 1051 | |
| 1052 | const struct_begin = self.code.items.len; |
| 1051 | 1053 | const field_vals = val.castTag(.@"struct").?.data; |
| 1052 | 1054 | for (field_vals) |field_val, index| { |
| 1053 | 1055 | const field_ty = ty.structFieldType(index); |
| 1054 | 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 | 1059 | .appended => {}, |
| 1057 | 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 | 1072 | return Result{ .appended = {} }; |
| 1061 | 1073 | }, |
| ... | ... | @@ -1064,12 +1076,12 @@ pub const DeclGen = struct { |
| 1064 | 1076 | const layout = ty.unionGetLayout(self.target()); |
| 1065 | 1077 | |
| 1066 | 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 | } |
| 1069 | 1081 | |
| 1070 | 1082 | // Check if we should store the tag first, in which case, do so now: |
| 1071 | 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 | 1085 | .appended => {}, |
| 1074 | 1086 | .externally_managed => |payload| try writer.writeAll(payload), |
| 1075 | 1087 | } |
| ... | ... | @@ -1082,7 +1094,7 @@ pub const DeclGen = struct { |
| 1082 | 1094 | if (!field_ty.hasRuntimeBits()) { |
| 1083 | 1095 | try writer.writeByteNTimes(0xaa, @intCast(usize, layout.payload_size)); |
| 1084 | 1096 | } else { |
| 1085 | | switch (try self.genTypedValue(field_ty, union_val.val, writer)) { |
| 1097 | switch (try self.genTypedValue(field_ty, union_val.val)) { |
| 1086 | 1098 | .appended => {}, |
| 1087 | 1099 | .externally_managed => |payload| try writer.writeAll(payload), |
| 1088 | 1100 | } |
| ... | ... | @@ -1098,26 +1110,26 @@ pub const DeclGen = struct { |
| 1098 | 1110 | if (layout.tag_size == 0) { |
| 1099 | 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 | 1115 | .Pointer => switch (val.tag()) { |
| 1104 | 1116 | .variable => { |
| 1105 | 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 | 1120 | .decl_ref => { |
| 1109 | 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 | 1124 | .slice => { |
| 1113 | 1125 | const slice = val.castTag(.slice).?.data; |
| 1114 | 1126 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1115 | 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 | 1129 | .externally_managed => |data| try writer.writeAll(data), |
| 1118 | 1130 | .appended => {}, |
| 1119 | 1131 | } |
| 1120 | | switch (try self.genTypedValue(Type.usize, slice.len, writer)) { |
| 1132 | switch (try self.genTypedValue(Type.usize, slice.len)) { |
| 1121 | 1133 | .externally_managed => |data| try writer.writeAll(data), |
| 1122 | 1134 | .appended => {}, |
| 1123 | 1135 | } |
| ... | ... | @@ -1135,14 +1147,14 @@ pub const DeclGen = struct { |
| 1135 | 1147 | const is_pl = val.errorUnionIsPayload(); |
| 1136 | 1148 | |
| 1137 | 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 | 1151 | .externally_managed => |data| try writer.writeAll(data), |
| 1140 | 1152 | .appended => {}, |
| 1141 | 1153 | } |
| 1142 | 1154 | |
| 1143 | 1155 | if (payload_ty.hasRuntimeBits()) { |
| 1144 | 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 | 1158 | .externally_managed => |data| try writer.writeAll(data), |
| 1147 | 1159 | .appended => {}, |
| 1148 | 1160 | } |
| ... | ... | @@ -1167,11 +1179,12 @@ pub const DeclGen = struct { |
| 1167 | 1179 | } |
| 1168 | 1180 | } |
| 1169 | 1181 | |
| 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 | 1184 | if (ty.isSlice()) { |
| 1172 | 1185 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1173 | 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 | 1188 | .appended => {}, |
| 1176 | 1189 | .externally_managed => |payload| try writer.writeAll(payload), |
| 1177 | 1190 | } |
| ... | ... | @@ -1179,7 +1192,7 @@ pub const DeclGen = struct { |
| 1179 | 1192 | .base = .{ .tag = .int_u64 }, |
| 1180 | 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 | } |
| 1184 | 1197 | |
| 1185 | 1198 | decl.markAlive(); |