| ... | @@ -441,46 +441,99 @@ pub fn generateSymbol( | ... | @@ -441,46 +441,99 @@ pub fn generateSymbol( |
| 441 | })) orelse return error.Overflow; | 441 | })) orelse return error.Overflow; |
| 442 | if (padding > 0) try code.writer().writeByteNTimes(0, padding); | 442 | if (padding > 0) try code.writer().writeByteNTimes(0, padding); |
| 443 | }, | 443 | }, |
| 444 | .struct_type, .anon_struct_type => { | 444 | .anon_struct_type => |tuple| { |
| 445 | if (typed_value.ty.containerLayout(mod) == .Packed) { | 445 | const struct_begin = code.items.len; |
| 446 | const struct_obj = mod.typeToStruct(typed_value.ty).?; | 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 | const fields = struct_obj.fields.values(); | 481 | const fields = struct_obj.fields.values(); |
| 448 | const field_vals = typed_value.val.castTag(.aggregate).?.data; | 482 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse |
| 449 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; | 483 | return error.Overflow; |
| 450 | const current_pos = code.items.len; | 484 | const current_pos = code.items.len; |
| 451 | try code.resize(current_pos + abi_size); | 485 | try code.resize(current_pos + abi_size); |
| 452 | var bits: u16 = 0; | 486 | var bits: u16 = 0; |
| 453 | | 487 | |
| 454 | for (field_vals, 0..) |field_val, index| { | 488 | for (fields, 0..) |field, index| { |
| 455 | const field_ty = fields[index].ty; | 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 | // pointer may point to a decl which must be marked used | 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 | if (field_ty.zigTypeTag(mod) == .Pointer) { | 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 | var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size); | 505 | var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size); |
| 461 | defer tmp_list.deinit(); | 506 | defer tmp_list.deinit(); |
| 462 | switch (try generateSymbol(bin_file, src_loc, .{ | 507 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 463 | .ty = field_ty, | 508 | .ty = field_ty, |
| 464 | .val = field_val, | 509 | .val = field_val.toValue(), |
| 465 | }, &tmp_list, debug_output, reloc_info)) { | 510 | }, &tmp_list, debug_output, reloc_info)) { |
| 466 | .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items), | 511 | .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items), |
| 467 | .fail => |em| return Result{ .fail = em }, | 512 | .fail => |em| return Result{ .fail = em }, |
| 468 | } | 513 | } |
| 469 | } else { | 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 | bits += @intCast(u16, field_ty.bitSize(mod)); | 517 | bits += @intCast(u16, field_ty.bitSize(mod)); |
| 473 | } | 518 | } |
| 474 | } else { | 519 | } else { |
| 475 | const struct_begin = code.items.len; | 520 | const struct_begin = code.items.len; |
| 476 | const field_vals = typed_value.val.castTag(.aggregate).?.data; | 521 | for (struct_obj.fields.values(), 0..) |field, index| { |
| 477 | for (field_vals, 0..) |field_val, index| { | 522 | const field_ty = field.ty; |
| 478 | const field_ty = typed_value.ty.structFieldType(index, mod); | | |
| 479 | if (!field_ty.hasRuntimeBits(mod)) continue; | 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 | switch (try generateSymbol(bin_file, src_loc, .{ | 534 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 482 | .ty = field_ty, | 535 | .ty = field_ty, |
| 483 | .val = field_val, | 536 | .val = field_val.toValue(), |
| 484 | }, code, debug_output, reloc_info)) { | 537 | }, code, debug_output, reloc_info)) { |
| 485 | .ok => {}, | 538 | .ok => {}, |
| 486 | .fail => |em| return Result{ .fail = em }, | 539 | .fail => |em| return Result{ .fail = em }, |