| ... | @@ -639,7 +639,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue { | ... | @@ -639,7 +639,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue { |
| 639 | } | 639 | } |
| 640 | | 640 | |
| 641 | // When we need to pass the value by reference (such as a struct), we will | 641 | // When we need to pass the value by reference (such as a struct), we will |
| 642 | // leverage `genTypedValue` to lower the constant to bytes and emit it | 642 | // leverage `generateSymbol` to lower the constant to bytes and emit it |
| 643 | // to the 'rodata' section. We then return the index into the section as `WValue`. | 643 | // to the 'rodata' section. We then return the index into the section as `WValue`. |
| 644 | // | 644 | // |
| 645 | // In the other cases, we will simply lower the constant to a value that fits | 645 | // In the other cases, we will simply lower the constant to a value that fits |
| ... | @@ -903,434 +903,6 @@ pub fn genFunc(self: *Self) InnerError!void { | ... | @@ -903,434 +903,6 @@ pub fn genFunc(self: *Self) InnerError!void { |
| 903 | }; | 903 | }; |
| 904 | } | 904 | } |
| 905 | | 905 | |
| 906 | pub const DeclGen = struct { | | |
| 907 | /// The decl we are generating code for. | | |
| 908 | decl: *Decl, | | |
| 909 | /// The symbol we're generating code for. | | |
| 910 | /// This can either be the symbol of the Decl itself, | | |
| 911 | /// or one of its locals. | | |
| 912 | symbol_index: u32, | | |
| 913 | gpa: Allocator, | | |
| 914 | /// A reference to the linker, that will process the decl's | | |
| 915 | /// code and create any relocations it deems neccesary. | | |
| 916 | bin_file: *link.File.Wasm, | | |
| 917 | /// This will be set when `InnerError` has been returned. | | |
| 918 | /// In any other case, this will be 'undefined'. | | |
| 919 | err_msg: *Module.ErrorMsg, | | |
| 920 | /// Reference to the Module that is being compiled. | | |
| 921 | /// Used to find the error value of an error. | | |
| 922 | module: *Module, | | |
| 923 | /// The list of bytes that have been generated so far, | | |
| 924 | /// can be used to calculate the offset into a section. | | |
| 925 | code: *std.ArrayList(u8), | | |
| 926 | | | |
| 927 | /// Sets `err_msg` on `DeclGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig | | |
| 928 | fn fail(self: *DeclGen, comptime fmt: []const u8, args: anytype) InnerError { | | |
| 929 | const src: LazySrcLoc = .{ .node_offset = 0 }; | | |
| 930 | const src_loc = src.toSrcLoc(self.decl); | | |
| 931 | self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, fmt, args); | | |
| 932 | return error.CodegenFail; | | |
| 933 | } | | |
| 934 | | | |
| 935 | fn target(self: *const DeclGen) std.Target { | | |
| 936 | return self.bin_file.base.options.target; | | |
| 937 | } | | |
| 938 | | | |
| 939 | pub fn genDecl(self: *DeclGen) InnerError!Result { | | |
| 940 | const decl = self.decl; | | |
| 941 | assert(decl.has_tv); | | |
| 942 | | | |
| 943 | log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val }); | | |
| 944 | | | |
| 945 | if (decl.val.castTag(.function)) |func_payload| { | | |
| 946 | _ = func_payload; | | |
| 947 | return self.fail("TODO wasm backend genDecl function pointer", .{}); | | |
| 948 | } else if (decl.val.castTag(.extern_fn)) |extern_fn| { | | |
| 949 | const ext_decl = extern_fn.data.owner_decl; | | |
| 950 | var func_type = try genFunctype(self.gpa, ext_decl.ty, self.target()); | | |
| 951 | defer func_type.deinit(self.gpa); | | |
| 952 | ext_decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type); | | |
| 953 | return Result{ .appended = {} }; | | |
| 954 | } else { | | |
| 955 | const init_val = if (decl.val.castTag(.variable)) |payload| init_val: { | | |
| 956 | break :init_val payload.data.init; | | |
| 957 | } else decl.val; | | |
| 958 | if (init_val.tag() != .unreachable_value) { | | |
| 959 | return self.genTypedValue(decl.ty, init_val); | | |
| 960 | } | | |
| 961 | return Result{ .appended = {} }; | | |
| 962 | } | | |
| 963 | } | | |
| 964 | | | |
| 965 | /// Generates the wasm bytecode for the declaration belonging to `Context` | | |
| 966 | pub fn genTypedValue(self: *DeclGen, ty: Type, val: Value) InnerError!Result { | | |
| 967 | log.debug("genTypedValue: ty = {}, val = {}", .{ ty, val }); | | |
| 968 | | | |
| 969 | const writer = self.code.writer(); | | |
| 970 | if (val.isUndef()) { | | |
| 971 | try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target()))); | | |
| 972 | return Result{ .appended = {} }; | | |
| 973 | } | | |
| 974 | switch (ty.zigTypeTag()) { | | |
| 975 | .Fn => { | | |
| 976 | const fn_decl = switch (val.tag()) { | | |
| 977 | .extern_fn => val.castTag(.extern_fn).?.data.owner_decl, | | |
| 978 | .function => val.castTag(.function).?.data.owner_decl, | | |
| 979 | else => unreachable, | | |
| 980 | }; | | |
| 981 | return try self.lowerDeclRefValue(ty, val, fn_decl, 0); | | |
| 982 | }, | | |
| 983 | .Optional => { | | |
| 984 | var opt_buf: Type.Payload.ElemType = undefined; | | |
| 985 | const payload_type = ty.optionalChild(&opt_buf); | | |
| 986 | const is_pl = !val.isNull(); | | |
| 987 | const abi_size = @intCast(usize, ty.abiSize(self.target())); | | |
| 988 | const offset = abi_size - @intCast(usize, payload_type.abiSize(self.target())); | | |
| 989 | | | |
| 990 | if (!payload_type.hasRuntimeBits()) { | | |
| 991 | try writer.writeByteNTimes(@boolToInt(is_pl), abi_size); | | |
| 992 | return Result{ .appended = {} }; | | |
| 993 | } | | |
| 994 | | | |
| 995 | if (ty.isPtrLikeOptional()) { | | |
| 996 | if (val.castTag(.opt_payload)) |payload| { | | |
| 997 | return self.genTypedValue(payload_type, payload.data); | | |
| 998 | } else if (!val.isNull()) { | | |
| 999 | return self.genTypedValue(payload_type, val); | | |
| 1000 | } else { | | |
| 1001 | try writer.writeByteNTimes(0, abi_size); | | |
| 1002 | return Result{ .appended = {} }; | | |
| 1003 | } | | |
| 1004 | } | | |
| 1005 | | | |
| 1006 | // `null-tag` bytes | | |
| 1007 | try writer.writeByteNTimes(@boolToInt(is_pl), offset); | | |
| 1008 | switch (try self.genTypedValue( | | |
| 1009 | payload_type, | | |
| 1010 | if (val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef), | | |
| 1011 | )) { | | |
| 1012 | .appended => {}, | | |
| 1013 | .externally_managed => |payload| try writer.writeAll(payload), | | |
| 1014 | } | | |
| 1015 | return Result{ .appended = {} }; | | |
| 1016 | }, | | |
| 1017 | .Array => switch (val.tag()) { | | |
| 1018 | .bytes => { | | |
| 1019 | const payload = val.castTag(.bytes).?; | | |
| 1020 | return Result{ .externally_managed = payload.data }; | | |
| 1021 | }, | | |
| 1022 | .array => { | | |
| 1023 | const elem_vals = val.castTag(.array).?.data; | | |
| 1024 | const elem_ty = ty.childType(); | | |
| 1025 | for (elem_vals) |elem_val| { | | |
| 1026 | switch (try self.genTypedValue(elem_ty, elem_val)) { | | |
| 1027 | .appended => {}, | | |
| 1028 | .externally_managed => |data| try writer.writeAll(data), | | |
| 1029 | } | | |
| 1030 | } | | |
| 1031 | return Result{ .appended = {} }; | | |
| 1032 | }, | | |
| 1033 | .repeated => { | | |
| 1034 | const array = val.castTag(.repeated).?.data; | | |
| 1035 | const elem_ty = ty.childType(); | | |
| 1036 | const sentinel = ty.sentinel(); | | |
| 1037 | const len = ty.arrayLen(); | | |
| 1038 | | | |
| 1039 | var index: u32 = 0; | | |
| 1040 | while (index < len) : (index += 1) { | | |
| 1041 | switch (try self.genTypedValue(elem_ty, array)) { | | |
| 1042 | .externally_managed => |data| try writer.writeAll(data), | | |
| 1043 | .appended => {}, | | |
| 1044 | } | | |
| 1045 | } | | |
| 1046 | if (sentinel) |sentinel_value| { | | |
| 1047 | return self.genTypedValue(elem_ty, sentinel_value); | | |
| 1048 | } | | |
| 1049 | return Result{ .appended = {} }; | | |
| 1050 | }, | | |
| 1051 | .empty_array_sentinel => { | | |
| 1052 | const elem_ty = ty.childType(); | | |
| 1053 | const sent_val = ty.sentinel().?; | | |
| 1054 | return self.genTypedValue(elem_ty, sent_val); | | |
| 1055 | }, | | |
| 1056 | else => unreachable, | | |
| 1057 | }, | | |
| 1058 | .Int => { | | |
| 1059 | const info = ty.intInfo(self.target()); | | |
| 1060 | const abi_size = @intCast(usize, ty.abiSize(self.target())); | | |
| 1061 | if (info.bits <= 64) { | | |
| 1062 | var buf: [8]u8 = undefined; | | |
| 1063 | if (info.signedness == .unsigned) { | | |
| 1064 | std.mem.writeIntLittle(u64, &buf, val.toUnsignedInt()); | | |
| 1065 | } else std.mem.writeIntLittle(i64, &buf, val.toSignedInt()); | | |
| 1066 | try writer.writeAll(buf[0..abi_size]); | | |
| 1067 | return Result{ .appended = {} }; | | |
| 1068 | } | | |
| 1069 | var space: Value.BigIntSpace = undefined; | | |
| 1070 | const bigint = val.toBigInt(&space); | | |
| 1071 | const iterations = @divExact(abi_size, @sizeOf(usize)); | | |
| 1072 | for (bigint.limbs) |_, index| { | | |
| 1073 | const limb = bigint.limbs[bigint.limbs.len - index - 1]; | | |
| 1074 | try writer.writeIntLittle(usize, limb); | | |
| 1075 | } else if (bigint.limbs.len < iterations) { | | |
| 1076 | // When the value is saved in less limbs than the required | | |
| 1077 | // abi size, we fill the remaining parts with 0's. | | |
| 1078 | var it_left = iterations - bigint.limbs.len; | | |
| 1079 | while (it_left > 0) { | | |
| 1080 | it_left -= 1; | | |
| 1081 | try writer.writeIntLittle(usize, 0); | | |
| 1082 | } | | |
| 1083 | } | | |
| 1084 | return Result{ .appended = {} }; | | |
| 1085 | }, | | |
| 1086 | .Float => { | | |
| 1087 | const float_bits = ty.floatBits(self.target()); | | |
| 1088 | if (float_bits > 64) { | | |
| 1089 | return self.fail("Wasm TODO: Implement f80 and f128", .{}); | | |
| 1090 | } | | |
| 1091 | | | |
| 1092 | switch (float_bits) { | | |
| 1093 | 16, 32 => try writer.writeIntLittle(u32, @bitCast(u32, val.toFloat(f32))), | | |
| 1094 | 64 => try writer.writeIntLittle(u64, @bitCast(u64, val.toFloat(f64))), | | |
| 1095 | else => unreachable, | | |
| 1096 | } | | |
| 1097 | | | |
| 1098 | return Result{ .appended = {} }; | | |
| 1099 | }, | | |
| 1100 | .Enum => { | | |
| 1101 | var int_buffer: Value.Payload.U64 = undefined; | | |
| 1102 | const int_val = val.enumToInt(ty, &int_buffer); | | |
| 1103 | var buf: Type.Payload.Bits = undefined; | | |
| 1104 | const int_ty = ty.intTagType(&buf); | | |
| 1105 | return self.genTypedValue(int_ty, int_val); | | |
| 1106 | }, | | |
| 1107 | .Bool => { | | |
| 1108 | try writer.writeByte(@boolToInt(val.toBool())); | | |
| 1109 | return Result{ .appended = {} }; | | |
| 1110 | }, | | |
| 1111 | .Struct => { | | |
| 1112 | const struct_obj = ty.castTag(.@"struct").?.data; | | |
| 1113 | if (struct_obj.layout == .Packed) { | | |
| 1114 | return self.fail("TODO: Packed structs for wasm", .{}); | | |
| 1115 | } | | |
| 1116 | | | |
| 1117 | const struct_begin = self.code.items.len; | | |
| 1118 | const field_vals = val.castTag(.@"struct").?.data; | | |
| 1119 | for (field_vals) |field_val, index| { | | |
| 1120 | const field_ty = ty.structFieldType(index); | | |
| 1121 | if (!field_ty.hasRuntimeBits()) continue; | | |
| 1122 | | | |
| 1123 | switch (try self.genTypedValue(field_ty, field_val)) { | | |
| 1124 | .appended => {}, | | |
| 1125 | .externally_managed => |payload| try writer.writeAll(payload), | | |
| 1126 | } | | |
| 1127 | const unpadded_field_len = self.code.items.len - struct_begin; | | |
| 1128 | | | |
| 1129 | // Pad struct members if required | | |
| 1130 | const padded_field_end = ty.structFieldOffset(index + 1, self.target()); | | |
| 1131 | const padding = try std.math.cast(usize, padded_field_end - unpadded_field_len); | | |
| 1132 | | | |
| 1133 | if (padding > 0) { | | |
| 1134 | try writer.writeByteNTimes(0, padding); | | |
| 1135 | } | | |
| 1136 | } | | |
| 1137 | return Result{ .appended = {} }; | | |
| 1138 | }, | | |
| 1139 | .Union => { | | |
| 1140 | const union_val = val.castTag(.@"union").?.data; | | |
| 1141 | const layout = ty.unionGetLayout(self.target()); | | |
| 1142 | | | |
| 1143 | if (layout.payload_size == 0) { | | |
| 1144 | return self.genTypedValue(ty.unionTagType().?, union_val.tag); | | |
| 1145 | } | | |
| 1146 | | | |
| 1147 | // Check if we should store the tag first, in which case, do so now: | | |
| 1148 | if (layout.tag_align >= layout.payload_align) { | | |
| 1149 | switch (try self.genTypedValue(ty.unionTagType().?, union_val.tag)) { | | |
| 1150 | .appended => {}, | | |
| 1151 | .externally_managed => |payload| try writer.writeAll(payload), | | |
| 1152 | } | | |
| 1153 | } | | |
| 1154 | | | |
| 1155 | const union_ty = ty.cast(Type.Payload.Union).?.data; | | |
| 1156 | const field_index = union_ty.tag_ty.enumTagFieldIndex(union_val.tag).?; | | |
| 1157 | assert(union_ty.haveFieldTypes()); | | |
| 1158 | const field_ty = union_ty.fields.values()[field_index].ty; | | |
| 1159 | if (!field_ty.hasRuntimeBits()) { | | |
| 1160 | try writer.writeByteNTimes(0xaa, @intCast(usize, layout.payload_size)); | | |
| 1161 | } else { | | |
| 1162 | switch (try self.genTypedValue(field_ty, union_val.val)) { | | |
| 1163 | .appended => {}, | | |
| 1164 | .externally_managed => |payload| try writer.writeAll(payload), | | |
| 1165 | } | | |
| 1166 | | | |
| 1167 | // Unions have the size of the largest field, so we must pad | | |
| 1168 | // whenever the active field has a smaller size. | | |
| 1169 | const diff = layout.payload_size - field_ty.abiSize(self.target()); | | |
| 1170 | if (diff > 0) { | | |
| 1171 | try writer.writeByteNTimes(0xaa, @intCast(usize, diff)); | | |
| 1172 | } | | |
| 1173 | } | | |
| 1174 | | | |
| 1175 | if (layout.tag_size == 0) { | | |
| 1176 | return Result{ .appended = {} }; | | |
| 1177 | } | | |
| 1178 | return self.genTypedValue(union_ty.tag_ty, union_val.tag); | | |
| 1179 | }, | | |
| 1180 | .Pointer => switch (val.tag()) { | | |
| 1181 | .variable => { | | |
| 1182 | const decl = val.castTag(.variable).?.data.owner_decl; | | |
| 1183 | return self.lowerDeclRefValue(ty, val, decl, 0); | | |
| 1184 | }, | | |
| 1185 | .decl_ref => { | | |
| 1186 | const decl = val.castTag(.decl_ref).?.data; | | |
| 1187 | return self.lowerDeclRefValue(ty, val, decl, 0); | | |
| 1188 | }, | | |
| 1189 | .slice => { | | |
| 1190 | const slice = val.castTag(.slice).?.data; | | |
| 1191 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | | |
| 1192 | const ptr_ty = ty.slicePtrFieldType(&buf); | | |
| 1193 | switch (try self.genTypedValue(ptr_ty, slice.ptr)) { | | |
| 1194 | .externally_managed => |data| try writer.writeAll(data), | | |
| 1195 | .appended => {}, | | |
| 1196 | } | | |
| 1197 | switch (try self.genTypedValue(Type.usize, slice.len)) { | | |
| 1198 | .externally_managed => |data| try writer.writeAll(data), | | |
| 1199 | .appended => {}, | | |
| 1200 | } | | |
| 1201 | return Result{ .appended = {} }; | | |
| 1202 | }, | | |
| 1203 | .zero => { | | |
| 1204 | try writer.writeByteNTimes(0, @divExact(self.target().cpu.arch.ptrBitWidth(), 8)); | | |
| 1205 | return Result{ .appended = {} }; | | |
| 1206 | }, | | |
| 1207 | .elem_ptr => { | | |
| 1208 | const elem_ptr = val.castTag(.elem_ptr).?.data; | | |
| 1209 | const elem_size = ty.childType().abiSize(self.target()); | | |
| 1210 | const offset = elem_ptr.index * elem_size; | | |
| 1211 | return self.lowerParentPtr(elem_ptr.array_ptr, @intCast(usize, offset)); | | |
| 1212 | }, | | |
| 1213 | .int_u64 => return self.genTypedValue(Type.usize, val), | | |
| 1214 | else => return self.fail("TODO: Implement zig decl gen for pointer type value: '{s}'", .{@tagName(val.tag())}), | | |
| 1215 | }, | | |
| 1216 | .ErrorUnion => { | | |
| 1217 | const error_ty = ty.errorUnionSet(); | | |
| 1218 | const payload_ty = ty.errorUnionPayload(); | | |
| 1219 | const is_pl = val.errorUnionIsPayload(); | | |
| 1220 | const abi_align = ty.abiAlignment(self.target()); | | |
| 1221 | | | |
| 1222 | { | | |
| 1223 | const err_val = if (!is_pl) val else Value.initTag(.zero); | | |
| 1224 | const start = self.code.items.len; | | |
| 1225 | switch (try self.genTypedValue(error_ty, err_val)) { | | |
| 1226 | .externally_managed => |data| try writer.writeAll(data), | | |
| 1227 | .appended => {}, | | |
| 1228 | } | | |
| 1229 | const unpadded_end = self.code.items.len - start; | | |
| 1230 | const padded_end = mem.alignForwardGeneric(usize, unpadded_end, abi_align); | | |
| 1231 | const padding = padded_end - unpadded_end; | | |
| 1232 | if (padding > 0) { | | |
| 1233 | try writer.writeByteNTimes(0, padding); | | |
| 1234 | } | | |
| 1235 | } | | |
| 1236 | | | |
| 1237 | if (payload_ty.hasRuntimeBits()) { | | |
| 1238 | const start = self.code.items.len; | | |
| 1239 | const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); | | |
| 1240 | switch (try self.genTypedValue(payload_ty, pl_val)) { | | |
| 1241 | .externally_managed => |data| try writer.writeAll(data), | | |
| 1242 | .appended => {}, | | |
| 1243 | } | | |
| 1244 | | | |
| 1245 | const unpadded_end = self.code.items.len - start; | | |
| 1246 | const padded_end = mem.alignForwardGeneric(usize, unpadded_end, abi_align); | | |
| 1247 | const padding = padded_end - unpadded_end; | | |
| 1248 | if (padding > 0) { | | |
| 1249 | try writer.writeByteNTimes(0, padding); | | |
| 1250 | } | | |
| 1251 | } | | |
| 1252 | | | |
| 1253 | return Result{ .appended = {} }; | | |
| 1254 | }, | | |
| 1255 | .ErrorSet => { | | |
| 1256 | switch (val.tag()) { | | |
| 1257 | .@"error" => { | | |
| 1258 | const name = val.castTag(.@"error").?.data.name; | | |
| 1259 | const kv = try self.module.getErrorValue(name); | | |
| 1260 | try writer.writeIntLittle(u32, kv.value); | | |
| 1261 | }, | | |
| 1262 | else => { | | |
| 1263 | try writer.writeByteNTimes(0, @intCast(usize, ty.abiSize(self.target()))); | | |
| 1264 | }, | | |
| 1265 | } | | |
| 1266 | return Result{ .appended = {} }; | | |
| 1267 | }, | | |
| 1268 | else => |tag| return self.fail("TODO: Implement zig type codegen for type: '{s}'", .{tag}), | | |
| 1269 | } | | |
| 1270 | } | | |
| 1271 | | | |
| 1272 | fn lowerParentPtr(self: *DeclGen, ptr_value: Value, offset: usize) InnerError!Result { | | |
| 1273 | switch (ptr_value.tag()) { | | |
| 1274 | .decl_ref => { | | |
| 1275 | const decl = ptr_value.castTag(.decl_ref).?.data; | | |
| 1276 | return self.lowerParentPtrDecl(ptr_value, decl, offset); | | |
| 1277 | }, | | |
| 1278 | else => |tag| return self.fail("TODO: Implement lowerParentPtr for pointer value tag: {s}", .{tag}), | | |
| 1279 | } | | |
| 1280 | } | | |
| 1281 | | | |
| 1282 | fn lowerParentPtrDecl(self: *DeclGen, ptr_val: Value, decl: *Module.Decl, offset: usize) InnerError!Result { | | |
| 1283 | decl.markAlive(); | | |
| 1284 | var ptr_ty_payload: Type.Payload.ElemType = .{ | | |
| 1285 | .base = .{ .tag = .single_mut_pointer }, | | |
| 1286 | .data = decl.ty, | | |
| 1287 | }; | | |
| 1288 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); | | |
| 1289 | return self.lowerDeclRefValue(ptr_ty, ptr_val, decl, offset); | | |
| 1290 | } | | |
| 1291 | | | |
| 1292 | fn lowerDeclRefValue( | | |
| 1293 | self: *DeclGen, | | |
| 1294 | ty: Type, | | |
| 1295 | val: Value, | | |
| 1296 | /// The target decl that is being pointed to | | |
| 1297 | decl: *Module.Decl, | | |
| 1298 | /// When lowering to an indexed pointer, we can specify the offset | | |
| 1299 | /// which will then be used as 'addend' to the relocation. | | |
| 1300 | offset: usize, | | |
| 1301 | ) InnerError!Result { | | |
| 1302 | const writer = self.code.writer(); | | |
| 1303 | if (ty.isSlice()) { | | |
| 1304 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | | |
| 1305 | const slice_ty = ty.slicePtrFieldType(&buf); | | |
| 1306 | switch (try self.genTypedValue(slice_ty, val)) { | | |
| 1307 | .appended => {}, | | |
| 1308 | .externally_managed => |payload| try writer.writeAll(payload), | | |
| 1309 | } | | |
| 1310 | var slice_len: Value.Payload.U64 = .{ | | |
| 1311 | .base = .{ .tag = .int_u64 }, | | |
| 1312 | .data = val.sliceLen(), | | |
| 1313 | }; | | |
| 1314 | return self.genTypedValue(Type.usize, Value.initPayload(&slice_len.base)); | | |
| 1315 | } | | |
| 1316 | | | |
| 1317 | decl.markAlive(); | | |
| 1318 | if (decl.link.wasm.sym_index == 0) { | | |
| 1319 | try writer.writeIntLittle(u32, 0); | | |
| 1320 | } else { | | |
| 1321 | try writer.writeIntLittle(u32, @intCast(u32, try self.bin_file.getDeclVAddr( | | |
| 1322 | decl, | | |
| 1323 | .{ | | |
| 1324 | .parent_atom_index = self.symbol_index, | | |
| 1325 | .offset = self.code.items.len, | | |
| 1326 | .addend = @intCast(u32, offset), | | |
| 1327 | }, | | |
| 1328 | ))); | | |
| 1329 | } | | |
| 1330 | return Result{ .appended = {} }; | | |
| 1331 | } | | |
| 1332 | }; | | |
| 1333 | | | |
| 1334 | const CallWValues = struct { | 906 | const CallWValues = struct { |
| 1335 | args: []WValue, | 907 | args: []WValue, |
| 1336 | return_value: WValue, | 908 | return_value: WValue, |