Skip to content

Commit 041d35b

Browse files
authored
fix: Fix rotl/rotr builtins for small integers (#1494)
1 parent a373d93 commit 041d35b

File tree

4 files changed

+193
-106
lines changed

4 files changed

+193
-106
lines changed

src/builtins.ts

+42-16
Original file line numberDiff line numberDiff line change
@@ -1126,8 +1126,8 @@ function builtin_popcnt(ctx: BuiltinContext): ExpressionRef {
11261126
var type = compiler.currentType;
11271127
if (type.isValue) {
11281128
switch (compiler.currentType.kind) {
1129-
case TypeKind.BOOL: // not wrapped
1130-
case TypeKind.I8:
1129+
case TypeKind.BOOL: return arg0;
1130+
case TypeKind.I8: // not wrapped
11311131
case TypeKind.U8:
11321132
case TypeKind.I16:
11331133
case TypeKind.U16:
@@ -1171,14 +1171,27 @@ function builtin_rotl(ctx: BuiltinContext): ExpressionRef {
11711171
if (type.isValue) {
11721172
let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT);
11731173
switch (type.kind) {
1174+
case TypeKind.BOOL: return arg0;
11741175
case TypeKind.I8:
11751176
case TypeKind.I16:
11761177
case TypeKind.U8:
1177-
case TypeKind.U16:
1178-
case TypeKind.BOOL: {
1179-
return compiler.ensureSmallIntegerWrap(
1180-
module.binary(BinaryOp.RotlI32, arg0, arg1),
1181-
type
1178+
case TypeKind.U16: {
1179+
// (value << (shift & mask)) | (value >>> ((0 - shift) & mask))
1180+
return module.binary(BinaryOp.OrI32,
1181+
module.binary(
1182+
BinaryOp.ShlI32,
1183+
arg0,
1184+
module.binary(BinaryOp.AndI32, arg1, module.i32(type.size - 1))
1185+
),
1186+
module.binary(
1187+
BinaryOp.ShrU32,
1188+
arg0,
1189+
module.binary(
1190+
BinaryOp.AndI32,
1191+
module.binary(BinaryOp.SubI32, module.i32(0), arg1),
1192+
module.i32(type.size - 1)
1193+
)
1194+
)
11821195
);
11831196
}
11841197
case TypeKind.I32:
@@ -1221,14 +1234,27 @@ function builtin_rotr(ctx: BuiltinContext): ExpressionRef {
12211234
if (type.isValue) {
12221235
let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT);
12231236
switch (type.kind) {
1237+
case TypeKind.BOOL: return arg0;
12241238
case TypeKind.I8:
12251239
case TypeKind.I16:
12261240
case TypeKind.U8:
1227-
case TypeKind.U16:
1228-
case TypeKind.BOOL: {
1229-
return compiler.ensureSmallIntegerWrap(
1230-
module.binary(BinaryOp.RotrI32, arg0, arg1),
1231-
type
1241+
case TypeKind.U16: {
1242+
// (value >>> (shift & mask)) | (value << ((0 - shift) & mask))
1243+
return module.binary(BinaryOp.OrI32,
1244+
module.binary(
1245+
BinaryOp.ShrU32,
1246+
arg0,
1247+
module.binary(BinaryOp.AndI32, arg1, module.i32(type.size - 1))
1248+
),
1249+
module.binary(
1250+
BinaryOp.ShlI32,
1251+
arg0,
1252+
module.binary(
1253+
BinaryOp.AndI32,
1254+
module.binary(BinaryOp.SubI32, module.i32(0), arg1),
1255+
module.i32(type.size - 1)
1256+
)
1257+
)
12321258
);
12331259
}
12341260
case TypeKind.I32:
@@ -2129,7 +2155,7 @@ function builtin_add(ctx: BuiltinContext): ExpressionRef {
21292155
{
21302156
op = BinaryOp.AddI32;
21312157
break;
2132-
}
2158+
}
21332159
case TypeKind.I64:
21342160
case TypeKind.U64: {
21352161
op = BinaryOp.AddI64;
@@ -2220,7 +2246,7 @@ function builtin_sub(ctx: BuiltinContext): ExpressionRef {
22202246
{
22212247
op = BinaryOp.SubI32;
22222248
break;
2223-
}
2249+
}
22242250
case TypeKind.I64:
22252251
case TypeKind.U64: {
22262252
op = BinaryOp.SubI64;
@@ -2311,7 +2337,7 @@ function builtin_mul(ctx: BuiltinContext): ExpressionRef {
23112337
{
23122338
op = BinaryOp.MulI32;
23132339
break;
2314-
}
2340+
}
23152341
case TypeKind.I64:
23162342
case TypeKind.U64: {
23172343
op = BinaryOp.MulI64;
@@ -3041,7 +3067,7 @@ function builtin_assert(ctx: BuiltinContext): ExpressionRef {
30413067
case TypeKind.EXTERNREF:
30423068
case TypeKind.EXNREF:
30433069
case TypeKind.ANYREF: return module.if(module.ref_is_null(arg0), abort);
3044-
3070+
30453071
}
30463072
} else {
30473073
compiler.currentType = type.nonNullableType;

tests/compiler/builtins.optimized.wat

+31-31
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@
503503
if
504504
i32.const 0
505505
i32.const 1088
506-
i32.const 294
506+
i32.const 298
507507
i32.const 1
508508
call $~lib/builtins/abort
509509
unreachable
@@ -518,7 +518,7 @@
518518
if
519519
i32.const 0
520520
i32.const 1088
521-
i32.const 295
521+
i32.const 299
522522
i32.const 1
523523
call $~lib/builtins/abort
524524
unreachable
@@ -530,7 +530,7 @@
530530
if
531531
i32.const 0
532532
i32.const 1088
533-
i32.const 296
533+
i32.const 300
534534
i32.const 1
535535
call $~lib/builtins/abort
536536
unreachable
@@ -542,7 +542,7 @@
542542
if
543543
i32.const 0
544544
i32.const 1088
545-
i32.const 299
545+
i32.const 303
546546
i32.const 1
547547
call $~lib/builtins/abort
548548
unreachable
@@ -621,7 +621,7 @@
621621
if
622622
i32.const 0
623623
i32.const 1088
624-
i32.const 475
624+
i32.const 479
625625
i32.const 1
626626
call $~lib/builtins/abort
627627
unreachable
@@ -633,7 +633,7 @@
633633
if
634634
i32.const 0
635635
i32.const 1088
636-
i32.const 476
636+
i32.const 480
637637
i32.const 1
638638
call $~lib/builtins/abort
639639
unreachable
@@ -645,7 +645,7 @@
645645
if
646646
i32.const 0
647647
i32.const 1088
648-
i32.const 477
648+
i32.const 481
649649
i32.const 1
650650
call $~lib/builtins/abort
651651
unreachable
@@ -655,7 +655,7 @@
655655
if
656656
i32.const 0
657657
i32.const 1088
658-
i32.const 478
658+
i32.const 482
659659
i32.const 1
660660
call $~lib/builtins/abort
661661
unreachable
@@ -667,7 +667,7 @@
667667
if
668668
i32.const 0
669669
i32.const 1088
670-
i32.const 479
670+
i32.const 483
671671
i32.const 1
672672
call $~lib/builtins/abort
673673
unreachable
@@ -677,7 +677,7 @@
677677
if
678678
i32.const 0
679679
i32.const 1088
680-
i32.const 480
680+
i32.const 484
681681
i32.const 1
682682
call $~lib/builtins/abort
683683
unreachable
@@ -687,7 +687,7 @@
687687
if
688688
i32.const 0
689689
i32.const 1088
690-
i32.const 481
690+
i32.const 485
691691
i32.const 1
692692
call $~lib/builtins/abort
693693
unreachable
@@ -707,7 +707,7 @@
707707
if
708708
i32.const 0
709709
i32.const 1088
710-
i32.const 498
710+
i32.const 502
711711
i32.const 3
712712
call $~lib/builtins/abort
713713
unreachable
@@ -719,7 +719,7 @@
719719
if
720720
i32.const 0
721721
i32.const 1088
722-
i32.const 499
722+
i32.const 503
723723
i32.const 3
724724
call $~lib/builtins/abort
725725
unreachable
@@ -731,7 +731,7 @@
731731
if
732732
i32.const 0
733733
i32.const 1088
734-
i32.const 500
734+
i32.const 504
735735
i32.const 3
736736
call $~lib/builtins/abort
737737
unreachable
@@ -743,7 +743,7 @@
743743
if
744744
i32.const 0
745745
i32.const 1088
746-
i32.const 501
746+
i32.const 505
747747
i32.const 3
748748
call $~lib/builtins/abort
749749
unreachable
@@ -755,7 +755,7 @@
755755
if
756756
i32.const 0
757757
i32.const 1088
758-
i32.const 502
758+
i32.const 506
759759
i32.const 3
760760
call $~lib/builtins/abort
761761
unreachable
@@ -767,7 +767,7 @@
767767
if
768768
i32.const 0
769769
i32.const 1088
770-
i32.const 503
770+
i32.const 507
771771
i32.const 3
772772
call $~lib/builtins/abort
773773
unreachable
@@ -779,7 +779,7 @@
779779
if
780780
i32.const 0
781781
i32.const 1088
782-
i32.const 504
782+
i32.const 508
783783
i32.const 3
784784
call $~lib/builtins/abort
785785
unreachable
@@ -791,7 +791,7 @@
791791
if
792792
i32.const 0
793793
i32.const 1088
794-
i32.const 505
794+
i32.const 509
795795
i32.const 3
796796
call $~lib/builtins/abort
797797
unreachable
@@ -803,7 +803,7 @@
803803
if
804804
i32.const 0
805805
i32.const 1088
806-
i32.const 506
806+
i32.const 510
807807
i32.const 3
808808
call $~lib/builtins/abort
809809
unreachable
@@ -815,7 +815,7 @@
815815
if
816816
i32.const 0
817817
i32.const 1088
818-
i32.const 507
818+
i32.const 511
819819
i32.const 3
820820
call $~lib/builtins/abort
821821
unreachable
@@ -827,7 +827,7 @@
827827
if
828828
i32.const 0
829829
i32.const 1088
830-
i32.const 508
830+
i32.const 512
831831
i32.const 3
832832
call $~lib/builtins/abort
833833
unreachable
@@ -839,7 +839,7 @@
839839
if
840840
i32.const 0
841841
i32.const 1088
842-
i32.const 509
842+
i32.const 513
843843
i32.const 3
844844
call $~lib/builtins/abort
845845
unreachable
@@ -851,7 +851,7 @@
851851
if
852852
i32.const 0
853853
i32.const 1088
854-
i32.const 510
854+
i32.const 514
855855
i32.const 3
856856
call $~lib/builtins/abort
857857
unreachable
@@ -863,7 +863,7 @@
863863
if
864864
i32.const 0
865865
i32.const 1088
866-
i32.const 511
866+
i32.const 515
867867
i32.const 3
868868
call $~lib/builtins/abort
869869
unreachable
@@ -875,7 +875,7 @@
875875
if
876876
i32.const 0
877877
i32.const 1088
878-
i32.const 512
878+
i32.const 516
879879
i32.const 3
880880
call $~lib/builtins/abort
881881
unreachable
@@ -887,7 +887,7 @@
887887
if
888888
i32.const 0
889889
i32.const 1088
890-
i32.const 513
890+
i32.const 517
891891
i32.const 3
892892
call $~lib/builtins/abort
893893
unreachable
@@ -899,7 +899,7 @@
899899
if
900900
i32.const 0
901901
i32.const 1088
902-
i32.const 514
902+
i32.const 518
903903
i32.const 3
904904
call $~lib/builtins/abort
905905
unreachable
@@ -911,7 +911,7 @@
911911
if
912912
i32.const 0
913913
i32.const 1088
914-
i32.const 515
914+
i32.const 519
915915
i32.const 3
916916
call $~lib/builtins/abort
917917
unreachable
@@ -923,7 +923,7 @@
923923
if
924924
i32.const 0
925925
i32.const 1088
926-
i32.const 516
926+
i32.const 520
927927
i32.const 3
928928
call $~lib/builtins/abort
929929
unreachable
@@ -935,7 +935,7 @@
935935
if
936936
i32.const 0
937937
i32.const 1088
938-
i32.const 517
938+
i32.const 521
939939
i32.const 3
940940
call $~lib/builtins/abort
941941
unreachable

0 commit comments

Comments
 (0)