@@ -2647,7 +2647,7 @@ pub const FuncGen = struct {
2647
2647
switch (struct_ty .zigTypeTag ()) {
2648
2648
.Struct = > {
2649
2649
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 ).? ;
2651
2651
const field_ptr = self .builder .buildStructGEP (struct_llvm_val , llvm_field_index , "" );
2652
2652
const field_ptr_ty = Type .initPayload (& ptr_ty_buf .base );
2653
2653
return self .load (field_ptr , field_ptr_ty );
@@ -4354,8 +4354,18 @@ pub const FuncGen = struct {
4354
4354
.Struct = > {
4355
4355
const target = self .dg .module .getTarget ();
4356
4356
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
+ }
4359
4369
},
4360
4370
.Union = > return self .unionFieldPtr (inst , struct_ptr , struct_ty , field_index ),
4361
4371
else = > unreachable ,
@@ -4750,32 +4760,37 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca
4750
4760
};
4751
4761
}
4752
4762
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.
4754
4765
fn llvmFieldIndex (
4755
4766
ty : Type ,
4756
4767
field_index : u32 ,
4757
4768
target : std.Target ,
4758
4769
ptr_pl_buf : * Type.Payload.Pointer ,
4759
- ) c_uint {
4770
+ ) ? c_uint {
4760
4771
const struct_obj = ty .castTag (.@"struct" ).? .data ;
4761
4772
if (struct_obj .layout != .Packed ) {
4762
4773
var llvm_field_index : c_uint = 0 ;
4763
4774
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 ;
4775
4780
}
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 ;
4777
4793
}
4778
- unreachable ;
4779
4794
}
4780
4795
4781
4796
// Our job here is to return the host integer field index.
@@ -4784,7 +4799,8 @@ fn llvmFieldIndex(
4784
4799
var running_bits : u16 = 0 ;
4785
4800
var llvm_field_index : c_uint = 0 ;
4786
4801
for (struct_obj .fields .values ()) | field , i | {
4787
- if (! field .ty .hasCodeGenBits ()) continue ;
4802
+ if (! field .ty .hasCodeGenBits ())
4803
+ continue ;
4788
4804
4789
4805
const field_align = field .packedAlignment ();
4790
4806
if (field_align == 0 ) {
0 commit comments