Skip to content

Commit 11c3a8c

Browse files
[asmgen] bugfixes in const_indexing_aggregates_function (#6834)
## Description Fixes #6810, fixes #6812 and fixes #6813 --------- Co-authored-by: Joshua Batty <joshpbatty@gmail.com>
1 parent a67e9a9 commit 11c3a8c

File tree

9 files changed

+217
-82
lines changed

9 files changed

+217
-82
lines changed

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

+6-2
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,9 @@ impl FuelAsmBuilder<'_, '_> {
902902
todo!("Enormous stack usage for locals.");
903903
}
904904
self.cur_bytecode.push(Op {
905-
opcode: Either::Left(VirtualOp::CFEI(VirtualImmediate24 {
905+
opcode: Either::Left(VirtualOp::CFEI(
906+
VirtualRegister::Constant(ConstantRegister::StackPointer),
907+
VirtualImmediate24 {
906908
value: locals_size_bytes as u32 + (max_num_extra_args * 8) as u32,
907909
})),
908910
comment: format!("allocate {locals_size_bytes} bytes for locals and {max_num_extra_args} slots for call arguments"),
@@ -1053,7 +1055,9 @@ impl FuelAsmBuilder<'_, '_> {
10531055
todo!("Enormous stack usage for locals.");
10541056
}
10551057
self.cur_bytecode.push(Op {
1056-
opcode: Either::Left(VirtualOp::CFSI(VirtualImmediate24 {
1058+
opcode: Either::Left(
1059+
VirtualOp::CFSI(VirtualRegister::Constant(ConstantRegister::StackPointer),
1060+
VirtualImmediate24 {
10571061
value: u32::try_from(locals_size_bytes + (max_num_extra_args * 8)).unwrap(),
10581062
})),
10591063
comment: format!("free {locals_size_bytes} bytes for locals and {max_num_extra_args} slots for extra call arguments"),

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

+17-18
Original file line numberDiff line numberDiff line change
@@ -145,25 +145,23 @@ impl AbstractInstructionSet {
145145
}
146146
VirtualOp::LW(dest, addr_reg, imm) => match reg_contents.get(addr_reg) {
147147
Some(RegContents::BaseOffset(base_reg, offset))
148-
if get_def_version(&latest_version, &base_reg.reg)
149-
== base_reg.ver
148+
if offset % 8 == 0
149+
&& get_def_version(&latest_version, &base_reg.reg)
150+
== base_reg.ver
150151
&& ((offset / 8) + imm.value as u64)
151152
< compiler_constants::TWELVE_BITS =>
152153
{
153-
// bail if LW cannot read where this memory is
154-
if offset % 8 == 0 {
155-
let new_imm = VirtualImmediate12::new_unchecked(
156-
(offset / 8) + imm.value as u64,
157-
"Immediate offset too big for LW",
158-
);
159-
let new_lw =
160-
VirtualOp::LW(dest.clone(), base_reg.reg.clone(), new_imm);
161-
// The register defined is no more useful for us. Forget anything from its past.
162-
reg_contents.remove(dest);
163-
record_new_def(&mut latest_version, dest);
164-
// Replace the LW with a new one in-place.
165-
*op = new_lw;
166-
}
154+
let new_imm = VirtualImmediate12::new_unchecked(
155+
(offset / 8) + imm.value as u64,
156+
"Immediate offset too big for LW",
157+
);
158+
let new_lw =
159+
VirtualOp::LW(dest.clone(), base_reg.reg.clone(), new_imm);
160+
// The register defined is no more useful for us. Forget anything from its past.
161+
reg_contents.remove(dest);
162+
record_new_def(&mut latest_version, dest);
163+
// Replace the LW with a new one in-place.
164+
*op = new_lw;
167165
}
168166
_ => {
169167
reg_contents.remove(dest);
@@ -172,8 +170,9 @@ impl AbstractInstructionSet {
172170
},
173171
VirtualOp::SW(addr_reg, src, imm) => match reg_contents.get(addr_reg) {
174172
Some(RegContents::BaseOffset(base_reg, offset))
175-
if get_def_version(&latest_version, &base_reg.reg)
176-
== base_reg.ver
173+
if offset % 8 == 0
174+
&& get_def_version(&latest_version, &base_reg.reg)
175+
== base_reg.ver
177176
&& ((offset / 8) + imm.value as u64)
178177
< compiler_constants::TWELVE_BITS =>
179178
{

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

+20-11
Original file line numberDiff line numberDiff line change
@@ -714,11 +714,11 @@ fn spill(ops: &[Op], spills: &FxHashSet<VirtualRegister>) -> Vec<Op> {
714714
let mut cfs_idx_opt = None;
715715
for (op_idx, op) in ops.iter().enumerate() {
716716
match &op.opcode {
717-
Either::Left(VirtualOp::CFEI(_)) => {
717+
Either::Left(VirtualOp::CFEI(..)) => {
718718
assert!(cfe_idx_opt.is_none(), "Found more than one stack extension");
719719
cfe_idx_opt = Some(op_idx);
720720
}
721-
Either::Left(VirtualOp::CFSI(_)) => {
721+
Either::Left(VirtualOp::CFSI(..)) => {
722722
assert!(cfs_idx_opt.is_none(), "Found more than one stack shrink");
723723
cfs_idx_opt = Some(op_idx);
724724
}
@@ -728,9 +728,12 @@ fn spill(ops: &[Op], spills: &FxHashSet<VirtualRegister>) -> Vec<Op> {
728728

729729
let cfe_idx = cfe_idx_opt.expect("Function does not have CFEI instruction for locals");
730730

731-
let Either::Left(VirtualOp::CFEI(VirtualImmediate24 {
732-
value: locals_size_bytes,
733-
})) = ops[cfe_idx].opcode
731+
let Either::Left(VirtualOp::CFEI(
732+
VirtualRegister::Constant(ConstantRegister::StackPointer),
733+
VirtualImmediate24 {
734+
value: locals_size_bytes,
735+
},
736+
)) = ops[cfe_idx].opcode
734737
else {
735738
panic!("Unexpected opcode");
736739
};
@@ -755,18 +758,24 @@ fn spill(ops: &[Op], spills: &FxHashSet<VirtualRegister>) -> Vec<Op> {
755758
if op_idx == cfe_idx {
756759
// This is the CFE instruction, use the new stack size.
757760
spilled.push(Op {
758-
opcode: Either::Left(VirtualOp::CFEI(VirtualImmediate24 {
759-
value: new_locals_byte_size,
760-
})),
761+
opcode: Either::Left(VirtualOp::CFEI(
762+
VirtualRegister::Constant(ConstantRegister::StackPointer),
763+
VirtualImmediate24 {
764+
value: new_locals_byte_size,
765+
},
766+
)),
761767
comment: op.comment.clone() + &format!(" and {spills_size} bytes for spills"),
762768
owning_span: op.owning_span.clone(),
763769
});
764770
} else if matches!(cfs_idx_opt, Some(cfs_idx) if cfs_idx == op_idx) {
765771
// This is the CFS instruction, use the new stack size.
766772
spilled.push(Op {
767-
opcode: Either::Left(VirtualOp::CFSI(VirtualImmediate24 {
768-
value: new_locals_byte_size,
769-
})),
773+
opcode: Either::Left(VirtualOp::CFSI(
774+
VirtualRegister::Constant(ConstantRegister::StackPointer),
775+
VirtualImmediate24 {
776+
value: new_locals_byte_size,
777+
},
778+
)),
770779
comment: op.comment.clone() + &format!(" and {spills_size} bytes for spills"),
771780
owning_span: op.owning_span.clone(),
772781
});

sway-core/src/asm_lang/mod.rs

+26-11
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,10 @@ impl Op {
120120
size_to_allocate_in_bytes: VirtualImmediate24,
121121
) -> Self {
122122
Op {
123-
opcode: Either::Left(VirtualOp::CFEI(size_to_allocate_in_bytes)),
123+
opcode: Either::Left(VirtualOp::CFEI(
124+
VirtualRegister::Constant(ConstantRegister::StackPointer),
125+
size_to_allocate_in_bytes,
126+
)),
124127
comment: String::new(),
125128
owning_span: None,
126129
}
@@ -481,23 +484,35 @@ impl Op {
481484
/* Memory Instructions */
482485
"aloc" => {
483486
let r1 = single_reg(handler, args, immediate, whole_op_span)?;
484-
VirtualOp::ALOC(r1)
487+
VirtualOp::ALOC(VirtualRegister::Constant(ConstantRegister::HeapPointer), r1)
485488
}
486489
"cfei" => {
487490
let imm = single_imm_24(handler, args, immediate, whole_op_span)?;
488-
VirtualOp::CFEI(imm)
491+
VirtualOp::CFEI(
492+
VirtualRegister::Constant(ConstantRegister::StackPointer),
493+
imm,
494+
)
489495
}
490496
"cfsi" => {
491497
let imm = single_imm_24(handler, args, immediate, whole_op_span)?;
492-
VirtualOp::CFSI(imm)
498+
VirtualOp::CFSI(
499+
VirtualRegister::Constant(ConstantRegister::StackPointer),
500+
imm,
501+
)
493502
}
494503
"cfe" => {
495504
let r1 = single_reg(handler, args, immediate, whole_op_span)?;
496-
VirtualOp::CFE(r1)
505+
VirtualOp::CFE(
506+
VirtualRegister::Constant(ConstantRegister::StackPointer),
507+
r1,
508+
)
497509
}
498510
"cfs" => {
499511
let r1 = single_reg(handler, args, immediate, whole_op_span)?;
500-
VirtualOp::CFS(r1)
512+
VirtualOp::CFS(
513+
VirtualRegister::Constant(ConstantRegister::StackPointer),
514+
r1,
515+
)
501516
}
502517
"lb" => {
503518
let (r1, r2, imm) = two_regs_imm_12(handler, args, immediate, whole_op_span)?;
@@ -1164,11 +1179,11 @@ impl fmt::Display for VirtualOp {
11641179
RET(a) => write!(fmtr, "ret {a}"),
11651180

11661181
/* Memory Instructions */
1167-
ALOC(a) => write!(fmtr, "aloc {a}"),
1168-
CFEI(a) => write!(fmtr, "cfei {a}"),
1169-
CFSI(a) => write!(fmtr, "cfsi {a}"),
1170-
CFE(a) => write!(fmtr, "cfe {a}"),
1171-
CFS(a) => write!(fmtr, "cfs {a}"),
1182+
ALOC(_hp, a) => write!(fmtr, "aloc {a}"),
1183+
CFEI(_sp, a) => write!(fmtr, "cfei {a}"),
1184+
CFSI(_sp, a) => write!(fmtr, "cfsi {a}"),
1185+
CFE(_sp, a) => write!(fmtr, "cfe {a}"),
1186+
CFS(_sp, a) => write!(fmtr, "cfs {a}"),
11721187
LB(a, b, c) => write!(fmtr, "lb {a} {b} {c}"),
11731188
LW(a, b, c) => write!(fmtr, "lw {a} {b} {c}"),
11741189
MCL(a, b) => write!(fmtr, "mcl {a} {b}"),

sway-core/src/asm_lang/virtual_ops.rs

+41-40
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ pub(crate) enum VirtualOp {
109109
RET(VirtualRegister),
110110

111111
/* Memory Instructions */
112-
ALOC(VirtualRegister),
113-
CFEI(VirtualImmediate24),
114-
CFSI(VirtualImmediate24),
115-
CFE(VirtualRegister),
116-
CFS(VirtualRegister),
112+
ALOC(VirtualRegister, VirtualRegister),
113+
CFEI(VirtualRegister, VirtualImmediate24),
114+
CFSI(VirtualRegister, VirtualImmediate24),
115+
CFE(VirtualRegister, VirtualRegister),
116+
CFS(VirtualRegister, VirtualRegister),
117117
LB(VirtualRegister, VirtualRegister, VirtualImmediate12),
118118
LW(VirtualRegister, VirtualRegister, VirtualImmediate12),
119119
MCL(VirtualRegister, VirtualRegister),
@@ -290,11 +290,11 @@ impl VirtualOp {
290290
RET(r1) => vec![r1],
291291

292292
/* Memory Instructions */
293-
ALOC(r1) => vec![r1],
294-
CFEI(_imm) => vec![],
295-
CFSI(_imm) => vec![],
296-
CFE(r1) => vec![r1],
297-
CFS(r1) => vec![r1],
293+
ALOC(hp, r1) => vec![hp, r1],
294+
CFEI(sp, _imm) => vec![sp],
295+
CFSI(sp, _imm) => vec![sp],
296+
CFE(sp, r1) => vec![sp, r1],
297+
CFS(sp, r1) => vec![sp, r1],
298298
LB(r1, r2, _i) => vec![r1, r2],
299299
LW(r1, r2, _i) => vec![r1, r2],
300300
MCL(r1, r2) => vec![r1, r2],
@@ -425,11 +425,11 @@ impl VirtualOp {
425425
| JNEI(_, _, _)
426426
| JNZI(_, _)
427427
| RET(_)
428-
| ALOC(_)
429-
| CFEI(_)
430-
| CFSI(_)
431-
| CFE(_)
432-
| CFS(_)
428+
| ALOC(..)
429+
| CFEI(..)
430+
| CFSI(..)
431+
| CFE(..)
432+
| CFS(..)
433433
| MCL(_, _)
434434
| MCLI(_, _)
435435
| MCP(_, _, _)
@@ -522,17 +522,17 @@ impl VirtualOp {
522522
| ED19(_, _, _, _)
523523
=> vec![&VirtualRegister::Constant(Overflow), &VirtualRegister::Constant(Error)],
524524
FLAG(_) => vec![&VirtualRegister::Constant(Flags)],
525+
| ALOC(hp, _) => vec![hp],
526+
| CFEI(sp, _)
527+
| CFSI(sp, _)
528+
| CFE(sp, _)
529+
| CFS(sp, _) => vec![sp],
525530
JMP(_)
526531
| JI(_)
527532
| JNE(_, _, _)
528533
| JNEI(_, _, _)
529534
| JNZI(_, _)
530535
| RET(_)
531-
| ALOC(_)
532-
| CFEI(_)
533-
| CFSI(_)
534-
| CFE(_)
535-
| CFS(_)
536536
| LB(_, _, _)
537537
| LW(_, _, _)
538538
| MCL(_, _)
@@ -638,11 +638,11 @@ impl VirtualOp {
638638
RET(r1) => vec![r1],
639639

640640
/* Memory Instructions */
641-
ALOC(r1) => vec![r1],
642-
CFEI(_imm) => vec![],
643-
CFSI(_imm) => vec![],
644-
CFE(r1) => vec![r1],
645-
CFS(r1) => vec![r1],
641+
ALOC(hp, r1) => vec![hp, r1],
642+
CFEI(sp, _imm) => vec![sp],
643+
CFSI(sp, _imm) => vec![sp],
644+
CFE(sp, r1) => vec![sp, r1],
645+
CFS(sp, r1) => vec![sp, r1],
646646
LB(_r1, r2, _i) => vec![r2],
647647
LW(_r1, r2, _i) => vec![r2],
648648
MCL(r1, r2) => vec![r1, r2],
@@ -760,11 +760,11 @@ impl VirtualOp {
760760
RET(_r1) => vec![],
761761

762762
/* Memory Instructions */
763-
ALOC(_r1) => vec![],
764-
CFEI(_imm) => vec![],
765-
CFSI(_imm) => vec![],
766-
CFE(_r1) => vec![],
767-
CFS(_r1) => vec![],
763+
ALOC(hp, _r1) => vec![hp],
764+
CFEI(sp, _imm) => vec![sp],
765+
CFSI(sp, _imm) => vec![sp],
766+
CFE(sp, _r1) => vec![sp],
767+
CFS(sp, _r1) => vec![sp],
768768
LB(r1, _r2, _i) => vec![r1],
769769
LW(r1, _r2, _i) => vec![r1],
770770
MCL(_r1, _r2) => vec![],
@@ -1060,11 +1060,11 @@ impl VirtualOp {
10601060
RET(r1) => Self::RET(update_reg(reg_to_reg_map, r1)),
10611061

10621062
/* Memory Instructions */
1063-
ALOC(r1) => Self::ALOC(update_reg(reg_to_reg_map, r1)),
1064-
CFEI(i) => Self::CFEI(i.clone()),
1065-
CFSI(i) => Self::CFSI(i.clone()),
1066-
CFE(r1) => Self::CFE(update_reg(reg_to_reg_map, r1)),
1067-
CFS(r1) => Self::CFS(update_reg(reg_to_reg_map, r1)),
1063+
ALOC(hp, r1) => Self::ALOC(hp.clone(), update_reg(reg_to_reg_map, r1)),
1064+
CFEI(sp, i) => Self::CFEI(sp.clone(), i.clone()),
1065+
CFSI(sp, i) => Self::CFSI(sp.clone(), i.clone()),
1066+
CFE(sp, r1) => Self::CFE(sp.clone(), update_reg(reg_to_reg_map, r1)),
1067+
CFS(sp, r1) => Self::CFS(sp.clone(), update_reg(reg_to_reg_map, r1)),
10681068
LB(r1, r2, i) => Self::LB(
10691069
update_reg(reg_to_reg_map, r1),
10701070
update_reg(reg_to_reg_map, r2),
@@ -1550,11 +1550,11 @@ impl VirtualOp {
15501550
RET(reg) => AllocatedOpcode::RET(map_reg(&mapping, reg)),
15511551

15521552
/* Memory Instructions */
1553-
ALOC(reg) => AllocatedOpcode::ALOC(map_reg(&mapping, reg)),
1554-
CFEI(imm) => AllocatedOpcode::CFEI(imm.clone()),
1555-
CFSI(imm) => AllocatedOpcode::CFSI(imm.clone()),
1556-
CFE(reg) => AllocatedOpcode::CFE(map_reg(&mapping, reg)),
1557-
CFS(reg) => AllocatedOpcode::CFS(map_reg(&mapping, reg)),
1553+
ALOC(_hp, reg) => AllocatedOpcode::ALOC(map_reg(&mapping, reg)),
1554+
CFEI(_sp, imm) => AllocatedOpcode::CFEI(imm.clone()),
1555+
CFSI(_sp, imm) => AllocatedOpcode::CFSI(imm.clone()),
1556+
CFE(_sp, reg) => AllocatedOpcode::CFE(map_reg(&mapping, reg)),
1557+
CFS(_sp, reg) => AllocatedOpcode::CFS(map_reg(&mapping, reg)),
15581558
LB(reg1, reg2, imm) => AllocatedOpcode::LB(
15591559
map_reg(&mapping, reg1),
15601560
map_reg(&mapping, reg2),
@@ -1775,6 +1775,7 @@ fn update_reg(
17751775
reg: &VirtualRegister,
17761776
) -> VirtualRegister {
17771777
if let Some(r) = reg_to_reg_map.get(reg) {
1778+
assert!(reg.is_virtual(), "Only virtual registers should be updated");
17781779
(*r).into()
17791780
} else {
17801781
reg.clone()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[[package]]
2+
name = "const_indexing_aggregates_asmgen"
3+
source = "member"
4+
dependencies = ["std"]
5+
6+
[[package]]
7+
name = "core"
8+
source = "path+from-root-BA8D9B16C05D491F"
9+
10+
[[package]]
11+
name = "std"
12+
source = "path+from-root-BA8D9B16C05D491F"
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 = "const_indexing_aggregates_asmgen"
6+
7+
[dependencies]
8+
std = { path = "../../../../reduced_std_libs/sway-lib-std-assert" }

0 commit comments

Comments
 (0)