@@ -818,9 +818,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
818
818
819
819
if (reg_ok ) {
820
820
// Make sure the type can fit in a register before we try to allocate one.
821
- const ptr_bits = self .target .cpu .arch .ptrBitWidth ();
822
- const ptr_bytes : u64 = @divExact (ptr_bits , 8 );
823
- if (abi_size <= ptr_bytes ) {
821
+ if (abi_size <= 8 ) {
824
822
if (self .register_manager .tryAllocReg (inst )) | reg | {
825
823
return MCValue { .register = registerAlias (reg , abi_size ) };
826
824
}
@@ -1038,7 +1036,20 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void {
1038
1036
fn airSlice (self : * Self , inst : Air.Inst.Index ) ! void {
1039
1037
const ty_pl = self .air .instructions .items (.data )[inst ].ty_pl ;
1040
1038
const bin_op = self .air .extraData (Air .Bin , ty_pl .payload ).data ;
1041
- const result : MCValue = if (self .liveness .isUnused (inst )) .dead else return self .fail ("TODO implement slice for {}" , .{self .target .cpu .arch });
1039
+ const result : MCValue = if (self .liveness .isUnused (inst )) .dead else result : {
1040
+ const ptr = try self .resolveInst (bin_op .lhs );
1041
+ const ptr_ty = self .air .typeOf (bin_op .lhs );
1042
+ const len = try self .resolveInst (bin_op .rhs );
1043
+ const len_ty = self .air .typeOf (bin_op .rhs );
1044
+
1045
+ const ptr_bits = self .target .cpu .arch .ptrBitWidth ();
1046
+ const ptr_bytes = @divExact (ptr_bits , 8 );
1047
+
1048
+ const stack_offset = try self .allocMem (inst , ptr_bytes * 2 , ptr_bytes * 2 );
1049
+ try self .genSetStack (ptr_ty , stack_offset + ptr_bytes , ptr );
1050
+ try self .genSetStack (len_ty , stack_offset , len );
1051
+ break :result MCValue { .stack_offset = stack_offset };
1052
+ };
1042
1053
return self .finishAir (inst , result , .{ bin_op .lhs , bin_op .rhs , .none });
1043
1054
}
1044
1055
@@ -1602,22 +1613,39 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
1602
1613
1603
1614
fn airSlicePtr (self : * Self , inst : Air.Inst.Index ) ! void {
1604
1615
const ty_op = self .air .instructions .items (.data )[inst ].ty_op ;
1605
- const result : MCValue = if (self .liveness .isUnused (inst )) .dead else return self .fail ("TODO implement slice_ptr for {}" , .{self .target .cpu .arch });
1616
+ const result : MCValue = if (self .liveness .isUnused (inst )) .dead else result : {
1617
+ const ptr_bits = self .target .cpu .arch .ptrBitWidth ();
1618
+ const ptr_bytes = @divExact (ptr_bits , 8 );
1619
+ const mcv = try self .resolveInst (ty_op .operand );
1620
+ switch (mcv ) {
1621
+ .dead , .unreach , .none = > unreachable ,
1622
+ .register = > unreachable , // a slice doesn't fit in one register
1623
+ .stack_offset = > | off | {
1624
+ break :result MCValue { .stack_offset = off + ptr_bytes };
1625
+ },
1626
+ .memory = > | addr | {
1627
+ break :result MCValue { .memory = addr };
1628
+ },
1629
+ else = > return self .fail ("TODO implement slice_len for {}" , .{mcv }),
1630
+ }
1631
+ };
1606
1632
return self .finishAir (inst , result , .{ ty_op .operand , .none , .none });
1607
1633
}
1608
1634
1609
1635
fn airSliceLen (self : * Self , inst : Air.Inst.Index ) ! void {
1610
1636
const ty_op = self .air .instructions .items (.data )[inst ].ty_op ;
1611
1637
const result : MCValue = if (self .liveness .isUnused (inst )) .dead else result : {
1638
+ const ptr_bits = self .target .cpu .arch .ptrBitWidth ();
1639
+ const ptr_bytes = @divExact (ptr_bits , 8 );
1612
1640
const mcv = try self .resolveInst (ty_op .operand );
1613
1641
switch (mcv ) {
1614
- .dead , .unreach = > unreachable ,
1642
+ .dead , .unreach , .none = > unreachable ,
1615
1643
.register = > unreachable , // a slice doesn't fit in one register
1616
1644
.stack_offset = > | off | {
1617
1645
break :result MCValue { .stack_offset = off };
1618
1646
},
1619
1647
.memory = > | addr | {
1620
- break :result MCValue { .memory = addr + 8 };
1648
+ break :result MCValue { .memory = addr + ptr_bytes };
1621
1649
},
1622
1650
else = > return self .fail ("TODO implement slice_len for {}" , .{mcv }),
1623
1651
}
@@ -1627,13 +1655,33 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
1627
1655
1628
1656
fn airPtrSliceLenPtr (self : * Self , inst : Air.Inst.Index ) ! void {
1629
1657
const ty_op = self .air .instructions .items (.data )[inst ].ty_op ;
1630
- const result : MCValue = if (self .liveness .isUnused (inst )) .dead else return self .fail ("TODO implement ptr_slice_len_ptr for {}" , .{self .target .cpu .arch });
1658
+ const result : MCValue = if (self .liveness .isUnused (inst )) .dead else result : {
1659
+ const ptr_bits = self .target .cpu .arch .ptrBitWidth ();
1660
+ const ptr_bytes = @divExact (ptr_bits , 8 );
1661
+ const mcv = try self .resolveInst (ty_op .operand );
1662
+ switch (mcv ) {
1663
+ .dead , .unreach , .none = > unreachable ,
1664
+ .ptr_stack_offset = > | off | {
1665
+ break :result MCValue { .ptr_stack_offset = off + ptr_bytes };
1666
+ },
1667
+ else = > return self .fail ("TODO implement ptr_slice_len_ptr for {}" , .{mcv }),
1668
+ }
1669
+ };
1631
1670
return self .finishAir (inst , result , .{ ty_op .operand , .none , .none });
1632
1671
}
1633
1672
1634
1673
fn airPtrSlicePtrPtr (self : * Self , inst : Air.Inst.Index ) ! void {
1635
1674
const ty_op = self .air .instructions .items (.data )[inst ].ty_op ;
1636
- const result : MCValue = if (self .liveness .isUnused (inst )) .dead else return self .fail ("TODO implement ptr_slice_ptr_ptr for {}" , .{self .target .cpu .arch });
1675
+ const result : MCValue = if (self .liveness .isUnused (inst )) .dead else result : {
1676
+ const mcv = try self .resolveInst (ty_op .operand );
1677
+ switch (mcv ) {
1678
+ .dead , .unreach , .none = > unreachable ,
1679
+ .ptr_stack_offset = > | off | {
1680
+ break :result MCValue { .ptr_stack_offset = off };
1681
+ },
1682
+ else = > return self .fail ("TODO implement ptr_slice_len_ptr for {}" , .{mcv }),
1683
+ }
1684
+ };
1637
1685
return self .finishAir (inst , result , .{ ty_op .operand , .none , .none });
1638
1686
}
1639
1687
@@ -3475,9 +3523,20 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
3475
3523
3476
3524
fn airArrayToSlice (self : * Self , inst : Air.Inst.Index ) ! void {
3477
3525
const ty_op = self .air .instructions .items (.data )[inst ].ty_op ;
3478
- const result : MCValue = if (self .liveness .isUnused (inst )) .dead else return self .fail ("TODO implement airArrayToSlice for {}" , .{
3479
- self .target .cpu .arch ,
3480
- });
3526
+ const result : MCValue = if (self .liveness .isUnused (inst )) .dead else result : {
3527
+ const ptr_ty = self .air .typeOf (ty_op .operand );
3528
+ const ptr = try self .resolveInst (ty_op .operand );
3529
+ const array_ty = ptr_ty .childType ();
3530
+ const array_len = @intCast (u32 , array_ty .arrayLen ());
3531
+
3532
+ const ptr_bits = self .target .cpu .arch .ptrBitWidth ();
3533
+ const ptr_bytes = @divExact (ptr_bits , 8 );
3534
+
3535
+ const stack_offset = try self .allocMem (inst , ptr_bytes * 2 , ptr_bytes * 2 );
3536
+ try self .genSetStack (ptr_ty , stack_offset + ptr_bytes , ptr );
3537
+ try self .genSetStack (Type .initTag (.usize ), stack_offset , .{ .immediate = array_len });
3538
+ break :result MCValue { .stack_offset = stack_offset };
3539
+ };
3481
3540
return self .finishAir (inst , result , .{ ty_op .operand , .none , .none });
3482
3541
}
3483
3542
0 commit comments