Skip to content

Commit 81fda4c

Browse files
authored
fix: Small integer rotl/rotr should use temp variables
1 parent a4dc45e commit 81fda4c

File tree

2 files changed

+54
-14
lines changed

2 files changed

+54
-14
lines changed

Diff for: src/builtins.ts

+46-10
Original file line numberDiff line numberDiff line change
@@ -1177,22 +1177,40 @@ function builtin_rotl(ctx: BuiltinContext): ExpressionRef {
11771177
case TypeKind.U8:
11781178
case TypeKind.U16: {
11791179
// (value << (shift & mask)) | (value >>> ((0 - shift) & mask))
1180-
return module.binary(BinaryOp.OrI32,
1180+
let flow = compiler.currentFlow;
1181+
let temp1 = flow.getTempLocal(type);
1182+
flow.setLocalFlag(temp1.index, LocalFlags.WRAPPED);
1183+
let temp2 = flow.getTempLocal(type);
1184+
flow.setLocalFlag(temp2.index, LocalFlags.WRAPPED);
1185+
1186+
let ret = module.binary(BinaryOp.OrI32,
11811187
module.binary(
11821188
BinaryOp.ShlI32,
1183-
arg0,
1184-
module.binary(BinaryOp.AndI32, arg1, module.i32(type.size - 1))
1189+
module.local_tee(temp1.index, arg0),
1190+
module.binary(
1191+
BinaryOp.AndI32,
1192+
module.local_tee(temp2.index, arg1),
1193+
module.i32(type.size - 1)
1194+
)
11851195
),
11861196
module.binary(
11871197
BinaryOp.ShrU32,
1188-
arg0,
1198+
module.local_get(temp1.index, NativeType.I32),
11891199
module.binary(
11901200
BinaryOp.AndI32,
1191-
module.binary(BinaryOp.SubI32, module.i32(0), arg1),
1201+
module.binary(
1202+
BinaryOp.SubI32,
1203+
module.i32(0),
1204+
module.local_get(temp2.index, NativeType.I32)
1205+
),
11921206
module.i32(type.size - 1)
11931207
)
11941208
)
11951209
);
1210+
flow.freeTempLocal(temp2);
1211+
flow.freeTempLocal(temp1);
1212+
1213+
return ret;
11961214
}
11971215
case TypeKind.I32:
11981216
case TypeKind.U32: return module.binary(BinaryOp.RotlI32, arg0, arg1);
@@ -1240,22 +1258,40 @@ function builtin_rotr(ctx: BuiltinContext): ExpressionRef {
12401258
case TypeKind.U8:
12411259
case TypeKind.U16: {
12421260
// (value >>> (shift & mask)) | (value << ((0 - shift) & mask))
1243-
return module.binary(BinaryOp.OrI32,
1261+
let flow = compiler.currentFlow;
1262+
let temp1 = flow.getTempLocal(type);
1263+
flow.setLocalFlag(temp1.index, LocalFlags.WRAPPED);
1264+
let temp2 = flow.getTempLocal(type);
1265+
flow.setLocalFlag(temp2.index, LocalFlags.WRAPPED);
1266+
1267+
let ret = module.binary(BinaryOp.OrI32,
12441268
module.binary(
12451269
BinaryOp.ShrU32,
1246-
arg0,
1247-
module.binary(BinaryOp.AndI32, arg1, module.i32(type.size - 1))
1270+
module.local_tee(temp1.index, arg0),
1271+
module.binary(
1272+
BinaryOp.AndI32,
1273+
module.local_tee(temp2.index, arg1),
1274+
module.i32(type.size - 1)
1275+
)
12481276
),
12491277
module.binary(
12501278
BinaryOp.ShlI32,
1251-
arg0,
1279+
module.local_get(temp1.index, NativeType.I32),
12521280
module.binary(
12531281
BinaryOp.AndI32,
1254-
module.binary(BinaryOp.SubI32, module.i32(0), arg1),
1282+
module.binary(
1283+
BinaryOp.SubI32,
1284+
module.i32(0),
1285+
module.local_get(temp2.index, NativeType.I32)
1286+
),
12551287
module.i32(type.size - 1)
12561288
)
12571289
)
12581290
);
1291+
flow.freeTempLocal(temp2);
1292+
flow.freeTempLocal(temp1);
1293+
1294+
return ret;
12591295
}
12601296
case TypeKind.I32:
12611297
case TypeKind.U32: return module.binary(BinaryOp.RotrI32, arg0, arg1);

Diff for: tests/compiler/builtins.untouched.wat

+8-4
Original file line numberDiff line numberDiff line change
@@ -502,13 +502,15 @@
502502
unreachable
503503
end
504504
i32.const 143
505+
local.tee $0
505506
i32.const 3
507+
local.tee $1
506508
i32.const 7
507509
i32.and
508510
i32.shl
509-
i32.const 143
511+
local.get $0
510512
i32.const 0
511-
i32.const 3
513+
local.get $1
512514
i32.sub
513515
i32.const 7
514516
i32.and
@@ -530,13 +532,15 @@
530532
unreachable
531533
end
532534
i32.const 170
535+
local.tee $0
533536
i32.const 1
537+
local.tee $1
534538
i32.const 7
535539
i32.and
536540
i32.shr_u
537-
i32.const 170
541+
local.get $0
538542
i32.const 0
539-
i32.const 1
543+
local.get $1
540544
i32.sub
541545
i32.const 7
542546
i32.and

0 commit comments

Comments
 (0)