| ... | ... | @@ -441,46 +441,99 @@ pub fn generateSymbol( |
| 441 | 441 | })) orelse return error.Overflow; |
| 442 | 442 | if (padding > 0) try code.writer().writeByteNTimes(0, padding); |
| 443 | 443 | }, |
| 444 | | .struct_type, .anon_struct_type => { |
| 445 | | if (typed_value.ty.containerLayout(mod) == .Packed) { |
| 446 | | const struct_obj = mod.typeToStruct(typed_value.ty).?; |
| 444 | .anon_struct_type => |tuple| { |
| 445 | const struct_begin = code.items.len; |
| 446 | for (tuple.types, 0..) |field_ty, index| { |
| 447 | if (!field_ty.toType().hasRuntimeBits(mod)) continue; |
| 448 | |
| 449 | const field_val = switch (aggregate.storage) { |
| 450 | .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{ |
| 451 | .ty = field_ty, |
| 452 | .storage = .{ .u64 = bytes[index] }, |
| 453 | } }), |
| 454 | .elems => |elems| elems[index], |
| 455 | .repeated_elem => |elem| elem, |
| 456 | }; |
| 457 | |
| 458 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 459 | .ty = field_ty.toType(), |
| 460 | .val = field_val.toValue(), |
| 461 | }, code, debug_output, reloc_info)) { |
| 462 | .ok => {}, |
| 463 | .fail => |em| return Result{ .fail = em }, |
| 464 | } |
| 465 | const unpadded_field_end = code.items.len - struct_begin; |
| 466 | |
| 467 | // Pad struct members if required |
| 468 | const padded_field_end = typed_value.ty.structFieldOffset(index + 1, mod); |
| 469 | const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse |
| 470 | return error.Overflow; |
| 471 | |
| 472 | if (padding > 0) { |
| 473 | try code.writer().writeByteNTimes(0, padding); |
| 474 | } |
| 475 | } |
| 476 | }, |
| 477 | .struct_type => |struct_type| { |
| 478 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; |
| 479 | |
| 480 | if (struct_obj.layout == .Packed) { |
| 447 | 481 | const fields = struct_obj.fields.values(); |
| 448 | | const field_vals = typed_value.val.castTag(.aggregate).?.data; |
| 449 | | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; |
| 482 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse |
| 483 | return error.Overflow; |
| 450 | 484 | const current_pos = code.items.len; |
| 451 | 485 | try code.resize(current_pos + abi_size); |
| 452 | 486 | var bits: u16 = 0; |
| 453 | 487 | |
| 454 | | for (field_vals, 0..) |field_val, index| { |
| 455 | | const field_ty = fields[index].ty; |
| 488 | for (fields, 0..) |field, index| { |
| 489 | const field_ty = field.ty; |
| 490 | |
| 491 | const field_val = switch (aggregate.storage) { |
| 492 | .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{ |
| 493 | .ty = field_ty.toIntern(), |
| 494 | .storage = .{ .u64 = bytes[index] }, |
| 495 | } }), |
| 496 | .elems => |elems| elems[index], |
| 497 | .repeated_elem => |elem| elem, |
| 498 | }; |
| 499 | |
| 456 | 500 | // pointer may point to a decl which must be marked used |
| 457 | | // but can also result in a relocation. Therefore we handle those seperately. |
| 501 | // but can also result in a relocation. Therefore we handle those separately. |
| 458 | 502 | if (field_ty.zigTypeTag(mod) == .Pointer) { |
| 459 | | const field_size = math.cast(usize, field_ty.abiSize(mod)) orelse return error.Overflow; |
| 503 | const field_size = math.cast(usize, field_ty.abiSize(mod)) orelse |
| 504 | return error.Overflow; |
| 460 | 505 | var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size); |
| 461 | 506 | defer tmp_list.deinit(); |
| 462 | 507 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 463 | 508 | .ty = field_ty, |
| 464 | | .val = field_val, |
| 509 | .val = field_val.toValue(), |
| 465 | 510 | }, &tmp_list, debug_output, reloc_info)) { |
| 466 | 511 | .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items), |
| 467 | 512 | .fail => |em| return Result{ .fail = em }, |
| 468 | 513 | } |
| 469 | 514 | } else { |
| 470 | | field_val.writeToPackedMemory(field_ty, mod, code.items[current_pos..], bits) catch unreachable; |
| 515 | field_val.toValue().writeToPackedMemory(field_ty, mod, code.items[current_pos..], bits) catch unreachable; |
| 471 | 516 | } |
| 472 | 517 | bits += @intCast(u16, field_ty.bitSize(mod)); |
| 473 | 518 | } |
| 474 | 519 | } else { |
| 475 | 520 | const struct_begin = code.items.len; |
| 476 | | const field_vals = typed_value.val.castTag(.aggregate).?.data; |
| 477 | | for (field_vals, 0..) |field_val, index| { |
| 478 | | const field_ty = typed_value.ty.structFieldType(index, mod); |
| 521 | for (struct_obj.fields.values(), 0..) |field, index| { |
| 522 | const field_ty = field.ty; |
| 479 | 523 | if (!field_ty.hasRuntimeBits(mod)) continue; |
| 480 | 524 | |
| 525 | const field_val = switch (aggregate.storage) { |
| 526 | .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{ |
| 527 | .ty = field_ty.toIntern(), |
| 528 | .storage = .{ .u64 = bytes[index] }, |
| 529 | } }), |
| 530 | .elems => |elems| elems[index], |
| 531 | .repeated_elem => |elem| elem, |
| 532 | }; |
| 533 | |
| 481 | 534 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 482 | 535 | .ty = field_ty, |
| 483 | | .val = field_val, |
| 536 | .val = field_val.toValue(), |
| 484 | 537 | }, code, debug_output, reloc_info)) { |
| 485 | 538 | .ok => {}, |
| 486 | 539 | .fail => |em| return Result{ .fail = em }, |