Skip to content

Commit

Permalink
Scatter unsigned int handling about.
Browse files Browse the repository at this point in the history
This probably doesn't cover everything, but it's a significant step
forward from before, where we essentially ignored it entirely for
locals and lexicals.
  • Loading branch information
jnthn committed Dec 18, 2015
1 parent 7818504 commit a31a3d0
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 23 deletions.
158 changes: 138 additions & 20 deletions src/vm/moar/QAST/QASTCompilerMAST.nqp
Expand Up @@ -417,7 +417,8 @@ my class MASTCompilerInstance {
elsif $desired == $MVM_reg_obj {
# See if we already have full-width native.
if $got == $MVM_reg_int64 || $got == $MVM_reg_num64 ||
$got == $MVM_reg_str || $got == $MVM_reg_void {
$got == $MVM_reg_str || $got == $MVM_reg_void ||
$got == $MVM_reg_uint64 {
return QAST::MASTOperations.box(self, $!hll, $got, $reg);
}
elsif $got == $MVM_reg_num32 {
Expand All @@ -436,13 +437,22 @@ my class MASTCompilerInstance {
push_ilist($il, $box);
$reg := $box.result_reg;
}
elsif $got == $MVM_reg_uint32 || $got == $MVM_reg_uint16 || $got == $MVM_reg_uint8 {
my $grow := self.coercion($res, $MVM_reg_uint64);
my $box := QAST::MASTOperations.box(self, $!hll, $MVM_reg_uint64,
$grow.result_reg);
$il := $grow.instructions;
push_ilist($il, $box);
$reg := $box.result_reg;
}
else {
nqp::die("Unknown boxing case; got: " ~ $got);
}
}
elsif $got == $MVM_reg_obj {
# See if we want a full-width native.
if $desired == $MVM_reg_int64 || $desired == $MVM_reg_num64 || $desired == $MVM_reg_str {
if $desired == $MVM_reg_int64 || $desired == $MVM_reg_num64 ||
$desired == $MVM_reg_str || $desired == $MVM_reg_uint64 {
return QAST::MASTOperations.unbox(self, $!hll, $desired, $reg);
}
elsif $desired == $MVM_reg_num32 {
Expand All @@ -459,12 +469,20 @@ my class MASTCompilerInstance {
push_ilist($il, $shrink);
$reg := $shrink.result_reg;
}
elsif $desired == $MVM_reg_uint32 || $desired == $MVM_reg_uint16 || $desired == $MVM_reg_uint8 {
my $unbox := QAST::MASTOperations.unbox(self, $!hll, $MVM_reg_uint64, $reg);
my $shrink := self.coercion($unbox, $desired);
$il := $unbox.instructions;
push_ilist($il, $shrink);
$reg := $shrink.result_reg;
}
else {
nqp::die("Unknown unboxing case; desired: " ~ $desired);
}
}
else {
my $res_reg := $*REGALLOC.fresh_register($desired);
my $release_type := $got;
if $desired == $MVM_reg_int64 {
if $got == $MVM_reg_num64 {
push_op($il, 'coerce_ni', $res_reg, $reg);
Expand All @@ -484,6 +502,16 @@ my class MASTCompilerInstance {
elsif $got == $MVM_reg_int8 {
push_op($il, 'extend_i8', $res_reg, $reg);
}
elsif $got == $MVM_reg_uint64 {
push_op($il, 'coerce_ui', $res_reg, $reg);
}
elsif $got == $MVM_reg_uint32 || $got == $MVM_reg_uint16 || $got == $MVM_reg_uint8 {
my $uint64 := self.coercion($res, $MVM_reg_uint64);
$il := $uint64.instructions;
$reg := $uint64.result_reg;
$release_type := $uint64.result_kind;
push_op($il, 'coerce_ui', $res_reg, $reg);
}
else {
nqp::die("Unknown coercion case for int; got: "~$got);
}
Expand Down Expand Up @@ -551,10 +579,57 @@ my class MASTCompilerInstance {
nqp::die("Unknown coercion case for int8; got: " ~ $got);
}
}
elsif $desired == $MVM_reg_uint64 {
if $got == $MVM_reg_uint32 {
push_op($il, 'extend_u32', $res_reg, $reg);
}
elsif $got == $MVM_reg_uint16 {
push_op($il, 'extend_u16', $res_reg, $reg);
}
elsif $got == $MVM_reg_uint8 {
push_op($il, 'extend_u8', $res_reg, $reg);
}
else {
unless $got == $MVM_reg_int64 {
my $int64 := self.coercion($res, $MVM_reg_int64);
$il := $int64.instructions;
$reg := $int64.result_reg;
$release_type := $int64.result_kind;
}
push_op($il, 'coerce_iu', $res_reg, $reg);
}
}
elsif $desired == $MVM_reg_uint32 {
unless $got == $MVM_reg_uint64 {
my $uint64 := self.coercion($res, $MVM_reg_uint64);
$il := $uint64.instructions;
$reg := $uint64.result_reg;
$release_type := $uint64.result_kind;
}
push_op($il, 'trunc_u32', $res_reg, $reg);
}
elsif $desired == $MVM_reg_uint16 {
unless $got == $MVM_reg_uint64 {
my $uint64 := self.coercion($res, $MVM_reg_uint64);
$il := $uint64.instructions;
$reg := $uint64.result_reg;
$release_type := $uint64.result_kind;
}
push_op($il, 'trunc_u16', $res_reg, $reg);
}
elsif $desired == $MVM_reg_uint8 {
unless $got == $MVM_reg_uint64 {
my $uint64 := self.coercion($res, $MVM_reg_uint64);
$il := $uint64.instructions;
$reg := $uint64.result_reg;
$release_type := $uint64.result_kind;
}
push_op($il, 'trunc_u8', $res_reg, $reg);
}
else {
nqp::die("Coercion from type '$got' to '$desired' NYI");
}
$*REGALLOC.release_register($reg, $got);
$*REGALLOC.release_register($reg, $release_type);
$reg := $res_reg;
}
MAST::InstructionList.new($il, $reg, $desired)
Expand Down Expand Up @@ -639,34 +714,40 @@ my class MASTCompilerInstance {
];

my @kind_to_op_slot := [
0, 0, 0, 0, 0, 1, 1, 2, 3
0, 0, 0, 0, 0, 1, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, 4, 4, 4, 4
];

my @param_opnames := [
'param_rp_i',
'param_rp_n',
'param_rp_s',
'param_rp_o',
'param_rp_u',
'param_op_i',
'param_op_n',
'param_op_s',
'param_op_o',
'param_op_u',
'param_rn_i',
'param_rn_n',
'param_rn_s',
'param_rn_o',
'param_rn_u',
'param_on_i',
'param_on_n',
'param_on_s',
'param_on_o',
'param_on_u',
'param_rn2_i',
'param_rn2_n',
'param_rn2_s',
'param_rn2_o',
'param_rn2_u',
'param_on2_i',
'param_on2_n',
'param_on2_s',
'param_on2_o'
'param_on2_o',
'param_on2_u'
];

my @return_types := [ NQPMu, int, int, int, int, num, num, str, NQPMu ];
Expand Down Expand Up @@ -927,7 +1008,9 @@ my class MASTCompilerInstance {
$ins := self.coerce($ins, $MVM_reg_num64);
}
elsif $ins_result_kind == $MVM_reg_int32 || $ins_result_kind == $MVM_reg_int16 ||
$ins_result_kind == $MVM_reg_int8 {
$ins_result_kind == $MVM_reg_int8 || $ins_result_kind == $MVM_reg_uint64 ||
$ins_result_kind == $MVM_reg_uint32 || $ins_result_kind == $MVM_reg_uint16 ||
$ins_result_kind == $MVM_reg_uint8 {
$ins := self.coerce($ins, $MVM_reg_int64);
}

Expand Down Expand Up @@ -1032,9 +1115,9 @@ my class MASTCompilerInstance {
my $opslot := @kind_to_op_slot[$param_kind];

my $opname_index := (nqp::defined($var.named)
?? (nqp::islist($var.named) ?? 16 !! 8)
?? (nqp::islist($var.named) ?? 20 !! 10)
!! 0)
+ ($var.default ?? 4 !! 0) + $opslot;
+ ($var.default ?? 5 !! 0) + $opslot;
my $opname := @param_opnames[$opname_index];

# what will be put in the value register
Expand Down Expand Up @@ -1075,7 +1158,8 @@ my class MASTCompilerInstance {
my $valreg;
my $truncop;
if $param_kind == $MVM_reg_obj || $param_kind == $MVM_reg_int64 ||
$param_kind == $MVM_reg_num64 || $param_kind == $MVM_reg_str {
$param_kind == $MVM_reg_num64 || $param_kind == $MVM_reg_str ||
$param_kind == $MVM_reg_uint64 {
$valreg := $targetreg;
}
elsif $param_kind == $MVM_reg_num32 {
Expand All @@ -1094,6 +1178,18 @@ my class MASTCompilerInstance {
$valreg := $*REGALLOC.fresh_register($MVM_reg_int64);
$truncop := 'trunc_i8';
}
elsif $param_kind == $MVM_reg_uint32 {
$valreg := $*REGALLOC.fresh_register($MVM_reg_uint64);
$truncop := 'trunc_u32';
}
elsif $param_kind == $MVM_reg_uint16 {
$valreg := $*REGALLOC.fresh_register($MVM_reg_uint64);
$truncop := 'trunc_u16';
}
elsif $param_kind == $MVM_reg_uint8 {
$valreg := $*REGALLOC.fresh_register($MVM_reg_uint64);
$truncop := 'trunc_u8';
}

# NQP->QAST always provides a default value for optional NQP params
# even if no default initializer expression is provided.
Expand Down Expand Up @@ -1347,7 +1443,8 @@ my class MASTCompilerInstance {
'lex_ni',
'lex_nn',
'lex_ns',
'lex_no'
'lex_no',
'lex_nu'
];

my @lexref_opnames := [
Expand All @@ -1358,13 +1455,20 @@ my class MASTCompilerInstance {
'getlexref_i',
'getlexref_n32',
'getlexref_n',
'getlexref_s'
'getlexref_s',
'', '', '', '', '', '', '', '', '',
'getlexref_u8',
'getlexref_u16',
'getlexref_u32',
'getlexref_u'
];

my @lexref_n_opnames := [
'getlexref_ni',
'getlexref_nn',
'getlexref_ns'
'getlexref_ns',
'',
'getlexref_nu',
];

my @localref_opnames := [
Expand All @@ -1375,14 +1479,20 @@ my class MASTCompilerInstance {
'getregref_i',
'getregref_n32',
'getregref_n',
'getregref_s'
'getregref_s',
'', '', '', '', '', '', '', '', '',
'getregref_u8',
'getregref_u16',
'getregref_u32',
'getregref_u'
];

my @decont_opnames := [
'decont_i',
'decont_n',
'decont_s',
'decont'
'decont',
'decont_u'
];

multi method compile_node(QAST::Var $node, :$want) {
Expand Down Expand Up @@ -1986,7 +2096,6 @@ my class MASTCompilerInstance {
$ilist.result_reg, $ilist.result_kind)
}

my @prim_to_reg := [$MVM_reg_obj, $MVM_reg_int64, $MVM_reg_num64, $MVM_reg_str];
method type_to_register_kind($type) {
if nqp::isnull($type) {
$MVM_reg_obj
Expand All @@ -1998,11 +2107,20 @@ my class MASTCompilerInstance {
}
elsif $primspec == 1 {
my int $size := nqp::objprimbits($type);
if $size == 64 { $MVM_reg_int64 }
elsif $size == 32 { $MVM_reg_int32 }
elsif $size == 16 { $MVM_reg_int16 }
elsif $size == 8 { $MVM_reg_int8 }
else { nqp::die("Unknown int size $size") }
if nqp::objprimunsigned($type) {
if $size == 64 { $MVM_reg_uint64 }
elsif $size == 32 { $MVM_reg_uint32 }
elsif $size == 16 { $MVM_reg_uint16 }
elsif $size == 8 { $MVM_reg_uint8 }
else { nqp::die("Unknown int size $size") }
}
else {
if $size == 64 { $MVM_reg_int64 }
elsif $size == 32 { $MVM_reg_int32 }
elsif $size == 16 { $MVM_reg_int16 }
elsif $size == 8 { $MVM_reg_int8 }
else { nqp::die("Unknown int size $size") }
}
}
elsif $primspec == 2 {
my int $size := nqp::objprimbits($type);
Expand Down
27 changes: 24 additions & 3 deletions src/vm/moar/QAST/QASTOperationsMAST.nqp
Expand Up @@ -443,7 +443,8 @@ class QAST::MASTOperations {

# Adds a HLL box handler.
method add_hll_box(str $hll, $type, $handler) {
unless $type == $MVM_reg_int64 || $type == $MVM_reg_num64 || $type == $MVM_reg_str || $type == $MVM_reg_void {
unless $type == $MVM_reg_int64 || $type == $MVM_reg_num64 || $type == $MVM_reg_str ||
$type == $MVM_reg_uint64 || $type == $MVM_reg_void {
nqp::die("Unknown box type '$type'");
}
%hll_box{$hll} := {} unless nqp::existskey(%hll_box, $hll);
Expand All @@ -452,7 +453,8 @@ class QAST::MASTOperations {

# Adds a HLL unbox handler.
method add_hll_unbox(str $hll, $type, $handler) {
unless $type == $MVM_reg_int64 || $type == $MVM_reg_num64 || $type == $MVM_reg_str {
unless $type == $MVM_reg_int64 || $type == $MVM_reg_num64 ||
$type == $MVM_reg_str || $type == $MVM_reg_uint64 {
nqp::die("Unknown unbox type '$type'");
}
%hll_unbox{$hll} := {} unless nqp::existskey(%hll_unbox, $hll);
Expand Down Expand Up @@ -1332,7 +1334,9 @@ sub handle_arg($arg, $qastcomp, @ins, @arg_regs, @arg_flags, @arg_kinds) {
$arg_mast := $qastcomp.coerce($arg_mast, $MVM_reg_num64);
}
elsif $arg_mast_kind == $MVM_reg_int32 || $arg_mast_kind == $MVM_reg_int16 ||
$arg_mast_kind == $MVM_reg_int8 {
$arg_mast_kind == $MVM_reg_int8 || $arg_mast_kind == $MVM_reg_uint64 ||
$arg_mast_kind == $MVM_reg_uint32 || $arg_mast_kind == $MVM_reg_uint16 ||
$arg_mast_kind == $MVM_reg_uint8 {
$arg_mast := $qastcomp.coerce($arg_mast, $MVM_reg_int64);
}

Expand Down Expand Up @@ -1804,6 +1808,20 @@ QAST::MASTOperations.add_hll_unbox('', $MVM_reg_str, -> $qastcomp, $reg {
$regalloc.release_register($dc, $MVM_reg_obj);
MAST::InstructionList.new($il, $res_reg, $MVM_reg_str)
});
QAST::MASTOperations.add_hll_unbox('', $MVM_reg_uint64, -> $qastcomp, $reg {
my $regalloc := $*REGALLOC;
my $il := nqp::list();
my $a := $regalloc.fresh_register($MVM_reg_num64);
my $b := $regalloc.fresh_register($MVM_reg_uint64);
$regalloc.release_register($reg, $MVM_reg_obj);
my $dc := $regalloc.fresh_register($MVM_reg_obj);
push_op($il, 'decont', $dc, $reg);
push_op($il, 'smrt_numify', $a, $dc);
push_op($il, 'coerce_nu', $b, $a);
$regalloc.release_register($a, $MVM_reg_num64);
$regalloc.release_register($dc, $MVM_reg_obj);
MAST::InstructionList.new($il, $b, $MVM_reg_int64)
});
sub boxer($kind, $type_op, $op) {
-> $qastcomp, $reg {
my $regalloc := $*REGALLOC;
Expand All @@ -1818,6 +1836,7 @@ sub boxer($kind, $type_op, $op) {
QAST::MASTOperations.add_hll_box('', $MVM_reg_int64, boxer($MVM_reg_int64, 'hllboxtype_i', 'box_i'));
QAST::MASTOperations.add_hll_box('', $MVM_reg_num64, boxer($MVM_reg_num64, 'hllboxtype_n', 'box_n'));
QAST::MASTOperations.add_hll_box('', $MVM_reg_str, boxer($MVM_reg_str, 'hllboxtype_s', 'box_s'));
QAST::MASTOperations.add_hll_box('', $MVM_reg_uint64, boxer($MVM_reg_uint64, 'hllboxtype_i', 'box_u'));
QAST::MASTOperations.add_hll_box('', $MVM_reg_void, -> $qastcomp, $reg {
my $il := nqp::list();
my $res_reg := $*REGALLOC.fresh_register($MVM_reg_obj);
Expand Down Expand Up @@ -2553,9 +2572,11 @@ QAST::MASTOperations.add_core_moarop_mapping('hintfor', 'hintfor');
QAST::MASTOperations.add_core_moarop_mapping('unbox_i', 'unbox_i', :decont(0));
QAST::MASTOperations.add_core_moarop_mapping('unbox_n', 'unbox_n', :decont(0));
QAST::MASTOperations.add_core_moarop_mapping('unbox_s', 'unbox_s', :decont(0));
QAST::MASTOperations.add_core_moarop_mapping('unbox_u', 'unbox_u', :decont(0));
QAST::MASTOperations.add_core_moarop_mapping('box_i', 'box_i');
QAST::MASTOperations.add_core_moarop_mapping('box_n', 'box_n');
QAST::MASTOperations.add_core_moarop_mapping('box_s', 'box_s');
QAST::MASTOperations.add_core_moarop_mapping('box_u', 'box_u');
QAST::MASTOperations.add_core_moarop_mapping('can', 'can_s', :decont(0));
QAST::MASTOperations.add_core_moarop_mapping('reprname', 'reprname', :decont(0));
QAST::MASTOperations.add_core_moarop_mapping('newtype', 'newtype', :decont(0));
Expand Down

0 comments on commit a31a3d0

Please sign in to comment.