@@ -1926,6 +1926,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1926
1926
.wrap_errunion_payload = > try cg .airWrapErrUnionPayload (inst ),
1927
1927
.wrap_errunion_err = > try cg .airWrapErrUnionErr (inst ),
1928
1928
1929
+ .@"try" , .try_cold = > try cg .airTry (inst ),
1930
+ .try_ptr , .try_ptr_cold = > try cg .airTryPtr (inst ),
1931
+
1929
1932
.unreach = > {},
1930
1933
1931
1934
.intcast_safe ,
@@ -2323,6 +2326,7 @@ fn genCopy(cg: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: Cop
2323
2326
const zcu = cg .pt .zcu ;
2324
2327
if (! ty .hasRuntimeBits (zcu )) return ;
2325
2328
2329
+ log .debug ("copying {} to {} ({}, safety = {})" , .{ src_mcv , dst_mcv , ty .fmt (cg .pt ), opts .safety });
2326
2330
switch (dst_mcv ) {
2327
2331
.register = > | reg | try cg .genCopyToReg (.fromByteSize (ty .abiSize (zcu )), reg , src_mcv , opts ),
2328
2332
inline .register_pair , .register_triple , .register_quadruple = > | regs | {
@@ -2602,6 +2606,7 @@ const Select = struct {
2602
2606
}
2603
2607
2604
2608
fn finish (sel : * Select , result : Temp ) ! void {
2609
+ cg_select_log .debug ("select finished: {}" , .{result });
2605
2610
if (sel .inst ) | inst | {
2606
2611
try result .finish (inst , sel .ops [0.. sel .ops_count ], sel .cg );
2607
2612
}
@@ -3615,10 +3620,7 @@ fn airBitCast(cg: *CodeGen, inst: Air.Inst.Index) !void {
3615
3620
// case 1: no operation needed
3616
3621
// src and dst must have the same ABI size
3617
3622
if (try sel .match (.{
3618
- .requirement = src_ty .abiSize (zcu ) == dst_ty .abiSize (zcu ) and
3619
- ((dst_ty .isAbiInt (zcu ) and src_ty .isAbiInt (zcu )) or
3620
- src_ty .isPtrAtRuntime (zcu ) or
3621
- dst_ty .isPtrAtRuntime (zcu )),
3623
+ .requirement = src_ty .abiSize (zcu ) == dst_ty .abiSize (zcu ),
3622
3624
.patterns = &.{.{ .srcs = &.{.any } }},
3623
3625
})) {
3624
3626
const src = sel .ops [0 ];
@@ -3692,9 +3694,9 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !void {
3692
3694
} else return sel .fail ();
3693
3695
}
3694
3696
3695
- fn airIsErr ( cg : * CodeGen , inst : Air.Inst.Index , inverted : bool ) ! void {
3696
- const un_op = cg . getAirData ( inst ). un_op ;
3697
- var sel = Select .init (cg , inst , & try cg . tempsFromOperands ( inst , .{ un_op }) );
3697
+ /// Checks if a error union value is error. Returns only register values.
3698
+ fn genIsErr ( cg : * CodeGen , eu : Temp , reuse : bool , inverted : bool ) ! Temp {
3699
+ var sel = Select .init (cg , null , &.{ eu } );
3698
3700
3699
3701
// case 1: error is in register
3700
3702
if (try sel .match (.{
@@ -3707,17 +3709,19 @@ fn airIsErr(cg: *CodeGen, inst: Air.Inst.Index, inverted: bool) !void {
3707
3709
const src_mcv = src .tracking (cg );
3708
3710
const err_reg = src_mcv .getRegs ()[0 ];
3709
3711
const dst = dst : {
3710
- if (cg . liveness . operandDies ( inst , 0 ) ) {
3712
+ if (reuse ) {
3711
3713
try src .die (cg );
3712
- break :dst err_reg ;
3713
- } else break :dst try cg .allocReg (.bool , inst );
3714
+ break :dst try cg . tempInit ( .bool , .{ . register = err_reg }) ;
3715
+ } else break :dst try cg .tempAlloc (.bool , .{ . use_frame = false } );
3714
3716
};
3717
+ const dst_reg = dst .getReg (cg );
3715
3718
3716
- try cg .asmInst (.sltui (dst , err_reg , 1 ));
3719
+ try cg .asmInst (.sltui (dst_reg , err_reg , 1 ));
3717
3720
if (! inverted )
3718
- try cg .asmInst (.xori (dst , dst , 1 ));
3721
+ try cg .asmInst (.xori (dst_reg , dst_reg , 1 ));
3719
3722
3720
- try sel .finish (try cg .tempInit (.bool , .{ .register = dst }));
3723
+ try sel .finish (dst );
3724
+ return dst ;
3721
3725
}
3722
3726
// case 2: error is in memory
3723
3727
else if (try sel .match (.{
@@ -3726,7 +3730,7 @@ fn airIsErr(cg: *CodeGen, inst: Air.Inst.Index, inverted: bool) !void {
3726
3730
},
3727
3731
})) {
3728
3732
const src = sel .ops [0 ];
3729
- var limb = try src .getLimb (.bool , 0 , cg , cg . liveness . operandDies ( inst , 0 ) );
3733
+ var limb = try src .getLimb (.bool , 0 , cg , reuse );
3730
3734
while (try limb .moveToRegister (cg , .int , true )) {}
3731
3735
limb .toType (cg , .bool );
3732
3736
const limb_reg = limb .getReg (cg );
@@ -3736,9 +3740,18 @@ fn airIsErr(cg: *CodeGen, inst: Air.Inst.Index, inverted: bool) !void {
3736
3740
try cg .asmInst (.xori (limb_reg , limb_reg , 1 ));
3737
3741
3738
3742
try sel .finish (limb );
3743
+ return limb ;
3739
3744
} else return sel .fail ();
3740
3745
}
3741
3746
3747
+ fn airIsErr (cg : * CodeGen , inst : Air.Inst.Index , inverted : bool ) ! void {
3748
+ const un_op = cg .getAirData (inst ).un_op ;
3749
+ const ops = try cg .tempsFromOperands (inst , .{un_op });
3750
+ const reuse = ! cg .liveness .operandDies (inst , 0 );
3751
+ const dst = try cg .genIsErr (ops [0 ], reuse , inverted );
3752
+ try dst .finish (inst , & ops , cg );
3753
+ }
3754
+
3742
3755
fn airSlicePtr (cg : * CodeGen , inst : Air.Inst.Index ) ! void {
3743
3756
const ty_op = cg .getAirData (inst ).ty_op ;
3744
3757
const op = (try cg .tempsFromOperands (inst , .{ty_op .operand }))[0 ];
@@ -3953,3 +3966,76 @@ fn airWrapErrUnionErr(cg: *CodeGen, inst: Air.Inst.Index) !void {
3953
3966
try eu .write (ops [0 ], cg , .{ .off = eu_err_off });
3954
3967
try eu .finish (inst , & ops , cg );
3955
3968
}
3969
+
3970
+ fn airTry (cg : * CodeGen , inst : Air.Inst.Index ) ! void {
3971
+ const pl_op = cg .getAirData (inst ).pl_op ;
3972
+ const extra = cg .air .extraData (Air .Try , pl_op .payload );
3973
+ const body : []const Air.Inst.Index = @ptrCast (cg .air .extra .items [extra .end .. ][0.. extra .data .body_len ]);
3974
+
3975
+ const operand_ty = cg .typeOf (pl_op .operand );
3976
+ const result = try cg .genTry (inst , pl_op .operand , operand_ty , false , body );
3977
+ try result .finish (inst , &.{}, cg );
3978
+ }
3979
+
3980
+ fn airTryPtr (cg : * CodeGen , inst : Air.Inst.Index ) ! void {
3981
+ const ty_pl = cg .getAirData (inst ).ty_pl ;
3982
+ const extra = cg .air .extraData (Air .TryPtr , ty_pl .payload );
3983
+ const body : []const Air.Inst.Index = @ptrCast (cg .air .extra .items [extra .end .. ][0.. extra .data .body_len ]);
3984
+
3985
+ const operand_ty = cg .typeOf (extra .data .ptr );
3986
+ const result = try cg .genTry (inst , extra .data .ptr , operand_ty , true , body );
3987
+ try result .finish (inst , &.{}, cg );
3988
+ }
3989
+
3990
+ fn genTry (
3991
+ cg : * CodeGen ,
3992
+ inst : Air.Inst.Index ,
3993
+ operand : Air.Inst.Ref ,
3994
+ operand_ty : Type ,
3995
+ operand_is_ptr : bool ,
3996
+ body : []const Air.Inst.Index ,
3997
+ ) ! Temp {
3998
+ const zcu = cg .pt .zcu ;
3999
+ const liveness_cond_br = cg .liveness .getCondBr (inst );
4000
+ const ops = try cg .tempsFromOperands (inst , .{operand });
4001
+ const reuse_op = ! cg .liveness .operandDies (inst , 0 );
4002
+
4003
+ const is_err_temp = if (operand_is_ptr )
4004
+ unreachable // TODO
4005
+ else
4006
+ try cg .genIsErr (ops [0 ], reuse_op , true );
4007
+ const is_err_reg = is_err_temp .getReg (cg );
4008
+
4009
+ if (! reuse_op )
4010
+ try ops [0 ].die (cg );
4011
+ try is_err_temp .die (cg );
4012
+ try cg .resetTemps (@enumFromInt (0 ));
4013
+
4014
+ const reloc = try cg .asmBr (null , .{ .ne = .{ is_err_reg , .zero } });
4015
+ const state = try cg .saveState ();
4016
+ for (liveness_cond_br .else_deaths ) | death | try cg .resolveInst (death ).die (cg , death );
4017
+ try cg .genBodyBlock (body );
4018
+ try cg .restoreState (state , &.{}, .{
4019
+ .emit_instructions = false ,
4020
+ .update_tracking = true ,
4021
+ .resurrect = true ,
4022
+ .close_scope = true ,
4023
+ });
4024
+ cg .performReloc (reloc );
4025
+
4026
+ for (liveness_cond_br .then_deaths ) | death | try cg .resolveInst (death ).die (cg , death );
4027
+
4028
+ const payload_ty = operand_ty .errorUnionPayload (zcu );
4029
+ const field_off : i32 = @intCast (codegen .errUnionPayloadOffset (payload_ty , zcu ));
4030
+ const result =
4031
+ if (cg .liveness .isUnused (inst ))
4032
+ try cg .tempInit (payload_ty , .unreach )
4033
+ else if (operand_is_ptr )
4034
+ unreachable // TODO
4035
+ else if (payload_ty .hasRuntimeBitsIgnoreComptime (zcu ))
4036
+ try ops [0 ].read (cg , payload_ty , .{ .off = field_off })
4037
+ else
4038
+ try cg .tempInit (payload_ty , .none );
4039
+
4040
+ return result ;
4041
+ }
0 commit comments