Skip to content

Commit 2c6bbb4

Browse files
committed
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 parent 9ac7ae0 commit 2c6bbb4

File tree

1 file changed

+35
-19
lines changed

1 file changed

+35
-19
lines changed

src/codegen/llvm.zig

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
47544765
fn 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) {

0 commit comments

Comments
 (0)