@@ -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
0 commit comments