| ... | ... | @@ -1770,8 +1770,8 @@ pub const FuncGen = struct { |
| 1770 | 1770 | .ptr_elem_val => try self.airPtrElemVal(inst), |
| 1771 | 1771 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), |
| 1772 | 1772 | |
| 1773 | | .optional_payload => try self.airOptionalPayload(inst, false), |
| 1774 | | .optional_payload_ptr => try self.airOptionalPayload(inst, true), |
| 1773 | .optional_payload => try self.airOptionalPayload(inst), |
| 1774 | .optional_payload_ptr => try self.airOptionalPayloadPtr(inst), |
| 1775 | 1775 | |
| 1776 | 1776 | .unwrap_errunion_payload => try self.airErrUnionPayload(inst, false), |
| 1777 | 1777 | .unwrap_errunion_payload_ptr => try self.airErrUnionPayload(inst, true), |
| ... | ... | @@ -2520,35 +2520,55 @@ pub const FuncGen = struct { |
| 2520 | 2520 | return self.builder.buildICmp(op, loaded, zero, ""); |
| 2521 | 2521 | } |
| 2522 | 2522 | |
| 2523 | | fn airOptionalPayload( |
| 2524 | | self: *FuncGen, |
| 2525 | | inst: Air.Inst.Index, |
| 2526 | | operand_is_ptr: bool, |
| 2527 | | ) !?*const llvm.Value { |
| 2528 | | if (self.liveness.isUnused(inst)) |
| 2529 | | return null; |
| 2523 | fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 2524 | if (self.liveness.isUnused(inst)) return null; |
| 2530 | 2525 | |
| 2531 | 2526 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2532 | 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) { |
| 2535 | | const operand_ty = self.air.typeOf(ty_op.operand).elemType(); |
| 2536 | | if (operand_ty.isPtrLikeOptional()) { |
| 2537 | | return self.builder.buildLoad(operand, ""); |
| 2538 | | } |
| 2548 | fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 2549 | if (self.liveness.isUnused(inst)) return null; |
| 2539 | 2550 | |
| 2540 | | const index_type = self.context.intType(32); |
| 2541 | | var indices: [2]*const llvm.Value = .{ |
| 2542 | | index_type.constNull(), index_type.constNull(), |
| 2543 | | }; |
| 2544 | | return self.builder.buildInBoundsGEP(operand, &indices, 2, ""); |
| 2545 | | } |
| 2551 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2552 | const operand = try self.resolveInst(ty_op.operand); |
| 2553 | const optional_ty = self.air.typeOf(ty_op.operand); |
| 2554 | const payload_ty = self.air.typeOfIndex(inst); |
| 2555 | if (!payload_ty.hasCodeGenBits()) return null; |
| 2546 | 2556 | |
| 2547 | | const operand_ty = self.air.typeOf(ty_op.operand); |
| 2548 | | if (operand_ty.isPtrLikeOptional()) { |
| 2557 | if (optional_ty.isPtrLikeOptional()) { |
| 2558 | // Payload value is the same as the optional value. |
| 2549 | 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 | 2572 | return self.builder.buildExtractValue(operand, 0, ""); |
| 2553 | 2573 | } |
| 2554 | 2574 | |