authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-18 20:59:39-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-19 11:26:18-07:00
logbab570a22540c2acb15c19e1d080a80d355407e3
treedb04874ddccbd5a341151ebea585d72675e60251
parent65bc4d915daf33255f16a1586e69040fd9148e87

LLVM: lower all structs as byref=true

Same reasoning as previous commit.

1 files changed, 64 insertions(+), 63 deletions(-)

src/codegen/llvm.zig+64-63
...@@ -5730,12 +5730,7 @@ pub const FuncGen = struct {...@@ -5730,12 +5730,7 @@ pub const FuncGen = struct {
5730 // The payload and the optional are the same value.5730 // The payload and the optional are the same value.
5731 return operand;5731 return operand;
5732 }5732 }
5733 const index_type = self.context.intType(32);5733 return self.builder.buildStructGEP(operand, 0, "");
5734 const indices: [2]*const llvm.Value = .{
5735 index_type.constNull(), // dereference the pointer
5736 index_type.constNull(), // first field is the payload
5737 };
5738 return self.builder.buildInBoundsGEP(operand, &indices, indices.len, "");
5739 }5734 }
57405735
5741 fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {5736 fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
...@@ -5761,24 +5756,17 @@ pub const FuncGen = struct {...@@ -5761,24 +5756,17 @@ pub const FuncGen = struct {
5761 // Setting to non-null will be done when the payload is set.5756 // Setting to non-null will be done when the payload is set.
5762 return operand;5757 return operand;
5763 }5758 }
5764 const index_type = self.context.intType(32);5759
5765 {5760 // First set the non-null bit.
5766 // First set the non-null bit.5761 const non_null_ptr = self.builder.buildStructGEP(operand, 1, "");
5767 const indices: [2]*const llvm.Value = .{5762 // TODO set alignment on this store
5768 index_type.constNull(), // dereference the pointer5763 _ = self.builder.buildStore(non_null_bit, non_null_ptr);
5769 index_type.constInt(1, .False), // second field is the non-null bit5764
5770 };
5771 const non_null_ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, "");
5772 _ = self.builder.buildStore(non_null_bit, non_null_ptr);
5773 }
5774 // Then return the payload pointer (only if it's used).5765 // Then return the payload pointer (only if it's used).
5775 if (self.liveness.isUnused(inst))5766 if (self.liveness.isUnused(inst))
5776 return null;5767 return null;
5777 const indices: [2]*const llvm.Value = .{5768
5778 index_type.constNull(), // dereference the pointer5769 return self.builder.buildStructGEP(operand, 0, "");
5779 index_type.constNull(), // first field is the payload
5780 };
5781 return self.builder.buildInBoundsGEP(operand, &indices, indices.len, "");
5782 }5770 }
57835771
5784 fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {5772 fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
...@@ -5874,16 +5862,11 @@ pub const FuncGen = struct {...@@ -5874,16 +5862,11 @@ pub const FuncGen = struct {
5874 _ = self.builder.buildStore(non_error_val, operand);5862 _ = self.builder.buildStore(non_error_val, operand);
5875 return operand;5863 return operand;
5876 }5864 }
5877 const index_type = self.context.intType(32);
5878 const target = self.dg.module.getTarget();5865 const target = self.dg.module.getTarget();
5879 {5866 {
5880 const error_offset = errUnionErrorOffset(payload_ty, target);5867 const error_offset = errUnionErrorOffset(payload_ty, target);
5881 // First set the non-error value.5868 // First set the non-error value.
5882 const indices: [2]*const llvm.Value = .{5869 const non_null_ptr = self.builder.buildStructGEP(operand, error_offset, "");
5883 index_type.constNull(), // dereference the pointer
5884 index_type.constInt(error_offset, .False),
5885 };
5886 const non_null_ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, "");
5887 const store_inst = self.builder.buildStore(non_error_val, non_null_ptr);5870 const store_inst = self.builder.buildStore(non_error_val, non_null_ptr);
5888 store_inst.setAlignment(Type.anyerror.abiAlignment(target));5871 store_inst.setAlignment(Type.anyerror.abiAlignment(target));
5889 }5872 }
...@@ -5892,11 +5875,7 @@ pub const FuncGen = struct {...@@ -5892,11 +5875,7 @@ pub const FuncGen = struct {
5892 return null;5875 return null;
58935876
5894 const payload_offset = errUnionPayloadOffset(payload_ty, target);5877 const payload_offset = errUnionPayloadOffset(payload_ty, target);
5895 const indices: [2]*const llvm.Value = .{5878 return self.builder.buildStructGEP(operand, payload_offset, "");
5896 index_type.constNull(), // dereference the pointer
5897 index_type.constInt(payload_offset, .False),
5898 };
5899 return self.builder.buildInBoundsGEP(operand, &indices, indices.len, "");
5900 }5879 }
59015880
5902 fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !?*const llvm.Value {5881 fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !?*const llvm.Value {
...@@ -6391,8 +6370,30 @@ pub const FuncGen = struct {...@@ -6391,8 +6370,30 @@ pub const FuncGen = struct {
6391 const overflow_bit = self.builder.buildExtractValue(result_struct, 1, "");6370 const overflow_bit = self.builder.buildExtractValue(result_struct, 1, "");
63926371
6393 var ty_buf: Type.Payload.Pointer = undefined;6372 var ty_buf: Type.Payload.Pointer = undefined;
6394 const partial = self.builder.buildInsertValue(llvm_dest_ty.getUndef(), result, llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?, "");6373 const result_index = llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?;
6395 return self.builder.buildInsertValue(partial, overflow_bit, llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?, "");6374 const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?;
6375
6376 if (isByRef(dest_ty)) {
6377 const target = self.dg.module.getTarget();
6378 const alloca_inst = self.buildAlloca(llvm_dest_ty);
6379 const result_alignment = dest_ty.abiAlignment(target);
6380 alloca_inst.setAlignment(result_alignment);
6381 {
6382 const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, "");
6383 const store_inst = self.builder.buildStore(result, field_ptr);
6384 store_inst.setAlignment(result_alignment);
6385 }
6386 {
6387 const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, "");
6388 const store_inst = self.builder.buildStore(overflow_bit, field_ptr);
6389 store_inst.setAlignment(1);
6390 }
6391
6392 return alloca_inst;
6393 }
6394
6395 const partial = self.builder.buildInsertValue(llvm_dest_ty.getUndef(), result, result_index, "");
6396 return self.builder.buildInsertValue(partial, overflow_bit, overflow_index, "");
6396 }6397 }
63976398
6398 fn buildElementwiseCall(6399 fn buildElementwiseCall(
...@@ -6721,8 +6722,30 @@ pub const FuncGen = struct {...@@ -6721,8 +6722,30 @@ pub const FuncGen = struct {
6721 const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, "");6722 const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, "");
67226723
6723 var ty_buf: Type.Payload.Pointer = undefined;6724 var ty_buf: Type.Payload.Pointer = undefined;
6724 const partial = self.builder.buildInsertValue(llvm_dest_ty.getUndef(), result, llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?, "");6725 const result_index = llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?;
6725 return self.builder.buildInsertValue(partial, overflow_bit, llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?, "");6726 const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?;
6727
6728 if (isByRef(dest_ty)) {
6729 const target = self.dg.module.getTarget();
6730 const alloca_inst = self.buildAlloca(llvm_dest_ty);
6731 const result_alignment = dest_ty.abiAlignment(target);
6732 alloca_inst.setAlignment(result_alignment);
6733 {
6734 const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, "");
6735 const store_inst = self.builder.buildStore(result, field_ptr);
6736 store_inst.setAlignment(result_alignment);
6737 }
6738 {
6739 const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, "");
6740 const store_inst = self.builder.buildStore(overflow_bit, field_ptr);
6741 store_inst.setAlignment(1);
6742 }
6743
6744 return alloca_inst;
6745 }
6746
6747 const partial = self.builder.buildInsertValue(llvm_dest_ty.getUndef(), result, result_index, "");
6748 return self.builder.buildInsertValue(partial, overflow_bit, overflow_index, "");
6726 }6749 }
67276750
6728 fn airAnd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {6751 fn airAnd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
...@@ -8336,17 +8359,9 @@ pub const FuncGen = struct {...@@ -8336,17 +8359,9 @@ pub const FuncGen = struct {
8336 fn optIsNonNull(self: *FuncGen, opt_handle: *const llvm.Value, is_by_ref: bool) *const llvm.Value {8359 fn optIsNonNull(self: *FuncGen, opt_handle: *const llvm.Value, is_by_ref: bool) *const llvm.Value {
8337 const field = b: {8360 const field = b: {
8338 if (is_by_ref) {8361 if (is_by_ref) {
8339 const index_type = self.context.intType(32);8362 const field_ptr = self.builder.buildStructGEP(opt_handle, 1, "");
8340
8341 const indices: [2]*const llvm.Value = .{
8342 index_type.constNull(),
8343 index_type.constInt(1, .False),
8344 };
8345
8346 const field_ptr = self.builder.buildInBoundsGEP(opt_handle, &indices, indices.len, "");
8347 break :b self.builder.buildLoad(field_ptr, "");8363 break :b self.builder.buildLoad(field_ptr, "");
8348 }8364 }
8349
8350 break :b self.builder.buildExtractValue(opt_handle, 1, "");8365 break :b self.builder.buildExtractValue(opt_handle, 1, "");
8351 };8366 };
8352 comptime assert(optional_layout_version == 3);8367 comptime assert(optional_layout_version == 3);
...@@ -8365,12 +8380,7 @@ pub const FuncGen = struct {...@@ -8365,12 +8380,7 @@ pub const FuncGen = struct {
83658380
8366 if (isByRef(opt_ty)) {8381 if (isByRef(opt_ty)) {
8367 // We have a pointer and we need to return a pointer to the first field.8382 // We have a pointer and we need to return a pointer to the first field.
8368 const index_type = fg.context.intType(32);8383 const payload_ptr = fg.builder.buildStructGEP(opt_handle, 0, "");
8369 const indices: [2]*const llvm.Value = .{
8370 index_type.constNull(), // dereference the pointer
8371 index_type.constNull(), // first field is the payload
8372 };
8373 const payload_ptr = fg.builder.buildInBoundsGEP(opt_handle, &indices, indices.len, "");
83748384
8375 if (isByRef(payload_ty)) {8385 if (isByRef(payload_ty)) {
8376 return payload_ptr;8386 return payload_ptr;
...@@ -8401,22 +8411,13 @@ pub const FuncGen = struct {...@@ -8401,22 +8411,13 @@ pub const FuncGen = struct {
8401 const payload_alignment = optional_ty.abiAlignment(target);8411 const payload_alignment = optional_ty.abiAlignment(target);
8402 alloca_inst.setAlignment(payload_alignment);8412 alloca_inst.setAlignment(payload_alignment);
84038413
8404 const index_type = self.context.intType(32);
8405 {8414 {
8406 const indices: [2]*const llvm.Value = .{8415 const field_ptr = self.builder.buildStructGEP(alloca_inst, 0, "");
8407 index_type.constNull(), // dereference the pointer
8408 index_type.constNull(), // first field is the payload
8409 };
8410 const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, "");
8411 const store_inst = self.builder.buildStore(payload, field_ptr);8416 const store_inst = self.builder.buildStore(payload, field_ptr);
8412 store_inst.setAlignment(payload_alignment);8417 store_inst.setAlignment(payload_alignment);
8413 }8418 }
8414 {8419 {
8415 const indices: [2]*const llvm.Value = .{8420 const field_ptr = self.builder.buildStructGEP(alloca_inst, 1, "");
8416 index_type.constNull(), // dereference the pointer
8417 index_type.constInt(1, .False), // second field is the non-null bit
8418 };
8419 const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, "");
8420 const store_inst = self.builder.buildStore(non_null_field, field_ptr);8421 const store_inst = self.builder.buildStore(non_null_field, field_ptr);
8421 store_inst.setAlignment(1);8422 store_inst.setAlignment(1);
8422 }8423 }
...@@ -9337,7 +9338,7 @@ fn ccAbiPromoteInt(...@@ -9337,7 +9338,7 @@ fn ccAbiPromoteInt(
9337fn isByRef(ty: Type) bool {9338fn isByRef(ty: Type) bool {
9338 // For tuples and structs, if there are more than this many non-void9339 // For tuples and structs, if there are more than this many non-void
9339 // fields, then we make it byref, otherwise byval.9340 // fields, then we make it byref, otherwise byval.
9340 const max_fields_byval = 2;9341 const max_fields_byval = 0;
93419342
9342 switch (ty.zigTypeTag()) {9343 switch (ty.zigTypeTag()) {
9343 .Type,9344 .Type,