Skip to content

Commit a67e9a9

Browse files
authored
[asmgen] pushing / popping registers for call should handle all def'd regs (#6826)
Fixes #6814
1 parent 9cd1b39 commit a67e9a9

File tree

5 files changed

+86
-6
lines changed

5 files changed

+86
-6
lines changed

sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -78,21 +78,21 @@ impl AllocatedAbstractInstructionSet {
7878
.fold(
7979
(IndexMap::new(), IndexSet::new()),
8080
|(mut reg_sets, mut active_sets), op| {
81-
let reg = match &op.opcode {
81+
let regs: Box<dyn Iterator<Item = &AllocatedRegister>> = match &op.opcode {
8282
Either::Right(ControlFlowOp::PushAll(label)) => {
8383
active_sets.insert(*label);
84-
None
84+
Box::new(std::iter::empty())
8585
}
8686
Either::Right(ControlFlowOp::PopAll(label)) => {
8787
active_sets.swap_remove(label);
88-
None
88+
Box::new(std::iter::empty())
8989
}
9090

91-
Either::Left(alloc_op) => alloc_op.def_registers().into_iter().next(),
92-
Either::Right(ctrl_op) => ctrl_op.def_registers().into_iter().next(),
91+
Either::Left(alloc_op) => Box::new(alloc_op.def_registers().into_iter()),
92+
Either::Right(ctrl_op) => Box::new(ctrl_op.def_registers().into_iter()),
9393
};
9494

95-
if let Some(reg) = reg {
95+
for reg in regs {
9696
for active_label in active_sets.clone() {
9797
reg_sets
9898
.entry(active_label)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[[package]]
2+
name = "core"
3+
source = "path+from-root-B299C98691745B40"
4+
5+
[[package]]
6+
name = "pusha_popa_multiple_defreg"
7+
source = "member"
8+
dependencies = ["std"]
9+
10+
[[package]]
11+
name = "std"
12+
source = "path+from-root-B299C98691745B40"
13+
dependencies = ["core"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[project]
2+
authors = ["Fuel Labs <contact@fuel.sh>"]
3+
entry = "main.sw"
4+
license = "Apache-2.0"
5+
name = "pusha_popa_multiple_defreg"
6+
7+
[dependencies]
8+
std = { path = "../../../../reduced_std_libs/sway-lib-std-assert" }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
contract;
2+
3+
abi IncorrectPushaPopa {
4+
#[storage(read)]
5+
fn incorrect_pusha_popa() -> ();
6+
}
7+
8+
impl IncorrectPushaPopa for Contract {
9+
#[storage(read)]
10+
fn incorrect_pusha_popa() -> () {
11+
setup();
12+
()
13+
}
14+
}
15+
16+
#[storage(read)]
17+
fn setup() -> () {
18+
let a: u64 = 1;
19+
let b: u64 = 1;
20+
let c: u64 = 1;
21+
//call a few times to avoid inline
22+
store_read();
23+
let r = asm(r, a: a, b: b, c: c, d: store_read()) {
24+
movi r i0;
25+
add r a b; // r = a + b = 2
26+
add r r c; // r = a + b + c = 3 c value is overwritten by store_read, so we get 2 instead
27+
add r r d; // r = a + b + c + d = 3 d returns 0
28+
r
29+
};
30+
assert(r == 3);
31+
()
32+
}
33+
34+
#[storage(read)]
35+
fn store_read() -> u64 {
36+
let a = asm(slot, a, b, c) {
37+
movi c i32;
38+
aloc c;
39+
move slot hp;
40+
srw a b slot; // somehow make b allocate to $r3
41+
movi c i0;
42+
add a a slot;
43+
sub a a slot;
44+
add a a b;
45+
add a a c;
46+
a
47+
};
48+
a - a // return 0 and make sure a is not dced
49+
}
50+
51+
#[test]
52+
fn incorrect_pusha_popa() -> () {
53+
let c = abi(IncorrectPushaPopa, CONTRACT_ID);
54+
c.incorrect_pusha_popa();
55+
()
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
category = "unit_tests_pass"
2+
validate_abi = false
3+
expected_warnings = 0

0 commit comments

Comments
 (0)