Skip to content

Commit

Permalink
Merge branch 'master' into ironcev/forc-migrate-tool
Browse files Browse the repository at this point in the history
  • Loading branch information
ironcev authored Jan 18, 2025
2 parents df8a28c + 11c3a8c commit 977ab63
Show file tree
Hide file tree
Showing 14 changed files with 303 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,21 @@ impl AllocatedAbstractInstructionSet {
.fold(
(IndexMap::new(), IndexSet::new()),
|(mut reg_sets, mut active_sets), op| {
let reg = match &op.opcode {
let regs: Box<dyn Iterator<Item = &AllocatedRegister>> = match &op.opcode {
Either::Right(ControlFlowOp::PushAll(label)) => {
active_sets.insert(*label);
None
Box::new(std::iter::empty())
}
Either::Right(ControlFlowOp::PopAll(label)) => {
active_sets.swap_remove(label);
None
Box::new(std::iter::empty())
}

Either::Left(alloc_op) => alloc_op.def_registers().into_iter().next(),
Either::Right(ctrl_op) => ctrl_op.def_registers().into_iter().next(),
Either::Left(alloc_op) => Box::new(alloc_op.def_registers().into_iter()),
Either::Right(ctrl_op) => Box::new(ctrl_op.def_registers().into_iter()),
};

if let Some(reg) = reg {
for reg in regs {
for active_label in active_sets.clone() {
reg_sets
.entry(active_label)
Expand Down
8 changes: 6 additions & 2 deletions sway-core/src/asm_generation/fuel/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,9 @@ impl FuelAsmBuilder<'_, '_> {
todo!("Enormous stack usage for locals.");
}
self.cur_bytecode.push(Op {
opcode: Either::Left(VirtualOp::CFEI(VirtualImmediate24 {
opcode: Either::Left(VirtualOp::CFEI(
VirtualRegister::Constant(ConstantRegister::StackPointer),
VirtualImmediate24 {
value: locals_size_bytes as u32 + (max_num_extra_args * 8) as u32,
})),
comment: format!("allocate {locals_size_bytes} bytes for locals and {max_num_extra_args} slots for call arguments"),
Expand Down Expand Up @@ -1053,7 +1055,9 @@ impl FuelAsmBuilder<'_, '_> {
todo!("Enormous stack usage for locals.");
}
self.cur_bytecode.push(Op {
opcode: Either::Left(VirtualOp::CFSI(VirtualImmediate24 {
opcode: Either::Left(
VirtualOp::CFSI(VirtualRegister::Constant(ConstantRegister::StackPointer),
VirtualImmediate24 {
value: u32::try_from(locals_size_bytes + (max_num_extra_args * 8)).unwrap(),
})),
comment: format!("free {locals_size_bytes} bytes for locals and {max_num_extra_args} slots for extra call arguments"),
Expand Down
35 changes: 17 additions & 18 deletions sway-core/src/asm_generation/fuel/optimizations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,25 +145,23 @@ impl AbstractInstructionSet {
}
VirtualOp::LW(dest, addr_reg, imm) => match reg_contents.get(addr_reg) {
Some(RegContents::BaseOffset(base_reg, offset))
if get_def_version(&latest_version, &base_reg.reg)
== base_reg.ver
if offset % 8 == 0
&& get_def_version(&latest_version, &base_reg.reg)
== base_reg.ver
&& ((offset / 8) + imm.value as u64)
< compiler_constants::TWELVE_BITS =>
{
// bail if LW cannot read where this memory is
if offset % 8 == 0 {
let new_imm = VirtualImmediate12::new_unchecked(
(offset / 8) + imm.value as u64,
"Immediate offset too big for LW",
);
let new_lw =
VirtualOp::LW(dest.clone(), base_reg.reg.clone(), new_imm);
// The register defined is no more useful for us. Forget anything from its past.
reg_contents.remove(dest);
record_new_def(&mut latest_version, dest);
// Replace the LW with a new one in-place.
*op = new_lw;
}
let new_imm = VirtualImmediate12::new_unchecked(
(offset / 8) + imm.value as u64,
"Immediate offset too big for LW",
);
let new_lw =
VirtualOp::LW(dest.clone(), base_reg.reg.clone(), new_imm);
// The register defined is no more useful for us. Forget anything from its past.
reg_contents.remove(dest);
record_new_def(&mut latest_version, dest);
// Replace the LW with a new one in-place.
*op = new_lw;
}
_ => {
reg_contents.remove(dest);
Expand All @@ -172,8 +170,9 @@ impl AbstractInstructionSet {
},
VirtualOp::SW(addr_reg, src, imm) => match reg_contents.get(addr_reg) {
Some(RegContents::BaseOffset(base_reg, offset))
if get_def_version(&latest_version, &base_reg.reg)
== base_reg.ver
if offset % 8 == 0
&& get_def_version(&latest_version, &base_reg.reg)
== base_reg.ver
&& ((offset / 8) + imm.value as u64)
< compiler_constants::TWELVE_BITS =>
{
Expand Down
31 changes: 20 additions & 11 deletions sway-core/src/asm_generation/fuel/register_allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,11 +714,11 @@ fn spill(ops: &[Op], spills: &FxHashSet<VirtualRegister>) -> Vec<Op> {
let mut cfs_idx_opt = None;
for (op_idx, op) in ops.iter().enumerate() {
match &op.opcode {
Either::Left(VirtualOp::CFEI(_)) => {
Either::Left(VirtualOp::CFEI(..)) => {
assert!(cfe_idx_opt.is_none(), "Found more than one stack extension");
cfe_idx_opt = Some(op_idx);
}
Either::Left(VirtualOp::CFSI(_)) => {
Either::Left(VirtualOp::CFSI(..)) => {
assert!(cfs_idx_opt.is_none(), "Found more than one stack shrink");
cfs_idx_opt = Some(op_idx);
}
Expand All @@ -728,9 +728,12 @@ fn spill(ops: &[Op], spills: &FxHashSet<VirtualRegister>) -> Vec<Op> {

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

let Either::Left(VirtualOp::CFEI(VirtualImmediate24 {
value: locals_size_bytes,
})) = ops[cfe_idx].opcode
let Either::Left(VirtualOp::CFEI(
VirtualRegister::Constant(ConstantRegister::StackPointer),
VirtualImmediate24 {
value: locals_size_bytes,
},
)) = ops[cfe_idx].opcode
else {
panic!("Unexpected opcode");
};
Expand All @@ -755,18 +758,24 @@ fn spill(ops: &[Op], spills: &FxHashSet<VirtualRegister>) -> Vec<Op> {
if op_idx == cfe_idx {
// This is the CFE instruction, use the new stack size.
spilled.push(Op {
opcode: Either::Left(VirtualOp::CFEI(VirtualImmediate24 {
value: new_locals_byte_size,
})),
opcode: Either::Left(VirtualOp::CFEI(
VirtualRegister::Constant(ConstantRegister::StackPointer),
VirtualImmediate24 {
value: new_locals_byte_size,
},
)),
comment: op.comment.clone() + &format!(" and {spills_size} bytes for spills"),
owning_span: op.owning_span.clone(),
});
} else if matches!(cfs_idx_opt, Some(cfs_idx) if cfs_idx == op_idx) {
// This is the CFS instruction, use the new stack size.
spilled.push(Op {
opcode: Either::Left(VirtualOp::CFSI(VirtualImmediate24 {
value: new_locals_byte_size,
})),
opcode: Either::Left(VirtualOp::CFSI(
VirtualRegister::Constant(ConstantRegister::StackPointer),
VirtualImmediate24 {
value: new_locals_byte_size,
},
)),
comment: op.comment.clone() + &format!(" and {spills_size} bytes for spills"),
owning_span: op.owning_span.clone(),
});
Expand Down
37 changes: 26 additions & 11 deletions sway-core/src/asm_lang/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ impl Op {
size_to_allocate_in_bytes: VirtualImmediate24,
) -> Self {
Op {
opcode: Either::Left(VirtualOp::CFEI(size_to_allocate_in_bytes)),
opcode: Either::Left(VirtualOp::CFEI(
VirtualRegister::Constant(ConstantRegister::StackPointer),
size_to_allocate_in_bytes,
)),
comment: String::new(),
owning_span: None,
}
Expand Down Expand Up @@ -481,23 +484,35 @@ impl Op {
/* Memory Instructions */
"aloc" => {
let r1 = single_reg(handler, args, immediate, whole_op_span)?;
VirtualOp::ALOC(r1)
VirtualOp::ALOC(VirtualRegister::Constant(ConstantRegister::HeapPointer), r1)
}
"cfei" => {
let imm = single_imm_24(handler, args, immediate, whole_op_span)?;
VirtualOp::CFEI(imm)
VirtualOp::CFEI(
VirtualRegister::Constant(ConstantRegister::StackPointer),
imm,
)
}
"cfsi" => {
let imm = single_imm_24(handler, args, immediate, whole_op_span)?;
VirtualOp::CFSI(imm)
VirtualOp::CFSI(
VirtualRegister::Constant(ConstantRegister::StackPointer),
imm,
)
}
"cfe" => {
let r1 = single_reg(handler, args, immediate, whole_op_span)?;
VirtualOp::CFE(r1)
VirtualOp::CFE(
VirtualRegister::Constant(ConstantRegister::StackPointer),
r1,
)
}
"cfs" => {
let r1 = single_reg(handler, args, immediate, whole_op_span)?;
VirtualOp::CFS(r1)
VirtualOp::CFS(
VirtualRegister::Constant(ConstantRegister::StackPointer),
r1,
)
}
"lb" => {
let (r1, r2, imm) = two_regs_imm_12(handler, args, immediate, whole_op_span)?;
Expand Down Expand Up @@ -1164,11 +1179,11 @@ impl fmt::Display for VirtualOp {
RET(a) => write!(fmtr, "ret {a}"),

/* Memory Instructions */
ALOC(a) => write!(fmtr, "aloc {a}"),
CFEI(a) => write!(fmtr, "cfei {a}"),
CFSI(a) => write!(fmtr, "cfsi {a}"),
CFE(a) => write!(fmtr, "cfe {a}"),
CFS(a) => write!(fmtr, "cfs {a}"),
ALOC(_hp, a) => write!(fmtr, "aloc {a}"),
CFEI(_sp, a) => write!(fmtr, "cfei {a}"),
CFSI(_sp, a) => write!(fmtr, "cfsi {a}"),
CFE(_sp, a) => write!(fmtr, "cfe {a}"),
CFS(_sp, a) => write!(fmtr, "cfs {a}"),
LB(a, b, c) => write!(fmtr, "lb {a} {b} {c}"),
LW(a, b, c) => write!(fmtr, "lw {a} {b} {c}"),
MCL(a, b) => write!(fmtr, "mcl {a} {b}"),
Expand Down
81 changes: 41 additions & 40 deletions sway-core/src/asm_lang/virtual_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ pub(crate) enum VirtualOp {
RET(VirtualRegister),

/* Memory Instructions */
ALOC(VirtualRegister),
CFEI(VirtualImmediate24),
CFSI(VirtualImmediate24),
CFE(VirtualRegister),
CFS(VirtualRegister),
ALOC(VirtualRegister, VirtualRegister),
CFEI(VirtualRegister, VirtualImmediate24),
CFSI(VirtualRegister, VirtualImmediate24),
CFE(VirtualRegister, VirtualRegister),
CFS(VirtualRegister, VirtualRegister),
LB(VirtualRegister, VirtualRegister, VirtualImmediate12),
LW(VirtualRegister, VirtualRegister, VirtualImmediate12),
MCL(VirtualRegister, VirtualRegister),
Expand Down Expand Up @@ -290,11 +290,11 @@ impl VirtualOp {
RET(r1) => vec![r1],

/* Memory Instructions */
ALOC(r1) => vec![r1],
CFEI(_imm) => vec![],
CFSI(_imm) => vec![],
CFE(r1) => vec![r1],
CFS(r1) => vec![r1],
ALOC(hp, r1) => vec![hp, r1],
CFEI(sp, _imm) => vec![sp],
CFSI(sp, _imm) => vec![sp],
CFE(sp, r1) => vec![sp, r1],
CFS(sp, r1) => vec![sp, r1],
LB(r1, r2, _i) => vec![r1, r2],
LW(r1, r2, _i) => vec![r1, r2],
MCL(r1, r2) => vec![r1, r2],
Expand Down Expand Up @@ -425,11 +425,11 @@ impl VirtualOp {
| JNEI(_, _, _)
| JNZI(_, _)
| RET(_)
| ALOC(_)
| CFEI(_)
| CFSI(_)
| CFE(_)
| CFS(_)
| ALOC(..)
| CFEI(..)
| CFSI(..)
| CFE(..)
| CFS(..)
| MCL(_, _)
| MCLI(_, _)
| MCP(_, _, _)
Expand Down Expand Up @@ -522,17 +522,17 @@ impl VirtualOp {
| ED19(_, _, _, _)
=> vec![&VirtualRegister::Constant(Overflow), &VirtualRegister::Constant(Error)],
FLAG(_) => vec![&VirtualRegister::Constant(Flags)],
| ALOC(hp, _) => vec![hp],
| CFEI(sp, _)
| CFSI(sp, _)
| CFE(sp, _)
| CFS(sp, _) => vec![sp],
JMP(_)
| JI(_)
| JNE(_, _, _)
| JNEI(_, _, _)
| JNZI(_, _)
| RET(_)
| ALOC(_)
| CFEI(_)
| CFSI(_)
| CFE(_)
| CFS(_)
| LB(_, _, _)
| LW(_, _, _)
| MCL(_, _)
Expand Down Expand Up @@ -638,11 +638,11 @@ impl VirtualOp {
RET(r1) => vec![r1],

/* Memory Instructions */
ALOC(r1) => vec![r1],
CFEI(_imm) => vec![],
CFSI(_imm) => vec![],
CFE(r1) => vec![r1],
CFS(r1) => vec![r1],
ALOC(hp, r1) => vec![hp, r1],
CFEI(sp, _imm) => vec![sp],
CFSI(sp, _imm) => vec![sp],
CFE(sp, r1) => vec![sp, r1],
CFS(sp, r1) => vec![sp, r1],
LB(_r1, r2, _i) => vec![r2],
LW(_r1, r2, _i) => vec![r2],
MCL(r1, r2) => vec![r1, r2],
Expand Down Expand Up @@ -760,11 +760,11 @@ impl VirtualOp {
RET(_r1) => vec![],

/* Memory Instructions */
ALOC(_r1) => vec![],
CFEI(_imm) => vec![],
CFSI(_imm) => vec![],
CFE(_r1) => vec![],
CFS(_r1) => vec![],
ALOC(hp, _r1) => vec![hp],
CFEI(sp, _imm) => vec![sp],
CFSI(sp, _imm) => vec![sp],
CFE(sp, _r1) => vec![sp],
CFS(sp, _r1) => vec![sp],
LB(r1, _r2, _i) => vec![r1],
LW(r1, _r2, _i) => vec![r1],
MCL(_r1, _r2) => vec![],
Expand Down Expand Up @@ -1060,11 +1060,11 @@ impl VirtualOp {
RET(r1) => Self::RET(update_reg(reg_to_reg_map, r1)),

/* Memory Instructions */
ALOC(r1) => Self::ALOC(update_reg(reg_to_reg_map, r1)),
CFEI(i) => Self::CFEI(i.clone()),
CFSI(i) => Self::CFSI(i.clone()),
CFE(r1) => Self::CFE(update_reg(reg_to_reg_map, r1)),
CFS(r1) => Self::CFS(update_reg(reg_to_reg_map, r1)),
ALOC(hp, r1) => Self::ALOC(hp.clone(), update_reg(reg_to_reg_map, r1)),
CFEI(sp, i) => Self::CFEI(sp.clone(), i.clone()),
CFSI(sp, i) => Self::CFSI(sp.clone(), i.clone()),
CFE(sp, r1) => Self::CFE(sp.clone(), update_reg(reg_to_reg_map, r1)),
CFS(sp, r1) => Self::CFS(sp.clone(), update_reg(reg_to_reg_map, r1)),
LB(r1, r2, i) => Self::LB(
update_reg(reg_to_reg_map, r1),
update_reg(reg_to_reg_map, r2),
Expand Down Expand Up @@ -1550,11 +1550,11 @@ impl VirtualOp {
RET(reg) => AllocatedOpcode::RET(map_reg(&mapping, reg)),

/* Memory Instructions */
ALOC(reg) => AllocatedOpcode::ALOC(map_reg(&mapping, reg)),
CFEI(imm) => AllocatedOpcode::CFEI(imm.clone()),
CFSI(imm) => AllocatedOpcode::CFSI(imm.clone()),
CFE(reg) => AllocatedOpcode::CFE(map_reg(&mapping, reg)),
CFS(reg) => AllocatedOpcode::CFS(map_reg(&mapping, reg)),
ALOC(_hp, reg) => AllocatedOpcode::ALOC(map_reg(&mapping, reg)),
CFEI(_sp, imm) => AllocatedOpcode::CFEI(imm.clone()),
CFSI(_sp, imm) => AllocatedOpcode::CFSI(imm.clone()),
CFE(_sp, reg) => AllocatedOpcode::CFE(map_reg(&mapping, reg)),
CFS(_sp, reg) => AllocatedOpcode::CFS(map_reg(&mapping, reg)),
LB(reg1, reg2, imm) => AllocatedOpcode::LB(
map_reg(&mapping, reg1),
map_reg(&mapping, reg2),
Expand Down Expand Up @@ -1775,6 +1775,7 @@ fn update_reg(
reg: &VirtualRegister,
) -> VirtualRegister {
if let Some(r) = reg_to_reg_map.get(reg) {
assert!(reg.is_virtual(), "Only virtual registers should be updated");
(*r).into()
} else {
reg.clone()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = "const_indexing_aggregates_asmgen"
source = "member"
dependencies = ["std"]

[[package]]
name = "core"
source = "path+from-root-BA8D9B16C05D491F"

[[package]]
name = "std"
source = "path+from-root-BA8D9B16C05D491F"
dependencies = ["core"]
Loading

0 comments on commit 977ab63

Please sign in to comment.