authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-19 14:50:03-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-07-19 14:50:03-04:00
log6fab6c3e4696d11c2040ed2ea381ada01e74c6b9
treedeb8a54263d2b2fe565634477859e9b15cf95b7b
parentc26d9f6287154774bea6dcea1cea4d1cafaed45c
parentfe8c3ffeb1c6cfb1cc0b7a81e433add3c57b2337
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12164 from ziglang/llvm-opt-byref

LLVM: lower optional types as byref=true

1 files changed, 162 insertions(+), 66 deletions(-)

src/codegen/llvm.zig+162-66
...@@ -4539,7 +4539,7 @@ pub const FuncGen = struct {...@@ -4539,7 +4539,7 @@ pub const FuncGen = struct {
4539 }4539 }
4540 // We need to emit instructions to check for equality/inequality4540 // We need to emit instructions to check for equality/inequality
4541 // of optionals that are not pointers.4541 // of optionals that are not pointers.
4542 const is_by_ref = isByRef(operand_ty);4542 const is_by_ref = isByRef(scalar_ty);
4543 const lhs_non_null = self.optIsNonNull(lhs, is_by_ref);4543 const lhs_non_null = self.optIsNonNull(lhs, is_by_ref);
4544 const rhs_non_null = self.optIsNonNull(rhs, is_by_ref);4544 const rhs_non_null = self.optIsNonNull(rhs, is_by_ref);
4545 const llvm_i2 = self.context.intType(2);4545 const llvm_i2 = self.context.intType(2);
...@@ -4564,8 +4564,8 @@ pub const FuncGen = struct {...@@ -4564,8 +4564,8 @@ pub const FuncGen = struct {
4564 _ = self.builder.buildBr(end_block);4564 _ = self.builder.buildBr(end_block);
45654565
4566 self.builder.positionBuilderAtEnd(both_pl_block);4566 self.builder.positionBuilderAtEnd(both_pl_block);
4567 const lhs_payload = self.optPayloadHandle(lhs, is_by_ref);4567 const lhs_payload = self.optPayloadHandle(lhs, scalar_ty);
4568 const rhs_payload = self.optPayloadHandle(rhs, is_by_ref);4568 const rhs_payload = self.optPayloadHandle(rhs, scalar_ty);
4569 const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op);4569 const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op);
4570 _ = self.builder.buildBr(end_block);4570 _ = self.builder.buildBr(end_block);
4571 const both_pl_block_end = self.builder.getInsertBlock();4571 const both_pl_block_end = self.builder.getInsertBlock();
...@@ -4740,12 +4740,14 @@ pub const FuncGen = struct {...@@ -4740,12 +4740,14 @@ pub const FuncGen = struct {
4740 const err_set_ty = try fg.dg.lowerType(Type.anyerror);4740 const err_set_ty = try fg.dg.lowerType(Type.anyerror);
4741 const zero = err_set_ty.constNull();4741 const zero = err_set_ty.constNull();
4742 if (!payload_has_bits) {4742 if (!payload_has_bits) {
4743 // TODO add alignment to this load
4743 const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union;4744 const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union;
4744 break :err fg.builder.buildICmp(.NE, loaded, zero, "");4745 break :err fg.builder.buildICmp(.NE, loaded, zero, "");
4745 }4746 }
4746 const err_field_index = errUnionErrorOffset(payload_ty, target);4747 const err_field_index = errUnionErrorOffset(payload_ty, target);
4747 if (operand_is_ptr or isByRef(err_union_ty)) {4748 if (operand_is_ptr or isByRef(err_union_ty)) {
4748 const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, "");4749 const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, "");
4750 // TODO add alignment to this load
4749 const loaded = fg.builder.buildLoad(err_field_ptr, "");4751 const loaded = fg.builder.buildLoad(err_field_ptr, "");
4750 break :err fg.builder.buildICmp(.NE, loaded, zero, "");4752 break :err fg.builder.buildICmp(.NE, loaded, zero, "");
4751 }4753 }
...@@ -4765,13 +4767,22 @@ pub const FuncGen = struct {...@@ -4765,13 +4767,22 @@ pub const FuncGen = struct {
4765 if (!payload_has_bits) {4767 if (!payload_has_bits) {
4766 if (!operand_is_ptr) return null;4768 if (!operand_is_ptr) return null;
47674769
4768 // TODO once we update to LLVM 14 this bitcast won't be necessary.4770 // TODO once we update to an LLVM version with opaque pointers
4771 // this bitcast won't be necessary.
4769 const res_ptr_ty = try fg.dg.lowerType(result_ty);4772 const res_ptr_ty = try fg.dg.lowerType(result_ty);
4770 return fg.builder.buildBitCast(err_union, res_ptr_ty, "");4773 return fg.builder.buildBitCast(err_union, res_ptr_ty, "");
4771 }4774 }
4772 const offset = errUnionPayloadOffset(payload_ty, target);4775 const offset = errUnionPayloadOffset(payload_ty, target);
4773 if (operand_is_ptr or isByRef(payload_ty)) {4776 if (operand_is_ptr or isByRef(payload_ty)) {
4774 return fg.builder.buildStructGEP(err_union, offset, "");4777 return fg.builder.buildStructGEP(err_union, offset, "");
4778 } else if (isByRef(err_union_ty)) {
4779 const payload_ptr = fg.builder.buildStructGEP(err_union, offset, "");
4780 if (isByRef(payload_ty)) {
4781 return payload_ptr;
4782 }
4783 const load_inst = fg.builder.buildLoad(payload_ptr, "");
4784 load_inst.setAlignment(payload_ty.abiAlignment(target));
4785 return load_inst;
4775 }4786 }
4776 return fg.builder.buildExtractValue(err_union, offset, "");4787 return fg.builder.buildExtractValue(err_union, offset, "");
4777 }4788 }
...@@ -5730,12 +5741,7 @@ pub const FuncGen = struct {...@@ -5730,12 +5741,7 @@ pub const FuncGen = struct {
5730 // The payload and the optional are the same value.5741 // The payload and the optional are the same value.
5731 return operand;5742 return operand;
5732 }5743 }
5733 const index_type = self.context.intType(32);5744 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 }5745 }
57405746
5741 fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {5747 fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
...@@ -5761,24 +5767,17 @@ pub const FuncGen = struct {...@@ -5761,24 +5767,17 @@ pub const FuncGen = struct {
5761 // Setting to non-null will be done when the payload is set.5767 // Setting to non-null will be done when the payload is set.
5762 return operand;5768 return operand;
5763 }5769 }
5764 const index_type = self.context.intType(32);5770
5765 {5771 // First set the non-null bit.
5766 // First set the non-null bit.5772 const non_null_ptr = self.builder.buildStructGEP(operand, 1, "");
5767 const indices: [2]*const llvm.Value = .{5773 // TODO set alignment on this store
5768 index_type.constNull(), // dereference the pointer5774 _ = self.builder.buildStore(non_null_bit, non_null_ptr);
5769 index_type.constInt(1, .False), // second field is the non-null bit5775
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).5776 // Then return the payload pointer (only if it's used).
5775 if (self.liveness.isUnused(inst))5777 if (self.liveness.isUnused(inst))
5776 return null;5778 return null;
5777 const indices: [2]*const llvm.Value = .{5779
5778 index_type.constNull(), // dereference the pointer5780 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 }5781 }
57835782
5784 fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {5783 fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
...@@ -5795,7 +5794,7 @@ pub const FuncGen = struct {...@@ -5795,7 +5794,7 @@ pub const FuncGen = struct {
5795 return operand;5794 return operand;
5796 }5795 }
57975796
5798 return self.optPayloadHandle(operand, isByRef(payload_ty));5797 return self.optPayloadHandle(operand, optional_ty);
5799 }5798 }
58005799
5801 fn airErrUnionPayload(5800 fn airErrUnionPayload(
...@@ -5807,6 +5806,8 @@ pub const FuncGen = struct {...@@ -5807,6 +5806,8 @@ pub const FuncGen = struct {
58075806
5808 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5807 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5809 const operand = try self.resolveInst(ty_op.operand);5808 const operand = try self.resolveInst(ty_op.operand);
5809 const operand_ty = self.air.typeOf(ty_op.operand);
5810 const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
5810 const result_ty = self.air.typeOfIndex(inst);5811 const result_ty = self.air.typeOfIndex(inst);
5811 const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty;5812 const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty;
5812 const target = self.dg.module.getTarget();5813 const target = self.dg.module.getTarget();
...@@ -5821,6 +5822,14 @@ pub const FuncGen = struct {...@@ -5821,6 +5822,14 @@ pub const FuncGen = struct {
5821 const offset = errUnionPayloadOffset(payload_ty, target);5822 const offset = errUnionPayloadOffset(payload_ty, target);
5822 if (operand_is_ptr or isByRef(payload_ty)) {5823 if (operand_is_ptr or isByRef(payload_ty)) {
5823 return self.builder.buildStructGEP(operand, offset, "");5824 return self.builder.buildStructGEP(operand, offset, "");
5825 } else if (isByRef(err_union_ty)) {
5826 const payload_ptr = self.builder.buildStructGEP(operand, offset, "");
5827 if (isByRef(payload_ty)) {
5828 return payload_ptr;
5829 }
5830 const load_inst = self.builder.buildLoad(payload_ptr, "");
5831 load_inst.setAlignment(payload_ty.abiAlignment(target));
5832 return load_inst;
5824 }5833 }
5825 return self.builder.buildExtractValue(operand, offset, "");5834 return self.builder.buildExtractValue(operand, offset, "");
5826 }5835 }
...@@ -5874,16 +5883,11 @@ pub const FuncGen = struct {...@@ -5874,16 +5883,11 @@ pub const FuncGen = struct {
5874 _ = self.builder.buildStore(non_error_val, operand);5883 _ = self.builder.buildStore(non_error_val, operand);
5875 return operand;5884 return operand;
5876 }5885 }
5877 const index_type = self.context.intType(32);
5878 const target = self.dg.module.getTarget();5886 const target = self.dg.module.getTarget();
5879 {5887 {
5880 const error_offset = errUnionErrorOffset(payload_ty, target);5888 const error_offset = errUnionErrorOffset(payload_ty, target);
5881 // First set the non-error value.5889 // First set the non-error value.
5882 const indices: [2]*const llvm.Value = .{5890 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);5891 const store_inst = self.builder.buildStore(non_error_val, non_null_ptr);
5888 store_inst.setAlignment(Type.anyerror.abiAlignment(target));5892 store_inst.setAlignment(Type.anyerror.abiAlignment(target));
5889 }5893 }
...@@ -5892,11 +5896,7 @@ pub const FuncGen = struct {...@@ -5892,11 +5896,7 @@ pub const FuncGen = struct {
5892 return null;5896 return null;
58935897
5894 const payload_offset = errUnionPayloadOffset(payload_ty, target);5898 const payload_offset = errUnionPayloadOffset(payload_ty, target);
5895 const indices: [2]*const llvm.Value = .{5899 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 }5900 }
59015901
5902 fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !?*const llvm.Value {5902 fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !?*const llvm.Value {
...@@ -6391,8 +6391,30 @@ pub const FuncGen = struct {...@@ -6391,8 +6391,30 @@ pub const FuncGen = struct {
6391 const overflow_bit = self.builder.buildExtractValue(result_struct, 1, "");6391 const overflow_bit = self.builder.buildExtractValue(result_struct, 1, "");
63926392
6393 var ty_buf: Type.Payload.Pointer = undefined;6393 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).?, "");6394 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).?, "");6395 const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?;
6396
6397 if (isByRef(dest_ty)) {
6398 const target = self.dg.module.getTarget();
6399 const alloca_inst = self.buildAlloca(llvm_dest_ty);
6400 const result_alignment = dest_ty.abiAlignment(target);
6401 alloca_inst.setAlignment(result_alignment);
6402 {
6403 const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, "");
6404 const store_inst = self.builder.buildStore(result, field_ptr);
6405 store_inst.setAlignment(result_alignment);
6406 }
6407 {
6408 const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, "");
6409 const store_inst = self.builder.buildStore(overflow_bit, field_ptr);
6410 store_inst.setAlignment(1);
6411 }
6412
6413 return alloca_inst;
6414 }
6415
6416 const partial = self.builder.buildInsertValue(llvm_dest_ty.getUndef(), result, result_index, "");
6417 return self.builder.buildInsertValue(partial, overflow_bit, overflow_index, "");
6396 }6418 }
63976419
6398 fn buildElementwiseCall(6420 fn buildElementwiseCall(
...@@ -6721,8 +6743,30 @@ pub const FuncGen = struct {...@@ -6721,8 +6743,30 @@ pub const FuncGen = struct {
6721 const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, "");6743 const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, "");
67226744
6723 var ty_buf: Type.Payload.Pointer = undefined;6745 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).?, "");6746 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).?, "");6747 const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?;
6748
6749 if (isByRef(dest_ty)) {
6750 const target = self.dg.module.getTarget();
6751 const alloca_inst = self.buildAlloca(llvm_dest_ty);
6752 const result_alignment = dest_ty.abiAlignment(target);
6753 alloca_inst.setAlignment(result_alignment);
6754 {
6755 const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, "");
6756 const store_inst = self.builder.buildStore(result, field_ptr);
6757 store_inst.setAlignment(result_alignment);
6758 }
6759 {
6760 const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, "");
6761 const store_inst = self.builder.buildStore(overflow_bit, field_ptr);
6762 store_inst.setAlignment(1);
6763 }
6764
6765 return alloca_inst;
6766 }
6767
6768 const partial = self.builder.buildInsertValue(llvm_dest_ty.getUndef(), result, result_index, "");
6769 return self.builder.buildInsertValue(partial, overflow_bit, overflow_index, "");
6726 }6770 }
67276771
6728 fn airAnd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {6772 fn airAnd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
...@@ -7347,11 +7391,9 @@ pub const FuncGen = struct {...@@ -7347,11 +7391,9 @@ pub const FuncGen = struct {
7347 }7391 }
73487392
7349 comptime assert(optional_layout_version == 3);7393 comptime assert(optional_layout_version == 3);
7350 const optional_llvm_ty = try self.dg.lowerType(optional_ty);7394
7351 const non_null_bit = self.builder.buildNot(success_bit, "");7395 const non_null_bit = self.builder.buildNot(success_bit, "");
7352 const non_null_field = self.builder.buildZExt(non_null_bit, self.dg.context.intType(8), "");7396 return buildOptional(self, optional_ty, payload, non_null_bit);
7353 const partial = self.builder.buildInsertValue(optional_llvm_ty.getUndef(), payload, 0, "");
7354 return self.builder.buildInsertValue(partial, non_null_field, 1, "");
7355 }7397 }
73567398
7357 fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {7399 fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
...@@ -7515,11 +7557,13 @@ pub const FuncGen = struct {...@@ -7515,11 +7557,13 @@ pub const FuncGen = struct {
7515 const union_ptr = try self.resolveInst(bin_op.lhs);7557 const union_ptr = try self.resolveInst(bin_op.lhs);
7516 const new_tag = try self.resolveInst(bin_op.rhs);7558 const new_tag = try self.resolveInst(bin_op.rhs);
7517 if (layout.payload_size == 0) {7559 if (layout.payload_size == 0) {
7560 // TODO alignment on this store
7518 _ = self.builder.buildStore(new_tag, union_ptr);7561 _ = self.builder.buildStore(new_tag, union_ptr);
7519 return null;7562 return null;
7520 }7563 }
7521 const tag_index = @boolToInt(layout.tag_align < layout.payload_align);7564 const tag_index = @boolToInt(layout.tag_align < layout.payload_align);
7522 const tag_field_ptr = self.builder.buildStructGEP(union_ptr, tag_index, "");7565 const tag_field_ptr = self.builder.buildStructGEP(union_ptr, tag_index, "");
7566 // TODO alignment on this store
7523 _ = self.builder.buildStore(new_tag, tag_field_ptr);7567 _ = self.builder.buildStore(new_tag, tag_field_ptr);
7524 return null;7568 return null;
7525 }7569 }
...@@ -8336,17 +8380,9 @@ pub const FuncGen = struct {...@@ -8336,17 +8380,9 @@ pub const FuncGen = struct {
8336 fn optIsNonNull(self: *FuncGen, opt_handle: *const llvm.Value, is_by_ref: bool) *const llvm.Value {8380 fn optIsNonNull(self: *FuncGen, opt_handle: *const llvm.Value, is_by_ref: bool) *const llvm.Value {
8337 const field = b: {8381 const field = b: {
8338 if (is_by_ref) {8382 if (is_by_ref) {
8339 const index_type = self.context.intType(32);8383 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, "");8384 break :b self.builder.buildLoad(field_ptr, "");
8348 }8385 }
8349
8350 break :b self.builder.buildExtractValue(opt_handle, 1, "");8386 break :b self.builder.buildExtractValue(opt_handle, 1, "");
8351 };8387 };
8352 comptime assert(optional_layout_version == 3);8388 comptime assert(optional_layout_version == 3);
...@@ -8355,18 +8391,63 @@ pub const FuncGen = struct {...@@ -8355,18 +8391,63 @@ pub const FuncGen = struct {
8355 }8391 }
83568392
8357 /// Assumes the optional is not pointer-like and payload has bits.8393 /// Assumes the optional is not pointer-like and payload has bits.
8358 fn optPayloadHandle(self: *FuncGen, opt_handle: *const llvm.Value, is_by_ref: bool) *const llvm.Value {8394 fn optPayloadHandle(
8359 if (is_by_ref) {8395 fg: *FuncGen,
8396 opt_handle: *const llvm.Value,
8397 opt_ty: Type,
8398 ) *const llvm.Value {
8399 var buf: Type.Payload.ElemType = undefined;
8400 const payload_ty = opt_ty.optionalChild(&buf);
8401
8402 if (isByRef(opt_ty)) {
8360 // We have a pointer and we need to return a pointer to the first field.8403 // We have a pointer and we need to return a pointer to the first field.
8361 const index_type = self.context.intType(32);8404 const payload_ptr = fg.builder.buildStructGEP(opt_handle, 0, "");
8362 const indices: [2]*const llvm.Value = .{8405
8363 index_type.constNull(), // dereference the pointer8406 if (isByRef(payload_ty)) {
8364 index_type.constNull(), // first field is the payload8407 return payload_ptr;
8365 };8408 }
8366 return self.builder.buildInBoundsGEP(opt_handle, &indices, indices.len, "");8409 const target = fg.dg.module.getTarget();
8410 const payload_alignment = payload_ty.abiAlignment(target);
8411 const load_inst = fg.builder.buildLoad(payload_ptr, "");
8412 load_inst.setAlignment(payload_alignment);
8413 return load_inst;
8414 }
8415
8416 assert(!isByRef(payload_ty));
8417 return fg.builder.buildExtractValue(opt_handle, 0, "");
8418 }
8419
8420 fn buildOptional(
8421 self: *FuncGen,
8422 optional_ty: Type,
8423 payload: *const llvm.Value,
8424 non_null_bit: *const llvm.Value,
8425 ) !?*const llvm.Value {
8426 const optional_llvm_ty = try self.dg.lowerType(optional_ty);
8427 const non_null_field = self.builder.buildZExt(non_null_bit, self.dg.context.intType(8), "");
8428
8429 if (isByRef(optional_ty)) {
8430 const target = self.dg.module.getTarget();
8431 const alloca_inst = self.buildAlloca(optional_llvm_ty);
8432 const payload_alignment = optional_ty.abiAlignment(target);
8433 alloca_inst.setAlignment(payload_alignment);
8434
8435 {
8436 const field_ptr = self.builder.buildStructGEP(alloca_inst, 0, "");
8437 const store_inst = self.builder.buildStore(payload, field_ptr);
8438 store_inst.setAlignment(payload_alignment);
8439 }
8440 {
8441 const field_ptr = self.builder.buildStructGEP(alloca_inst, 1, "");
8442 const store_inst = self.builder.buildStore(non_null_field, field_ptr);
8443 store_inst.setAlignment(1);
8444 }
8445
8446 return alloca_inst;
8367 }8447 }
83688448
8369 return self.builder.buildExtractValue(opt_handle, 0, "");8449 const partial = self.builder.buildInsertValue(optional_llvm_ty.getUndef(), payload, 0, "");
8450 return self.builder.buildInsertValue(partial, non_null_field, 1, "");
8370 }8451 }
83718452
8372 fn fieldPtr(8453 fn fieldPtr(
...@@ -9275,10 +9356,12 @@ fn ccAbiPromoteInt(...@@ -9275,10 +9356,12 @@ fn ccAbiPromoteInt(
9275 return null;9356 return null;
9276}9357}
92779358
9359/// This is the one source of truth for whether a type is passed around as an LLVM pointer,
9360/// or as an LLVM value.
9278fn isByRef(ty: Type) bool {9361fn isByRef(ty: Type) bool {
9279 // For tuples and structs, if there are more than this many non-void9362 // For tuples and structs, if there are more than this many non-void
9280 // fields, then we make it byref, otherwise byval.9363 // fields, then we make it byref, otherwise byval.
9281 const max_fields_byval = 2;9364 const max_fields_byval = 0;
92829365
9283 switch (ty.zigTypeTag()) {9366 switch (ty.zigTypeTag()) {
9284 .Type,9367 .Type,
...@@ -9332,10 +9415,23 @@ fn isByRef(ty: Type) bool {...@@ -9332,10 +9415,23 @@ fn isByRef(ty: Type) bool {
9332 return false;9415 return false;
9333 },9416 },
9334 .Union => return ty.hasRuntimeBits(),9417 .Union => return ty.hasRuntimeBits(),
9335 .ErrorUnion => return isByRef(ty.errorUnionPayload()),9418 .ErrorUnion => {
9419 const payload_ty = ty.errorUnionPayload();
9420 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
9421 return false;
9422 }
9423 return true;
9424 },
9336 .Optional => {9425 .Optional => {
9337 var buf: Type.Payload.ElemType = undefined;9426 var buf: Type.Payload.ElemType = undefined;
9338 return isByRef(ty.optionalChild(&buf));9427 const payload_ty = ty.optionalChild(&buf);
9428 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
9429 return false;
9430 }
9431 if (ty.optionalReprIsPayload()) {
9432 return false;
9433 }
9434 return true;
9339 },9435 },
9340 }9436 }
9341}9437}