| ... | @@ -1770,8 +1770,8 @@ pub const FuncGen = struct { | ... | @@ -1770,8 +1770,8 @@ pub const FuncGen = struct { |
| 1770 | .ptr_elem_val => try self.airPtrElemVal(inst), | 1770 | .ptr_elem_val => try self.airPtrElemVal(inst), |
| 1771 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), | 1771 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), |
| 1772 | | 1772 | |
| 1773 | .optional_payload => try self.airOptionalPayload(inst, false), | 1773 | .optional_payload => try self.airOptionalPayload(inst), |
| 1774 | .optional_payload_ptr => try self.airOptionalPayload(inst, true), | 1774 | .optional_payload_ptr => try self.airOptionalPayloadPtr(inst), |
| 1775 | | 1775 | |
| 1776 | .unwrap_errunion_payload => try self.airErrUnionPayload(inst, false), | 1776 | .unwrap_errunion_payload => try self.airErrUnionPayload(inst, false), |
| 1777 | .unwrap_errunion_payload_ptr => try self.airErrUnionPayload(inst, true), | 1777 | .unwrap_errunion_payload_ptr => try self.airErrUnionPayload(inst, true), |
| ... | @@ -2520,35 +2520,55 @@ pub const FuncGen = struct { | ... | @@ -2520,35 +2520,55 @@ pub const FuncGen = struct { |
| 2520 | return self.builder.buildICmp(op, loaded, zero, ""); | 2520 | return self.builder.buildICmp(op, loaded, zero, ""); |
| 2521 | } | 2521 | } |
| 2522 | | 2522 | |
| 2523 | fn airOptionalPayload( | 2523 | fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 2524 | self: *FuncGen, | 2524 | if (self.liveness.isUnused(inst)) return null; |
| 2525 | inst: Air.Inst.Index, | | |
| 2526 | operand_is_ptr: bool, | | |
| 2527 | ) !?*const llvm.Value { | | |
| 2528 | if (self.liveness.isUnused(inst)) | | |
| 2529 | return null; | | |
| 2530 | | 2525 | |
| 2531 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2526 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2532 | const operand = try self.resolveInst(ty_op.operand); | 2527 | const operand = try self.resolveInst(ty_op.operand); |
| | 2528 | const optional_ty = self.air.typeOf(ty_op.operand).childType(); |
| | 2529 | var buf: Type.Payload.ElemType = undefined; |
| | 2530 | const payload_ty = optional_ty.optionalChild(&buf); |
| | 2531 | if (!payload_ty.hasCodeGenBits()) { |
| | 2532 | // We have a pointer to a zero-bit value and we need to return |
| | 2533 | // a pointer to a zero-bit value. |
| | 2534 | return operand; |
| | 2535 | } |
| | 2536 | if (optional_ty.isPtrLikeOptional()) { |
| | 2537 | // The payload and the optional are the same value. |
| | 2538 | return operand; |
| | 2539 | } |
| | 2540 | const index_type = self.context.intType(32); |
| | 2541 | const indices: [2]*const llvm.Value = .{ |
| | 2542 | index_type.constNull(), // dereference the pointer |
| | 2543 | index_type.constNull(), // first field is the payload |
| | 2544 | }; |
| | 2545 | return self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); |
| | 2546 | } |
| 2533 | | 2547 | |
| 2534 | if (operand_is_ptr) { | 2548 | fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 2535 | const operand_ty = self.air.typeOf(ty_op.operand).elemType(); | 2549 | if (self.liveness.isUnused(inst)) return null; |
| 2536 | if (operand_ty.isPtrLikeOptional()) { | | |
| 2537 | return self.builder.buildLoad(operand, ""); | | |
| 2538 | } | | |
| 2539 | | 2550 | |
| 2540 | const index_type = self.context.intType(32); | 2551 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2541 | var indices: [2]*const llvm.Value = .{ | 2552 | const operand = try self.resolveInst(ty_op.operand); |
| 2542 | index_type.constNull(), index_type.constNull(), | 2553 | const optional_ty = self.air.typeOf(ty_op.operand); |
| 2543 | }; | 2554 | const payload_ty = self.air.typeOfIndex(inst); |
| 2544 | return self.builder.buildInBoundsGEP(operand, &indices, 2, ""); | 2555 | if (!payload_ty.hasCodeGenBits()) return null; |
| 2545 | } | | |
| 2546 | | 2556 | |
| 2547 | const operand_ty = self.air.typeOf(ty_op.operand); | 2557 | if (optional_ty.isPtrLikeOptional()) { |
| 2548 | if (operand_ty.isPtrLikeOptional()) { | 2558 | // Payload value is the same as the optional value. |
| 2549 | return operand; | 2559 | return operand; |
| 2550 | } | 2560 | } |
| 2551 | | 2561 | |
| | 2562 | if (isByRef(payload_ty)) { |
| | 2563 | // We have a pointer and we need to return a pointer to the first field. |
| | 2564 | const index_type = self.context.intType(32); |
| | 2565 | const indices: [2]*const llvm.Value = .{ |
| | 2566 | index_type.constNull(), // dereference the pointer |
| | 2567 | index_type.constNull(), // first field is the payload |
| | 2568 | }; |
| | 2569 | return self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); |
| | 2570 | } |
| | 2571 | |
| 2552 | return self.builder.buildExtractValue(operand, 0, ""); | 2572 | return self.builder.buildExtractValue(operand, 0, ""); |
| 2553 | } | 2573 | } |
| 2554 | | 2574 | |