authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2022-01-07 19:02:24+01:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2022-01-07 22:10:36+01:00
logf48f687c051602bfc0e8098cb91b43d971541271
tree96ec22f2a2528495d66957f425d1b950a79d3d42
parentf78d3b27ca1bea33c92e2f8eae84589db28c06cb

Fix llvmFieldIndex for zero sized fields

It is possible for Zig to emit field ptr instructions to fields whos type is zero sized. In this case llvm should return a pointer which points to the next none zero sized parameter.

1 files changed, 35 insertions(+), 19 deletions(-)

src/codegen/llvm.zig+35-19
......@@ -2647,7 +2647,7 @@ pub const FuncGen = struct {
26472647 switch (struct_ty.zigTypeTag()) {
26482648 .Struct => {
26492649 var ptr_ty_buf: Type.Payload.Pointer = undefined;
2650 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf);
2650 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?;
26512651 const field_ptr = self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, "");
26522652 const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base);
26532653 return self.load(field_ptr, field_ptr_ty);
......@@ -4354,8 +4354,18 @@ pub const FuncGen = struct {
43544354 .Struct => {
43554355 const target = self.dg.module.getTarget();
43564356 var ty_buf: Type.Payload.Pointer = undefined;
4357 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ty_buf);
4358 return self.builder.buildStructGEP(struct_ptr, llvm_field_index, "");
4357 if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| {
4358 return self.builder.buildStructGEP(struct_ptr, llvm_field_index, "");
4359 } else {
4360 // If we found no index then this means this is a zero sized field at the
4361 // end of the struct. Treat our struct pointer as an array of two and get
4362 // the index to the element at index `1` to get a pointer to the end of
4363 // the struct.
4364 const llvm_usize = try self.dg.llvmType(Type.usize);
4365 const llvm_index = llvm_usize.constInt(1, .False);
4366 const indices: [1]*const llvm.Value = .{llvm_index};
4367 return self.builder.buildInBoundsGEP(struct_ptr, &indices, indices.len, "");
4368 }
43594369 },
43604370 .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty, field_index),
43614371 else => unreachable,
......@@ -4750,32 +4760,37 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca
47504760 };
47514761}
47524762
4753/// Take into account 0 bit fields.
4763/// Take into account 0 bit fields. Returns null if an llvm field could not be found. This only
4764/// happends if you want the field index of a zero sized field at the end of the struct.
47544765fn llvmFieldIndex(
47554766 ty: Type,
47564767 field_index: u32,
47574768 target: std.Target,
47584769 ptr_pl_buf: *Type.Payload.Pointer,
4759) c_uint {
4770) ?c_uint {
47604771 const struct_obj = ty.castTag(.@"struct").?.data;
47614772 if (struct_obj.layout != .Packed) {
47624773 var llvm_field_index: c_uint = 0;
47634774 for (struct_obj.fields.values()) |field, i| {
4764 if (!field.ty.hasCodeGenBits()) continue;
4765
4766 if (i == field_index) {
4767 ptr_pl_buf.* = .{
4768 .data = .{
4769 .pointee_type = field.ty,
4770 .@"align" = field.normalAlignment(target),
4771 .@"addrspace" = .generic,
4772 },
4773 };
4774 return llvm_field_index;
4775 if (!field.ty.hasCodeGenBits())
4776 continue;
4777 if (field_index > i) {
4778 llvm_field_index += 1;
4779 continue;
47754780 }
4776 llvm_field_index += 1;
4781
4782 ptr_pl_buf.* = .{
4783 .data = .{
4784 .pointee_type = field.ty,
4785 .@"align" = field.normalAlignment(target),
4786 .@"addrspace" = .generic,
4787 },
4788 };
4789 return llvm_field_index;
4790 } else {
4791 // We did not find an llvm field that corrispons to this zig field.
4792 return null;
47774793 }
4778 unreachable;
47794794 }
47804795
47814796 // Our job here is to return the host integer field index.
......@@ -4784,7 +4799,8 @@ fn llvmFieldIndex(
47844799 var running_bits: u16 = 0;
47854800 var llvm_field_index: c_uint = 0;
47864801 for (struct_obj.fields.values()) |field, i| {
4787 if (!field.ty.hasCodeGenBits()) continue;
4802 if (!field.ty.hasCodeGenBits())
4803 continue;
47884804
47894805 const field_align = field.packedAlignment();
47904806 if (field_align == 0) {