| ... | @@ -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 | } |
| 5740 | | 5735 | |
| 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 pointer | 5763 | _ = self.builder.buildStore(non_null_bit, non_null_ptr); |
| 5769 | index_type.constInt(1, .False), // second field is the non-null bit | 5764 | |
| 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 pointer | 5769 | 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 | } |
| 5783 | | 5771 | |
| 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; |
| 5893 | | 5876 | |
| 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 | } |
| 5901 | | 5880 | |
| 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, ""); |
| 6392 | | 6371 | |
| 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 | } |
| 6397 | | 6398 | |
| 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, ""); |
| 6722 | | 6723 | |
| 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 | } |
| 6727 | | 6750 | |
| 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 { |
| 8365 | | 8380 | |
| 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, ""); | | |
| 8374 | | 8384 | |
| 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); |
| 8403 | | 8413 | |
| 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( |
| 9337 | fn isByRef(ty: Type) bool { | 9338 | fn isByRef(ty: Type) bool { |
| 9338 | // For tuples and structs, if there are more than this many non-void | 9339 | // 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; |
| 9341 | | 9342 | |
| 9342 | switch (ty.zigTypeTag()) { | 9343 | switch (ty.zigTypeTag()) { |
| 9343 | .Type, | 9344 | .Type, |