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