authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-26 13:21:59-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:55-07:00
logd5f0ee0d62e48e623625779a0cf722c3f0f66921
tree913515f3acda55dec2df5f1c45f83c0d7bdd50ae
parentace5a5e3ccfce69c93426913f247ea7bad7703ff

codegen: fix lowering of constant structs


1 files changed, 68 insertions(+), 15 deletions(-)

src/codegen.zig+68-15
......@@ -441,46 +441,99 @@ pub fn generateSymbol(
441441 })) orelse return error.Overflow;
442442 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
443443 },
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) {
447481 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;
450484 const current_pos = code.items.len;
451485 try code.resize(current_pos + abi_size);
452486 var bits: u16 = 0;
453487
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
456500 // 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.
458502 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;
460505 var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size);
461506 defer tmp_list.deinit();
462507 switch (try generateSymbol(bin_file, src_loc, .{
463508 .ty = field_ty,
464 .val = field_val,
509 .val = field_val.toValue(),
465510 }, &tmp_list, debug_output, reloc_info)) {
466511 .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),
467512 .fail => |em| return Result{ .fail = em },
468513 }
469514 } 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;
471516 }
472517 bits += @intCast(u16, field_ty.bitSize(mod));
473518 }
474519 } else {
475520 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;
479523 if (!field_ty.hasRuntimeBits(mod)) continue;
480524
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
481534 switch (try generateSymbol(bin_file, src_loc, .{
482535 .ty = field_ty,
483 .val = field_val,
536 .val = field_val.toValue(),
484537 }, code, debug_output, reloc_info)) {
485538 .ok => {},
486539 .fail => |em| return Result{ .fail = em },